]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #42006 - jseyfried:fix_include_regression, r=nrc
authorMark Simulacrum <mark.simulacrum@gmail.com>
Fri, 19 May 2017 20:16:15 +0000 (14:16 -0600)
committerGitHub <noreply@github.com>
Fri, 19 May 2017 20:16:15 +0000 (14:16 -0600)
Fix ICE on `include!(line!())` (regression)

Fixes #41776.
r? @nrc

517 files changed:
.gitmodules
.travis.yml
CONTRIBUTING.md
RELEASES.md
appveyor.yml
configure
src/Cargo.lock
src/Cargo.toml
src/bootstrap/Cargo.toml
src/bootstrap/bin/rustc.rs
src/bootstrap/bootstrap.py
src/bootstrap/config.rs
src/bootstrap/config.toml.example
src/bootstrap/dist.rs
src/bootstrap/install.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/step.rs
src/ci/docker/README.md
src/ci/docker/arm-android/Dockerfile
src/ci/docker/arm-android/accept-licenses.sh [deleted file]
src/ci/docker/arm-android/install-ndk.sh [deleted file]
src/ci/docker/arm-android/install-sdk.sh [deleted file]
src/ci/docker/arm-android/start-emulator.sh [deleted file]
src/ci/docker/armhf-gnu/Dockerfile
src/ci/docker/cross/Dockerfile
src/ci/docker/disabled/dist-aarch64-android/Dockerfile [new file with mode: 0644]
src/ci/docker/disabled/dist-armv7-android/Dockerfile [new file with mode: 0644]
src/ci/docker/disabled/dist-i686-android/Dockerfile [new file with mode: 0644]
src/ci/docker/disabled/dist-x86_64-android/Dockerfile [new file with mode: 0644]
src/ci/docker/dist-aarch64-linux/Dockerfile
src/ci/docker/dist-android/Dockerfile
src/ci/docker/dist-android/install-ndk.sh [deleted file]
src/ci/docker/dist-arm-linux/Dockerfile
src/ci/docker/dist-armhf-linux/Dockerfile
src/ci/docker/dist-armv7-linux/Dockerfile
src/ci/docker/dist-fuchsia/Dockerfile
src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile
src/ci/docker/dist-i686-freebsd/Dockerfile
src/ci/docker/dist-i686-linux/Dockerfile
src/ci/docker/dist-mips-linux/Dockerfile
src/ci/docker/dist-mips64-linux/Dockerfile
src/ci/docker/dist-mips64el-linux/Dockerfile
src/ci/docker/dist-mipsel-linux/Dockerfile
src/ci/docker/dist-powerpc-linux/Dockerfile
src/ci/docker/dist-powerpc64-linux/Dockerfile
src/ci/docker/dist-powerpc64le-linux/Dockerfile
src/ci/docker/dist-s390x-linux/Dockerfile
src/ci/docker/dist-x86_64-freebsd/Dockerfile
src/ci/docker/dist-x86_64-linux/Dockerfile
src/ci/docker/dist-x86_64-musl/Dockerfile
src/ci/docker/dist-x86_64-netbsd/Dockerfile
src/ci/docker/emscripten/Dockerfile
src/ci/docker/i686-gnu-nopt/Dockerfile
src/ci/docker/i686-gnu/Dockerfile
src/ci/docker/run.sh
src/ci/docker/scripts/android-ndk.sh [new file with mode: 0644]
src/ci/docker/scripts/android-sdk.sh [new file with mode: 0644]
src/ci/docker/scripts/android-start-emulator.sh [new file with mode: 0755]
src/ci/docker/scripts/dumb-init.sh [new file with mode: 0644]
src/ci/docker/scripts/sccache.sh [new file with mode: 0644]
src/ci/docker/x86_64-gnu-aux/Dockerfile
src/ci/docker/x86_64-gnu-debug/Dockerfile
src/ci/docker/x86_64-gnu-distcheck/Dockerfile
src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile
src/ci/docker/x86_64-gnu-incremental/Dockerfile
src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile
src/ci/docker/x86_64-gnu-nopt/Dockerfile
src/ci/docker/x86_64-gnu/Dockerfile
src/doc/book
src/doc/reference
src/doc/rustc-ux-guidelines.md
src/doc/unstable-book/src/SUMMARY.md
src/doc/unstable-book/src/language-features/advanced-slice-patterns.md
src/doc/unstable-book/src/language-features/asm.md
src/doc/unstable-book/src/language-features/box-patterns.md
src/doc/unstable-book/src/language-features/box-syntax.md
src/doc/unstable-book/src/language-features/global_asm.md
src/doc/unstable-book/src/language-features/loop-break-value.md
src/doc/unstable-book/src/language-features/plugin-registrar.md
src/doc/unstable-book/src/language-features/plugin.md
src/doc/unstable-book/src/language-features/proc-macro.md
src/doc/unstable-book/src/language-features/slice-patterns.md
src/doc/unstable-book/src/library-features/alloc-jemalloc.md
src/doc/unstable-book/src/library-features/alloc-system.md
src/doc/unstable-book/src/library-features/print-internals.md [new file with mode: 0644]
src/doc/unstable-book/src/library-features/print.md [deleted file]
src/doc/unstable-book/src/library-features/vec-resize-default.md [new file with mode: 0644]
src/etc/platform-intrinsics/hexagon/hvx_v60.json [new file with mode: 0644]
src/grammar/.gitignore [new file with mode: 0644]
src/grammar/lexer.l [new file with mode: 0644]
src/grammar/parser-lalr-main.c [new file with mode: 0644]
src/grammar/parser-lalr.y [new file with mode: 0644]
src/grammar/raw-string-literal-ambiguity.md [new file with mode: 0644]
src/grammar/testparser.py [new file with mode: 0755]
src/grammar/tokens.h [new file with mode: 0644]
src/jemalloc
src/liballoc/arc.rs
src/liballoc_jemalloc/build.rs
src/libarena/lib.rs
src/libcollections/benches/lib.rs
src/libcollections/benches/slice.rs
src/libcollections/str.rs
src/libcollections/tests/slice.rs
src/libcollections/vec.rs
src/libcore/fmt/float.rs
src/libcore/iter/iterator.rs
src/libcore/lib.rs
src/libcore/num/float_macros.rs [deleted file]
src/libcore/num/flt2dec/mod.rs
src/libcore/num/mod.rs
src/libcore/num/wrapping.rs
src/libcore/ops.rs
src/libcore/ptr.rs
src/libcore/slice/mod.rs
src/libflate/lib.rs
src/libfmt_macros/lib.rs
src/libgetopts/lib.rs
src/libgraphviz/lib.rs
src/libproc_macro_plugin/lib.rs
src/libproc_macro_plugin/quote.rs
src/librustc/Cargo.toml
src/librustc/cfg/construct.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/mod.rs
src/librustc/diagnostics.rs
src/librustc/hir/check_attr.rs
src/librustc/hir/def_id.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/svh.rs
src/librustc/ich/caching_codemap_view.rs
src/librustc/ich/fingerprint.rs
src/librustc/ich/hcx.rs
src/librustc/ich/impls_cstore.rs [new file with mode: 0644]
src/librustc/ich/impls_hir.rs
src/librustc/ich/impls_syntax.rs
src/librustc/ich/impls_ty.rs
src/librustc/ich/mod.rs
src/librustc/infer/combine.rs
src/librustc/infer/equate.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/error_reporting/note.rs
src/librustc/infer/freshen.rs
src/librustc/infer/higher_ranked/mod.rs
src/librustc/infer/mod.rs
src/librustc/infer/region_inference/graphviz.rs
src/librustc/infer/region_inference/mod.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/lint/context.rs
src/librustc/middle/const_val.rs
src/librustc/middle/cstore.rs
src/librustc/middle/effect.rs
src/librustc/middle/entry.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/free_region.rs
src/librustc/middle/intrinsicck.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/region.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc/mir/mod.rs
src/librustc/mir/tcx.rs
src/librustc/mir/visit.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/mod.rs
src/librustc/traits/object_safety.rs
src/librustc/traits/project.rs
src/librustc/traits/specialize/mod.rs
src/librustc/traits/specialize/specialization_graph.rs
src/librustc/traits/util.rs
src/librustc/ty/context.rs
src/librustc/ty/fold.rs
src/librustc/ty/layout.rs
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc/ty/outlives.rs
src/librustc/ty/relate.rs
src/librustc/ty/sty.rs
src/librustc/ty/subst.rs
src/librustc/ty/trait_def.rs
src/librustc/ty/util.rs
src/librustc/util/common.rs
src/librustc/util/ppaux.rs
src/librustc_back/lib.rs
src/librustc_bitflags/lib.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_borrowck/borrowck/gather_loans/move_error.rs
src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
src/librustc_borrowck/borrowck/mir/mod.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/lib.rs
src/librustc_const_eval/check_match.rs
src/librustc_const_eval/eval.rs
src/librustc_const_eval/lib.rs
src/librustc_const_math/lib.rs
src/librustc_data_structures/lib.rs
src/librustc_data_structures/stable_hasher.rs
src/librustc_driver/Cargo.toml
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/target_features.rs
src/librustc_driver/test.rs
src/librustc_errors/diagnostic.rs
src/librustc_errors/diagnostic_builder.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_incremental/assert_dep_graph.rs
src/librustc_incremental/calculate_svh/mod.rs
src/librustc_incremental/lib.rs
src/librustc_incremental/persist/data.rs
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_incremental/persist/hash.rs
src/librustc_incremental/persist/load.rs
src/librustc_incremental/persist/preds/compress/test_macro.rs
src/librustc_incremental/persist/save.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_lint/unused.rs
src/librustc_llvm/lib.rs
src/librustc_metadata/Cargo.toml
src/librustc_metadata/astencode.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/index_builder.rs
src/librustc_metadata/isolated_encoder.rs [new file with mode: 0644]
src/librustc_metadata/lib.rs
src/librustc_metadata/locator.rs
src/librustc_metadata/schema.rs
src/librustc_mir/build/cfg.rs
src/librustc_mir/build/expr/as_operand.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/build/expr/as_temp.rs
src/librustc_mir/build/expr/stmt.rs
src/librustc_mir/build/matches/test.rs
src/librustc_mir/build/misc.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/hair/cx/block.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/mod.rs
src/librustc_mir/lib.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/copy_prop.rs
src/librustc_mir/transform/deaggregator.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/promote_consts.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/simplify_branches.rs
src/librustc_mir/transform/type_check.rs
src/librustc_mir/util/pretty.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/consts.rs
src/librustc_passes/hir_stats.rs
src/librustc_passes/lib.rs
src/librustc_passes/loops.rs
src/librustc_passes/mir_stats.rs
src/librustc_passes/static_recursion.rs
src/librustc_platform_intrinsics/hexagon.rs [new file with mode: 0644]
src/librustc_platform_intrinsics/lib.rs
src/librustc_plugin/lib.rs
src/librustc_plugin/registry.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/diagnostics.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/Cargo.toml
src/librustc_save_analysis/data.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/external_data.rs
src/librustc_save_analysis/json_api_dumper.rs
src/librustc_save_analysis/json_dumper.rs
src/librustc_save_analysis/lib.rs
src/librustc_trans/Cargo.toml
src/librustc_trans/back/archive.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/msvc/mod.rs
src/librustc_trans/back/symbol_names.rs
src/librustc_trans/base.rs
src/librustc_trans/collector.rs
src/librustc_trans/common.rs
src/librustc_trans/consts.rs
src/librustc_trans/lib.rs
src/librustc_trans/llvm_util.rs [new file with mode: 0644]
src/librustc_trans/macros.rs [deleted file]
src/librustc_trans/metadata.rs [new file with mode: 0644]
src/librustc_trans/mir/analyze.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/rvalue.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/autoderef.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/suggest.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/check/writeback.rs
src/librustc_typeck/coherence/builtin.rs
src/librustc_typeck/coherence/inherent_impls.rs
src/librustc_typeck/coherence/inherent_impls_overlap.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/orphan.rs
src/librustc_typeck/coherence/overlap.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/impl_wf_check.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/variance/constraints.rs
src/librustc_typeck/variance/xform.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/librustdoc/externalfiles.rs
src/librustdoc/html/format.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/lib.rs
src/librustdoc/test.rs
src/libserialize/lib.rs
src/libstd/ffi/c_str.rs
src/libstd/fs.rs
src/libstd/io/mod.rs
src/libstd/io/stdio.rs
src/libstd/macros.rs
src/libstd/path.rs
src/libstd/rt.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/ext/ffi.rs
src/libstd/sys/windows/ext/fs.rs
src/libstd/sys/windows/ext/mod.rs
src/libstd/sys/windows/os.rs
src/libstd/sys_common/backtrace.rs
src/libstd/sys_common/wtf8.rs
src/libstd/thread/local.rs
src/libstd/thread/mod.rs
src/libstd_unicode/lib.rs
src/libstd_unicode/u_str.rs
src/libsyntax/ast.rs
src/libsyntax/attr.rs
src/libsyntax/codemap.rs
src/libsyntax/config.rs
src/libsyntax/diagnostics/plugin.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/quote.rs
src/libsyntax/ext/source_util.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/json.rs
src/libsyntax/lib.rs
src/libsyntax/parse/attr.rs
src/libsyntax/parse/classify.rs
src/libsyntax/parse/common.rs
src/libsyntax/parse/lexer/comments.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/obsolete.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pp.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs
src/libsyntax/test.rs
src/libsyntax/tokenstream.rs
src/libsyntax/util/lev_distance.rs
src/libsyntax/util/move_map.rs
src/libsyntax/util/node_count.rs
src/libsyntax/visit.rs
src/libsyntax_ext/deriving/mod.rs
src/libsyntax_ext/lib.rs
src/libsyntax_ext/proc_macro_registrar.rs
src/libsyntax_pos/lib.rs
src/libterm/lib.rs
src/libtest/lib.rs
src/llvm
src/rust-installer [deleted submodule]
src/rustllvm/llvm-rebuild-trigger
src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs
src/test/compile-fail/E0435.rs
src/test/compile-fail/associated-const-type-parameter-arrays-2.rs
src/test/compile-fail/associated-const-type-parameter-arrays.rs
src/test/compile-fail/closure-no-fn-1.rs [new file with mode: 0644]
src/test/compile-fail/closure-no-fn-2.rs [new file with mode: 0644]
src/test/compile-fail/closure-no-fn-3.rs [new file with mode: 0644]
src/test/compile-fail/closure-no-fn.rs [deleted file]
src/test/compile-fail/coherence-inherited-assoc-ty-cycle-err.rs [new file with mode: 0644]
src/test/compile-fail/crt-static-gated.rs [deleted file]
src/test/compile-fail/feature-gate-allow-internal-unstable-nested-macro.rs
src/test/compile-fail/feature-gate-allow-internal-unstable.rs
src/test/compile-fail/inner-static-type-parameter.rs
src/test/compile-fail/invalid-macro-matcher.rs
src/test/compile-fail/issue-21356.rs
src/test/compile-fail/issue-27433.rs
src/test/compile-fail/issue-27942.rs
src/test/compile-fail/issue-3521-2.rs
src/test/compile-fail/issue-35675.rs
src/test/compile-fail/issue-3668-2.rs
src/test/compile-fail/issue-3668.rs
src/test/compile-fail/issue-37884.rs
src/test/compile-fail/issue-39388.rs
src/test/compile-fail/issue-39404.rs
src/test/compile-fail/issue-39559-2.rs [new file with mode: 0644]
src/test/compile-fail/issue-39559.rs
src/test/compile-fail/issue-40000.rs
src/test/compile-fail/issue-41255.rs [new file with mode: 0644]
src/test/compile-fail/issue-41726.rs [new file with mode: 0644]
src/test/compile-fail/issue-41742.rs [new file with mode: 0644]
src/test/compile-fail/issue-5067.rs
src/test/compile-fail/macro-expansion-tests.rs
src/test/compile-fail/macro-follow.rs
src/test/compile-fail/macro-followed-by-seq-bad.rs
src/test/compile-fail/macro-input-future-proofing.rs
src/test/compile-fail/macro-shadowing.rs
src/test/compile-fail/method-help-unsatisfied-bound.rs [deleted file]
src/test/compile-fail/non-exhaustive-match.rs
src/test/compile-fail/region-invariant-static-error-reporting.rs
src/test/compile-fail/regions-adjusted-lvalue-op.rs [new file with mode: 0644]
src/test/compile-fail/regions-trait-object-subtyping.rs
src/test/compile-fail/unused-macro-with-bad-frag-spec.rs
src/test/compile-fail/unused-macro-with-follow-violation.rs
src/test/compile-fail/unused-macro.rs [new file with mode: 0644]
src/test/compile-fail/user-defined-macro-rules.rs
src/test/compile-fail/variance-contravariant-arg-object.rs
src/test/compile-fail/variance-covariant-arg-object.rs
src/test/compile-fail/variance-invariant-arg-object.rs
src/test/incremental/add_private_fn_at_krate_root_cc/auxiliary/point.rs
src/test/incremental/callee_caller_cross_crate/auxiliary/a.rs
src/test/incremental/change_private_fn_cc/auxiliary/point.rs
src/test/incremental/change_private_impl_method_cc/auxiliary/point.rs
src/test/incremental/remapped_paths_cc/auxiliary/extern_crate.rs [new file with mode: 0644]
src/test/incremental/remapped_paths_cc/main.rs [new file with mode: 0644]
src/test/incremental/remove-private-item-cross-crate/auxiliary/a.rs
src/test/incremental/remove_source_file/auxiliary/mod.rs [new file with mode: 0644]
src/test/incremental/remove_source_file/main.rs [new file with mode: 0644]
src/test/incremental/rlib_cross_crate/auxiliary/a.rs
src/test/incremental/struct_change_field_type_cross_crate/auxiliary/a.rs
src/test/incremental/type_alias_cross_crate/auxiliary/a.rs
src/test/mir-opt/issue-41697.rs [new file with mode: 0644]
src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs
src/test/parse-fail/underscore-suffix-for-float.rs [new file with mode: 0644]
src/test/run-make/issue-19371/foo.rs
src/test/run-make/llvm-pass/plugin.rs
src/test/run-make/trace-macros-flag/Makefile [deleted file]
src/test/run-make/trace-macros-flag/hello.rs [deleted file]
src/test/run-make/trace-macros-flag/hello.trace [deleted file]
src/test/run-pass-fulldeps/issue-35829.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/macro-quote-1.rs
src/test/run-pass/associated-const-type-parameters.rs
src/test/run-pass/closure_to_fn_coercion-expected-types.rs [new file with mode: 0644]
src/test/run-pass/issue-41677.rs [new file with mode: 0644]
src/test/run-pass/issue-41696.rs [new file with mode: 0644]
src/test/run-pass/issue-41744.rs [new file with mode: 0644]
src/test/run-pass/issue-41803.rs [new file with mode: 0644]
src/test/run-pass/issue-41849-variance-req.rs [new file with mode: 0644]
src/test/run-pass/issue-41936-variance-coerce-unsized-cycle.rs [new file with mode: 0644]
src/test/run-pass/lex-bare-cr-nondoc-comment.rs [new file with mode: 0644]
src/test/run-pass/print-stdout-eprint-stderr.rs [new file with mode: 0644]
src/test/run-pass/specialization/assoc-ty-graph-cycle.rs [new file with mode: 0644]
src/test/run-pass/underscore-method-after-integer.rs [new file with mode: 0644]
src/test/rustdoc/extern-impl.rs
src/test/rustdoc/ffi.rs
src/test/rustdoc/issue-22038.rs
src/test/rustdoc/variadic.rs
src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr
src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr
src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr
src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr
src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr
src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr
src/test/ui/macros/trace-macro.rs [new file with mode: 0644]
src/test/ui/macros/trace-macro.stderr [new file with mode: 0644]
src/test/ui/mismatched_types/issue-36053-2.stderr
src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs [new file with mode: 0644]
src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr [new file with mode: 0644]
src/test/ui/resolve/enums-are-namespaced-xc.stderr
src/test/ui/resolve/issue-16058.stderr
src/test/ui/resolve/issue-17518.stderr
src/test/ui/resolve/issue-21221-1.stderr
src/test/ui/resolve/issue-21221-2.stderr
src/test/ui/resolve/issue-21221-3.stderr
src/test/ui/resolve/issue-21221-4.stderr
src/test/ui/resolve/issue-3907.stderr
src/test/ui/resolve/privacy-struct-ctor.stderr
src/test/ui/span/issue-35987.stderr
src/test/ui/static-lifetime.rs [new file with mode: 0644]
src/test/ui/static-lifetime.stderr [new file with mode: 0644]
src/tools/cargo
src/tools/compiletest/src/runtest.rs
src/tools/linkchecker/main.rs
src/tools/rls
src/tools/rust-installer [new submodule]
src/tools/tidy/src/deps.rs
src/tools/tidy/src/main.rs
src/tools/tidy/src/style.rs

index 7cd896b763f543fe87345089b5432036b6c24952..1ef3c086a1c232566edfb66c4bcd2b3836542530 100644 (file)
@@ -13,7 +13,7 @@
        path = src/jemalloc
        url = https://github.com/rust-lang/jemalloc.git
 [submodule "src/rust-installer"]
-       path = src/rust-installer
+       path = src/tools/rust-installer
        url = https://github.com/rust-lang/rust-installer.git
 [submodule "src/liblibc"]
        path = src/liblibc
@@ -23,7 +23,7 @@
        url = https://github.com/rust-lang-nursery/nomicon.git
 [submodule "src/tools/cargo"]
        path = src/tools/cargo
-       url = https://github.com/rust-lang/cargo
+       url = https://github.com/rust-lang/cargo.git
 [submodule "reference"]
        path = src/doc/reference
        url = https://github.com/rust-lang-nursery/reference.git
@@ -32,4 +32,4 @@
        url = https://github.com/rust-lang/book.git
 [submodule "src/tools/rls"]
        path = src/tools/rls
-       url = https://github.com/rust-lang-nursery/rls
+       url = https://github.com/rust-lang-nursery/rls.git
index 4fcf6f02defc4bd4666574d5247fc6a69d16f92d..190cb3380a18c633870f6c4d0f7baf677bf3d09a 100644 (file)
@@ -63,7 +63,7 @@ matrix:
       os: osx
       osx_image: xcode8.2
       install: &osx_install_sccache >
-        travis_retry curl -o /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-apple-darwin &&
+        travis_retry curl -o /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-apple-darwin &&
           chmod +x /usr/local/bin/sccache &&
         travis_retry curl -o /usr/local/bin/stamp https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin &&
           chmod +x /usr/local/bin/stamp
index 0314a5dfd8d02a5b283d317ef83cadad445fd8ce..8f121f8d6ed9b54434c5f1bb4e23a149a42381d6 100644 (file)
@@ -177,7 +177,7 @@ python x.py test src/test/rustdoc
 python x.py build src/libcore --stage 0
 ```
 
-You can explore the build system throught the various `--help` pages for each
+You can explore the build system through the various `--help` pages for each
 subcommand. For example to learn more about a command you can run:
 
 ```
index 571389041d6b643bdedff3ad52e2b36f9b9f7d04..8f641792add66cf519096bf6db50f13aacbc266b 100644 (file)
@@ -1,3 +1,261 @@
+Version 1.17.0 (2017-04-27)
+===========================
+
+Language
+--------
+
+* [The lifetime of statics and consts defaults to `'static`][39265]. [RFC 1623]
+* [Fields of structs may be initialized without duplicating the field/variable
+  names][39761]. [RFC 1682]
+* [`Self` may be included in the `where` clause of `impls`][38864]. [RFC 1647]
+* [When coercing to an unsized type lifetimes must be equal][40319]. That is,
+  there is no subtyping between `T` and `U` when `T: Unsize<U>`. For example,
+  coercing `&mut [&'a X; N]` to `&mut [&'b X]` requires `'a` be equal to
+  `'b`. Soundness fix.
+* [Values passed to the indexing operator, `[]`, automatically coerce][40166]
+* [Static variables may contain references to other statics][40027]
+
+Compiler
+--------
+
+* [Exit quickly on only `--emit dep-info`][40336]
+* [Make `-C relocation-model` more correctly determine whether the linker
+  creates a position-independent executable][40245]
+* [Add `-C overflow-checks` to directly control whether integer overflow
+  panics][40037]
+* [The rustc type checker now checks items on demand instead of in a single
+  in-order pass][40008]. This is mostly an internal refactoring in support of
+  future work, including incremental type checking, but also resolves [RFC
+  1647], allowing `Self` to appear in `impl` `where` clauses.
+* [Optimize vtable loads][39995]
+* [Turn off vectorization for Emscripten targets][39990]
+* [Provide suggestions for unknown macros imported with `use`][39953]
+* [Fix ICEs in path resolution][39939]
+* [Strip exception handling code on Emscripten when `panic=abort`][39193]
+* [Add clearer error message using `&str + &str`][39116]
+
+Stabilized APIs
+---------------
+
+* [`Arc::into_raw`]
+* [`Arc::from_raw`]
+* [`Arc::ptr_eq`]
+* [`Rc::into_raw`]
+* [`Rc::from_raw`]
+* [`Rc::ptr_eq`]
+* [`Ordering::then`]
+* [`Ordering::then_with`]
+* [`BTreeMap::range`]
+* [`BTreeMap::range_mut`]
+* [`collections::Bound`]
+* [`process::abort`]
+* [`ptr::read_unaligned`]
+* [`ptr::write_unaligned`]
+* [`Result::expect_err`]
+* [`Cell::swap`]
+* [`Cell::replace`]
+* [`Cell::into_inner`]
+* [`Cell::take`]
+
+Libraries
+---------
+
+* [`BTreeMap` and `BTreeSet` can iterate over ranges][27787]
+* [`Cell` can store non-`Copy` types][39793]. [RFC 1651]
+* [`String` implements `FromIterator<&char>`][40028]
+* `Box` [implements][40009] a number of new conversions:
+  `From<Box<str>> for String`,
+  `From<Box<[T]>> for Vec<T>`,
+  `From<Box<CStr>> for CString`,
+  `From<Box<OsStr>> for OsString`,
+  `From<Box<Path>> for PathBuf`,
+  `Into<Box<str>> for String`,
+  `Into<Box<[T]>> for Vec<T>`,
+  `Into<Box<CStr>> for CString`,
+  `Into<Box<OsStr>> for OsString`,
+  `Into<Box<Path>> for PathBuf`,
+  `Default for Box<str>`,
+  `Default for Box<CStr>`,
+  `Default for Box<OsStr>`,
+  `From<&CStr> for Box<CStr>`,
+  `From<&OsStr> for Box<OsStr>`,
+  `From<&Path> for Box<Path>`
+* [`ffi::FromBytesWithNulError` implements `Error` and `Display`][39960]
+* [Specialize `PartialOrd<A> for [A] where A: Ord`][39642]
+* [Slightly optimize `slice::sort`][39538]
+* [Add `ToString` trait specialization for `Cow<'a, str>` and `String`][39440]
+* [`Box<[T]>` implements `From<&[T]> where T: Copy`,
+  `Box<str>` implements `From<&str>`][39438]
+* [`IpAddr` implements `From` for various arrays. `SocketAddr` implements
+  `From<(I, u16)> where I: Into<IpAddr>`][39372]
+* [`format!` estimates the needed capacity before writing a string][39356]
+* [Support unprivileged symlink creation in Windows][38921]
+* [`PathBuf` implements `Default`][38764]
+* [Implement `PartialEq<[A]>` for `VecDeque<A>`][38661]
+* [`HashMap` resizes adaptively][38368] to guard against DOS attacks
+  and poor hash functions.
+
+Cargo
+-----
+
+* [Add `cargo check --all`][cargo/3731]
+* [Add an option to ignore SSL revocation checking][cargo/3699]
+* [Add `cargo run --package`][cargo/3691]
+* [Add `required_features`][cargo/3667]
+* [Assume `build.rs` is a build script][cargo/3664]
+* [Find workspace via `workspace_root` link in containing member][cargo/3562]
+
+Misc
+----
+
+* [Documentation is rendered with mdbook instead of the obsolete, in-tree
+  `rustbook`][39633]
+* [The "Unstable Book" documents nightly-only features][ubook]
+* [Improve the style of the sidebar in rustdoc output][40265]
+* [Configure build correctly on 64-bit CPU's with the armhf ABI][40261]
+* [Fix MSP430 breakage due to `i128`][40257]
+* [Preliminary Solaris/SPARCv9 support][39903]
+* [`rustc` is linked statically on Windows MSVC targets][39837], allowing it to
+  run without installing the MSVC runtime.
+* [`rustdoc --test` includes file names in test names][39788]
+* This release includes builds of `std` for `sparc64-unknown-linux-gnu`,
+  `aarch64-unknown-linux-fuchsia`, and `x86_64-unknown-linux-fuchsia`.
+* [Initial support for `aarch64-unknown-freebsd`][39491]
+* [Initial support for `i686-unknown-netbsd`][39426]
+* [This release no longer includes the old makefile build system][39431]. Rust
+  is built with a custom build system, written in Rust, and with Cargo.
+* [Add Debug implementations for libcollection structs][39002]
+* [`TypeId` implements `PartialOrd` and `Ord`][38981]
+* [`--test-threads=0` produces an error][38945]
+* [`rustup` installs documentation by default][40526]
+* [The Rust source includes NatVis visualizations][39843]. These can be used by
+  WinDbg and Visual Studio to improve the debugging experience.
+
+Compatibility Notes
+-------------------
+
+* [Rust 1.17 does not correctly detect the MSVC 2017 linker][38584]. As a
+  workaround, either use MSVC 2015 or run vcvars.bat.
+* [When coercing to an unsized type lifetimes must be equal][40319]. That is,
+  disallow subtyping between `T` and `U` when `T: Unsize<U>`, e.g. coercing
+  `&mut [&'a X; N]` to `&mut [&'b X]` requires `'a` be equal to `'b`. Soundness
+  fix.
+* [`format!` and `Display::to_string` panic if an underlying formatting
+  implementation returns an error][40117]. Previously the error was silently
+  ignored. It is incorrect for `write_fmt` to return an error when writing
+  to a string.
+* [In-tree crates are verified to be unstable][39851]. Previously, some minor
+  crates were marked stable and could be accessed from the stable toolchain.
+* [Rust git source no longer includes vendored crates][39728]. Those that need
+  to build with vendored crates should build from release tarballs.
+* [Fix inert attributes from `proc_macro_derives`][39572]
+* [During crate resolution, rustc prefers a crate in the sysroot if two crates
+  are otherwise identical][39518]. Unlikely to be encountered outside the Rust
+  build system.
+* [Fixed bugs around how type inference interacts with dead-code][39485]. The
+  existing code generally ignores the type of dead-code unless a type-hint is
+  provided; this can cause surprising inference interactions particularly around
+  defaulting. The new code uniformly ignores the result type of dead-code.
+* [Tuple-struct constructors with private fields are no longer visible][38932]
+* [Lifetime parameters that do not appear in the arguments are now considered
+  early-bound][38897], resolving a soundness bug (#[32330]). The
+  `hr_lifetime_in_assoc_type` future-compatibility lint has been in effect since
+  April of 2016.
+* [rustdoc: fix doctests with non-feature crate attributes][38161]
+* [Make transmuting from fn item types to pointer-sized types a hard
+  error][34198]
+
+[27787]: https://github.com/rust-lang/rust/issues/27787
+[32330]: https://github.com/rust-lang/rust/issues/32330
+[34198]: https://github.com/rust-lang/rust/pull/34198
+[38161]: https://github.com/rust-lang/rust/pull/38161
+[38368]: https://github.com/rust-lang/rust/pull/38368
+[38584]: https://github.com/rust-lang/rust/issues/38584
+[38661]: https://github.com/rust-lang/rust/pull/38661
+[38764]: https://github.com/rust-lang/rust/pull/38764
+[38864]: https://github.com/rust-lang/rust/issues/38864
+[38897]: https://github.com/rust-lang/rust/pull/38897
+[38921]: https://github.com/rust-lang/rust/pull/38921
+[38932]: https://github.com/rust-lang/rust/pull/38932
+[38945]: https://github.com/rust-lang/rust/pull/38945
+[38981]: https://github.com/rust-lang/rust/pull/38981
+[39002]: https://github.com/rust-lang/rust/pull/39002
+[39116]: https://github.com/rust-lang/rust/pull/39116
+[39193]: https://github.com/rust-lang/rust/pull/39193
+[39265]: https://github.com/rust-lang/rust/pull/39265
+[39356]: https://github.com/rust-lang/rust/pull/39356
+[39372]: https://github.com/rust-lang/rust/pull/39372
+[39426]: https://github.com/rust-lang/rust/pull/39426
+[39431]: https://github.com/rust-lang/rust/pull/39431
+[39438]: https://github.com/rust-lang/rust/pull/39438
+[39440]: https://github.com/rust-lang/rust/pull/39440
+[39485]: https://github.com/rust-lang/rust/pull/39485
+[39491]: https://github.com/rust-lang/rust/pull/39491
+[39518]: https://github.com/rust-lang/rust/pull/39518
+[39538]: https://github.com/rust-lang/rust/pull/39538
+[39572]: https://github.com/rust-lang/rust/pull/39572
+[39633]: https://github.com/rust-lang/rust/pull/39633
+[39642]: https://github.com/rust-lang/rust/pull/39642
+[39728]: https://github.com/rust-lang/rust/pull/39728
+[39761]: https://github.com/rust-lang/rust/pull/39761
+[39788]: https://github.com/rust-lang/rust/pull/39788
+[39793]: https://github.com/rust-lang/rust/pull/39793
+[39837]: https://github.com/rust-lang/rust/pull/39837
+[39843]: https://github.com/rust-lang/rust/pull/39843
+[39851]: https://github.com/rust-lang/rust/pull/39851
+[39903]: https://github.com/rust-lang/rust/pull/39903
+[39939]: https://github.com/rust-lang/rust/pull/39939
+[39953]: https://github.com/rust-lang/rust/pull/39953
+[39960]: https://github.com/rust-lang/rust/pull/39960
+[39990]: https://github.com/rust-lang/rust/pull/39990
+[39995]: https://github.com/rust-lang/rust/pull/39995
+[40008]: https://github.com/rust-lang/rust/pull/40008
+[40009]: https://github.com/rust-lang/rust/pull/40009
+[40027]: https://github.com/rust-lang/rust/pull/40027
+[40028]: https://github.com/rust-lang/rust/pull/40028
+[40037]: https://github.com/rust-lang/rust/pull/40037
+[40117]: https://github.com/rust-lang/rust/pull/40117
+[40166]: https://github.com/rust-lang/rust/pull/40166
+[40245]: https://github.com/rust-lang/rust/pull/40245
+[40257]: https://github.com/rust-lang/rust/pull/40257
+[40261]: https://github.com/rust-lang/rust/pull/40261
+[40265]: https://github.com/rust-lang/rust/pull/40265
+[40319]: https://github.com/rust-lang/rust/pull/40319
+[40336]: https://github.com/rust-lang/rust/pull/40336
+[40526]: https://github.com/rust-lang/rust/pull/40526
+[RFC 1623]: https://github.com/rust-lang/rfcs/blob/master/text/1623-static.md
+[RFC 1647]: https://github.com/rust-lang/rfcs/blob/master/text/1647-allow-self-in-where-clauses.md
+[RFC 1651]: https://github.com/rust-lang/rfcs/blob/master/text/1651-movecell.md
+[RFC 1682]: https://github.com/rust-lang/rfcs/blob/master/text/1682-field-init-shorthand.md
+[`Arc::from_raw`]: https://doc.rust-lang.org/std/sync/struct.Arc.html#method.from_raw
+[`Arc::into_raw`]: https://doc.rust-lang.org/std/sync/struct.Arc.html#method.into_raw
+[`Arc::ptr_eq`]: https://doc.rust-lang.org/std/sync/struct.Arc.html#method.ptr_eq
+[`BTreeMap::range_mut`]: https://doc.rust-lang.org/std/collections/btree_map/struct.BTreeMap.html#method.range_mut
+[`BTreeMap::range`]: https://doc.rust-lang.org/std/collections/btree_map/struct.BTreeMap.html#method.range
+[`Cell::into_inner`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.into_inner
+[`Cell::replace`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.replace
+[`Cell::swap`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.swap
+[`Cell::take`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.take
+[`Ordering::then_with`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.then_with
+[`Ordering::then`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.then
+[`Rc::from_raw`]: https://doc.rust-lang.org/std/rc/struct.Rc.html#method.from_raw
+[`Rc::into_raw`]: https://doc.rust-lang.org/std/rc/struct.Rc.html#method.into_raw
+[`Rc::ptr_eq`]: https://doc.rust-lang.org/std/rc/struct.Rc.html#method.ptr_eq
+[`Result::expect_err`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.expect_err
+[`collections::Bound`]: https://doc.rust-lang.org/std/collections/enum.Bound.html
+[`process::abort`]: https://doc.rust-lang.org/std/process/fn.abort.html
+[`ptr::read_unaligned`]: https://doc.rust-lang.org/std/ptr/fn.read_unaligned.html
+[`ptr::write_unaligned`]: https://doc.rust-lang.org/std/ptr/fn.write_unaligned.html
+[cargo/3562]: https://github.com/rust-lang/cargo/pull/3562
+[cargo/3664]: https://github.com/rust-lang/cargo/pull/3664
+[cargo/3667]: https://github.com/rust-lang/cargo/pull/3667
+[cargo/3691]: https://github.com/rust-lang/cargo/pull/3691
+[cargo/3699]: https://github.com/rust-lang/cargo/pull/3699
+[cargo/3731]: https://github.com/rust-lang/cargo/pull/3731
+[mdbook]: https://crates.io/crates/mdbook
+[ubook]: https://doc.rust-lang.org/unstable-book/
+
+
 Version 1.16.0 (2017-03-16)
 ===========================
 
index 8ace91c3d89e37f0d1b1006c9bf52fc5bf690940..96de1d90f25e623319f3defd8e2e5e2c0cceb2fe 100644 (file)
@@ -124,8 +124,8 @@ install:
   - set PATH=C:\Python27;%PATH%
 
   # Download and install sccache
-  - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-pc-windows-msvc
-  - mv 2017-04-29-sccache-x86_64-pc-windows-msvc sccache.exe
+  - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-pc-windows-msvc
+  - mv 2017-05-12-sccache-x86_64-pc-windows-msvc sccache.exe
   - set PATH=%PATH%;%CD%
 
   # Download and install ninja
@@ -141,9 +141,9 @@ install:
   - set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH%
 
   # Help debug some handle issues on AppVeyor
-  - ps: Invoke-WebRequest -Uri https://download.sysinternals.com/files/Handle.zip -OutFile handle.zip
+  - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-15-Handle.zip
   - mkdir handle
-  - ps: Expand-Archive handle.zip -dest handle
+  - 7z x -ohandle 2017-05-15-Handle.zip
   - set PATH=%PATH%;%CD%\handle
   - handle.exe -accepteula -help
 
index db41f0dfb94f388be9b8c405fa34def58bf29b62..af59d5b0bb88977d2c512af7fa1f1c096ed398ea 100755 (executable)
--- a/configure
+++ b/configure
@@ -519,6 +519,7 @@ valopt_nosave host "${CFG_BUILD}" "GNUs ./configure syntax LLVM host triples"
 valopt_nosave target "${CFG_HOST}" "GNUs ./configure syntax LLVM target triples"
 valopt_nosave mandir "${CFG_PREFIX}/share/man" "install man pages in PATH"
 valopt_nosave docdir "${CFG_PREFIX}/share/doc/rust" "install documentation in PATH"
+valopt_nosave bindir "${CFG_PREFIX}/bin" "install binaries"
 
 # On Windows this determines root of the subtree for target libraries.
 # Host runtime libs always go to 'bin'.
@@ -710,6 +711,7 @@ envopt LDFLAGS
 CFG_PREFIX=${CFG_PREFIX%/}
 CFG_MANDIR=${CFG_MANDIR%/}
 CFG_DOCDIR=${CFG_DOCDIR%/}
+CFG_BINDIR=${CFG_BINDIR%/}
 CFG_HOST="$(echo $CFG_HOST | tr ',' ' ')"
 CFG_TARGET="$(echo $CFG_TARGET | tr ',' ' ')"
 
@@ -750,6 +752,7 @@ putvar CFG_X86_64_LINUX_ANDROID_NDK
 putvar CFG_NACL_CROSS_PATH
 putvar CFG_MANDIR
 putvar CFG_DOCDIR
+putvar CFG_BINDIR
 putvar CFG_USING_LIBCPP
 
 msg
index 0b21ec986502109c1b62b4288b57f9d9da488fcf..804fd5807735f619c6cc62a7e01fd4665f3e2602 100644 (file)
@@ -6,6 +6,23 @@ dependencies = [
  "libc 0.0.0",
 ]
 
+[[package]]
+name = "advapi32-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "aho-corasick"
 version = "0.6.3"
@@ -27,7 +44,7 @@ version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
  "core 0.0.0",
- "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
 ]
 
@@ -49,20 +66,38 @@ name = "arena"
 version = "0.0.0"
 
 [[package]]
-name = "atty"
-version = "0.2.2"
+name = "backtrace"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
+ "backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "backtrace-sys"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "bitflags"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "bitflags"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "bitflags"
 version = "0.8.2"
@@ -73,21 +108,26 @@ name = "bootstrap"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "bufstream"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "build-manifest"
 version = "0.1.0"
 dependencies = [
- "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -98,31 +138,118 @@ dependencies = [
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "cargo"
+version = "0.20.0"
+source = "git+https://github.com/rust-lang/cargo#2b32084293d8da63b48de56363a0f2e986ec3367"
+replace = "cargo 0.20.0"
+
+[[package]]
+name = "cargo"
+version = "0.20.0"
+dependencies = [
+ "advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cargotest 0.1.0",
+ "chrono 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crates-io 0.9.0",
+ "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fs2 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "git2 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libgit2-sys 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tar 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cargotest"
+version = "0.1.0"
+dependencies = [
+ "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cargo 0.20.0",
+ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "git2 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tar 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "cargotest2"
 version = "0.1.0"
 
+[[package]]
+name = "cfg-if"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "chrono"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "clap"
-version = "2.22.1"
+version = "2.19.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "vec_map 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cmake"
-version = "0.1.22"
+version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -140,7 +267,7 @@ version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
  "core 0.0.0",
- "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -151,23 +278,115 @@ dependencies = [
  "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "core"
 version = "0.0.0"
 
+[[package]]
+name = "crates-io"
+version = "0.9.0"
+dependencies = [
+ "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "crossbeam"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "curl"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "curl-sys 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "curl-sys"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "dbghelp-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "derive-new"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "diff"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "docopt"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "dtoa"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "either"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "enum_primitive"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "env_logger"
 version = "0.4.2"
@@ -177,6 +396,14 @@ dependencies = [
  "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "error-chain"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "error_index_generator"
 version = "0.0.0"
@@ -186,7 +413,7 @@ name = "filetime"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -194,18 +421,51 @@ name = "flate"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "flate2"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "fmt_macros"
 version = "0.0.0"
 
+[[package]]
+name = "foreign-types"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "fs2"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "gcc"
-version = "0.3.45"
+version = "0.3.46"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "gdi32-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "getopts"
 version = "0.0.0"
@@ -215,22 +475,93 @@ name = "getopts"
 version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "git2"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libgit2-sys 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "git2-curl"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "git2 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "glob"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "graphviz"
 version = "0.0.0"
 
+[[package]]
+name = "hamcrest"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "handlebars"
-version = "0.25.2"
+version = "0.25.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "idna"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "installer"
+version = "0.0.0"
+dependencies = [
+ "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tar 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "itertools"
+version = "0.5.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -247,9 +578,22 @@ dependencies = [
  "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "languageserver-types"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "lazy_static"
-version = "0.2.5"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -261,8 +605,45 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.21"
+version = "0.2.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libgit2-sys"
+version = "0.6.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "libssh2-sys"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "libz-sys"
+version = "1.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "linkchecker"
@@ -273,21 +654,44 @@ name = "log"
 version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "lzma-sys"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "matches"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "mdbook"
 version = "0.0.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "handlebars 0.25.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "handlebars 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "memchr"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -295,7 +699,105 @@ name = "memchr"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "miniz-sys"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "miow"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "multimap"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "net2"
+version = "0.2.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-complex 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-complex"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-iter"
+version = "0.1.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.1.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -308,7 +810,7 @@ name = "num_cpus"
 version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -316,6 +818,43 @@ name = "open"
 version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "openssl"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "owning_ref"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "panic_abort"
 version = "0.0.0"
@@ -339,6 +878,11 @@ name = "pest"
 version = "0.3.3"
 source = "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 = "proc_macro"
 version = "0.0.0"
@@ -355,6 +899,15 @@ dependencies = [
  "syntax_pos 0.0.0",
 ]
 
+[[package]]
+name = "psapi-sys"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "pulldown-cmark"
 version = "0.0.8"
@@ -374,9 +927,33 @@ dependencies = [
 
 [[package]]
 name = "quick-error"
-version = "1.1.0"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "quote"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "quote"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "racer"
+version = "2.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "typed-arena 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rand"
 version = "0.0.0"
@@ -384,6 +961,31 @@ dependencies = [
  "core 0.0.0",
 ]
 
+[[package]]
+name = "rand"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.1.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "regex"
+version = "0.1.80"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "regex"
 version = "0.2.1"
@@ -396,6 +998,11 @@ dependencies = [
  "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "regex-syntax"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "regex-syntax"
 version = "0.4.0"
@@ -410,27 +1017,73 @@ name = "remote-test-server"
 version = "0.1.0"
 
 [[package]]
-name = "rls-data"
+name = "rls"
 version = "0.1.0"
+dependencies = [
+ "cargo 0.20.0 (git+https://github.com/rust-lang/cargo)",
+ "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-analysis 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfmt 0.8.4 (git+https://github.com/rust-lang-nursery/rustfmt)",
+ "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rls-analysis"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rls-data"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rls-span 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rls-span"
-version = "0.1.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rls-vfs"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "racer 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustbook"
 version = "0.1.0"
 dependencies = [
- "clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "mdbook 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -442,17 +1095,22 @@ dependencies = [
  "fmt_macros 0.0.0",
  "graphviz 0.0.0",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_back 0.0.0",
  "rustc_bitflags 0.0.0",
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
- "rustc_llvm 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
 
+[[package]]
+name = "rustc-demangle"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "rustc-main"
 version = "0.0.0"
@@ -464,7 +1122,7 @@ dependencies = [
 
 [[package]]
 name = "rustc-serialize"
-version = "0.3.23"
+version = "0.3.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -473,7 +1131,7 @@ version = "0.0.0"
 dependencies = [
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -552,7 +1210,6 @@ dependencies = [
  "rustc_errors 0.0.0",
  "rustc_incremental 0.0.0",
  "rustc_lint 0.0.0",
- "rustc_llvm 0.0.0",
  "rustc_metadata 0.0.0",
  "rustc_mir 0.0.0",
  "rustc_passes 0.0.0",
@@ -606,7 +1263,7 @@ name = "rustc_llvm"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_bitflags 0.0.0",
 ]
 
@@ -616,7 +1273,7 @@ version = "0.0.0"
 dependencies = [
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -626,13 +1283,13 @@ version = "0.0.0"
 dependencies = [
  "flate 0.0.0",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
- "rustc_llvm 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_ext 0.0.0",
@@ -660,7 +1317,7 @@ version = "0.0.0"
 dependencies = [
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -719,10 +1376,10 @@ name = "rustc_save_analysis"
 version = "0.0.0"
 dependencies = [
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-data 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-span 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_typeck 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
@@ -734,6 +1391,7 @@ version = "0.0.0"
 dependencies = [
  "flate 0.0.0",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_bitflags 0.0.0",
@@ -754,7 +1412,7 @@ version = "0.0.0"
 dependencies = [
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -782,7 +1440,7 @@ dependencies = [
  "arena 0.0.0",
  "build_helper 0.1.0",
  "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
@@ -800,26 +1458,128 @@ dependencies = [
  "syntax_pos 0.0.0",
 ]
 
+[[package]]
+name = "rustfmt"
+version = "0.8.4"
+source = "git+https://github.com/rust-lang-nursery/rustfmt#bf9b3fa1d7cab2f7bd541539d397a92b4954ec96"
+dependencies = [
+ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "same-file"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "serde"
+version = "0.9.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "serde"
-version = "0.9.11"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "serde_derive"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_derive_internals"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_ignored"
+version = "0.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_json"
+version = "0.9.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "serde_json"
-version = "0.9.9"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serialize"
 version = "0.0.0"
 
+[[package]]
+name = "shell-escape"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "std"
 version = "0.0.0"
@@ -831,7 +1591,7 @@ dependencies = [
  "collections 0.0.0",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
- "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
@@ -851,11 +1611,51 @@ dependencies = [
  "core 0.0.0",
 ]
 
+[[package]]
+name = "strings"
+version = "0.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "strsim"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "strsim"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "syn"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syn"
+version = "0.11.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "synom"
+version = "0.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "syntax"
 version = "0.0.0"
@@ -887,17 +1687,113 @@ dependencies = [
  "serialize 0.0.0",
 ]
 
+[[package]]
+name = "syntex_errors"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syntex_errors"
+version = "0.58.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syntex_pos"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syntex_pos"
+version = "0.58.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syntex_syntax"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syntex_syntax"
+version = "0.58.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tar"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tempdir"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "term"
 version = "0.0.0"
 
+[[package]]
+name = "term"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "term_size"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -911,11 +1807,28 @@ dependencies = [
 
 [[package]]
 name = "thread-id"
-version = "3.0.0"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thread-id"
+version = "3.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thread_local"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -923,7 +1836,7 @@ name = "thread_local"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -931,25 +1844,75 @@ dependencies = [
 name = "tidy"
 version = "0.1.0"
 
+[[package]]
+name = "time"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "toml"
 version = "0.1.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "toml"
-version = "0.3.1"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "toml"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "toml"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "typed-arena"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "unicode-bidi"
+version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "unicode-normalization"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "unicode-segmentation"
-version = "1.1.0"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -957,6 +1920,16 @@ name = "unicode-width"
 version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "unicode-xid"
+version = "0.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "unicode-xid"
+version = "0.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "unreachable"
 version = "0.1.1"
@@ -965,6 +1938,38 @@ dependencies = [
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "url"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "url_serde"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "user32-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "utf8-ranges"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "utf8-ranges"
 version = "1.0.0"
@@ -972,7 +1977,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "vec_map"
-version = "0.7.0"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -980,6 +1985,16 @@ name = "void"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "walkdir"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "winapi"
 version = "0.2.8"
@@ -990,53 +2005,189 @@ name = "winapi-build"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "ws2_32-sys"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "xattr"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "xz2"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lzma-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "yaml-rust"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [metadata]
+"checksum advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06588080cb19d0acb6739808aafa5f26bfb2ca015b2b6370028b44cf7cb8a9a"
+"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
 "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
 "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
-"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
+"checksum backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80"
+"checksum backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d192fd129132fbc97497c1f2ec2c2c5174e376b95f535199ef4fe0a293d33842"
 "checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
+"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
 "checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4"
-"checksum clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e17a4a72ffea176f77d6e2db609c6c919ef221f23862c9915e687fb54d833485"
-"checksum cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "d18d68987ed4c516dcc3e7913659bfa4076f5182eea4a7e0038bb060953e76ac"
+"checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
+"checksum cargo 0.20.0 (git+https://github.com/rust-lang/cargo)" = "<none>"
+"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
+"checksum chrono 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d9123be86fd2a8f627836c235ecdf331fdd067ecf7ac05aa1a68fbcf2429f056"
+"checksum clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95b78f3fe0fc94c13c731714363260e04b557a637166f33a4570d3189d642374"
+"checksum cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "92278eb79412c8f75cfc89e707a1bb3a6490b68f7f2e78d15c774f30fe701122"
+"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
+"checksum curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c90e1240ef340dd4027ade439e5c7c2064dd9dc652682117bd50d1486a3add7b"
+"checksum curl-sys 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "23e7e544dc5e1ba42c4a4a678bd47985e84b9c3f4d3404c29700622a029db9c3"
+"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
+"checksum derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41be6ca3b99e0c0483fb2389685448f650459c3ecbe4e18d7705d8010ec4ab8e"
 "checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472"
+"checksum docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab32ea6e284d87987066f21a9e809a73c14720571ef34516f0890b3d355ccfd8"
 "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
+"checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"
+"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
+"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
 "checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83"
+"checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8"
 "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
-"checksum gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "40899336fb50db0c78710f53e87afc54d8c7266fb76262fecc78ca1a7f09deae"
+"checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c"
+"checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d"
+"checksum fs2 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34edaee07555859dc13ca387e6ae05686bb4d0364c95d649b6dab959511f4baf"
+"checksum gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)" = "181e3cebba1d663bd92eb90e2da787e10597e027eb00de8d742b260a7850948f"
+"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
 "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
-"checksum handlebars 0.25.2 (registry+https://github.com/rust-lang/crates.io-index)" = "663e1728d8037fb0d4e13bcd1b1909fb5d913690a9929eb385922df157c2ff8f"
+"checksum git2 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9de9df4358c17e448a778d90cd0272e1dab5eae30244502333fa2001c4e24357"
+"checksum git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68676bc784bf0bef83278898929bf64a251e87c0340723d0b93fa096c9c5bf8e"
+"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
+"checksum hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bf088f042a467089e9baa4972f57f9247e42a0cc549ba264c7a04fbb8ecb89d4"
+"checksum handlebars 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)" = "15bdf598fc3c2de40c6b340213028301c0d225eea55a2294e6cc148074e557a1"
+"checksum idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac85ec3f80c8e4e99d9325521337e14ec7555c458a14e377d189659a427f375"
+"checksum itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4833d6978da405305126af4ac88569b5d71ff758581ce5a987dbfa3755f694fc"
 "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-"checksum lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4732c563b9a21a406565c4747daa7b46742f082911ae4753f390dc9ec7ee1a97"
-"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135"
+"checksum languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97c2985bfcbbcb0189cfa25e1c10c1ac7111df2b6214b652c690127aefdf4e5b"
+"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
+"checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502"
+"checksum libgit2-sys 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "dd89dd7196d5fa35b659c3eaf3c1b14b9bd961bfd1a07dfca49adeb8a6aa3763"
+"checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75"
+"checksum libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e5ee912a45d686d393d5ac87fac15ba0ba18daae14e8e7543c63ebf7fb7e970c"
 "checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad"
+"checksum lzma-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fedff6a5cbb24494ec6ee4784e9ac5c187161fede04c7767d49bf87544013afa"
+"checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1"
 "checksum mdbook 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e2e9d848514dcfad4195788d0d42ae5153a477c191d75d5b84fab10f222fbd"
+"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
 "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
+"checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726"
+"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
+"checksum multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9223f4774d08e06185e44e555b9a7561243d387bac49c78a6205c42d6975fbf2"
+"checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67"
+"checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40"
+"checksum num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "ba6d838b16e56da1b6c383d065ff1ec3c7d7797f65a3e8f6ba7092fd87820bac"
+"checksum num-complex 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "148eb324ca772230853418731ffdf13531738b50f89b30692a01fcdcb0a64677"
+"checksum num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "ef1a4bf6f9174aa5783a9b4cc892cacd11aebad6c69ad027a0b65c6ca5f8aa37"
+"checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e"
+"checksum num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dc5ea04020a8f18318ae485c751f8cfa1c0e69dcf465c29ddaaa64a313cc44"
 "checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
 "checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167"
 "checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842"
+"checksum openssl 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bb5d1663b73d10c6a3eda53e2e9d0346f822394e7b858d7257718f65f61dfbe2"
+"checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf"
+"checksum openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3a5886d87d3e2a0d890bf62dc8944f5e3769a405f7e1e9ef6e517e47fd7a0897"
+"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
+"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
+"checksum psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abcd5d1a07d360e29727f757a9decb3ce8bc6e0efa8969cfaad669a8317a2478"
 "checksum pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ab1e588ef8efd702c7ed9d2bd774db5e6f4d878bb5a1a9f371828fbdff6973"
 "checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41"
-"checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c"
+"checksum quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c36987d4978eb1be2e422b1e0423a557923a5c3e7e6f31d5699e9aafaefa469"
+"checksum quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5cf478fe1006dbcc72567121d23dbdae5f1632386068c5c86ff4f645628504"
+"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
+"checksum racer 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b0d72b3afd67882adfca61d609fafb8d7aa5f9e814f12c32fcc6e171995920e8"
+"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
+"checksum redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "29dbdfd4b9df8ab31dec47c6087b7b13cbf4a776f335e4de8efba8288dda075b"
+"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
 "checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
+"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
 "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457"
-"checksum rls-data 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af1dfff00189fd7b78edb9af131b0de703676c04fa8126aed77fd2c586775a4d"
-"checksum rls-span 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8656f7b850ac85fb204ef94318c641bbb15a32766e12f9a589a23e4c0fbc38db"
-"checksum rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "684ce48436d6465300c9ea783b6b14c4361d6b8dcbb1375b486a69cc19e2dfb0"
-"checksum serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a702319c807c016e51f672e5c77d6f0b46afddd744b5e437d6b8436b888b458f"
-"checksum serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)" = "dbc45439552eb8fb86907a2c41c1fd0ef97458efb87ff7f878db466eb581824e"
+"checksum rls-analysis 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a62d88c341375c6f3f8b2e18b9b364896e7d3e7aa916907de717d0267e116506"
+"checksum rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc4277ce3c57f456b11fe3145b181a844a25201bab5cbaa1978457e6e2f27d47"
+"checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
+"checksum rls-vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "986eada111517bcb5a7a75205b3f2b70c82e7766653cca61a23f5afce79bdb94"
+"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
+"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
+"checksum rustfmt 0.8.4 (git+https://github.com/rust-lang-nursery/rustfmt)" = "<none>"
+"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
+"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
+"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+"checksum serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34b623917345a631dc9608d5194cc206b3fe6c3554cd1c75b937e55e285254af"
+"checksum serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "38a3db3a5757f68069aba764b793823ea9fb9717c42c016f8903f8add50f508a"
+"checksum serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e46ef71ee001a4279a4513e79a6ebbb59da3a4987bf77a6df2e5534cd6f21d82"
+"checksum serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "021c338d22c7e30f957a6ab7e388cb6098499dda9fd4ba1661ee074ca7a180d1"
+"checksum serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c10e798e4405d7dcec3658989e35ee6706f730a9ed7c1184d5ebd84317e82f46"
+"checksum serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ad8bcf487be7d2e15d3d543f04312de991d631cfe1b43ea0ade69e6a8a5b16a1"
+"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b"
+"checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8"
+"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
+"checksum strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "54f86446ab480b4f60782188f4f78886465c5793aee248cbb48b7fdc0d022420"
+"checksum strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c"
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
+"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
+"checksum syn 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6ae6fb0dcc9bd85f89a1a4adc0df2fd90c90c98849d61433983dd7a9df6363f7"
+"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
+"checksum syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e52bffe6202cfb67587784cf23e0ec5bf26d331eef4922a16d5c42e12aa1e9b"
+"checksum syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "867cc5c2d7140ae7eaad2ae9e8bf39cb18a67ca651b7834f88d46ca98faadb9c"
+"checksum syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "955ef4b16af4c468e4680d1497f873ff288f557d338180649e18f915af5e15ac"
+"checksum syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13ad4762fe52abc9f4008e85c4fb1b1fe3aa91ccb99ff4826a439c7c598e1047"
+"checksum syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76a302e717e348aa372ff577791c3832395650073b8d8432f8b3cb170b34afde"
+"checksum syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e0e4dbae163dd98989464c23dd503161b338790640e11537686f2ef0f25c791"
+"checksum tar 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ab0ef9ead2fe0aa9e18475a96a207bfd5143f4124779ef7429503a8665416ce8"
+"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
+"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989"
 "checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a"
-"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a"
+"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
+"checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773"
+"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
 "checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
+"checksum time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd7ccbf969a892bf83f1e441126968a07a3941c24ff522a26af9f9f4585d1a3"
 "checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796"
-"checksum toml 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3474f3c6eaf32eedb4f4a66a26214f020f828a6d96c37e38a35e3a379bbcfd11"
-"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
+"checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
+"checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f"
+"checksum toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4cc5dbfb20a481e64b99eb7ae280859ec76730c7191570ba5edaa962394edb0a"
+"checksum typed-arena 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e2f9dc90da4f9d66ffc9ad3ead2c7d57582a26f4a3292d2ce7011bd29965100"
+"checksum unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a078ebdd62c0e71a709c3d53d2af693fe09fe93fbff8344aebe289b78f9032"
+"checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff"
+"checksum unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c3bc443ded17b11305ffffe6b37e2076f328a5a8cb6aa877b1b98f77699e98b5"
+"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946"
 "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
+"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 unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
+"checksum url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5ba8a749fb4479b043733416c244fa9d1d3af3d7c23804944651c8a448cb87e"
+"checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea"
+"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47"
+"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
-"checksum vec_map 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8cdc8b93bd0198ed872357fb2e667f7125646b1762f16d60b2c96350d361897"
+"checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
+"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
+"checksum xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "5f04de8a1346489a2f9e9bd8526b73d135ec554227b17568456e86aa35b6f3fc"
+"checksum xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e9510bdf100731599107c61f77daf46713a69a568f75458999c1f9dbf6ba25b0"
+"checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992"
index 9aca3e134d6555aa6cd220675174267d3596cf11..85a6df3573ae120f377870a59a5162b3188c809f 100644 (file)
@@ -13,10 +13,7 @@ members = [
   "tools/build-manifest",
   "tools/remote-test-client",
   "tools/remote-test-server",
-]
-
-# These projects have their own Cargo.lock
-exclude = [
+  "tools/rust-installer",
   "tools/cargo",
   "tools/rls",
 ]
@@ -37,3 +34,6 @@ debug-assertions = false
 [profile.test]
 debug = false
 debug-assertions = false
+
+[replace]
+"https://github.com/rust-lang/cargo#0.20.0" = { path = "tools/cargo" }
index 1088067c2de57dce0df437d9ab661e5bd710c813..cc560e0172e3a3fa63a6e92e2bc873b028d49633 100644 (file)
@@ -30,11 +30,11 @@ test = false
 
 [dependencies]
 build_helper = { path = "../build_helper" }
-cmake = "0.1.17"
+cmake = "0.1.23"
 filetime = "0.1"
 num_cpus = "1.0"
 toml = "0.1"
 getopts = "0.2"
 rustc-serialize = "0.3"
-gcc = "0.3.38"
+gcc = "0.3.46"
 libc = "0.2"
index 62b7f6cb72e3baf51199d72942eb65d069a4fa89..eb2cef133a34f2401b014f7a9b545bb7535845ab 100644 (file)
 use std::process::{Command, ExitStatus};
 
 fn main() {
-    let args = env::args_os().skip(1).collect::<Vec<_>>();
+    let mut args = env::args_os().skip(1).collect::<Vec<_>>();
+
+    // Append metadata suffix for internal crates. See the corresponding entry
+    // in bootstrap/lib.rs for details.
+    if let Ok(s) = env::var("RUSTC_METADATA_SUFFIX") {
+        for i in 1..args.len() {
+            // Dirty code for borrowing issues
+            let mut new = None;
+            if let Some(current_as_str) = args[i].to_str() {
+                if (&*args[i - 1] == "-C" && current_as_str.starts_with("metadata")) ||
+                   current_as_str.starts_with("-Cmetadata") {
+                    new = Some(format!("{}-{}", current_as_str, s));
+                }
+            }
+            if let Some(new) = new { args[i] = new.into(); }
+        }
+    }
+
     // Detect whether or not we're a build script depending on whether --target
     // is passed (a bit janky...)
     let target = args.windows(2)
@@ -194,6 +211,8 @@ fn main() {
                 // do that we pass a weird flag to the compiler to get it to do
                 // so. Note that this is definitely a hack, and we should likely
                 // flesh out rpath support more fully in the future.
+                //
+                // FIXME: remove condition after next stage0
                 if stage != "0" {
                     cmd.arg("-Z").arg("osx-rpath-install-name");
                 }
@@ -218,6 +237,17 @@ fn main() {
             cmd.arg("-Z").arg("unstable-options");
             cmd.arg("-C").arg("target-feature=+crt-static");
         }
+
+        // Force all crates compiled by this compiler to (a) be unstable and (b)
+        // allow the `rustc_private` feature to link to other unstable crates
+        // also in the sysroot.
+        //
+        // FIXME: remove condition after next stage0
+        if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() {
+            if stage != "0" {
+                cmd.arg("-Z").arg("force-unstable-if-unmarked");
+            }
+        }
     }
 
     if verbose > 1 {
index ad3cf31c1b921b50d41e0d256958eb22b841f241..e15304a7e6e67b318ce93837d32769082b774c54 100644 (file)
@@ -14,6 +14,7 @@ import contextlib
 import datetime
 import hashlib
 import os
+import re
 import shutil
 import subprocess
 import sys
@@ -126,13 +127,13 @@ def unpack(tarball, dst, verbose=False, match=None):
             shutil.move(tp, fp)
     shutil.rmtree(os.path.join(dst, fname))
 
-def run(args, verbose=False, exception=False):
+def run(args, verbose=False, exception=False, cwd=None):
     if verbose:
         print("running: " + ' '.join(args))
     sys.stdout.flush()
     # Use Popen here instead of call() as it apparently allows powershell on
     # Windows to not lock up waiting for input presumably.
-    ret = subprocess.Popen(args)
+    ret = subprocess.Popen(args, cwd=cwd)
     code = ret.wait()
     if code != 0:
         err = "failed to run: " + ' '.join(args)
@@ -297,8 +298,10 @@ class RustBuild(object):
 
     def get_toml(self, key):
         for line in self.config_toml.splitlines():
-            if line.startswith(key + ' ='):
-                return self.get_string(line)
+            match = re.match(r'^{}\s*=(.*)$'.format(key), line)
+            if match is not None:
+                value = match.group(1)
+                return self.get_string(value) or value.strip()
         return None
 
     def get_mk(self, key):
@@ -329,6 +332,8 @@ class RustBuild(object):
 
     def get_string(self, line):
         start = line.find('"')
+        if start == -1:
+            return None
         end = start + 1 + line[start + 1:].find('"')
         return line[start + 1:end]
 
@@ -386,12 +391,21 @@ class RustBuild(object):
             args.append("--frozen")
         self.run(args, env)
 
-    def run(self, args, env):
-        proc = subprocess.Popen(args, env=env)
+    def run(self, args, env=None, cwd=None):
+        proc = subprocess.Popen(args, env=env, cwd=cwd)
         ret = proc.wait()
         if ret != 0:
             sys.exit(ret)
 
+    def output(self, args, env=None, cwd=None):
+        proc = subprocess.Popen(args, stdout=subprocess.PIPE, env=env, cwd=cwd)
+        (out, err) = proc.communicate()
+        ret = proc.wait()
+        if ret != 0:
+            print(out)
+            sys.exit(ret)
+        return out
+
     def build_triple(self):
         default_encoding = sys.getdefaultencoding()
         config = self.get_toml('build')
@@ -529,6 +543,54 @@ class RustBuild(object):
 
         return "{}-{}".format(cputype, ostype)
 
+    def update_submodules(self):
+        if (not os.path.exists(os.path.join(self.rust_root, ".git"))) or \
+            self.get_toml('submodules') == "false" or \
+            self.get_mk('CFG_DISABLE_MANAGE_SUBMODULES') == "1":
+            return
+
+        print('Updating submodules')
+        output = self.output(["git", "submodule", "status"], cwd=self.rust_root)
+        submodules = []
+        for line in output.splitlines():
+            # NOTE `git submodule status` output looks like this:
+            #
+            # -5066b7dcab7e700844b0e2ba71b8af9dc627a59b src/liblibc
+            # +b37ef24aa82d2be3a3cc0fe89bf82292f4ca181c src/compiler-rt (remotes/origin/..)
+            #  e058ca661692a8d01f8cf9d35939dfe3105ce968 src/jemalloc (3.6.0-533-ge058ca6)
+            #
+            # The first character can be '-', '+' or ' ' and denotes the
+            # `State` of the submodule Right next to this character is the
+            # SHA-1 of the submodule HEAD And after that comes the path to the
+            # submodule
+            path = line[1:].split(' ')[1]
+            submodules.append([path, line[0]])
+
+        self.run(["git", "submodule", "sync"], cwd=self.rust_root)
+
+        for submod in submodules:
+            path, status = submod
+            if path.endswith(b"llvm") and \
+                (self.get_toml('llvm-config') or self.get_mk('CFG_LLVM_ROOT')):
+                continue
+            if path.endswith(b"jemalloc") and \
+                (self.get_toml('jemalloc') or self.get_mk('CFG_JEMALLOC_ROOT')):
+                continue
+            submod_path = os.path.join(self.rust_root, path)
+
+            if status == ' ':
+                self.run(["git", "reset", "--hard"], cwd=submod_path)
+                self.run(["git", "clean", "-fdx"], cwd=submod_path)
+            elif status == '+':
+                self.run(["git", "submodule", "update", path], cwd=self.rust_root)
+                self.run(["git", "reset", "--hard"], cwd=submod_path)
+                self.run(["git", "clean", "-fdx"], cwd=submod_path)
+            elif status == '-':
+                self.run(["git", "submodule", "init", path], cwd=self.rust_root)
+                self.run(["git", "submodule", "update", path], cwd=self.rust_root)
+            else:
+                raise ValueError('unknown submodule status: ' + status)
+
 def bootstrap():
     parser = argparse.ArgumentParser(description='Build rust')
     parser.add_argument('--config')
@@ -597,6 +659,8 @@ def bootstrap():
     else:
         rb._download_url = 'https://static.rust-lang.org'
 
+    rb.update_submodules()
+
     # Fetch/build the bootstrap
     rb.build = rb.build_triple()
     rb.download_stage0()
index 34fbc33d981afddfdc8af7662b85e2ed82a885d4..0fb597564e33de15c2bc6defc8fd35273dfb43df 100644 (file)
@@ -99,7 +99,9 @@ pub struct Config {
     // Fallback musl-root for all targets
     pub musl_root: Option<PathBuf>,
     pub prefix: Option<PathBuf>,
+    pub sysconfdir: Option<PathBuf>,
     pub docdir: Option<PathBuf>,
+    pub bindir: Option<PathBuf>,
     pub libdir: Option<PathBuf>,
     pub libdir_relative: Option<PathBuf>,
     pub mandir: Option<PathBuf>,
@@ -165,9 +167,11 @@ struct Build {
 #[derive(RustcDecodable, Default, Clone)]
 struct Install {
     prefix: Option<String>,
-    mandir: Option<String>,
+    sysconfdir: Option<String>,
     docdir: Option<String>,
+    bindir: Option<String>,
     libdir: Option<String>,
+    mandir: Option<String>,
 }
 
 /// TOML representation of how the LLVM build is configured.
@@ -264,7 +268,7 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
             let table = match p.parse() {
                 Some(table) => table,
                 None => {
-                    println!("failed to parse TOML configuration:");
+                    println!("failed to parse TOML configuration '{}':", file.to_str().unwrap());
                     for err in p.errors.iter() {
                         let (loline, locol) = p.to_linecol(err.lo);
                         let (hiline, hicol) = p.to_linecol(err.hi);
@@ -315,9 +319,11 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
 
         if let Some(ref install) = toml.install {
             config.prefix = install.prefix.clone().map(PathBuf::from);
-            config.mandir = install.mandir.clone().map(PathBuf::from);
+            config.sysconfdir = install.sysconfdir.clone().map(PathBuf::from);
             config.docdir = install.docdir.clone().map(PathBuf::from);
+            config.bindir = install.bindir.clone().map(PathBuf::from);
             config.libdir = install.libdir.clone().map(PathBuf::from);
+            config.mandir = install.mandir.clone().map(PathBuf::from);
         }
 
         if let Some(ref llvm) = toml.llvm {
@@ -523,9 +529,15 @@ macro_rules! check {
                 "CFG_PREFIX" => {
                     self.prefix = Some(PathBuf::from(value));
                 }
+                "CFG_SYSCONFDIR" => {
+                    self.sysconfdir = Some(PathBuf::from(value));
+                }
                 "CFG_DOCDIR" => {
                     self.docdir = Some(PathBuf::from(value));
                 }
+                "CFG_BINDIR" => {
+                    self.bindir = Some(PathBuf::from(value));
+                }
                 "CFG_LIBDIR" => {
                     self.libdir = Some(PathBuf::from(value));
                 }
index 0309eca0e5deaec6a4f94081843386434397b684..df180be4e27ab0836b6df75d4b939aeac3c4fe7d 100644 (file)
 # Instead of installing to /usr/local, install to this path instead.
 #prefix = "/usr/local"
 
+# Where to install system configuration files
+# If this is a relative path, it will get installed in `prefix` above
+#sysconfdir = "/etc"
+
+# Where to install documentation in `prefix` above
+#docdir = "share/doc/rust"
+
+# Where to install binaries in `prefix` above
+#bindir = "bin"
+
 # Where to install libraries in `prefix` above
 #libdir = "lib"
 
 # Where to install man pages in `prefix` above
 #mandir = "share/man"
 
-# Where to install documentation in `prefix` above
-#docdir = "share/doc/rust"
-
 # =============================================================================
 # Options for compiling Rust code itself
 # =============================================================================
 [rust]
 
 # Whether or not to optimize the compiler and standard library
+# Note: the slowness of the non optimized compiler compiling itself usually
+#       outweighs the time gains in not doing optimizations, therefore a
+#       full bootstrap takes much more time with optimize set to false.
 #optimize = true
 
 # Number of codegen units to use for each compiler invocation. A value of 0
index 1b69f7413b569744664e1990a2c70c825a250503..511f2c9e80ec72e732caba01da7cbb468850745b 100644 (file)
 
 use build_helper::output;
 
-#[cfg(not(target_os = "solaris"))]
-const SH_CMD: &'static str = "sh";
-// On Solaris, sh is the historical bourne shell, not a POSIX shell, or bash.
-#[cfg(target_os = "solaris")]
-const SH_CMD: &'static str = "bash";
-
 use {Build, Compiler, Mode};
 use channel;
 use util::{cp_r, libdir, is_dylib, cp_filtered, copy, exe};
@@ -55,6 +49,10 @@ pub fn tmpdir(build: &Build) -> PathBuf {
     build.out.join("tmp/dist")
 }
 
+fn rust_installer(build: &Build) -> Command {
+    build.tool_cmd(&Compiler::new(0, &build.config.build), "rust-installer")
+}
+
 /// Builds the `rust-docs` installer component.
 ///
 /// Slurps up documentation from the `stage`'s `host`.
@@ -74,14 +72,14 @@ pub fn docs(build: &Build, stage: u32, host: &str) {
     let src = build.out.join(host).join("doc");
     cp_r(&src, &dst);
 
-    let mut cmd = Command::new(SH_CMD);
-    cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+    let mut cmd = rust_installer(build);
+    cmd.arg("generate")
        .arg("--product-name=Rust-Documentation")
        .arg("--rel-manifest-dir=rustlib")
        .arg("--success-message=Rust-documentation-is-installed.")
-       .arg(format!("--image-dir={}", sanitize_sh(&image)))
-       .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
-       .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
+       .arg("--image-dir").arg(&image)
+       .arg("--work-dir").arg(&tmpdir(build))
+       .arg("--output-dir").arg(&distdir(build))
        .arg(format!("--package-name={}-{}", name, host))
        .arg("--component-name=rust-docs")
        .arg("--legacy-manifest-dirs=rustlib,cargo")
@@ -124,14 +122,14 @@ pub fn mingw(build: &Build, host: &str) {
        .arg(host);
     build.run(&mut cmd);
 
-    let mut cmd = Command::new(SH_CMD);
-    cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+    let mut cmd = rust_installer(build);
+    cmd.arg("generate")
        .arg("--product-name=Rust-MinGW")
        .arg("--rel-manifest-dir=rustlib")
        .arg("--success-message=Rust-MinGW-is-installed.")
-       .arg(format!("--image-dir={}", sanitize_sh(&image)))
-       .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
-       .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
+       .arg("--image-dir").arg(&image)
+       .arg("--work-dir").arg(&tmpdir(build))
+       .arg("--output-dir").arg(&distdir(build))
        .arg(format!("--package-name={}-{}", name, host))
        .arg("--component-name=rust-mingw")
        .arg("--legacy-manifest-dirs=rustlib,cargo");
@@ -190,15 +188,15 @@ pub fn rustc(build: &Build, stage: u32, host: &str) {
     }
 
     // Finally, wrap everything up in a nice tarball!
-    let mut cmd = Command::new(SH_CMD);
-    cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+    let mut cmd = rust_installer(build);
+    cmd.arg("generate")
        .arg("--product-name=Rust")
        .arg("--rel-manifest-dir=rustlib")
        .arg("--success-message=Rust-is-ready-to-roll.")
-       .arg(format!("--image-dir={}", sanitize_sh(&image)))
-       .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
-       .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
-       .arg(format!("--non-installed-overlay={}", sanitize_sh(&overlay)))
+       .arg("--image-dir").arg(&image)
+       .arg("--work-dir").arg(&tmpdir(build))
+       .arg("--output-dir").arg(&distdir(build))
+       .arg("--non-installed-overlay").arg(&overlay)
        .arg(format!("--package-name={}-{}", name, host))
        .arg("--component-name=rustc")
        .arg("--legacy-manifest-dirs=rustlib,cargo");
@@ -300,14 +298,14 @@ pub fn std(build: &Build, compiler: &Compiler, target: &str) {
     let src = build.sysroot(compiler).join("lib/rustlib");
     cp_r(&src.join(target), &dst);
 
-    let mut cmd = Command::new(SH_CMD);
-    cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+    let mut cmd = rust_installer(build);
+    cmd.arg("generate")
        .arg("--product-name=Rust")
        .arg("--rel-manifest-dir=rustlib")
        .arg("--success-message=std-is-standing-at-the-ready.")
-       .arg(format!("--image-dir={}", sanitize_sh(&image)))
-       .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
-       .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
+       .arg("--image-dir").arg(&image)
+       .arg("--work-dir").arg(&tmpdir(build))
+       .arg("--output-dir").arg(&distdir(build))
        .arg(format!("--package-name={}-{}", name, target))
        .arg(format!("--component-name=rust-std-{}", target))
        .arg("--legacy-manifest-dirs=rustlib,cargo");
@@ -356,14 +354,14 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) {
     println!("image_src: {:?}, dst: {:?}", image_src, dst);
     cp_r(&image_src, &dst);
 
-    let mut cmd = Command::new(SH_CMD);
-    cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+    let mut cmd = rust_installer(build);
+    cmd.arg("generate")
        .arg("--product-name=Rust")
        .arg("--rel-manifest-dir=rustlib")
        .arg("--success-message=save-analysis-saved.")
-       .arg(format!("--image-dir={}", sanitize_sh(&image)))
-       .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
-       .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
+       .arg("--image-dir").arg(&image)
+       .arg("--work-dir").arg(&tmpdir(build))
+       .arg("--output-dir").arg(&distdir(build))
        .arg(format!("--package-name={}-{}", name, target))
        .arg(format!("--component-name=rust-analysis-{}", target))
        .arg("--legacy-manifest-dirs=rustlib,cargo");
@@ -471,13 +469,17 @@ pub fn rust_src(build: &Build) {
     write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes());
 
     // Create plain source tarball
-    let tarball = rust_src_location(build);
+    let mut tarball = rust_src_location(build);
+    tarball.set_extension(""); // strip .gz
+    tarball.set_extension(""); // strip .tar
     if let Some(dir) = tarball.parent() {
         t!(fs::create_dir_all(dir));
     }
-    let mut cmd = Command::new("tar");
-    cmd.arg("-czf").arg(sanitize_sh(&tarball))
-       .arg(&plain_name)
+    let mut cmd = rust_installer(build);
+    cmd.arg("tarball")
+       .arg("--input").arg(&plain_name)
+       .arg("--output").arg(&tarball)
+       .arg("--work-dir=.")
        .current_dir(tmpdir(build));
     build.run(&mut cmd);
 
@@ -521,14 +523,14 @@ pub fn rust_src(build: &Build) {
     }
 
     // Create source tarball in rust-installer format
-    let mut cmd = Command::new(SH_CMD);
-    cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+    let mut cmd = rust_installer(build);
+    cmd.arg("generate")
        .arg("--product-name=Rust")
        .arg("--rel-manifest-dir=rustlib")
        .arg("--success-message=Awesome-Source.")
-       .arg(format!("--image-dir={}", sanitize_sh(&image)))
-       .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
-       .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
+       .arg("--image-dir").arg(&image)
+       .arg("--work-dir").arg(&tmpdir(build))
+       .arg("--output-dir").arg(&distdir(build))
        .arg(format!("--package-name={}", name))
        .arg("--component-name=rust-src")
        .arg("--legacy-manifest-dirs=rustlib,cargo");
@@ -594,7 +596,7 @@ pub fn cargo(build: &Build, stage: u32, target: &str) {
 
     // Prepare the image directory
     t!(fs::create_dir_all(image.join("share/zsh/site-functions")));
-    t!(fs::create_dir_all(image.join("etc/bash_completions.d")));
+    t!(fs::create_dir_all(image.join("etc/bash_completion.d")));
     let cargo = build.cargo_out(&compiler, Mode::Tool, target)
                      .join(exe("cargo", target));
     install(&cargo, &image.join("bin"), 0o755);
@@ -604,7 +606,7 @@ pub fn cargo(build: &Build, stage: u32, target: &str) {
     }
     install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644);
     copy(&etc.join("cargo.bashcomp.sh"),
-         &image.join("etc/bash_completions.d/cargo"));
+         &image.join("etc/bash_completion.d/cargo"));
     let doc = image.join("share/doc/cargo");
     install(&src.join("README.md"), &doc, 0o644);
     install(&src.join("LICENSE-MIT"), &doc, 0o644);
@@ -622,15 +624,15 @@ pub fn cargo(build: &Build, stage: u32, target: &str) {
     t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
 
     // Generate the installer tarball
-    let mut cmd = Command::new("sh");
-    cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+    let mut cmd = rust_installer(build);
+    cmd.arg("generate")
        .arg("--product-name=Rust")
        .arg("--rel-manifest-dir=rustlib")
        .arg("--success-message=Rust-is-ready-to-roll.")
-       .arg(format!("--image-dir={}", sanitize_sh(&image)))
-       .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
-       .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
-       .arg(format!("--non-installed-overlay={}", sanitize_sh(&overlay)))
+       .arg("--image-dir").arg(&image)
+       .arg("--work-dir").arg(&tmpdir(build))
+       .arg("--output-dir").arg(&distdir(build))
+       .arg("--non-installed-overlay").arg(&overlay)
        .arg(format!("--package-name={}-{}", name, target))
        .arg("--component-name=cargo")
        .arg("--legacy-manifest-dirs=rustlib,cargo");
@@ -671,15 +673,15 @@ pub fn rls(build: &Build, stage: u32, target: &str) {
     t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
 
     // Generate the installer tarball
-    let mut cmd = Command::new("sh");
-    cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+    let mut cmd = rust_installer(build);
+    cmd.arg("generate")
        .arg("--product-name=Rust")
        .arg("--rel-manifest-dir=rustlib")
        .arg("--success-message=RLS-ready-to-serve.")
-       .arg(format!("--image-dir={}", sanitize_sh(&image)))
-       .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
-       .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
-       .arg(format!("--non-installed-overlay={}", sanitize_sh(&overlay)))
+       .arg("--image-dir").arg(&image)
+       .arg("--work-dir").arg(&tmpdir(build))
+       .arg("--output-dir").arg(&distdir(build))
+       .arg("--non-installed-overlay").arg(&overlay)
        .arg(format!("--package-name={}-{}", name, target))
        .arg("--component-name=rls")
        .arg("--legacy-manifest-dirs=rustlib,cargo");
@@ -730,29 +732,28 @@ pub fn extended(build: &Build, stage: u32, target: &str) {
     // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
     // the std files during uninstall. To do this ensure that rustc comes
     // before rust-std in the list below.
-    let mut input_tarballs = format!("{},{},{},{},{},{}",
-                                     sanitize_sh(&rustc_installer),
-                                     sanitize_sh(&cargo_installer),
-                                     sanitize_sh(&rls_installer),
-                                     sanitize_sh(&analysis_installer),
-                                     sanitize_sh(&docs_installer),
-                                     sanitize_sh(&std_installer));
+    let mut tarballs = vec![rustc_installer, cargo_installer, rls_installer,
+                            analysis_installer, docs_installer, std_installer];
     if target.contains("pc-windows-gnu") {
-        input_tarballs.push_str(",");
-        input_tarballs.push_str(&sanitize_sh(&mingw_installer));
+        tarballs.push(mingw_installer);
+    }
+    let mut input_tarballs = tarballs[0].as_os_str().to_owned();
+    for tarball in &tarballs[1..] {
+        input_tarballs.push(",");
+        input_tarballs.push(tarball);
     }
 
-    let mut cmd = Command::new(SH_CMD);
-    cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/combine-installers.sh")))
+    let mut cmd = rust_installer(build);
+    cmd.arg("combine")
        .arg("--product-name=Rust")
        .arg("--rel-manifest-dir=rustlib")
        .arg("--success-message=Rust-is-ready-to-roll.")
-       .arg(format!("--work-dir={}", sanitize_sh(&work)))
-       .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
+       .arg("--work-dir").arg(&work)
+       .arg("--output-dir").arg(&distdir(build))
        .arg(format!("--package-name={}-{}", pkgname(build, "rust"), target))
        .arg("--legacy-manifest-dirs=rustlib,cargo")
-       .arg(format!("--input-tarballs={}", input_tarballs))
-       .arg(format!("--non-installed-overlay={}", sanitize_sh(&overlay)));
+       .arg("--input-tarballs").arg(input_tarballs)
+       .arg("--non-installed-overlay").arg(&overlay);
     build.run(&mut cmd);
 
     let mut license = String::new();
index c805522fbf588d06b4676bb8bd0647fa2c1aea54..386b001971bad43c978fc91984b9537c119f41ae 100644 (file)
 /// Installs everything.
 pub fn install(build: &Build, stage: u32, host: &str) {
     let prefix_default = PathBuf::from("/usr/local");
+    let sysconfdir_default = PathBuf::from("/etc");
     let docdir_default = PathBuf::from("share/doc/rust");
-    let mandir_default = PathBuf::from("share/man");
+    let bindir_default = PathBuf::from("bin");
     let libdir_default = PathBuf::from("lib");
+    let mandir_default = PathBuf::from("share/man");
     let prefix = build.config.prefix.as_ref().unwrap_or(&prefix_default);
+    let sysconfdir = build.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
     let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default);
+    let bindir = build.config.bindir.as_ref().unwrap_or(&bindir_default);
     let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default);
     let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default);
 
+    let sysconfdir = prefix.join(sysconfdir);
     let docdir = prefix.join(docdir);
+    let bindir = prefix.join(bindir);
     let libdir = prefix.join(libdir);
     let mandir = prefix.join(mandir);
 
     let destdir = env::var_os("DESTDIR").map(PathBuf::from);
 
     let prefix = add_destdir(&prefix, &destdir);
+    let sysconfdir = add_destdir(&sysconfdir, &destdir);
     let docdir = add_destdir(&docdir, &destdir);
+    let bindir = add_destdir(&bindir, &destdir);
     let libdir = add_destdir(&libdir, &destdir);
     let mandir = add_destdir(&mandir, &destdir);
 
@@ -47,29 +55,35 @@ pub fn install(build: &Build, stage: u32, host: &str) {
     t!(fs::create_dir_all(&empty_dir));
     if build.config.docs {
         install_sh(&build, "docs", "rust-docs", &build.rust_package_vers(),
-                   stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);
+                   stage, host, &prefix, &sysconfdir, &docdir, &bindir, &libdir,
+                   &mandir, &empty_dir);
     }
 
     for target in build.config.target.iter() {
         install_sh(&build, "std", "rust-std", &build.rust_package_vers(),
-                   stage, target, &prefix, &docdir, &libdir, &mandir, &empty_dir);
+                   stage, target, &prefix, &sysconfdir, &docdir, &bindir, &libdir,
+                   &mandir, &empty_dir);
     }
 
     if build.config.extended {
         install_sh(&build, "cargo", "cargo", &build.cargo_package_vers(),
-                   stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);
+                   stage, host, &prefix, &sysconfdir, &docdir, &bindir, &libdir,
+                   &mandir, &empty_dir);
         install_sh(&build, "rls", "rls", &build.rls_package_vers(),
-                   stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);
+                   stage, host, &prefix, &sysconfdir, &docdir, &bindir, &libdir,
+                   &mandir, &empty_dir);
     }
 
     install_sh(&build, "rustc", "rustc", &build.rust_package_vers(),
-               stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);
+               stage, host, &prefix, &sysconfdir, &docdir, &bindir, &libdir,
+               &mandir, &empty_dir);
 
     t!(fs::remove_dir_all(&empty_dir));
 }
 
 fn install_sh(build: &Build, package: &str, name: &str, version: &str, stage: u32, host: &str,
-              prefix: &Path, docdir: &Path, libdir: &Path, mandir: &Path, empty_dir: &Path) {
+              prefix: &Path, sysconfdir: &Path, docdir: &Path, bindir: &Path, libdir: &Path,
+              mandir: &Path, empty_dir: &Path) {
     println!("Install {} stage{} ({})", package, stage, host);
     let package_name = format!("{}-{}-{}", name, version, host);
 
@@ -77,7 +91,9 @@ fn install_sh(build: &Build, package: &str, name: &str, version: &str, stage: u3
     cmd.current_dir(empty_dir)
        .arg(sanitize_sh(&tmpdir(build).join(&package_name).join("install.sh")))
        .arg(format!("--prefix={}", sanitize_sh(prefix)))
+       .arg(format!("--sysconfdir={}", sanitize_sh(sysconfdir)))
        .arg(format!("--docdir={}", sanitize_sh(docdir)))
+       .arg(format!("--bindir={}", sanitize_sh(bindir)))
        .arg(format!("--libdir={}", sanitize_sh(libdir)))
        .arg(format!("--mandir={}", sanitize_sh(mandir)))
        .arg("--disable-ldconfig");
index 017d4015134d0371e209157938c184a707d46a99..ca9de43f542193364b1806fe62f8f78be35ebb07 100644 (file)
@@ -82,7 +82,7 @@
 use std::ffi::OsString;
 use std::fs::{self, File};
 use std::io::Read;
-use std::path::{Component, PathBuf, Path};
+use std::path::{PathBuf, Path};
 use std::process::Command;
 
 use build_helper::{run_silent, run_suppressed, output, mtime};
@@ -285,129 +285,12 @@ pub fn build(&mut self) {
             self.verbose(&format!("auto-detected local-rebuild {}", local_release));
             self.local_rebuild = true;
         }
-        self.verbose("updating submodules");
-        self.update_submodules();
         self.verbose("learning about cargo");
         metadata::build(self);
 
         step::run(self);
     }
 
-    /// Updates all git submodules that we have.
-    ///
-    /// This will detect if any submodules are out of date an run the necessary
-    /// commands to sync them all with upstream.
-    fn update_submodules(&self) {
-        struct Submodule<'a> {
-            path: &'a Path,
-            state: State,
-        }
-
-        enum State {
-            // The submodule may have staged/unstaged changes
-            MaybeDirty,
-            // Or could be initialized but never updated
-            NotInitialized,
-            // The submodule, itself, has extra commits but those changes haven't been commited to
-            // the (outer) git repository
-            OutOfSync,
-        }
-
-        if !self.src_is_git || !self.config.submodules {
-            return
-        }
-        let git = || {
-            let mut cmd = Command::new("git");
-            cmd.current_dir(&self.src);
-            return cmd
-        };
-        let git_submodule = || {
-            let mut cmd = Command::new("git");
-            cmd.current_dir(&self.src).arg("submodule");
-            return cmd
-        };
-
-        // FIXME: this takes a seriously long time to execute on Windows and a
-        //        nontrivial amount of time on Unix, we should have a better way
-        //        of detecting whether we need to run all the submodule commands
-        //        below.
-        let out = output(git_submodule().arg("status"));
-        let mut submodules = vec![];
-        for line in out.lines() {
-            // NOTE `git submodule status` output looks like this:
-            //
-            // -5066b7dcab7e700844b0e2ba71b8af9dc627a59b src/liblibc
-            // +b37ef24aa82d2be3a3cc0fe89bf82292f4ca181c src/compiler-rt (remotes/origin/..)
-            //  e058ca661692a8d01f8cf9d35939dfe3105ce968 src/jemalloc (3.6.0-533-ge058ca6)
-            //
-            // The first character can be '-', '+' or ' ' and denotes the `State` of the submodule
-            // Right next to this character is the SHA-1 of the submodule HEAD
-            // And after that comes the path to the submodule
-            let path = Path::new(line[1..].split(' ').skip(1).next().unwrap());
-            let state = if line.starts_with('-') {
-                State::NotInitialized
-            } else if line.starts_with('+') {
-                State::OutOfSync
-            } else if line.starts_with(' ') {
-                State::MaybeDirty
-            } else {
-                panic!("unexpected git submodule state: {:?}", line.chars().next());
-            };
-
-            submodules.push(Submodule { path: path, state: state })
-        }
-
-        self.run(git_submodule().arg("sync"));
-
-        for submodule in submodules {
-            // If using llvm-root then don't touch the llvm submodule.
-            if submodule.path.components().any(|c| c == Component::Normal("llvm".as_ref())) &&
-                self.config.target_config.get(&self.config.build)
-                    .and_then(|c| c.llvm_config.as_ref()).is_some()
-            {
-                continue
-            }
-
-            if submodule.path.components().any(|c| c == Component::Normal("jemalloc".as_ref())) &&
-                !self.config.use_jemalloc
-            {
-                continue
-            }
-
-            // `submodule.path` is the relative path to a submodule (from the repository root)
-            // `submodule_path` is the path to a submodule from the cwd
-
-            // use `submodule.path` when e.g. executing a submodule specific command from the
-            // repository root
-            // use `submodule_path` when e.g. executing a normal git command for the submodule
-            // (set via `current_dir`)
-            let submodule_path = self.src.join(submodule.path);
-
-            match submodule.state {
-                State::MaybeDirty => {
-                    // drop staged changes
-                    self.run(git().current_dir(&submodule_path)
-                                  .args(&["reset", "--hard"]));
-                    // drops unstaged changes
-                    self.run(git().current_dir(&submodule_path)
-                                  .args(&["clean", "-fdx"]));
-                },
-                State::NotInitialized => {
-                    self.run(git_submodule().arg("init").arg(submodule.path));
-                    self.run(git_submodule().arg("update").arg(submodule.path));
-                },
-                State::OutOfSync => {
-                    // drops submodule commits that weren't reported to the (outer) git repository
-                    self.run(git_submodule().arg("update").arg(submodule.path));
-                    self.run(git().current_dir(&submodule_path)
-                                  .args(&["reset", "--hard"]));
-                    self.run(git().current_dir(&submodule_path)
-                                  .args(&["clean", "-fdx"]));
-                },
-            }
-        }
-    }
-
     /// Clear out `dir` if `input` is newer.
     ///
     /// After this executes, it will also ensure that `dir` exists.
@@ -475,11 +358,30 @@ fn cargo(&self,
              .env("RUSTDOC_REAL", self.rustdoc(compiler))
              .env("RUSTC_FLAGS", self.rustc_flags(target).join(" "));
 
-        // Tools don't get debuginfo right now, e.g. cargo and rls don't get
-        // compiled with debuginfo.
         if mode != Mode::Tool {
-             cargo.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string())
-                  .env("RUSTC_DEBUGINFO_LINES", self.config.rust_debuginfo_lines.to_string());
+            // Tools don't get debuginfo right now, e.g. cargo and rls don't
+            // get compiled with debuginfo.
+            cargo.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string())
+                 .env("RUSTC_DEBUGINFO_LINES", self.config.rust_debuginfo_lines.to_string())
+                 .env("RUSTC_FORCE_UNSTABLE", "1");
+
+            // Currently the compiler depends on crates from crates.io, and
+            // then other crates can depend on the compiler (e.g. proc-macro
+            // crates). Let's say, for example that rustc itself depends on the
+            // bitflags crate. If an external crate then depends on the
+            // bitflags crate as well, we need to make sure they don't
+            // conflict, even if they pick the same verison of bitflags. We'll
+            // want to make sure that e.g. a plugin and rustc each get their
+            // own copy of bitflags.
+
+            // Cargo ensures that this works in general through the -C metadata
+            // flag. This flag will frob the symbols in the binary to make sure
+            // they're different, even though the source code is the exact
+            // same. To solve this problem for the compiler we extend Cargo's
+            // already-passed -C metadata flag with our own. Our rustc.rs
+            // wrapper around the actual rustc will detect -C metadata being
+            // passed and frob it with this extra string we're passing in.
+            cargo.env("RUSTC_METADATA_SUFFIX", "rustc");
         }
 
         // Enable usage of unstable features
@@ -524,7 +426,9 @@ fn cargo(&self,
         // the comipiler, libs, and tests are stable and we don't want to make
         // their deps unstable (since this would break the first invariant
         // above).
-        if mode != Mode::Tool {
+        //
+        // FIXME: remove this after next stage0
+        if mode != Mode::Tool && stage == 0 {
             cargo.env("RUSTBUILD_UNSTABLE", "1");
         }
 
index 3d87f701b2a56971b1c8fc34f30bf6086a72ce2f..6cb1d1fc4bf05b47c14c968bd56f16e7da135faf 100644 (file)
@@ -108,6 +108,7 @@ pub fn llvm(build: &Build, target: &str) {
         cfg.define("LLVM_USE_CRT_DEBUG", "MT");
         cfg.define("LLVM_USE_CRT_RELEASE", "MT");
         cfg.define("LLVM_USE_CRT_RELWITHDEBINFO", "MT");
+        cfg.static_crt(true);
     }
 
     if target.starts_with("i686") {
@@ -309,11 +310,15 @@ pub fn openssl(build: &Build, target: &str) {
     configure.arg("no-ssl3");
 
     let os = match target {
+        "aarch64-linux-android" => "linux-aarch64",
         "aarch64-unknown-linux-gnu" => "linux-aarch64",
+        "arm-linux-androideabi" => "android",
         "arm-unknown-linux-gnueabi" => "linux-armv4",
         "arm-unknown-linux-gnueabihf" => "linux-armv4",
+        "armv7-linux-androideabi" => "android-armv7",
         "armv7-unknown-linux-gnueabihf" => "linux-armv4",
         "i686-apple-darwin" => "darwin-i386-cc",
+        "i686-linux-android" => "android-x86",
         "i686-unknown-freebsd" => "BSD-x86-elf",
         "i686-unknown-linux-gnu" => "linux-elf",
         "i686-unknown-linux-musl" => "linux-elf",
@@ -326,6 +331,7 @@ pub fn openssl(build: &Build, target: &str) {
         "powerpc64le-unknown-linux-gnu" => "linux-ppc64le",
         "s390x-unknown-linux-gnu" => "linux64-s390x",
         "x86_64-apple-darwin" => "darwin64-x86_64-cc",
+        "x86_64-linux-android" => "linux-x86_64",
         "x86_64-unknown-freebsd" => "BSD-x86_64",
         "x86_64-unknown-linux-gnu" => "linux-x86_64",
         "x86_64-unknown-linux-musl" => "linux-x86_64",
@@ -337,6 +343,18 @@ pub fn openssl(build: &Build, target: &str) {
     for flag in build.cflags(target) {
         configure.arg(flag);
     }
+    // There is no specific os target for android aarch64 or x86_64,
+    // so we need to pass some extra cflags
+    if target == "aarch64-linux-android" || target == "x86_64-linux-android" {
+        configure.arg("-mandroid");
+        configure.arg("-fomit-frame-pointer");
+    }
+    // Make PIE binaries
+    // Non-PIE linker support was removed in Lollipop
+    // https://source.android.com/security/enhancements/enhancements50
+    if target == "i686-linux-android" {
+        configure.arg("no-asm");
+    }
     configure.current_dir(&obj);
     println!("Configuring openssl for {}", target);
     build.run_quiet(&mut configure);
index 970c0bc565d864c533c255483c8a0e63a1d12d8c..92666e8e63907caec309922aae24759a968fdd33 100644 (file)
@@ -574,6 +574,10 @@ fn crate_rule<'a, 'b>(build: &'a Build,
          .dep(|s| s.name("maybe-clean-tools"))
          .dep(|s| s.name("libstd-tool"))
          .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-client"));
+    rules.build("tool-rust-installer", "src/tools/rust-installer")
+         .dep(|s| s.name("maybe-clean-tools"))
+         .dep(|s| s.name("libstd-tool"))
+         .run(move |s| compile::tool(build, s.stage, s.target, "rust-installer"));
     rules.build("tool-cargo", "src/tools/cargo")
          .host(true)
          .default(build.config.extended)
@@ -704,6 +708,7 @@ fn crate_rule<'a, 'b>(build: &'a Build,
          .host(true)
          .only_host_build(true)
          .default(true)
+         .dep(move |s| tool_rust_installer(build, s))
          .run(move |s| dist::rustc(build, s.stage, s.target));
     rules.dist("dist-std", "src/libstd")
          .dep(move |s| {
@@ -718,10 +723,12 @@ fn crate_rule<'a, 'b>(build: &'a Build,
          })
          .default(true)
          .only_host_build(true)
+         .dep(move |s| tool_rust_installer(build, s))
          .run(move |s| dist::std(build, &s.compiler(), s.target));
     rules.dist("dist-mingw", "path/to/nowhere")
          .default(true)
          .only_host_build(true)
+         .dep(move |s| tool_rust_installer(build, s))
          .run(move |s| {
              if s.target.contains("pc-windows-gnu") {
                  dist::mingw(build, s.target)
@@ -732,21 +739,25 @@ fn crate_rule<'a, 'b>(build: &'a Build,
          .host(true)
          .only_build(true)
          .only_host_build(true)
+         .dep(move |s| tool_rust_installer(build, s))
          .run(move |_| dist::rust_src(build));
     rules.dist("dist-docs", "src/doc")
          .default(true)
          .only_host_build(true)
          .dep(|s| s.name("default:doc"))
+         .dep(move |s| tool_rust_installer(build, s))
          .run(move |s| dist::docs(build, s.stage, s.target));
     rules.dist("dist-analysis", "analysis")
          .default(build.config.extended)
          .dep(|s| s.name("dist-std"))
          .only_host_build(true)
+         .dep(move |s| tool_rust_installer(build, s))
          .run(move |s| dist::analysis(build, &s.compiler(), s.target));
     rules.dist("dist-rls", "rls")
          .host(true)
          .only_host_build(true)
          .dep(|s| s.name("tool-rls"))
+         .dep(move |s| tool_rust_installer(build, s))
          .run(move |s| dist::rls(build, s.stage, s.target));
     rules.dist("install", "path/to/nowhere")
          .dep(|s| s.name("default:dist"))
@@ -755,6 +766,7 @@ fn crate_rule<'a, 'b>(build: &'a Build,
          .host(true)
          .only_host_build(true)
          .dep(|s| s.name("tool-cargo"))
+         .dep(move |s| tool_rust_installer(build, s))
          .run(move |s| dist::cargo(build, s.stage, s.target));
     rules.dist("dist-extended", "extended")
          .default(build.config.extended)
@@ -767,6 +779,7 @@ fn crate_rule<'a, 'b>(build: &'a Build,
          .dep(|d| d.name("dist-cargo"))
          .dep(|d| d.name("dist-rls"))
          .dep(|d| d.name("dist-analysis"))
+         .dep(move |s| tool_rust_installer(build, s))
          .run(move |s| dist::extended(build, s.stage, s.target));
 
     rules.dist("dist-sign", "hash-and-sign")
@@ -778,6 +791,14 @@ fn crate_rule<'a, 'b>(build: &'a Build,
 
     rules.verify();
     return rules;
+
+    /// Helper to depend on a stage0 build-only rust-installer tool.
+    fn tool_rust_installer<'a>(build: &'a Build, step: &Step<'a>) -> Step<'a> {
+        step.name("tool-rust-installer")
+            .host(&build.config.build)
+            .target(&build.config.build)
+            .stage(0)
+    }
 }
 
 #[derive(PartialEq, Eq, Hash, Clone, Debug)]
index 6f3a7e091e1edb78ecf2feaa4afdbee02bb16a40..627b5062df3334701e4a64c0995bb42ada55c2e0 100644 (file)
@@ -16,6 +16,12 @@ for example:
 
 Images will output artifacts in an `obj` dir at the root of a repository.
 
+## Filesystem layout
+
+- Each directory, excluding `scripts` and `disabled`, corresponds to a docker image
+- `scripts` contains files shared by docker images
+- `disabled` contains images that are not build travis
+
 ## Cross toolchains
 
 A number of these images take quite a long time to compile as they're building
index 04ca6d76c557b9086af1e91fbc3c4ca9a1e63b73..2a928c5ec7e894b4a1f331e879be3db19e15441d 100644 (file)
@@ -1,46 +1,60 @@
 FROM ubuntu:16.04
 
-RUN dpkg --add-architecture i386 && \
-    apt-get update && \
+RUN apt-get update && \
     apt-get install -y --no-install-recommends \
+  ca-certificates \
+  cmake \
+  curl \
+  file \
   g++ \
+  git \
+  libssl-dev \
   make \
-  file \
-  curl \
-  ca-certificates \
+  pkg-config \
   python2.7 \
-  git \
-  cmake \
-  unzip \
-  expect \
-  openjdk-9-jre-headless \
   sudo \
-  libstdc++6:i386 \
-  xz-utils \
-  libssl-dev \
-  pkg-config
+  unzip \
+  xz-utils
 
-WORKDIR /android/
-ENV PATH=$PATH:/android/ndk-arm-9/bin:/android/sdk/tools:/android/sdk/platform-tools
+# dumb-init
+COPY scripts/dumb-init.sh /scripts/
+RUN sh /scripts/dumb-init.sh
 
-COPY install-ndk.sh install-sdk.sh accept-licenses.sh /android/
-RUN sh /android/install-ndk.sh
-RUN sh /android/install-sdk.sh
+# ndk
+COPY scripts/android-ndk.sh /scripts/
+RUN . /scripts/android-ndk.sh && \
+    download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip arm 9
 
-RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
-    dpkg -i dumb-init_*.deb && \
-    rm dumb-init_*.deb
+# sdk
+RUN dpkg --add-architecture i386 && \
+    apt-get update && \
+    apt-get install -y --no-install-recommends \
+  libgl1-mesa-glx \
+  libpulse0 \
+  libstdc++6:i386 \
+  openjdk-9-jre-headless \
+  tzdata
 
-COPY start-emulator.sh /android/
+COPY scripts/android-sdk.sh /scripts/
+RUN . /scripts/android-sdk.sh && \
+    download_and_create_avd tools_r25.2.5-linux.zip armeabi-v7a 18
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--", "/android/start-emulator.sh"]
+# env
+ENV PATH=$PATH:/android/sdk/tools
+ENV PATH=$PATH:/android/sdk/platform-tools
 
-RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-02-24-sccache-x86_64-unknown-linux-gnu && \
-      chmod +x /usr/local/bin/sccache
+ENV TARGETS=arm-linux-androideabi
 
 ENV RUST_CONFIGURE_ARGS \
-      --target=arm-linux-androideabi \
-      --arm-linux-androideabi-ndk=/android/ndk-arm-9
+      --target=$TARGETS \
+      --arm-linux-androideabi-ndk=/android/ndk/arm-9
+
+ENV SCRIPT python2.7 ../x.py test --target $TARGETS
+
+# sccache
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
 
-ENV SCRIPT python2.7 ../x.py test --target arm-linux-androideabi
+# init
+COPY scripts/android-start-emulator.sh /scripts/
+ENTRYPOINT ["/usr/bin/dumb-init", "--", "/scripts/android-start-emulator.sh"]
diff --git a/src/ci/docker/arm-android/accept-licenses.sh b/src/ci/docker/arm-android/accept-licenses.sh
deleted file mode 100755 (executable)
index 8d8f60a..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/expect -f
-# ignore-license
-
-set timeout 1800
-set cmd [lindex $argv 0]
-set licenses [lindex $argv 1]
-
-spawn {*}$cmd
-expect {
-  "Do you accept the license '*'*" {
-        exp_send "y\r"
-        exp_continue
-  }
-  eof
-}
diff --git a/src/ci/docker/arm-android/install-ndk.sh b/src/ci/docker/arm-android/install-ndk.sh
deleted file mode 100644 (file)
index 389ec06..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-# 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.
-
-set -ex
-
-cpgdb() {
-  cp android-ndk-r11c/prebuilt/linux-x86_64/bin/gdb /android/$1/bin/$2-gdb
-  cp android-ndk-r11c/prebuilt/linux-x86_64/bin/gdb-orig /android/$1/bin/gdb-orig
-  cp -r android-ndk-r11c/prebuilt/linux-x86_64/share /android/$1/share
-}
-
-# Prep the Android NDK
-#
-# See https://github.com/servo/servo/wiki/Building-for-Android
-curl -O https://dl.google.com/android/repository/android-ndk-r11c-linux-x86_64.zip
-unzip -q android-ndk-r11c-linux-x86_64.zip
-bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \
-        --platform=android-9 \
-        --toolchain=arm-linux-androideabi-4.9 \
-        --install-dir=/android/ndk-arm-9 \
-        --ndk-dir=/android/android-ndk-r11c \
-        --arch=arm
-cpgdb ndk-arm-9 arm-linux-androideabi
-
-rm -rf ./android-ndk-r11c-linux-x86_64.zip ./android-ndk-r11c
diff --git a/src/ci/docker/arm-android/install-sdk.sh b/src/ci/docker/arm-android/install-sdk.sh
deleted file mode 100644 (file)
index 2db1d46..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-# 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.
-
-set -ex
-
-# Prep the SDK and emulator
-#
-# Note that the update process requires that we accept a bunch of licenses, and
-# we can't just pipe `yes` into it for some reason, so we take the same strategy
-# located in https://github.com/appunite/docker by just wrapping it in a script
-# which apparently magically accepts the licenses.
-
-mkdir sdk
-curl https://dl.google.com/android/android-sdk_r24.4-linux.tgz | \
-    tar xzf - -C sdk --strip-components=1
-
-filter="platform-tools,android-18"
-filter="$filter,sys-img-armeabi-v7a-android-18"
-
-./accept-licenses.sh "android - update sdk -a --no-ui --filter $filter"
-
-echo "no" | android create avd \
-                --name arm-18 \
-                --target android-18 \
-                --abi armeabi-v7a
diff --git a/src/ci/docker/arm-android/start-emulator.sh b/src/ci/docker/arm-android/start-emulator.sh
deleted file mode 100755 (executable)
index 4a73637..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/sh
-# 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.
-
-set -ex
-
-# Setting SHELL to a file instead on a symlink helps android
-# emulator identify the system
-export SHELL=/bin/bash
-nohup nohup emulator @arm-18 -no-window -partition-size 2047 0<&- &>/dev/null &
-exec "$@"
index 5dfdf093081cb3ba7dd117e1ba5c9e01307dc3d3..03e0b78ba89b3d83a8c3e2b6444aa0c7fe54b25d 100644 (file)
@@ -31,7 +31,7 @@ WORKDIR /build
 # The `vexpress_config` config file was a previously generated config file for
 # the kernel. This file was generated by running `make vexpress_defconfig`
 # followed by `make menuconfig` and then enabling the IPv6 protocol page.
-COPY vexpress_config /build/.config
+COPY armhf-gnu/vexpress_config /build/.config
 RUN curl https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.42.tar.xz | \
       tar xJf - && \
       cd /build/linux-4.4.42 && \
@@ -63,18 +63,18 @@ RUN curl http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/ubuntu-bas
 
 # Copy over our init script, which starts up our test server and also a few
 # other misc tasks.
-COPY rcS rootfs/etc/init.d/rcS
+COPY armhf-gnu/rcS rootfs/etc/init.d/rcS
 RUN chmod +x rootfs/etc/init.d/rcS
 
 # Helper to quickly fill the entropy pool in the kernel.
-COPY addentropy.c /tmp/
+COPY armhf-gnu/addentropy.c /tmp/
 RUN arm-linux-gnueabihf-gcc addentropy.c -o rootfs/addentropy -static
 
 # TODO: What is this?!
 RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/current/images/device-tree/vexpress-v2p-ca15-tc1.dtb
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 5de00d5b02151af9255852dd3e6f645174e49882..7759d91e1bb635c41ba6b89a426616ebda65a293 100644 (file)
@@ -22,7 +22,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
@@ -32,10 +32,10 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 WORKDIR /tmp
 
-COPY build-rumprun.sh /tmp/
+COPY cross/build-rumprun.sh /tmp/
 RUN ./build-rumprun.sh
 
-COPY build-arm-musl.sh /tmp/
+COPY cross/build-arm-musl.sh /tmp/
 RUN ./build-arm-musl.sh
 
 # originally from
diff --git a/src/ci/docker/disabled/dist-aarch64-android/Dockerfile b/src/ci/docker/disabled/dist-aarch64-android/Dockerfile
new file mode 100644 (file)
index 0000000..918d291
--- /dev/null
@@ -0,0 +1,50 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && \
+    apt-get install -y --no-install-recommends \
+  ca-certificates \
+  cmake \
+  curl \
+  file \
+  g++ \
+  git \
+  libssl-dev \
+  make \
+  pkg-config \
+  python2.7 \
+  sudo \
+  unzip \
+  xz-utils
+
+# dumb-init
+COPY scripts/dumb-init.sh /scripts/
+RUN sh /scripts/dumb-init.sh
+
+# ndk
+COPY scripts/android-ndk.sh /scripts/
+RUN . /scripts/android-ndk.sh && \
+    download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip arm64 21
+
+# env
+ENV PATH=$PATH:/android/ndk/arm64-21/bin
+
+ENV DEP_Z_ROOT=/android/ndk/arm64-21/sysroot/usr/
+
+ENV HOSTS=aarch64-linux-android
+
+ENV RUST_CONFIGURE_ARGS \
+      --host=$HOSTS \
+      --target=$HOSTS \
+      --aarch64-linux-android-ndk=/android/ndk/arm64-21 \
+      --disable-rpath \
+      --enable-extended \
+      --enable-cargo-openssl-static
+
+ENV SCRIPT python2.7 ../x.py dist --target $HOSTS --host $HOSTS
+
+# sccache
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# init
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
diff --git a/src/ci/docker/disabled/dist-armv7-android/Dockerfile b/src/ci/docker/disabled/dist-armv7-android/Dockerfile
new file mode 100644 (file)
index 0000000..aed82e6
--- /dev/null
@@ -0,0 +1,68 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && \
+    apt-get install -y --no-install-recommends \
+  ca-certificates \
+  cmake \
+  curl \
+  file \
+  g++ \
+  git \
+  libssl-dev \
+  make \
+  pkg-config \
+  python2.7 \
+  sudo \
+  unzip \
+  xz-utils
+
+# dumb-init
+COPY scripts/dumb-init.sh /scripts/
+RUN sh /scripts/dumb-init.sh
+
+# ndk
+COPY scripts/android-ndk.sh /scripts/
+RUN . /scripts/android-ndk.sh && \
+    download_ndk android-ndk-r13b-linux-x86_64.zip && \
+    make_standalone_toolchain arm 9 && \
+    make_standalone_toolchain arm 21 && \
+    remove_ndk
+
+RUN chmod 777 /android/ndk && \
+    ln -s /android/ndk/arm-21 /android/ndk/arm
+
+# env
+ENV PATH=$PATH:/android/ndk/arm-9/bin
+
+ENV DEP_Z_ROOT=/android/ndk/arm-9/sysroot/usr/
+
+ENV HOSTS=armv7-linux-androideabi
+
+ENV RUST_CONFIGURE_ARGS \
+      --host=$HOSTS \
+      --target=$HOSTS \
+      --armv7-linux-androideabi-ndk=/android/ndk/arm \
+      --disable-rpath \
+      --enable-extended \
+      --enable-cargo-openssl-static
+
+# We support api level 9, but api level 21 is required to build llvm. To
+# overcome this problem we use a ndk with api level 21 to build llvm and then
+# switch to a ndk with api level 9 to complete the build. When the linker is
+# invoked there are missing symbols (like sigsetempty, not available with api
+# level 9), the default linker behavior is to generate an error, to allow the
+# build to finish we use --warn-unresolved-symbols. Note that the missing
+# symbols does not affect std, only the compiler (llvm) and cargo (openssl).
+ENV SCRIPT \
+  python2.7 ../x.py build src/llvm --host $HOSTS --target $HOSTS && \
+  (export RUSTFLAGS="\"-C link-arg=-Wl,--warn-unresolved-symbols\""; \
+    rm /android/ndk/arm && \
+    ln -s /android/ndk/arm-9 /android/ndk/arm && \
+    python2.7 ../x.py dist --host $HOSTS --target $HOSTS)
+
+# sccache
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# init
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
diff --git a/src/ci/docker/disabled/dist-i686-android/Dockerfile b/src/ci/docker/disabled/dist-i686-android/Dockerfile
new file mode 100644 (file)
index 0000000..f012e86
--- /dev/null
@@ -0,0 +1,68 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && \
+    apt-get install -y --no-install-recommends \
+  ca-certificates \
+  cmake \
+  curl \
+  file \
+  g++ \
+  git \
+  libssl-dev \
+  make \
+  pkg-config \
+  python2.7 \
+  sudo \
+  unzip \
+  xz-utils
+
+# dumb-init
+COPY scripts/dumb-init.sh /scripts/
+RUN sh /scripts/dumb-init.sh
+
+# ndk
+COPY scripts/android-ndk.sh /scripts/
+RUN . /scripts/android-ndk.sh && \
+    download_ndk android-ndk-r13b-linux-x86_64.zip && \
+    make_standalone_toolchain x86 9 && \
+    make_standalone_toolchain x86 21 && \
+    remove_ndk
+
+RUN chmod 777 /android/ndk && \
+    ln -s /android/ndk/x86-21 /android/ndk/x86
+
+# env
+ENV PATH=$PATH:/android/ndk/x86-9/bin
+
+ENV DEP_Z_ROOT=/android/ndk/x86-9/sysroot/usr/
+
+ENV HOSTS=i686-linux-android
+
+ENV RUST_CONFIGURE_ARGS \
+      --host=$HOSTS \
+      --target=$HOSTS \
+      --i686-linux-android-ndk=/android/ndk/x86 \
+      --disable-rpath \
+      --enable-extended \
+      --enable-cargo-openssl-static
+
+# We support api level 9, but api level 21 is required to build llvm. To
+# overcome this problem we use a ndk with api level 21 to build llvm and then
+# switch to a ndk with api level 9 to complete the build. When the linker is
+# invoked there are missing symbols (like sigsetempty, not available with api
+# level 9), the default linker behavior is to generate an error, to allow the
+# build to finish we use --warn-unresolved-symbols. Note that the missing
+# symbols does not affect std, only the compiler (llvm) and cargo (openssl).
+ENV SCRIPT \
+  python2.7 ../x.py build src/llvm --host $HOSTS --target $HOSTS && \
+  (export RUSTFLAGS="\"-C link-arg=-Wl,--warn-unresolved-symbols\""; \
+    rm /android/ndk/x86 && \
+    ln -s /android/ndk/x86-9 /android/ndk/x86 && \
+    python2.7 ../x.py dist --host $HOSTS --target $HOSTS)
+
+# sccache
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# init
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
diff --git a/src/ci/docker/disabled/dist-x86_64-android/Dockerfile b/src/ci/docker/disabled/dist-x86_64-android/Dockerfile
new file mode 100644 (file)
index 0000000..0c58645
--- /dev/null
@@ -0,0 +1,50 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && \
+    apt-get install -y --no-install-recommends \
+  ca-certificates \
+  cmake \
+  curl \
+  file \
+  g++ \
+  git \
+  libssl-dev \
+  make \
+  pkg-config \
+  python2.7 \
+  sudo \
+  unzip \
+  xz-utils
+
+# dumb-init
+COPY scripts/dumb-init.sh /scripts/
+RUN sh /scripts/dumb-init.sh
+
+# ndk
+COPY scripts/android-ndk.sh /scripts/
+RUN . /scripts/android-ndk.sh && \
+    download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip x86_64 21
+
+# env
+ENV PATH=$PATH:/android/ndk/x86_64-21/bin
+
+ENV DEP_Z_ROOT=/android/ndk/x86_64-21/sysroot/usr/
+
+ENV HOSTS=x86_64-linux-android
+
+ENV RUST_CONFIGURE_ARGS \
+      --host=$HOSTS \
+      --target=$HOSTS \
+      --x86_64-linux-android-ndk=/android/ndk/x86_64-21 \
+      --disable-rpath \
+      --enable-extended \
+      --enable-cargo-openssl-static
+
+ENV SCRIPT python2.7 ../x.py dist --target $HOSTS --host $HOSTS
+
+# sccache
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# init
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
index a694bf84b18cdbc4fbd6f1db28d90a55cb88883b..0134a5407932ad08906e86e786fcaa5da3a05700 100644 (file)
@@ -56,13 +56,13 @@ RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools
 USER rustbuild
 WORKDIR /tmp
 
-COPY aarch64-linux-gnu.config build-toolchains.sh /tmp/
+COPY dist-aarch64-linux/aarch64-linux-gnu.config dist-aarch64-linux/build-toolchains.sh /tmp/
 RUN ./build-toolchains.sh
 
 USER root
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV PATH=$PATH:/x-tools/aarch64-unknown-linux-gnueabi/bin
index 1dd97fd4e047145223da8d449263f8c483c3b41e..31389dd148a8ae0cd23dc3f95f775226d4a5038f 100644 (file)
@@ -1,40 +1,36 @@
 FROM ubuntu:16.04
 
-RUN dpkg --add-architecture i386 && \
-    apt-get update && \
+RUN apt-get update && \
     apt-get install -y --no-install-recommends \
+  ca-certificates \
+  cmake \
+  curl \
+  file \
   g++ \
+  git \
+  libssl-dev \
   make \
-  file \
-  curl \
-  ca-certificates \
+  pkg-config \
   python2.7 \
-  git \
-  cmake \
-  unzip \
-  expect \
-  openjdk-9-jre \
   sudo \
-  libstdc++6:i386 \
-  xz-utils \
-  libssl-dev \
-  pkg-config
-
-WORKDIR /android/
-ENV PATH=$PATH:/android/ndk-arm-9/bin:/android/sdk/tools:/android/sdk/platform-tools
-
-COPY install-ndk.sh /android/
-RUN sh /android/install-ndk.sh
-
-RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
-    dpkg -i dumb-init_*.deb && \
-    rm dumb-init_*.deb
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
-RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
-      chmod +x /usr/local/bin/sccache
-
+  unzip \
+  xz-utils
+
+# dumb-init
+COPY scripts/dumb-init.sh /scripts/
+RUN sh /scripts/dumb-init.sh
+
+# ndk
+COPY scripts/android-ndk.sh /scripts/
+RUN . /scripts/android-ndk.sh && \
+    download_ndk android-ndk-r13b-linux-x86_64.zip && \
+    make_standalone_toolchain arm 9 && \
+    make_standalone_toolchain x86 9 && \
+    make_standalone_toolchain arm64 21 && \
+    make_standalone_toolchain x86_64 21 && \
+    remove_ndk
+
+# env
 ENV TARGETS=arm-linux-androideabi
 ENV TARGETS=$TARGETS,armv7-linux-androideabi
 ENV TARGETS=$TARGETS,i686-linux-android
@@ -44,10 +40,17 @@ ENV TARGETS=$TARGETS,x86_64-linux-android
 ENV RUST_CONFIGURE_ARGS \
       --target=$TARGETS \
       --enable-extended \
-      --arm-linux-androideabi-ndk=/android/ndk-arm-9 \
-      --armv7-linux-androideabi-ndk=/android/ndk-arm-9 \
-      --i686-linux-android-ndk=/android/ndk-x86-9 \
-      --aarch64-linux-android-ndk=/android/ndk-arm64-21 \
-      --x86_64-linux-android-ndk=/android/ndk-x86_64-21
+      --arm-linux-androideabi-ndk=/android/ndk/arm-9 \
+      --armv7-linux-androideabi-ndk=/android/ndk/arm-9 \
+      --i686-linux-android-ndk=/android/ndk/x86-9 \
+      --aarch64-linux-android-ndk=/android/ndk/arm64-21 \
+      --x86_64-linux-android-ndk=/android/ndk/x86_64-21
 
 ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
+
+# cache
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# init
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
diff --git a/src/ci/docker/dist-android/install-ndk.sh b/src/ci/docker/dist-android/install-ndk.sh
deleted file mode 100644 (file)
index d3a2d31..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/sh
-# 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.
-
-set -ex
-
-# Prep the Android NDK
-#
-# See https://github.com/servo/servo/wiki/Building-for-Android
-curl -O https://dl.google.com/android/repository/android-ndk-r11c-linux-x86_64.zip
-unzip -q android-ndk-r11c-linux-x86_64.zip
-bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \
-        --platform=android-9 \
-        --toolchain=arm-linux-androideabi-4.9 \
-        --install-dir=/android/ndk-arm-9 \
-        --ndk-dir=/android/android-ndk-r11c \
-        --arch=arm
-bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \
-        --platform=android-21 \
-        --toolchain=aarch64-linux-android-4.9 \
-        --install-dir=/android/ndk-arm64-21 \
-        --ndk-dir=/android/android-ndk-r11c \
-        --arch=arm64
-bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \
-        --platform=android-9 \
-        --toolchain=x86-4.9 \
-        --install-dir=/android/ndk-x86-9 \
-        --ndk-dir=/android/android-ndk-r11c \
-        --arch=x86
-bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \
-        --platform=android-21 \
-        --toolchain=x86_64-4.9 \
-        --install-dir=/android/ndk-x86_64-21 \
-        --ndk-dir=/android/android-ndk-r11c \
-        --arch=x86_64
-
-rm -rf ./android-ndk-r11c-linux-x86_64.zip ./android-ndk-r11c
index 3ee183115724201994937c071df0540f47f64790..862818a7c918250b43f6d7ac20287cd829520a3e 100644 (file)
@@ -56,13 +56,13 @@ RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools
 USER rustbuild
 WORKDIR /tmp
 
-COPY arm-linux-gnueabi.config build-toolchains.sh /tmp/
+COPY dist-arm-linux/arm-linux-gnueabi.config dist-arm-linux/build-toolchains.sh /tmp/
 RUN ./build-toolchains.sh
 
 USER root
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabi/bin
index 902e2e7e6e140265fd01f48bc516c9c055764d56..7f1f91f844c771ba31c15fa22029ab6a5ddfecdf 100644 (file)
@@ -56,13 +56,13 @@ RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools
 USER rustbuild
 WORKDIR /tmp
 
-COPY arm-linux-gnueabihf.config build-toolchains.sh /tmp/
+COPY dist-armhf-linux/arm-linux-gnueabihf.config dist-armhf-linux/build-toolchains.sh /tmp/
 RUN ./build-toolchains.sh
 
 USER root
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabihf/bin
index d6a66c2f4a33b5e134371e28d31966f486ba9087..030fd24ebcdd0c1daa5d69b724175d65c21c4933 100644 (file)
@@ -56,13 +56,13 @@ RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools
 USER rustbuild
 WORKDIR /tmp
 
-COPY build-toolchains.sh armv7-linux-gnueabihf.config /tmp/
+COPY dist-armv7-linux/build-toolchains.sh dist-armv7-linux/armv7-linux-gnueabihf.config /tmp/
 RUN ./build-toolchains.sh
 
 USER root
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV PATH=$PATH:/x-tools/armv7-unknown-linux-gnueabihf/bin
index b079f12f7e5e8f67efbe6e6011e3ad8c707eac66..d1d9767d35e631c9c70f572b55a2ebc07f90a4ba 100644 (file)
@@ -21,7 +21,7 @@ RUN curl -L https://cmake.org/files/v3.8/cmake-3.8.0-rc1-Linux-x86_64.tar.gz | \
       tar xzf - -C /usr/local --strip-components=1
 
 WORKDIR /tmp
-COPY shared.sh build-toolchain.sh compiler-rt-dso-handle.patch /tmp/
+COPY dist-fuchsia/shared.sh dist-fuchsia/build-toolchain.sh dist-fuchsia/compiler-rt-dso-handle.patch /tmp/
 RUN /tmp/build-toolchain.sh
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
@@ -30,7 +30,7 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
 ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV \
index 6ea7db03cd51f61024e777340460f85d4c528e58..805d238de1f9b5c78dcc4a9d7d281e07c38ca717 100644 (file)
@@ -17,7 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 WORKDIR /build/
-COPY musl-libunwind-patch.patch build-musl.sh /build/
+COPY dist-i586-gnu-i686-musl/musl-libunwind-patch.patch dist-i586-gnu-i686-musl/build-musl.sh /build/
 RUN sh /build/build-musl.sh && rm -rf /build
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
@@ -26,7 +26,7 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
 ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV RUST_CONFIGURE_ARGS \
index b9e5f91b373a8da6eeefaa2d9d58754bd97599c5..9c4d43bfa92bc600899cc8acd0881bd343f4b2cb 100644 (file)
@@ -16,7 +16,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   libssl-dev \
   pkg-config
 
-COPY build-toolchain.sh /tmp/
+COPY dist-i686-freebsd/build-toolchain.sh /tmp/
 RUN /tmp/build-toolchain.sh i686
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
@@ -25,7 +25,7 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
 ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV \
index a15d6c4e53dbac3305f50b7ea1af0a5144132cf7..a3c08e93ed158ce47175d05deef91f95bd5feaf5 100644 (file)
@@ -29,13 +29,13 @@ ENV PATH=/rustroot/bin:$PATH
 ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib
 ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig
 WORKDIR /tmp
-COPY shared.sh build-binutils.sh /tmp/
+COPY dist-i686-linux/shared.sh dist-i686-linux/build-binutils.sh /tmp/
 
 # We need a build of openssl which supports SNI to download artifacts from
 # static.rust-lang.org. This'll be used to link into libcurl below (and used
 # later as well), so build a copy of OpenSSL with dynamic libraries into our
 # generic root.
-COPY build-openssl.sh /tmp/
+COPY dist-i686-linux/build-openssl.sh /tmp/
 RUN ./build-openssl.sh
 
 # The `curl` binary on CentOS doesn't support SNI which is needed for fetching
@@ -44,7 +44,7 @@ RUN ./build-openssl.sh
 #
 # Note that we also disable a bunch of optional features of curl that we don't
 # really need.
-COPY build-curl.sh /tmp/
+COPY dist-i686-linux/build-curl.sh /tmp/
 RUN ./build-curl.sh
 
 # binutils < 2.22 has a bug where the 32-bit executables it generates
@@ -54,26 +54,26 @@ RUN ./build-curl.sh
 RUN ./build-binutils.sh
 
 # Need a newer version of gcc than centos has to compile LLVM nowadays
-COPY build-gcc.sh /tmp/
+COPY dist-i686-linux/build-gcc.sh /tmp/
 RUN ./build-gcc.sh
 
 # CentOS 5.5 has Python 2.4 by default, but LLVM needs 2.7+
-COPY build-python.sh /tmp/
+COPY dist-i686-linux/build-python.sh /tmp/
 RUN ./build-python.sh
 
 # Apparently CentOS 5.5 desn't have `git` in yum, but we're gonna need it for
 # cloning, so download and build it here.
-COPY build-git.sh /tmp/
+COPY dist-i686-linux/build-git.sh /tmp/
 RUN ./build-git.sh
 
 # libssh2 (a dependency of Cargo) requires cmake 2.8.11 or higher but CentOS
 # only has 2.6.4, so build our own
-COPY build-cmake.sh /tmp/
+COPY dist-i686-linux/build-cmake.sh /tmp/
 RUN ./build-cmake.sh
 
 # for sanitizers, we need kernel headers files newer than the ones CentOS ships
 # with so we install newer ones here
-COPY build-headers.sh /tmp/
+COPY dist-i686-linux/build-headers.sh /tmp/
 RUN ./build-headers.sh
 
 RUN curl -Lo /rustroot/dumb-init \
@@ -82,7 +82,7 @@ RUN curl -Lo /rustroot/dumb-init \
 ENTRYPOINT ["/rustroot/dumb-init", "--"]
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV HOSTS=i686-unknown-linux-gnu
index dbcdf2eb9d6a5ae2a149baa6da1ce9610bc7de63..c23240f0c70f9a4475c587158781c7bae20819de 100644 (file)
@@ -17,7 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index d0e59253a0f3edfbafb519ab77a3126de1e7e3e3..415dca99d95ee1ec427b2fc526f391929309742c 100644 (file)
@@ -17,7 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 6645d0cbaad5b10f23d9dd3a728ea660274c7e06..2aba5f615baba476103944d4856bf80b6eb699f9 100644 (file)
@@ -17,7 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index dae1972e49688fb441bce99e96f671a153ec8709..d15e3010863c464827b9916fbece7ea4d0b134c8 100644 (file)
@@ -17,7 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index b43bf8beb26e1a7c94e9e736cc0f86d26d5d7e16..0074665f34f7ed54f0ddff57da78bfa71dfbf89e 100644 (file)
@@ -56,14 +56,14 @@ RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools
 USER rustbuild
 WORKDIR /tmp
 
-COPY patches/ /tmp/patches/
-COPY powerpc-linux-gnu.config build-powerpc-toolchain.sh /tmp/
+COPY dist-powerpc-linux/patches/ /tmp/patches/
+COPY dist-powerpc-linux/powerpc-linux-gnu.config dist-powerpc-linux/build-powerpc-toolchain.sh /tmp/
 RUN ./build-powerpc-toolchain.sh
 
 USER root
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV PATH=$PATH:/x-tools/powerpc-unknown-linux-gnu/bin
index 540415e7e272ee8cd543e57f5e8f4645b9767107..bd38ee0c111582a2f88dbf4f53d2ddb87b7eac57 100644 (file)
@@ -56,14 +56,14 @@ RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools
 USER rustbuild
 WORKDIR /tmp
 
-COPY patches/ /tmp/patches/
-COPY shared.sh powerpc64-linux-gnu.config build-powerpc64-toolchain.sh /tmp/
+COPY dist-powerpc64-linux/patches/ /tmp/patches/
+COPY dist-powerpc64-linux/shared.sh dist-powerpc64-linux/powerpc64-linux-gnu.config dist-powerpc64-linux/build-powerpc64-toolchain.sh /tmp/
 RUN ./build-powerpc64-toolchain.sh
 
 USER root
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV PATH=$PATH:/x-tools/powerpc64-unknown-linux-gnu/bin
index 08ab0f37b62570627ad6b65f1fae73463bd88d6d..cbded156b4cbde53f26d4ce6508eaeeb9e74395b 100644 (file)
@@ -59,11 +59,11 @@ WORKDIR /tmp
 USER root
 
 RUN apt-get install -y --no-install-recommends rpm2cpio cpio
-COPY shared.sh build-powerpc64le-toolchain.sh /tmp/
+COPY dist-powerpc64le-linux/shared.sh dist-powerpc64le-linux/build-powerpc64le-toolchain.sh /tmp/
 RUN ./build-powerpc64le-toolchain.sh
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV \
index a758559e0c108b4d8604ce5dfd53c0412f1e2e1b..5c00287107aa3be399eda238a718a0050ec65b82 100644 (file)
@@ -56,14 +56,14 @@ RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools
 USER rustbuild
 WORKDIR /tmp
 
-COPY patches/ /tmp/patches/
-COPY s390x-linux-gnu.config build-s390x-toolchain.sh /tmp/
+COPY dist-s390x-linux/patches/ /tmp/patches/
+COPY dist-s390x-linux/s390x-linux-gnu.config dist-s390x-linux/build-s390x-toolchain.sh /tmp/
 RUN ./build-s390x-toolchain.sh
 
 USER root
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV PATH=$PATH:/x-tools/s390x-ibm-linux-gnu/bin
index 8c3e86fd9ad71b19731b1ed8b35d03aa90fe787e..a6c4eee5e812c5407e07fdce89ee73c4864e60de 100644 (file)
@@ -16,7 +16,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   libssl-dev \
   pkg-config
 
-COPY build-toolchain.sh /tmp/
+COPY dist-x86_64-freebsd/build-toolchain.sh /tmp/
 RUN /tmp/build-toolchain.sh x86_64
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
@@ -25,7 +25,7 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
 ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV \
index d3db8bde0391be158c4f5f135b61dcef87b68bc5..e2e42836dcdaf136786b7ad9b0194493d817cc83 100644 (file)
@@ -29,13 +29,13 @@ ENV PATH=/rustroot/bin:$PATH
 ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib
 ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig
 WORKDIR /tmp
-COPY shared.sh build-binutils.sh /tmp/
+COPY dist-x86_64-linux/shared.sh dist-x86_64-linux/build-binutils.sh /tmp/
 
 # We need a build of openssl which supports SNI to download artifacts from
 # static.rust-lang.org. This'll be used to link into libcurl below (and used
 # later as well), so build a copy of OpenSSL with dynamic libraries into our
 # generic root.
-COPY build-openssl.sh /tmp/
+COPY dist-x86_64-linux/build-openssl.sh /tmp/
 RUN ./build-openssl.sh
 
 # The `curl` binary on CentOS doesn't support SNI which is needed for fetching
@@ -44,7 +44,7 @@ RUN ./build-openssl.sh
 #
 # Note that we also disable a bunch of optional features of curl that we don't
 # really need.
-COPY build-curl.sh /tmp/
+COPY dist-x86_64-linux/build-curl.sh /tmp/
 RUN ./build-curl.sh
 
 # binutils < 2.22 has a bug where the 32-bit executables it generates
@@ -54,26 +54,26 @@ RUN ./build-curl.sh
 RUN ./build-binutils.sh
 
 # Need a newer version of gcc than centos has to compile LLVM nowadays
-COPY build-gcc.sh /tmp/
+COPY dist-x86_64-linux/build-gcc.sh /tmp/
 RUN ./build-gcc.sh
 
 # CentOS 5.5 has Python 2.4 by default, but LLVM needs 2.7+
-COPY build-python.sh /tmp/
+COPY dist-x86_64-linux/build-python.sh /tmp/
 RUN ./build-python.sh
 
 # Apparently CentOS 5.5 desn't have `git` in yum, but we're gonna need it for
 # cloning, so download and build it here.
-COPY build-git.sh /tmp/
+COPY dist-x86_64-linux/build-git.sh /tmp/
 RUN ./build-git.sh
 
 # libssh2 (a dependency of Cargo) requires cmake 2.8.11 or higher but CentOS
 # only has 2.6.4, so build our own
-COPY build-cmake.sh /tmp/
+COPY dist-x86_64-linux/build-cmake.sh /tmp/
 RUN ./build-cmake.sh
 
 # for sanitizers, we need kernel headers files newer than the ones CentOS ships
 # with so we install newer ones here
-COPY build-headers.sh /tmp/
+COPY dist-x86_64-linux/build-headers.sh /tmp/
 RUN ./build-headers.sh
 
 RUN curl -Lo /rustroot/dumb-init \
@@ -82,7 +82,7 @@ RUN curl -Lo /rustroot/dumb-init \
 ENTRYPOINT ["/rustroot/dumb-init", "--"]
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV HOSTS=x86_64-unknown-linux-gnu
index d58741132dccc905caf206acf132fa237cf06b37..2eea5ab1469728e210795b257e85ce33f2fb56db 100644 (file)
@@ -17,7 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 WORKDIR /build/
-COPY build-musl.sh /build/
+COPY dist-x86_64-musl/build-musl.sh /build/
 RUN sh /build/build-musl.sh && rm -rf /build
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
@@ -26,7 +26,7 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
 ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV RUST_CONFIGURE_ARGS \
index 5c2fbbdf30f3618b8f0f3f7e674f9e2cb1ac3714..f76e6271f4c8c22eddfbb4eec38760f60570fac3 100644 (file)
@@ -56,13 +56,13 @@ RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools
 USER rustbuild
 WORKDIR /tmp
 
-COPY build-netbsd-toolchain.sh /tmp/
+COPY dist-x86_64-netbsd/build-netbsd-toolchain.sh /tmp/
 RUN ./build-netbsd-toolchain.sh
 
 USER root
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV PATH=$PATH:/x-tools/x86_64-unknown-netbsd/bin
index dcbf1c7396376eb6d8880dfe5b94ee606992e2ee..0f0e5b69c32cf787d2a2fafb6dacbd370bce6c7a 100644 (file)
@@ -15,7 +15,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   lib32stdc++6
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
@@ -24,7 +24,7 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
 ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 WORKDIR /tmp
-COPY build-emscripten.sh /tmp/
+COPY emscripten/build-emscripten.sh /tmp/
 RUN ./build-emscripten.sh
 ENV PATH=$PATH:/tmp/emsdk_portable
 ENV PATH=$PATH:/tmp/emsdk_portable/clang/tag-e1.37.10/build_tag-e1.37.10_32/bin
index 94554111104498bf7611803fc90a9996623afbda..076be8f429116581f088eb49f1e09d4452a27c29 100644 (file)
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 12c9cdf4a112c876d4515afeaa667702c41dd7dd..5fac05735746761982775c05d14be3758701d1fe 100644 (file)
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 59b93b784b2f6f27db319fc06d23c2fa93a4600c..bb9a860574dd2f175245cd6e8e97fc911d8787c7 100755 (executable)
@@ -21,11 +21,28 @@ root_dir="`dirname $src_dir`"
 
 source "$ci_dir/shared.sh"
 
-retry docker \
-  build \
-  --rm \
-  -t rust-ci \
-  "`dirname "$script"`/$image"
+if [ -f "$docker_dir/$image/Dockerfile" ]; then
+    retry docker \
+      build \
+      --rm \
+      -t rust-ci \
+      -f "$docker_dir/$image/Dockerfile" \
+      "$docker_dir"
+elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then
+    if [ -n "$TRAVIS_OS_NAME" ]; then
+        echo Cannot run disabled images on travis!
+        exit 1
+    fi
+    retry docker \
+      build \
+      --rm \
+      -t rust-ci \
+      -f "$docker_dir/disabled/$image/Dockerfile" \
+      "$docker_dir"
+else
+    echo Invalid image: $image
+    exit 1
+fi
 
 objdir=$root_dir/obj
 
diff --git a/src/ci/docker/scripts/android-ndk.sh b/src/ci/docker/scripts/android-ndk.sh
new file mode 100644 (file)
index 0000000..c3d83c0
--- /dev/null
@@ -0,0 +1,40 @@
+# 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.
+
+set -ex
+
+URL=https://dl.google.com/android/repository
+
+download_ndk() {
+    mkdir -p /android/ndk
+    cd /android/ndk
+    curl -O $URL/$1
+    unzip -q $1
+    rm $1
+    mv android-ndk-* ndk
+}
+
+make_standalone_toolchain() {
+    # See https://developer.android.com/ndk/guides/standalone_toolchain.htm
+    python2.7 /android/ndk/ndk/build/tools/make_standalone_toolchain.py \
+        --install-dir /android/ndk/$1-$2 \
+        --arch $1 \
+        --api $2
+}
+
+remove_ndk() {
+    rm -rf /android/ndk/ndk
+}
+
+download_and_make_toolchain() {
+    download_ndk $1 && \
+    make_standalone_toolchain $2 $3 && \
+    remove_ndk
+}
diff --git a/src/ci/docker/scripts/android-sdk.sh b/src/ci/docker/scripts/android-sdk.sh
new file mode 100644 (file)
index 0000000..7d8110e
--- /dev/null
@@ -0,0 +1,53 @@
+# 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.
+
+set -ex
+
+URL=https://dl.google.com/android/repository
+
+download_sdk() {
+    mkdir -p /android/sdk
+    cd /android/sdk
+    curl -O $URL/$1
+    unzip -q $1
+    rm -rf $1
+}
+
+download_sysimage() {
+    # See https://developer.android.com/studio/tools/help/android.html
+    abi=$1
+    api=$2
+
+    filter="platform-tools,android-$api"
+    filter="$filter,sys-img-$abi-android-$api"
+
+    # Keep printing yes to accept the licenses
+    while true; do echo yes; sleep 10; done | \
+        /android/sdk/tools/android update sdk -a --no-ui \
+            --filter "$filter"
+}
+
+create_avd() {
+    # See https://developer.android.com/studio/tools/help/android.html
+    abi=$1
+    api=$2
+
+    echo no | \
+        /android/sdk/tools/android create avd \
+            --name $abi-$api \
+            --target android-$api \
+            --abi $abi
+}
+
+download_and_create_avd() {
+    download_sdk $1
+    download_sysimage $2 $3
+    create_avd $2 $3
+}
diff --git a/src/ci/docker/scripts/android-start-emulator.sh b/src/ci/docker/scripts/android-start-emulator.sh
new file mode 100755 (executable)
index 0000000..cd3369d
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/sh
+# 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.
+
+set -ex
+
+# Setting SHELL to a file instead on a symlink helps android
+# emulator identify the system
+export SHELL=/bin/bash
+
+# Using the default qemu2 engine makes time::tests::since_epoch fails because
+# the emulator date is set to unix epoch (in armeabi-v7a-18 image). Using
+# classic engine the emulator starts with the current date and the tests run
+# fine. If another image is used, this need to be evaluated again.
+nohup nohup emulator @armeabi-v7a-18 \
+    -engine classic -no-window -partition-size 2047 0<&- &>/dev/null &
+
+exec "$@"
diff --git a/src/ci/docker/scripts/dumb-init.sh b/src/ci/docker/scripts/dumb-init.sh
new file mode 100644 (file)
index 0000000..839c390
--- /dev/null
@@ -0,0 +1,15 @@
+# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+set -ex
+
+curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb
+dpkg -i dumb-init_*.deb
+rm dumb-init_*.deb
diff --git a/src/ci/docker/scripts/sccache.sh b/src/ci/docker/scripts/sccache.sh
new file mode 100644 (file)
index 0000000..7a2befa
--- /dev/null
@@ -0,0 +1,16 @@
+# 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.
+
+set -ex
+
+curl -o /usr/local/bin/sccache \
+  https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl
+
+chmod +x /usr/local/bin/sccache
index d1f421248df5bfadb5f6c1beed987881f06af0d2..06c7c2824fd9d45b76b40d21e1f788d5a32affce 100644 (file)
@@ -15,7 +15,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 86704126700be4c9165b0482a5635c474bb89a93..6ea54ac4db3e7f2a8b384b2a869cbe19dff85695 100644 (file)
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 26d1f82efcc59ba0945e308f91e0fcc019b65683..e24c660a8c36d804fe267d7a8f2ed0662e7cf660 100644 (file)
@@ -16,7 +16,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 3626301d7e9a22be0db82bb6c9ca65a9de78353c..78035c7fe3d7f9410321bd7f89783b24f48cbc30 100644 (file)
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 42b2d98d332eb1fa12822fa220b60609eb74ffd1..0aaed64e384ed486e9dcaafa5e4737c3bf29897c 100644 (file)
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 8bff767609f415117bb86f01c53a6d46c4bc52a4..7c136fa39bc8bb2accc5b5c0d1bd6dffcdf6e978 100644 (file)
@@ -17,7 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index c2c1ac8787903117afd29ce7bc910bbf3e2eab4c..4499736967cf49194a8c398d7b9a7b3968be804c 100644 (file)
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 727cc84643fbec74b41c14d99930d76f8a994882..de85e1ff36af8ca3f2e5515afc1427c6fd9a216f 100644 (file)
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index ad7de198561b3a12217ea2da76d796d9c7fc0ed3..97422981c53a00f7c3d6584d363443117f179fff 160000 (submodule)
@@ -1 +1 @@
-Subproject commit ad7de198561b3a12217ea2da76d796d9c7fc0ed3
+Subproject commit 97422981c53a00f7c3d6584d363443117f179fff
index 6b0de90d87dda15e323ef24cdf7ed873ac5cf4d3..f7a108dfa9e90b07821700c55d01f08a9adf005c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 6b0de90d87dda15e323ef24cdf7ed873ac5cf4d3
+Subproject commit f7a108dfa9e90b07821700c55d01f08a9adf005c
index 0b2069e25aaf8a92e95d6f88be5b8fcfeb0ae44a..323d49e46912001c9610ddf3357e1acb80a057e3 100644 (file)
@@ -1,14 +1,14 @@
 % Rustc UX guidelines
 
 Don't forget the user. Whether human or another program, such as an IDE, a
-good user experience with the compiler goes a long way into making developer
-lives better. We don't want users to be baffled by compiler output or
+good user experience with the compiler goes a long way toward making developers'
+lives better. We do not want users to be baffled by compiler output or
 learn arcane patterns to compile their program.
 
 ## Error, Warning, Help, Note Messages
 
-When the compiler detects a problem, it can emit either an error, warning,
-note, or help message.
+When the compiler detects a problem, it can emit one of the following: an error, a warning,
+a note, or a help message.
 
 An `error` is emitted when the compiler detects a problem that makes it unable
  to compile the program, either because the program is invalid or the
@@ -17,11 +17,11 @@ An `error` is emitted when the compiler detects a problem that makes it unable
 A `warning` is emitted when the compiler detects something odd about a
 program. For instance, dead code and unused `Result` values.
 
-A `help` is emitted following either an `error` or `warning` giving extra
+A `help` message is emitted following an `error` or `warning` to give additional
 information to the user about how to solve their problem.
 
-A `note` is for identifying additional circumstances and parts of the code
-that lead to a warning or error. For example, the borrow checker will note any
+A `note` is emitted to identify additional circumstances and parts of the code
+that caused the warning or error. For example, the borrow checker will note any
 previous conflicting borrows.
 
 * Write in plain simple English. If your message, when shown on a – possibly
index 3d9e7c7fd860dd33f1b3b793f83ca3d102fc0425..39f800591483bdbf05528244bf24281e76c992d2 100644 (file)
     - [peek](library-features/peek.md)
     - [placement_in](library-features/placement-in.md)
     - [placement_new_protocol](library-features/placement-new-protocol.md)
-    - [print](library-features/print.md)
+    - [print_internals](library-features/print-internals.md)
     - [proc_macro_internals](library-features/proc-macro-internals.md)
     - [process_try_wait](library-features/process-try-wait.md)
     - [question_mark_carrier](library-features/question-mark-carrier.md)
     - [unique](library-features/unique.md)
     - [unsize](library-features/unsize.md)
     - [utf8_error_error_len](library-features/utf8-error-error-len.md)
+    - [vec_resize_default](library-features/vec-resize-default.md)
     - [vec_remove_item](library-features/vec-remove-item.md)
     - [windows_c](library-features/windows-c.md)
     - [windows_handle](library-features/windows-handle.md)
index 30d22ca8208bff24c1b24f3ce7c3833e9a33609a..e8256469b145078be9889c75600c86e64081012c 100644 (file)
@@ -4,7 +4,7 @@ The tracking issue for this feature is: [#23121]
 
 [#23121]: https://github.com/rust-lang/rust/issues/23121
 
-See also [`slice_patterns`](slice-patterns.html).
+See also [`slice_patterns`](language-features/slice-patterns.html).
 
 ------------------------
 
index 5e68be633e7ab2d69aa066853c888b7ccf5c3467..8deb8f462562063f67cac3e1bb1ac85621444ba7 100644 (file)
@@ -190,4 +190,4 @@ constraints, etc.
 [llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions
 
 If you need more power and don't mind losing some of the niceties of
-`asm!`, check out [global_asm](global_asm.html).
+`asm!`, check out [global_asm](language-features/global_asm.html).
index 86346364a71356caf4d19ad45f82c36d05d4d5c3..0896627acae1b3203a39d1463bcae4d6e470fa19 100644 (file)
@@ -4,7 +4,7 @@ The tracking issue for this feature is: [#29641]
 
 [#29641]: https://github.com/rust-lang/rust/issues/29641
 
-See also [`box_syntax`](box-syntax.html)
+See also [`box_syntax`](language-features/box-syntax.html)
 
 ------------------------
 
index 47aade0d04563016192fac4f0d8a8c0a6f930a79..50e59231a4df22d19608d91d470f54fceb645a83 100644 (file)
@@ -4,7 +4,7 @@ The tracking issue for this feature is: [#27779]
 
 [#27779]: https://github.com/rust-lang/rust/issues/27779
 
-See also [`box_patterns`](box-patterns.html)
+See also [`box_patterns`](language-features/box-patterns.html)
 
 ------------------------
 
index 44921aa309f8444218554757121cc1b2a9b5967e..f1ef74a63b513acedd4ff96396812640b451ac9b 100644 (file)
@@ -74,5 +74,5 @@ usages and placed the larger, single usage in the crate root.
 
 If you don't need quite as much power and flexibility as
 `global_asm!` provides, and you don't mind restricting your inline
-assembly to `fn` bodies only, you might try the [asm](asm.html)
-feature instead.
+assembly to `fn` bodies only, you might try the
+[asm](language-features/asm.html) feature instead.
index 54d6e62ce4c526b088fbfb2d22940bddd35d4b57..e8fefe3b73344b4376cfce092dc8b9d37cf21bff 100644 (file)
@@ -4,7 +4,80 @@ The tracking issue for this feature is: [#37339]
 
 [#37339]: https://github.com/rust-lang/rust/issues/37339
 
+Documentation to be appended to section G of the book.
+
 ------------------------
 
+### Loops as expressions
+
+Like most things in Rust, loops are expressions, and have a value; normally `()` unless the loop
+never exits.
+A `loop` can instead evaluate to a useful value via *break with value*:
+
+```rust
+#![feature(loop_break_value)]
+
+// Find the first square number over 1000:
+let mut n = 1;
+let square = loop {
+    if n * n > 1000 {
+        break n * n;
+    }
+    n += 1;
+};
+```
+
+The evaluation type may be specified externally:
+
+```rust
+#![feature(loop_break_value)]
+
+// Declare that value returned is unsigned 64-bit:
+let n: u64 = loop {
+    break 1;
+};
+```
+
+It is an error if types do not agree, either between a "break" value and an external requirement,
+or between multiple "break" values:
+
+```no_compile
+#![feature(loop_break_value)]
+
+loop {
+    if true {
+        break 1u32;
+    } else {
+        break 0u8;  // error: types do not agree
+    }
+};
+
+let n: i32 = loop {
+    break 0u32; // error: type does not agree with external requirement
+};
+```
+
+#### Break: label, value
+
+Four forms of `break` are available, where EXPR is some expression which evaluates to a value:
+
+1.  `break;`
+2.  `break 'label;`
+3.  `break EXPR;`
+4.  `break 'label EXPR;`
+
+When no value is given, the value `()` is assumed, thus `break;` is equivalent to `break ();`.
+
+Using a label allows returning a value from an inner loop:
 
+```rust
+#![feature(loop_break_value)]
 
+let result = 'outer: loop {
+    for n in 1..10 {
+        if n > 4 {
+            break 'outer n;
+        }
+    }
+};
+```
index ca3738bd93f831dbb5b5955f2d227468f121c7f9..b16e2ac2d221c97941e4f4ba0c01b31781335bed 100644 (file)
@@ -8,6 +8,6 @@ This feature is part of "compiler plugins." It will often be used with the
 [`plugin`] and `rustc_private` features as well. For more details, see
 their docs.
 
-[`plugin`]: plugin.html
+[`plugin`]: language-features/plugin.html
 
 ------------------------
index 3a1872e18ddb8a6968594016964fa4f8a5569522..4b8603e3c445045147c42de687955d1582c44e7d 100644 (file)
@@ -8,7 +8,7 @@ The tracking issue for this feature is: [#29597]
 This feature is part of "compiler plugins." It will often be used with the
 [`plugin_registrar`] and `rustc_private` features.
 
-[`plugin_registrar`]: plugin-registrar.html
+[`plugin_registrar`]: language-features/plugin-registrar.html
 
 ------------------------
 
index f8b53bd5a2fd398a9119c3b1506dff84550f4db3..1bd8c41629eea01712d001f940d2e797ee47138f 100644 (file)
@@ -6,5 +6,236 @@ The tracking issue for this feature is: [#38356]
 
 ------------------------
 
+This feature flag guards the new procedural macro features as laid out by [RFC 1566], which alongside the now-stable 
+[custom derives], provide stabilizable alternatives to the compiler plugin API (which requires the use of 
+perma-unstable internal APIs) for programmatically modifying Rust code at compile-time.
 
+The two new procedural macro kinds are:
+* Function-like procedural macros which are invoked like regular declarative macros, and:
 
+* Attribute-like procedural macros which can be applied to any item which built-in attributes can
+be applied to, and which can take arguments in their invocation as well.
+
+Additionally, this feature flag implicitly enables the [`use_extern_macros`](language-features/use-extern-macros.html) feature,
+which allows macros to be imported like any other item with `use` statements, as compared to 
+applying `#[macro_use]` to an `extern crate` declaration. It is important to note that procedural macros may
+**only** be imported in this manner, and will throw an error otherwise.
+
+You **must** declare the `proc_macro` feature in both the crate declaring these new procedural macro kinds as well as 
+in any crates that use them.
+
+### Common Concepts
+
+As with custom derives, procedural macros may only be declared in crates of the `proc-macro` type, and must be public
+functions. No other public items may be declared in `proc-macro` crates, but private items are fine.
+
+To declare your crate as a `proc-macro` crate, simply add:
+
+```toml
+[lib]
+proc-macro = true
+```
+
+to your `Cargo.toml`. 
+
+Unlike custom derives, however, the name of the function implementing the procedural macro is used directly as the 
+procedural macro's name, so choose carefully.
+
+Additionally, both new kinds of procedural macros return a `TokenStream` which *wholly* replaces the original 
+invocation and its input.
+
+#### Importing
+
+As referenced above, the new procedural macros are not meant to be imported via `#[macro_use]` and will throw an 
+error if they are. Instead, they are meant to be imported like any other item in Rust, with `use` statements:
+
+```rust,ignore
+#![feature(proc_macro)]
+
+// Where `my_proc_macros` is some crate of type `proc_macro`
+extern crate my_proc_macros;
+
+// And declares a `#[proc_macro] pub fn my_bang_macro()` at its root.
+use my_proc_macros::my_bang_macro;
+
+fn main() {
+    println!("{}", my_bang_macro!());
+}
+```
+
+#### Error Reporting
+
+Any panics in a procedural macro implementation will be caught by the compiler and turned into an error message pointing 
+to the problematic invocation. Thus, it is important to make your panic messages as informative as possible: use 
+`Option::expect` instead of `Option::unwrap` and `Result::expect` instead of `Result::unwrap`, and inform the user of 
+the error condition as unambiguously as you can.
+#### `TokenStream`
+
+The `proc_macro::TokenStream` type is hardcoded into the signatures of procedural macro functions for both input and 
+output. It is a wrapper around the compiler's internal representation for a given chunk of Rust code.
+
+### Function-like Procedural Macros
+
+These are procedural macros that are invoked like regular declarative macros. They are declared as public functions in 
+crates of the `proc_macro` type and using the `#[proc_macro]` attribute. The name of the declared function becomes the 
+name of the macro as it is to be imported and used. The function must be of the kind `fn(TokenStream) -> TokenStream` 
+where the sole argument is the input to the macro and the return type is the macro's output.
+
+This kind of macro can expand to anything that is valid for the context it is invoked in, including expressions and
+statements, as well as items.
+
+**Note**: invocations of this kind of macro require a wrapping `[]`, `{}` or `()` like regular macros, but these do not 
+appear in the input, only the tokens between them. The tokens between the braces do not need to be valid Rust syntax.
+
+<span class="filename">my_macro_crate/src/lib.rs</span>
+
+```rust,ignore
+#![feature(proc_macro)]
+
+// This is always necessary to get the `TokenStream` typedef.
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn say_hello(_input: TokenStream) -> TokenStream {
+    // This macro will accept any input because it ignores it. 
+    // To enforce correctness in macros which don't take input,
+    // you may want to add `assert!(_input.to_string().is_empty());`.
+    "println!(\"Hello, world!\")".parse().unwrap()
+}
+```
+
+<span class="filename">my_macro_user/Cargo.toml</span>
+
+```toml
+[dependencies]
+my_macro_crate = { path = "<relative path to my_macro_crate>" }
+```
+
+<span class="filename">my_macro_user/src/lib.rs</span>
+
+```rust,ignore
+#![feature(proc_macro)]
+
+extern crate my_macro_crate;
+
+use my_macro_crate::say_hello;
+
+fn main() {
+    say_hello!();
+}
+```
+
+As expected, this prints `Hello, world!`.
+
+### Attribute-like Procedural Macros
+
+These are arguably the most powerful flavor of procedural macro as they can be applied anywhere attributes are allowed. 
+
+They are declared as public functions in crates of the `proc-macro` type, using the `#[proc_macro_attribute]` attribute. 
+The name of the function becomes the name of the attribute as it is to be imported and used. The function must be of the 
+kind `fn(TokenStream, TokenStream) -> TokenStream` where:
+
+The first argument represents any metadata for the attribute (see [the reference chapter on attributes][refr-attr]). 
+Only the metadata itself will appear in this argument, for example:
+ * `#[my_macro]` will get an empty string.
+ * `#[my_macro = "string"]` will get `= "string"`.
+ * `#[my_macro(ident)]` will get `(ident)`.
+ * etc.
+The second argument is the item that the attribute is applied to. It can be a function, a type definition, 
+an impl block, an `extern` block, or a module—attribute invocations can take the inner form (`#![my_attr]`) 
+or outer form (`#[my_attr]`).
+
+The return type is the output of the macro which *wholly* replaces the item it was applied to. Thus, if your intention
+is to merely modify an item, it *must* be copied to the output. The output must be an item; expressions, statements
+and bare blocks are not allowed.
+
+There is no restriction on how many items an attribute-like procedural macro can emit as long as they are valid in 
+the given context.
+
+<span class="filename">my_macro_crate/src/lib.rs</span>
+
+```rust,ignore
+#![feature(proc_macro)]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+/// Adds a `/// ### Panics` docstring to the end of the input's documentation
+///
+/// Does not assert that its receiver is a function or method.
+#[proc_macro_attribute]
+pub fn panics_note(args: TokenStream, input: TokenStream) -> TokenStream {
+    let args = args.to_string();
+    let mut input = input.to_string();
+
+    assert!(args.starts_with("= \""), "`#[panics_note]` requires an argument of the form \
+                                       `#[panics_note = \"panic note here\"]`");
+
+    // Get just the bare note string
+    let panics_note = args.trim_matches(&['=', ' ', '"'][..]);
+
+    // The input will include all docstrings regardless of where the attribute is placed,
+    // so we need to find the last index before the start of the item
+    let insert_idx = idx_after_last_docstring(&input);
+
+    // And insert our `### Panics` note there so it always appears at the end of an item's docs
+    input.insert_str(insert_idx, &format!("/// # Panics \n/// {}\n", panics_note));
+
+    input.parse().unwrap()
+}
+
+// `proc-macro` crates can contain any kind of private item still
+fn idx_after_last_docstring(input: &str) -> usize {
+    // Skip docstring lines to find the start of the item proper
+    input.lines().skip_while(|line| line.trim_left().starts_with("///")).next()
+        // Find the index of the first non-docstring line in the input
+        // Note: assumes this exact line is unique in the input
+        .and_then(|line_after| input.find(line_after))
+        // No docstrings in the input
+        .unwrap_or(0)
+}
+```
+
+<span class="filename">my_macro_user/Cargo.toml</span>
+
+```toml
+[dependencies]
+my_macro_crate = { path = "<relative path to my_macro_crate>" }
+```
+
+<span class="filename">my_macro_user/src/lib.rs</span>
+
+```rust,ignore
+#![feature(proc_macro)]
+
+extern crate my_macro_crate;
+
+use my_macro_crate::panics_note;
+
+/// Do the `foo` thing.
+#[panics_note = "Always."]
+pub fn foo() {
+    panic!()
+}
+```
+
+Then the rendered documentation for `pub fn foo` will look like this:
+
+> `pub fn foo()`
+> 
+> ----
+> Do the `foo` thing.
+> # Panics
+> Always.
+
+[RFC 1566]: https://github.com/rust-lang/rfcs/blob/master/text/1566-proc-macros.md
+[custom derives]: https://doc.rust-lang.org/book/procedural-macros.html
+[rust-lang/rust#41430]: https://github.com/rust-lang/rust/issues/41430
+[refr-attr]: https://doc.rust-lang.org/reference/attributes.html
index 1e9e1eaafda46dade9f4c92cc49035259251d6e0..69857297582da4068b9c3c464d818657c7ce6877 100644 (file)
@@ -4,7 +4,8 @@ The tracking issue for this feature is: [#23121]
 
 [#23121]: https://github.com/rust-lang/rust/issues/23121
 
-See also [`advanced_slice_patterns`](advanced-slice-patterns.html).
+See also
+[`advanced_slice_patterns`](language-features/advanced-slice-patterns.html).
 
 ------------------------
 
index 9bffa2ff99bf3d0db7fdcc0455d610fe9b187115..18ff838dd32b961743f14b03a95d13d0d14790f9 100644 (file)
@@ -4,7 +4,7 @@ The tracking issue for this feature is: [#33082]
 
 [#33082]: https://github.com/rust-lang/rust/issues/33082
 
-See also [`alloc_system`](alloc-system.html).
+See also [`alloc_system`](library-features/alloc-system.html).
 
 ------------------------
 
index 6fa89179d8e1150c54e4367b394ae3f60d1214f3..1d261db6ba1b3f810a08aa3892837c99cdeaf280 100644 (file)
@@ -4,7 +4,7 @@ The tracking issue for this feature is: [#33082]
 
 [#33082]: https://github.com/rust-lang/rust/issues/33082
 
-See also [`alloc_jemalloc`](alloc-jemalloc.html).
+See also [`alloc_jemalloc`](library-features/alloc-jemalloc.html).
 
 ------------------------
 
diff --git a/src/doc/unstable-book/src/library-features/print-internals.md b/src/doc/unstable-book/src/library-features/print-internals.md
new file mode 100644 (file)
index 0000000..a685578
--- /dev/null
@@ -0,0 +1,5 @@
+# `print_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/print.md b/src/doc/unstable-book/src/library-features/print.md
deleted file mode 100644 (file)
index dc25cb2..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# `print`
-
-This feature is internal to the Rust compiler and is not intended for general use.
-
-------------------------
diff --git a/src/doc/unstable-book/src/library-features/vec-resize-default.md b/src/doc/unstable-book/src/library-features/vec-resize-default.md
new file mode 100644 (file)
index 0000000..5803d32
--- /dev/null
@@ -0,0 +1,7 @@
+# `vec_resize_default`
+
+The tracking issue for this feature is: [#41758]
+
+[#41758]: https://github.com/rust-lang/rust/issues/41758
+
+------------------------
diff --git a/src/etc/platform-intrinsics/hexagon/hvx_v60.json b/src/etc/platform-intrinsics/hexagon/hvx_v60.json
new file mode 100644 (file)
index 0000000..a1897e6
--- /dev/null
@@ -0,0 +1,1326 @@
+{
+    "platform": "Q6_",
+    "intrinsic_prefix": "",
+    "llvm_prefix": "llvm.hexagon.V6.",
+    "number_info": {
+        "signed": {
+            "kind": "s",
+            "data_type": { "8": "b", "16": "h", "32": "w" },
+            "data_type_plain": { "8": "b", "16": "h", "32": "w" }
+        },
+        "unsigned": {
+            "kind": "u",
+            "data_type": { "8": "ub", "16": "uh", "32": "uw" },
+            "data_type_plain": { "8": "b", "16": "h", "32": "w" }
+        },
+        "float": {
+            "kind": "f",
+            "data_type": { "8": "b", "16": "h", "32": "w" },
+            "data_type_plain": { "8": "b", "16": "h", "32": "w" }
+        }
+    },
+    "width_info": {
+        "64": { "width_b": "64", "width_suffix": "" },
+        "128": { "width_b": "128", "width_suffix": ".128B" },
+        "512": { "width_b": "64", "width_suffix": "" },
+        "1024": { "widthd_b": "64", "width_b": "128", "width_suffix": ".128B",  "widthd_suffix": "" },
+        "2048": { "widthd_b": "128", "widthd_suffix": ".128B" }
+    },
+    "intrinsics": [
+        {
+            "intrinsic": "R_vextract{1.width_b}",
+            "width": [512, 1024],
+            "llvm": "extractw{1.width_suffix}",
+            "ret": "U32",
+            "args": ["u32", "U32"]
+        },
+        {
+            "intrinsic": "V_lo{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "lo{0.width_suffix}",
+            "ret": "u32",
+            "args": ["0d"]
+        },
+        {
+            "intrinsic": "V_hi{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "hi{0.width_suffix}",
+            "ret": "u32",
+            "args": ["0d"]
+        },
+        {
+            "intrinsic": "V_vsplat_R{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "lvsplat{1.data_type}{0.width_suffix}",
+            "ret": "u32",
+            "args": ["0S"]
+        },
+        {
+            "intrinsic": "Q_and_QQ{0.width_b}",
+            "width": [64, 128],
+            "llvm": "pred.and{0.width_suffix}",
+            "ret": "u32",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "Q_not_Q{0.width_b}",
+            "width": [64, 128],
+            "llvm": "pred.not{0.width_suffix}",
+            "ret": "u32",
+            "args": ["0"]
+        },
+        {
+            "intrinsic": "Q_or_QQ{0.width_b}",
+            "width": [64, 128],
+            "llvm": "pred.or{0.width_suffix}",
+            "ret": "u32",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "Q_xor_QQ{0.width_b}",
+            "width": [64, 128],
+            "llvm": "pred.xor{0.width_suffix}",
+            "ret": "u32",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vabsdiff_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vabsdiff{1.data_type}{0.width_suffix}",
+            "ret": "u(8-16)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vabsdiff_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vabsdiff{1.data_type}{0.width_suffix}",
+            "ret": "u(16-32)",
+            "args": ["0s", "0s"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vabs_V{1.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vabs{1.data_type}{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vabs_V{1.data_type}_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vabs{1.data_type}.sat{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vadd_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vadd{0.data_type}{0.width_suffix}",
+            "ret": "s(8-32)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vadd_V{1.data_type}V{2.data_type}_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vadd{0.data_type}sat{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vadd_V{1.data_type}V{2.data_type}_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vadd{0.data_type}sat{0.width_suffix}",
+            "ret": "u(8-16)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vadd_W{1.data_type}W{2.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vadd{0.data_type}.dv{0.widthd_suffix}",
+            "ret": "s(8-32)d",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vadd_W{1.data_type}W{2.data_type}_sat{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vadd{0.data_type}sat.dv{0.widthd_suffix}",
+            "ret": "s(16-32)d",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vadd_W{1.data_type}W{2.data_type}_sat{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vadd{0.data_type}sat.dv{0.widthd_suffix}",
+            "ret": "u(8-16)d",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V_valign_VVR{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "valignb{0.width_suffix}",
+            "ret": "u8",
+            "args": ["0", "0", "U32"]
+        },
+        {
+            "intrinsic": "V_valign_VVI{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "valignbi{0.width_suffix}",
+            "ret": "u8",
+            "args": ["0", "0", "U32"]
+        },
+        {
+            "intrinsic": "V_vlalign_VVR{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vlalignb{0.width_suffix}",
+            "ret": "u8",
+            "args": ["0", "0", "U32"]
+        },
+        {
+            "intrinsic": "V_vlalign_VVI{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vlalignbi{0.width_suffix}",
+            "ret": "u8",
+            "args": ["0", "0", "U32"]
+        },
+        {
+            "intrinsic": "V_vand_VV{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vand{0.width_suffix}",
+            "ret": "u16",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V_vand_QR{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vandqrt{0.width_suffix}",
+            "ret": "u8",
+            "args": ["u32hhh", "U32"]
+        },
+        {
+            "intrinsic": "V_vandor_VQR{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vandqrt.acc{0.width_suffix}",
+            "ret": "u8",
+            "args": ["0", "u32hhh", "U32"]
+        },
+        {
+            "intrinsic": "Q_vand_VR{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vandvrt{0.width_suffix}",
+            "ret": "u32hhh",
+            "args": ["u8", "U32"]
+        },
+        {
+            "intrinsic": "Q_vandor_QVR{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vandvrt{0.width_suffix}",
+            "ret": "u32hhh",
+            "args": ["0", "u8", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vasl_V{1.data_type}R{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vasl{0.data_type}{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vasl_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vasl{0.data_type}v{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vaslacc_V{1.data_type}V{2.data_type}R{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vasl{0.data_type}.acc{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "0", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vasr_V{1.data_type}R{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vasr{0.data_type}{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vasr_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vasr{0.data_type}v{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vasracc_V{1.data_type}V{2.data_type}R{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vasr{0.data_type}.acc{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "0", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vasr_V{1.data_type}V{2.data_type}R{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vasr{0.data_type}{1.data_type}{0.width_suffix}",
+            "ret": "s16",
+            "args": ["0hw", "0hw", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vasr_V{1.data_type}V{2.data_type}R_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vasr{1.data_type}{0.data_type_plain}sat{0.width_suffix}",
+            "ret": "i(8-16)",
+            "args": ["0hws", "0hws", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vasr_V{1.data_type}V{2.data_type}R_rnd_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vasr{1.data_type}{0.data_type_plain}rndsat{0.width_suffix}",
+            "ret": "i(8-16)",
+            "args": ["0hws", "0hws", "U32"]
+        },
+        {
+            "intrinsic": "V_equals_V{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vassign{0.width_suffix}",
+            "ret": "u32",
+            "args": ["0"]
+        },
+        {
+            "intrinsic": "W_equals_W{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vassignp{0.widthd_suffix}",
+            "ret": "u32d",
+            "args": ["0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vavg_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vavg{0.data_type}{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vavg_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vavg{0.data_type}{0.width_suffix}",
+            "ret": "u(8-16)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vavg_V{1.data_type}V{2.data_type}_rnd{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vavgrnd{0.data_type}{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vavg_V{1.data_type}V{2.data_type}_rnd{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vavgrnd{0.data_type}{0.width_suffix}",
+            "ret": "u(8-16)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vcl0_V{1.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vcl0{0.data_type_plain}{0.width_suffix}",
+            "ret": "u(16-32)",
+            "args": ["0"]
+        },
+        {
+            "intrinsic": "W_vcombine_VV{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vcombine{0.widthd_suffix}",
+            "ret": "u8d",
+            "args": ["0h", "0h"]
+        },
+        {
+            "intrinsic": "V_vzero{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vd0{0.width_suffix}",
+            "ret": "u32",
+            "args": []
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdeal_V{1.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdeal{1.data_type}{0.width_suffix}",
+            "ret": "s(8-16)",
+            "args": ["0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdeale_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdeal{1.data_type}4w{0.width_suffix}",
+            "ret": "s8",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "W_vdeal_VVR{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vdealvdd{0.widthd_suffix}",
+            "ret": "u8d",
+            "args": ["0h", "0h", "U32"]
+        },
+        {
+            "intrinsic": "V_vdelta_VV{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdelta{0.width_suffix}",
+            "ret": "u8",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdmpy_V{1.data_type}Rb{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpybus{0.width_suffix}",
+            "ret": "s16",
+            "args": ["u8", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdmpyacc_V{1.data_type}V{2.data_type}Rb{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpybus.acc{0.width_suffix}",
+            "ret": "s16",
+            "args": ["s16", "u8", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vdmpy_W{1.data_type}Rb{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpybus.dv{0.widthd_suffix}",
+            "ret": "s16d",
+            "args": ["u8d", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vdmpyacc_W{1.data_type}W{2.data_type}Rb{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpybus.dv.acc{0.widthd_suffix}",
+            "ret": "s16d",
+            "args": ["s16d", "u8d", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdmpy_V{1.data_type}Rb{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpyhb{0.width_suffix}",
+            "ret": "s32",
+            "args": ["s16", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdmpyacc_V{1.data_type}V{2.data_type}Rb{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpyhb.acc{0.width_suffix}",
+            "ret": "s32",
+            "args": ["s32", "s16", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vdmpy_W{1.data_type}Rb{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpyhb.dv{0.widthd_suffix}",
+            "ret": "s32d",
+            "args": ["s16d", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vdmpyacc_W{1.data_type}W{2.data_type}Rb{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpyhb.dv.acc{0.widthd_suffix}",
+            "ret": "s32d",
+            "args": ["s32d", "s16d", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdmpy_W{1.data_type}Rh_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpyhisat{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0d", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdmpy_V{1.data_type}Rh_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpyhsat{0.width_suffix}",
+            "ret": "s32",
+            "args": ["s16", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdmpy_W{1.data_type}Ruh_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpyhsuisat{0.width_suffix}",
+            "ret": "s32",
+            "args": ["s16d", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdmpy_V{1.data_type}Ruh_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpyhsusat{0.width_suffix}",
+            "ret": "s32",
+            "args": ["s16", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdmpy_V{1.data_type}V{2.data_type}_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpyhvsat{0.width_suffix}",
+            "ret": "s32",
+            "args": ["s16", "s16"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdmpyacc_V{1.data_type}W{2.data_type}Rh_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpyhisat_acc{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "0d", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vdsad_W{1.data_type}Ruh{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vdsaduh{0.widthd_suffix}",
+            "ret": "u32d",
+            "args": ["u16d", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vdsadacc_W{1.data_type}W{2.data_type}Ruh{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vdsaduh.acc{0.widthd_suffix}",
+            "ret": "u32d",
+            "args": ["0", "u16d", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdmpyacc_V{1.data_type}V{2.data_type}Rh_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpyhsat_acc{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "s16", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdmpyacc_V{1.data_type}W{2.data_type}Ruh_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpyhsuisat_acc{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "s16d", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdmpyacc_V{1.data_type}V{2.data_type}Ruh_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpyhsusat_acc{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "s16", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vdmpyacc_V{1.data_type}V{2.data_type}V{3.data_type}_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vdmpyhvsat_acc{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "s16", "s16"]
+        },
+        {
+            "intrinsic": "Q_vcmp_eq_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "veq{1.data_type}{0.width_suffix}",
+            "ret": "u32hhh",
+            "args": ["s(8-32)", "1"]
+        },
+        {
+            "intrinsic": "Q_vcmp_eqand_QV{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "veq{2.data_type}.and{0.width_suffix}",
+            "ret": "u32hhh",
+            "args": ["0", "s(8-32)", "2"]
+        },
+        {
+            "intrinsic": "Q_vcmp_eqor_QV{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "veq{2.data_type}.or{0.width_suffix}",
+            "ret": "u32hhh",
+            "args": ["0", "s(8-32)", "2"]
+        },
+        {
+            "intrinsic": "Q_vcmp_eqxacc_QV{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "veq{2.data_type}.xor{0.width_suffix}",
+            "ret": "u32hhh",
+            "args": ["0", "s(8-32)", "2"]
+        },
+        {
+            "intrinsic": "Q_vcmp_gt_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vgt{1.data_type}{0.width_suffix}",
+            "ret": "u32hhh",
+            "args": ["s(8-32)", "1"]
+        },
+        {
+            "intrinsic": "Q_vcmp_gt_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vgt{1.data_type}{0.width_suffix}",
+            "ret": "u32hhh",
+            "args": ["u(8-16)", "1"]
+        },
+        {
+            "intrinsic": "Q_vcmp_gtand_QV{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vgt{2.data_type}.and{0.width_suffix}",
+            "ret": "u32hhh",
+            "args": ["0", "s(8-32)", "2"]
+        },
+        {
+            "intrinsic": "Q_vcmp_gtand_QV{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vgt{2.data_type}.and{0.width_suffix}",
+            "ret": "u32hhh",
+            "args": ["0", "u(8-16)", "2"]
+        },
+        {
+            "intrinsic": "Q_vcmp_gtor_QV{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vgt{2.data_type}.or{0.width_suffix}",
+            "ret": "u32hhh",
+            "args": ["0", "s(8-32)", "2"]
+        },
+        {
+            "intrinsic": "Q_vcmp_gtor_QV{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vgt{2.data_type}.or{0.width_suffix}",
+            "ret": "u32hhh",
+            "args": ["0", "u(8-16)", "2"]
+        },
+        {
+            "intrinsic": "Q_vcmp_gtxacc_QV{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vgt{2.data_type}.xor{0.width_suffix}",
+            "ret": "u32hhh",
+            "args": ["0", "s(8-32)", "2"]
+        },
+        {
+            "intrinsic": "Q_vcmp_gtxacc_QV{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vgt{2.data_type}.xor{0.width_suffix}",
+            "ret": "u32hhh",
+            "args": ["0", "u(8-16)", "2"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vinsert_V{1.data_type}R{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vinsertwr{0.width_suffix}",
+            "ret": "s32",
+            "args": ["S32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vlsr_V{1.data_type}R{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vlsr{0.data_type_plain}{0.width_suffix}",
+            "ret": "u(16-32)",
+            "args": ["0", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vlsr_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vlsr{0.data_type}v{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vlut32_V{1.data_type}V{2.data_type}R{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vlutvv{0.data_type}{0.width_suffix}",
+            "ret": "s8",
+            "args": ["0", "0", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vlut16_V{1.data_type}V{2.data_type}R{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vlutvw{0.data_type}{0.widthd_suffix}",
+            "ret": "s16d",
+            "args": ["s8", "s16", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vlut32or_V{1.data_type}V{2.data_type}V{3.data_type}R{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vlutvv{0.data_type}.oracc{0.width_suffix}",
+            "ret": "s8",
+            "args": ["0", "0", "0", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vlut16or_W{1.data_type}V{2.data_type}V{3.data_type}R{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vlutvw{0.data_type}.oracc{0.widthd_suffix}",
+            "ret": "s16d",
+            "args": ["0", "s8", "s16", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmax_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmax{0.data_type}{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmax_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmax{0.data_type}{0.width_suffix}",
+            "ret": "u(8-16)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmin_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmin{0.data_type}{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmin_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmin{0.data_type}{0.width_suffix}",
+            "ret": "u(8-16)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vmpa_W{1.data_type}Rb{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vmpabus{0.widthd_suffix}",
+            "ret": "s16d",
+            "args": ["u8d", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vmpaacc_W{1.data_type}W{2.data_type}Rb{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vmpabus.acc{0.widthd_suffix}",
+            "ret": "s16d",
+            "args": ["0", "u8d", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vmpa_W{1.data_type}W{2.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vmpab{1.kind}{2.kind}v{0.widthd_suffix}",
+            "ret": "s16d",
+            "args": ["u8d", "i8d"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vmpa_W{1.data_type}Rb{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vmpahb{0.widthd_suffix}",
+            "ret": "s32d",
+            "args": ["s16d", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vmpaacc_W{1.data_type}W{2.data_type}Rb{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vmpahb.acc{0.widthd_suffix}",
+            "ret": "s32d",
+            "args": ["0", "s16d", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vmpy_V{1.data_type}V{2.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vmpy{1.data_type}us{0.widthd_suffix}",
+            "ret": "s(16-32)d",
+            "args": ["0n", "0nu"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vmpyacc_W{1.data_type}V{2.data_type}V{3.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vmpy{2.data_type}us.acc{0.widthd_suffix}",
+            "ret": "s(16-32)d",
+            "args": ["0", "0n", "0nu"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vmpy_V{1.data_type}V{2.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vmpybusv{0.widthd_suffix}",
+            "ret": "s16d",
+            "args": ["u8", "s8"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vmpyacc_W{1.data_type}V{2.data_type}V{3.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vmpybusv.acc{0.widthd_suffix}",
+            "ret": "s16d",
+            "args": ["0", "0nu", "0n"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vmpy_V{1.data_type}V{2.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vmpy{1.data_type}v{0.widthd_suffix}",
+            "ret": "i(16-32)d",
+            "args": ["0n", "0n"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vmpyacc_W{1.data_type}V{2.data_type}V{3.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vmpy{2.data_type}v.acc{0.widthd_suffix}",
+            "ret": "i(16-32)d",
+            "args": ["0", "0n", "0n"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpye_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyewuh{0.width_suffix}",
+            "ret": "s32",
+            "args": ["s32", "u16"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vmpy_V{1.data_type}R{1.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vmpy{1.data_type}{0.widthd_suffix}",
+            "ret": "i32d",
+            "args": ["0n", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vmpyacc_W{1.data_type}V{2.data_type}R{2.data_type}_sat{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vmpy{2.data_type}sat.acc{0.widthd_suffix}",
+            "ret": "s32d",
+            "args": ["0", "0n", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpy_V{1.data_type}R{1.data_type}_s1_rnd_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpy{1.data_type}srs{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0nd", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpy_V{1.data_type}R{1.data_type}_s1_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpy{1.data_type}ss{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0nd", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpy_V{1.data_type}V{2.data_type}_s1_rnd_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpy{1.data_type}vsrs{0.width_suffix}",
+            "ret": "s16",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyieo_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyieo{1.data_type}{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0nd", "0nd"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyieacc_V{1.data_type}V{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyie{2.data_type}{3.data_type}.acc{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "0", "i16"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyie_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyie{1.data_type}{2.data_type}{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "u16"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyi_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyi{1.data_type}{0.width_suffix}",
+            "ret": "s16",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyiacc_V{1.data_type}V{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyi{1.data_type}.acc{0.width_suffix}",
+            "ret": "s16",
+            "args": ["0", "0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyi_V{1.data_type}Rb{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyi{1.data_type}b{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyiacc_V{1.data_type}V{2.data_type}Rb{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyi{1.data_type}b.acc{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0", "0", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyi_V{1.data_type}Rh{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyi{1.data_type}h{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyiacc_V{1.data_type}V{2.data_type}Rh{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyi{1.data_type}h.acc{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "0", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyi_V{1.data_type}Rub{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyi{1.data_type}ub{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyiacc_V{1.data_type}V{2.data_type}Rub{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyi{1.data_type}ub.acc{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "0", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyo_V{1.data_type}V{2.data_type}_s1_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyo{1.data_type}{2.data_type}{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "0nd"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyo_V{1.data_type}V{2.data_type}_s1_rnd_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyo{1.data_type}{2.data_type}.rnd{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "0nd"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyo_V{1.data_type}V{2.data_type}_s1_rnd_sat_shift{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyo{1.data_type}{2.data_type}.rnd.sacc{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "0nd"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyo_V{1.data_type}V{2.data_type}_s1_sat_shift{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyo{1.data_type}{2.data_type}.sacc{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "0nd"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmpyio_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmpyio{1.data_type}{2.data_type}{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "0nd"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vmpy_V{1.data_type}R{1.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vmpy{1.data_type}{0.widthd_suffix}",
+            "ret": "u16d",
+            "args": ["0n", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vmpyacc_W{1.data_type}V{2.data_type}R{2.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vmpy{2.data_type}.acc{0.widthd_suffix}",
+            "ret": "u(16-32)d",
+            "args": ["0", "0n", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vmux_QVV{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vmux{0.width_suffix}",
+            "ret": "u32",
+            "args": ["0hhh", "0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vnavg_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vnavg{0.data_type}{0.width_suffix}",
+            "ret": "i(16-32)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vnavg_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vnavg{0.data_type}{0.width_suffix}",
+            "ret": "u8",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vnormamt_V{1.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vnormamt{0.data_type}{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0"]
+        },
+        {
+            "intrinsic": "V_vnot_VV{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vnot{0.width_suffix}",
+            "ret": "u16",
+            "args": ["0"]
+        },
+        {
+            "intrinsic": "V_vor_VV{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vor{0.width_suffix}",
+            "ret": "u16",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vpacke_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vpack{1.data_type}e{0.width_suffix}",
+            "ret": "s(8-16)",
+            "args": ["0hw", "0hw"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vpacko_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vpack{1.data_type}o{0.width_suffix}",
+            "ret": "s(8-16)",
+            "args": ["0hw", "0hw"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vpack_V{1.data_type}V{2.data_type}_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vpack{1.data_type}{0.data_type}.sat{0.width_suffix}",
+            "ret": "i(8-16)",
+            "args": ["0hws", "0hws"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vpopcount_V{1.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vpopcount{0.data_type}{0.width_suffix}",
+            "ret": "s16",
+            "args": ["0"]
+        },
+        {
+            "intrinsic": "V_vrdelta_VV{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vrdelta{0.width_suffix}",
+            "ret": "u8",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vrmpy_V{1.data_type}Rb{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vrmpybus{0.width_suffix}",
+            "ret": "s32",
+            "args": ["u8", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vrmpyacc_V{1.data_type}V{2.data_type}Rb{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vrmpybus.acc{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "u8", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vrmpy_W{1.data_type}RbI{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vrmpybusi{0.widthd_suffix}",
+            "ret": "s32d",
+            "args": ["u8d", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vrmpyacc_W{1.data_type}W{2.data_type}RbI{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vrmpybusi.acc{0.widthd_suffix}",
+            "ret": "s32d",
+            "args": ["0", "u8d", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vrmpy_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vrmpybusv{0.width_suffix}",
+            "ret": "s32",
+            "args": ["u8", "s8"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vrmpyacc_V{1.data_type}V{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vrmpybusv.acc{0.width_suffix}",
+            "ret": "s32",
+            "args": ["0", "u8", "s8"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vrmpy_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vrmpy{1.data_type}v{0.width_suffix}",
+            "ret": "i32",
+            "args": ["0nndd", "0nndd"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vrmpyacc_V{1.data_type}V{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vrmpy{1.data_type}v.acc{0.width_suffix}",
+            "ret": "i32",
+            "args": ["0", "0nndd", "0nndd"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vrmpy_V{1.data_type}Rub{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vrmpyub{0.width_suffix}",
+            "ret": "u32",
+            "args": ["u8", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vrmpyacc_V{1.data_type}V{2.data_type}Rub{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vrmpyub.acc{0.width_suffix}",
+            "ret": "u32",
+            "args": ["0", "u8", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vrmpy_W{1.data_type}RubI{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vrmpyubi{0.widthd_suffix}",
+            "ret": "u32d",
+            "args": ["u8d", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vrmpyacc_W{1.data_type}W{2.data_type}RubI{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vrmpyubi.acc{0.widthd_suffix}",
+            "ret": "u32d",
+            "args": ["0", "u8d", "U32"]
+        },
+        {
+            "intrinsic": "V_vror_VR{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vror{0.width_suffix}",
+            "ret": "u8",
+            "args": ["0", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vround_V{1.data_type}V{2.data_type}_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vround{1.data_type}{0.data_type}{0.width_suffix}",
+            "ret": "i(8-16)",
+            "args": ["0hws", "0hws"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vrsad_W{1.data_type}RubI{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vrsadubi{0.widthd_suffix}",
+            "ret": "u32d",
+            "args": ["u8d", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vrsadacc_W{1.data_type}W{2.data_type}RubI{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vrsadubi.acc{0.widthd_suffix}",
+            "ret": "u32d",
+            "args": ["0", "u8d", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vsat_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vsat{1.data_type}{0.data_type}{0.width_suffix}",
+            "ret": "u8",
+            "args": ["0hws", "0hws"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vsat_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vsat{1.data_type}{0.data_type}{0.width_suffix}",
+            "ret": "s16",
+            "args": ["0hw", "0hw"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vsxt_V{1.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vs{1.data_type}{0.widthd_suffix}",
+            "ret": "s(16-32)d",
+            "args": ["0n"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vzxt_V{1.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vz{1.data_type_plain}{0.widthd_suffix}",
+            "ret": "u(16-32)d",
+            "args": ["0n"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_condacc_QV{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vadd{0.data_type}q{0.width_suffix}",
+            "ret": "s(8-32)",
+            "args": ["u32hhh", "0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_condacc_QnV{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vadd{0.data_type}nq{0.width_suffix}",
+            "ret": "s(8-32)",
+            "args": ["u32hhh", "0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_condnac_QV{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vsub{0.data_type}q{0.width_suffix}",
+            "ret": "s(8-32)",
+            "args": ["u32hhh", "0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_condnac_QnV{2.data_type}V{3.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vsub{0.data_type}nq{0.width_suffix}",
+            "ret": "s(8-32)",
+            "args": ["u32hhh", "0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vshuffe_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vshufe{1.data_type}{0.width_suffix}",
+            "ret": "s16",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vshuffo_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vshufo{1.data_type}{0.width_suffix}",
+            "ret": "s16",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vshuff_V{1.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vshuff{1.data_type}{0.width_suffix}",
+            "ret": "s(8-16)",
+            "args": ["0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vshuffe_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vshuffe{1.data_type}{0.width_suffix}",
+            "ret": "s8",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vshuffo_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vshuffo{1.data_type}{0.width_suffix}",
+            "ret": "s8",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vshuffoe_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vshuffoe{1.data_type}{0.width_suffix}",
+            "ret": "s(8-16)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "W_vshuff_VVR{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vshufvvd{0.widthd_suffix}",
+            "ret": "u8d",
+            "args": ["0h", "0h", "U32"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vsub_V{1.data_type}V{2.data_type}{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vsub{0.data_type}{0.width_suffix}",
+            "ret": "s(8-32)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vsub_V{1.data_type}V{2.data_type}_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vsub{0.data_type}sat{0.width_suffix}",
+            "ret": "s(16-32)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "V{0.data_type}_vsub_V{1.data_type}V{2.data_type}_sat{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vsub{0.data_type}sat{0.width_suffix}",
+            "ret": "u(8-16)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vsub_W{1.data_type}W{2.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vsub{0.data_type}.dv{0.widthd_suffix}",
+            "ret": "s(8-32)d",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vsub_W{1.data_type}W{2.data_type}_sat{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vsub{0.data_type}sat.dv{0.widthd_suffix}",
+            "ret": "s(16-32)d",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vsub_W{1.data_type}W{2.data_type}_sat{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vsub{0.data_type}sat.dv{0.widthd_suffix}",
+            "ret": "u(8-16)d",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "W_vswap_QVV{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vswap{0.widthd_suffix}",
+            "ret": "u8d",
+            "args": ["u32hhh", "0h", "0h"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vtmpy_W{1.data_type}Rb{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vtmpyb{0.widthd_suffix}",
+            "ret": "s16d",
+            "args": ["0nd", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vtmpyacc_W{1.data_type}W{2.data_type}Rb{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vtmpyb.acc{0.widthd_suffix}",
+            "ret": "s16d",
+            "args": ["0", "0nd", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vtmpy_W{1.data_type}Rb{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vtmpybus{0.widthd_suffix}",
+            "ret": "s16d",
+            "args": ["u8d", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vtmpyacc_W{1.data_type}W{2.data_type}Rb{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vtmpybus.acc{0.widthd_suffix}",
+            "ret": "s16d",
+            "args": ["0", "u8d", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vtmpy_W{1.data_type}Rb{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vtmpyhb{0.widthd_suffix}",
+            "ret": "s32d",
+            "args": ["0nd", "U32"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vunpack_V{1.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vunpack{1.data_type}{0.widthd_suffix}",
+            "ret": "i(16-32)d",
+            "args": ["0n"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vunpackoor_W{1.data_type}V{2.data_type}{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vunpacko{2.data_type}{0.widthd_suffix}",
+            "ret": "s(16-32)d",
+            "args": ["0", "0n"]
+        },
+        {
+            "intrinsic": "W{0.data_type}_vtmpyacc_W{1.data_type}W{2.data_type}Rb{0.widthd_b}",
+            "width": [512, 1024],
+            "llvm": "vtmpyhb.acc{0.widthd_suffix}",
+            "ret": "s32d",
+            "args": ["0", "0nd", "U32"]
+        },
+        {
+            "intrinsic": "V_vxor_VV{0.width_b}",
+            "width": [512, 1024],
+            "llvm": "vxor{0.width_suffix}",
+            "ret": "u16",
+            "args": ["0", "0"]
+        }
+    ]
+}
diff --git a/src/grammar/.gitignore b/src/grammar/.gitignore
new file mode 100644 (file)
index 0000000..3e44987
--- /dev/null
@@ -0,0 +1,3 @@
+*.class
+*.java
+*.tokens
diff --git a/src/grammar/lexer.l b/src/grammar/lexer.l
new file mode 100644 (file)
index 0000000..77737c9
--- /dev/null
@@ -0,0 +1,343 @@
+%{
+// 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.
+
+#include <stdio.h>
+#include <ctype.h>
+
+static int num_hashes;
+static int end_hashes;
+static int saw_non_hash;
+
+%}
+
+%option stack
+%option yylineno
+
+%x str
+%x rawstr
+%x rawstr_esc_begin
+%x rawstr_esc_body
+%x rawstr_esc_end
+%x byte
+%x bytestr
+%x rawbytestr
+%x rawbytestr_nohash
+%x pound
+%x shebang_or_attr
+%x ltorchar
+%x linecomment
+%x doc_line
+%x blockcomment
+%x doc_block
+%x suffix
+
+ident [a-zA-Z\x80-\xff_][a-zA-Z0-9\x80-\xff_]*
+
+%%
+
+<suffix>{ident}            { BEGIN(INITIAL); }
+<suffix>(.|\n)  { yyless(0); BEGIN(INITIAL); }
+
+[ \n\t\r]             { }
+
+\xef\xbb\xbf {
+  // UTF-8 byte order mark (BOM), ignore if in line 1, error otherwise
+  if (yyget_lineno() != 1) {
+    return -1;
+  }
+}
+
+\/\/(\/|\!)           { BEGIN(doc_line); yymore(); }
+<doc_line>\n          { BEGIN(INITIAL);
+                        yyleng--;
+                        yytext[yyleng] = 0;
+                        return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT);
+                      }
+<doc_line>[^\n]*      { yymore(); }
+
+\/\/|\/\/\/\/         { BEGIN(linecomment); }
+<linecomment>\n       { BEGIN(INITIAL); }
+<linecomment>[^\n]*   { }
+
+\/\*(\*|\!)[^*]       { yy_push_state(INITIAL); yy_push_state(doc_block); yymore(); }
+<doc_block>\/\*       { yy_push_state(doc_block); yymore(); }
+<doc_block>\*\/       {
+    yy_pop_state();
+    if (yy_top_state() == doc_block) {
+        yymore();
+    } else {
+        return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT);
+    }
+}
+<doc_block>(.|\n)     { yymore(); }
+
+\/\*                  { yy_push_state(blockcomment); }
+<blockcomment>\/\*    { yy_push_state(blockcomment); }
+<blockcomment>\*\/    { yy_pop_state(); }
+<blockcomment>(.|\n)   { }
+
+_        { return UNDERSCORE; }
+as       { return AS; }
+box      { return BOX; }
+break    { return BREAK; }
+const    { return CONST; }
+continue { return CONTINUE; }
+crate    { return CRATE; }
+else     { return ELSE; }
+enum     { return ENUM; }
+extern   { return EXTERN; }
+false    { return FALSE; }
+fn       { return FN; }
+for      { return FOR; }
+if       { return IF; }
+impl     { return IMPL; }
+in       { return IN; }
+let      { return LET; }
+loop     { return LOOP; }
+match    { return MATCH; }
+mod      { return MOD; }
+move     { return MOVE; }
+mut      { return MUT; }
+priv     { return PRIV; }
+proc     { return PROC; }
+pub      { return PUB; }
+ref      { return REF; }
+return   { return RETURN; }
+self     { return SELF; }
+static   { return STATIC; }
+struct   { return STRUCT; }
+trait    { return TRAIT; }
+true     { return TRUE; }
+type     { return TYPE; }
+typeof   { return TYPEOF; }
+unsafe   { return UNSAFE; }
+use      { return USE; }
+where    { return WHERE; }
+while    { return WHILE; }
+
+{ident}  { return IDENT; }
+
+0x[0-9a-fA-F_]+                                    { BEGIN(suffix); return LIT_INTEGER; }
+0o[0-8_]+                                          { BEGIN(suffix); return LIT_INTEGER; }
+0b[01_]+                                           { BEGIN(suffix); return LIT_INTEGER; }
+[0-9][0-9_]*                                       { BEGIN(suffix); return LIT_INTEGER; }
+[0-9][0-9_]*\.(\.|[a-zA-Z])    { yyless(yyleng - 2); BEGIN(suffix); return LIT_INTEGER; }
+
+[0-9][0-9_]*\.[0-9_]*([eE][-\+]?[0-9_]+)?          { BEGIN(suffix); return LIT_FLOAT; }
+[0-9][0-9_]*(\.[0-9_]*)?[eE][-\+]?[0-9_]+          { BEGIN(suffix); return LIT_FLOAT; }
+
+;      { return ';'; }
+,      { return ','; }
+\.\.\. { return DOTDOTDOT; }
+\.\.   { return DOTDOT; }
+\.     { return '.'; }
+\(     { return '('; }
+\)     { return ')'; }
+\{     { return '{'; }
+\}     { return '}'; }
+\[     { return '['; }
+\]     { return ']'; }
+@      { return '@'; }
+#      { BEGIN(pound); yymore(); }
+<pound>\! { BEGIN(shebang_or_attr); yymore(); }
+<shebang_or_attr>\[ {
+  BEGIN(INITIAL);
+  yyless(2);
+  return SHEBANG;
+}
+<shebang_or_attr>[^\[\n]*\n {
+  // Since the \n was eaten as part of the token, yylineno will have
+  // been incremented to the value 2 if the shebang was on the first
+  // line. This yyless undoes that, setting yylineno back to 1.
+  yyless(yyleng - 1);
+  if (yyget_lineno() == 1) {
+    BEGIN(INITIAL);
+    return SHEBANG_LINE;
+  } else {
+    BEGIN(INITIAL);
+    yyless(2);
+    return SHEBANG;
+  }
+}
+<pound>. { BEGIN(INITIAL); yyless(1); return '#'; }
+
+\~     { return '~'; }
+::     { return MOD_SEP; }
+:      { return ':'; }
+\$     { return '$'; }
+\?     { return '?'; }
+
+==    { return EQEQ; }
+=>    { return FAT_ARROW; }
+=     { return '='; }
+\!=   { return NE; }
+\!    { return '!'; }
+\<=   { return LE; }
+\<\<  { return SHL; }
+\<\<= { return SHLEQ; }
+\<    { return '<'; }
+\>=   { return GE; }
+\>\>  { return SHR; }
+\>\>= { return SHREQ; }
+\>    { return '>'; }
+
+\x27                                  { BEGIN(ltorchar); yymore(); }
+<ltorchar>static                      { BEGIN(INITIAL); return STATIC_LIFETIME; }
+<ltorchar>{ident}                     { BEGIN(INITIAL); return LIFETIME; }
+<ltorchar>\\[nrt\\\x27\x220]\x27      { BEGIN(suffix); return LIT_CHAR; }
+<ltorchar>\\x[0-9a-fA-F]{2}\x27       { BEGIN(suffix); return LIT_CHAR; }
+<ltorchar>\\u\{[0-9a-fA-F]?{6}\}\x27  { BEGIN(suffix); return LIT_CHAR; }
+<ltorchar>.\x27                       { BEGIN(suffix); return LIT_CHAR; }
+<ltorchar>[\x80-\xff]{2,4}\x27        { BEGIN(suffix); return LIT_CHAR; }
+<ltorchar><<EOF>>                     { BEGIN(INITIAL); return -1; }
+
+b\x22              { BEGIN(bytestr); yymore(); }
+<bytestr>\x22      { BEGIN(suffix); return LIT_BYTE_STR; }
+
+<bytestr><<EOF>>                { return -1; }
+<bytestr>\\[n\nrt\\\x27\x220]   { yymore(); }
+<bytestr>\\x[0-9a-fA-F]{2}      { yymore(); }
+<bytestr>\\u\{[0-9a-fA-F]?{6}\} { yymore(); }
+<bytestr>\\[^n\nrt\\\x27\x220]  { return -1; }
+<bytestr>(.|\n)                 { yymore(); }
+
+br\x22                      { BEGIN(rawbytestr_nohash); yymore(); }
+<rawbytestr_nohash>\x22     { BEGIN(suffix); return LIT_BYTE_STR_RAW; }
+<rawbytestr_nohash>(.|\n)   { yymore(); }
+<rawbytestr_nohash><<EOF>>  { return -1; }
+
+br/# {
+    BEGIN(rawbytestr);
+    yymore();
+    num_hashes = 0;
+    saw_non_hash = 0;
+    end_hashes = 0;
+}
+<rawbytestr># {
+    if (!saw_non_hash) {
+        num_hashes++;
+    } else if (end_hashes != 0) {
+        end_hashes++;
+        if (end_hashes == num_hashes) {
+            BEGIN(INITIAL);
+            return LIT_BYTE_STR_RAW;
+        }
+    }
+    yymore();
+}
+<rawbytestr>\x22# {
+    end_hashes = 1;
+    if (end_hashes == num_hashes) {
+        BEGIN(INITIAL);
+        return LIT_BYTE_STR_RAW;
+    }
+    yymore();
+}
+<rawbytestr>(.|\n) {
+    if (!saw_non_hash) {
+        saw_non_hash = 1;
+    }
+    if (end_hashes != 0) {
+        end_hashes = 0;
+    }
+    yymore();
+}
+<rawbytestr><<EOF>> { return -1; }
+
+b\x27                        { BEGIN(byte); yymore(); }
+<byte>\\[nrt\\\x27\x220]\x27 { BEGIN(INITIAL); return LIT_BYTE; }
+<byte>\\x[0-9a-fA-F]{2}\x27  { BEGIN(INITIAL); return LIT_BYTE; }
+<byte>\\u[0-9a-fA-F]{4}\x27  { BEGIN(INITIAL); return LIT_BYTE; }
+<byte>\\U[0-9a-fA-F]{8}\x27  { BEGIN(INITIAL); return LIT_BYTE; }
+<byte>.\x27                  { BEGIN(INITIAL); return LIT_BYTE; }
+<byte><<EOF>>                { BEGIN(INITIAL); return -1; }
+
+r\x22           { BEGIN(rawstr); yymore(); }
+<rawstr>\x22    { BEGIN(suffix); return LIT_STR_RAW; }
+<rawstr>(.|\n)  { yymore(); }
+<rawstr><<EOF>> { return -1; }
+
+r/#             {
+    BEGIN(rawstr_esc_begin);
+    yymore();
+    num_hashes = 0;
+    saw_non_hash = 0;
+    end_hashes = 0;
+}
+
+<rawstr_esc_begin># {
+    num_hashes++;
+    yymore();
+}
+<rawstr_esc_begin>\x22 {
+    BEGIN(rawstr_esc_body);
+    yymore();
+}
+<rawstr_esc_begin>(.|\n) { return -1; }
+
+<rawstr_esc_body>\x22/# {
+  BEGIN(rawstr_esc_end);
+  yymore();
+ }
+<rawstr_esc_body>(.|\n) {
+  yymore();
+ }
+
+<rawstr_esc_end># {
+  end_hashes++;
+  if (end_hashes == num_hashes) {
+    BEGIN(INITIAL);
+    return LIT_STR_RAW;
+  }
+  yymore();
+ }
+<rawstr_esc_end>[^#] {
+  end_hashes = 0;
+  BEGIN(rawstr_esc_body);
+  yymore();
+ }
+
+<rawstr_esc_begin,rawstr_esc_body,rawstr_esc_end><<EOF>> { return -1; }
+
+\x22                     { BEGIN(str); yymore(); }
+<str>\x22                { BEGIN(suffix); return LIT_STR; }
+
+<str><<EOF>>                { return -1; }
+<str>\\[n\nr\rt\\\x27\x220] { yymore(); }
+<str>\\x[0-9a-fA-F]{2}      { yymore(); }
+<str>\\u\{[0-9a-fA-F]?{6}\} { yymore(); }
+<str>\\[^n\nrt\\\x27\x220]  { return -1; }
+<str>(.|\n)                 { yymore(); }
+
+\<-  { return LARROW; }
+-\>  { return RARROW; }
+-    { return '-'; }
+-=   { return MINUSEQ; }
+&&   { return ANDAND; }
+&    { return '&'; }
+&=   { return ANDEQ; }
+\|\| { return OROR; }
+\|   { return '|'; }
+\|=  { return OREQ; }
+\+   { return '+'; }
+\+=  { return PLUSEQ; }
+\*   { return '*'; }
+\*=  { return STAREQ; }
+\/   { return '/'; }
+\/=  { return SLASHEQ; }
+\^   { return '^'; }
+\^=  { return CARETEQ; }
+%    { return '%'; }
+%=   { return PERCENTEQ; }
+
+<<EOF>> { return 0; }
+
+%%
diff --git a/src/grammar/parser-lalr-main.c b/src/grammar/parser-lalr-main.c
new file mode 100644 (file)
index 0000000..db88a1f
--- /dev/null
@@ -0,0 +1,203 @@
+// 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.
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern int yylex();
+extern int rsparse();
+
+#define PUSHBACK_LEN 4
+
+static char pushback[PUSHBACK_LEN];
+static int verbose;
+
+void print(const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  if (verbose) {
+    vprintf(format, args);
+  }
+  va_end(args);
+}
+
+// If there is a non-null char at the head of the pushback queue,
+// dequeue it and shift the rest of the queue forwards. Otherwise,
+// return the token from calling yylex.
+int rslex() {
+  if (pushback[0] == '\0') {
+    return yylex();
+  } else {
+    char c = pushback[0];
+    memmove(pushback, pushback + 1, PUSHBACK_LEN - 1);
+    pushback[PUSHBACK_LEN - 1] = '\0';
+    return c;
+  }
+}
+
+// Note: this does nothing if the pushback queue is full. As long as
+// there aren't more than PUSHBACK_LEN consecutive calls to push_back
+// in an action, this shouldn't be a problem.
+void push_back(char c) {
+  for (int i = 0; i < PUSHBACK_LEN; ++i) {
+    if (pushback[i] == '\0') {
+      pushback[i] = c;
+      break;
+    }
+  }
+}
+
+extern int rsdebug;
+
+struct node {
+  struct node *next;
+  struct node *prev;
+  int own_string;
+  char const *name;
+  int n_elems;
+  struct node *elems[];
+};
+
+struct node *nodes = NULL;
+int n_nodes;
+
+struct node *mk_node(char const *name, int n, ...) {
+  va_list ap;
+  int i = 0;
+  unsigned sz = sizeof(struct node) + (n * sizeof(struct node *));
+  struct node *nn, *nd = (struct node *)malloc(sz);
+
+  print("# New %d-ary node: %s = %p\n", n, name, nd);
+
+  nd->own_string = 0;
+  nd->prev = NULL;
+  nd->next = nodes;
+  if (nodes) {
+    nodes->prev = nd;
+  }
+  nodes = nd;
+
+  nd->name = name;
+  nd->n_elems = n;
+
+  va_start(ap, n);
+  while (i < n) {
+    nn = va_arg(ap, struct node *);
+    print("#   arg[%d]: %p\n", i, nn);
+    print("#            (%s ...)\n", nn->name);
+    nd->elems[i++] = nn;
+  }
+  va_end(ap);
+  n_nodes++;
+  return nd;
+}
+
+struct node *mk_atom(char *name) {
+  struct node *nd = mk_node((char const *)strdup(name), 0);
+  nd->own_string = 1;
+  return nd;
+}
+
+struct node *mk_none() {
+  return mk_atom("<none>");
+}
+
+struct node *ext_node(struct node *nd, int n, ...) {
+  va_list ap;
+  int i = 0, c = nd->n_elems + n;
+  unsigned sz = sizeof(struct node) + (c * sizeof(struct node *));
+  struct node *nn;
+
+  print("# Extending %d-ary node by %d nodes: %s = %p",
+        nd->n_elems, c, nd->name, nd);
+
+  if (nd->next) {
+    nd->next->prev = nd->prev;
+  }
+  if (nd->prev) {
+    nd->prev->next = nd->next;
+  }
+  nd = realloc(nd, sz);
+  nd->prev = NULL;
+  nd->next = nodes;
+  nodes->prev = nd;
+  nodes = nd;
+
+  print(" ==> %p\n", nd);
+
+  va_start(ap, n);
+  while (i < n) {
+    nn = va_arg(ap, struct node *);
+    print("#   arg[%d]: %p\n", i, nn);
+    print("#            (%s ...)\n", nn->name);
+    nd->elems[nd->n_elems++] = nn;
+    ++i;
+  }
+  va_end(ap);
+  return nd;
+}
+
+int const indent_step = 4;
+
+void print_indent(int depth) {
+  while (depth) {
+    if (depth-- % indent_step == 0) {
+      print("|");
+    } else {
+      print(" ");
+    }
+  }
+}
+
+void print_node(struct node *n, int depth) {
+  int i = 0;
+  print_indent(depth);
+  if (n->n_elems == 0) {
+    print("%s\n", n->name);
+  } else {
+    print("(%s\n", n->name);
+    for (i = 0; i < n->n_elems; ++i) {
+      print_node(n->elems[i], depth + indent_step);
+    }
+    print_indent(depth);
+    print(")\n");
+  }
+}
+
+int main(int argc, char **argv) {
+  if (argc == 2 && strcmp(argv[1], "-v") == 0) {
+    verbose = 1;
+  } else {
+    verbose = 0;
+  }
+  int ret = 0;
+  struct node *tmp;
+  memset(pushback, '\0', PUSHBACK_LEN);
+  ret = rsparse();
+  print("--- PARSE COMPLETE: ret:%d, n_nodes:%d ---\n", ret, n_nodes);
+  if (nodes) {
+    print_node(nodes, 0);
+  }
+  while (nodes) {
+    tmp = nodes;
+    nodes = tmp->next;
+    if (tmp->own_string) {
+      free((void*)tmp->name);
+    }
+    free(tmp);
+  }
+  return ret;
+}
+
+void rserror(char const *s) {
+  fprintf(stderr, "%s\n", s);
+}
diff --git a/src/grammar/parser-lalr.y b/src/grammar/parser-lalr.y
new file mode 100644 (file)
index 0000000..c9fcdf7
--- /dev/null
@@ -0,0 +1,1945 @@
+// 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.
+
+%{
+#define YYERROR_VERBOSE
+#define YYSTYPE struct node *
+struct node;
+extern int yylex();
+extern void yyerror(char const *s);
+extern struct node *mk_node(char const *name, int n, ...);
+extern struct node *mk_atom(char *text);
+extern struct node *mk_none();
+extern struct node *ext_node(struct node *nd, int n, ...);
+extern void push_back(char c);
+extern char *yytext;
+%}
+%debug
+
+%token SHL
+%token SHR
+%token LE
+%token EQEQ
+%token NE
+%token GE
+%token ANDAND
+%token OROR
+%token SHLEQ
+%token SHREQ
+%token MINUSEQ
+%token ANDEQ
+%token OREQ
+%token PLUSEQ
+%token STAREQ
+%token SLASHEQ
+%token CARETEQ
+%token PERCENTEQ
+%token DOTDOT
+%token DOTDOTDOT
+%token MOD_SEP
+%token RARROW
+%token LARROW
+%token FAT_ARROW
+%token LIT_BYTE
+%token LIT_CHAR
+%token LIT_INTEGER
+%token LIT_FLOAT
+%token LIT_STR
+%token LIT_STR_RAW
+%token LIT_BYTE_STR
+%token LIT_BYTE_STR_RAW
+%token IDENT
+%token UNDERSCORE
+%token LIFETIME
+
+// keywords
+%token SELF
+%token STATIC
+%token AS
+%token BREAK
+%token CRATE
+%token ELSE
+%token ENUM
+%token EXTERN
+%token FALSE
+%token FN
+%token FOR
+%token IF
+%token IMPL
+%token IN
+%token LET
+%token LOOP
+%token MATCH
+%token MOD
+%token MOVE
+%token MUT
+%token PRIV
+%token PUB
+%token REF
+%token RETURN
+%token STRUCT
+%token TRUE
+%token TRAIT
+%token TYPE
+%token UNSAFE
+%token DEFAULT
+%token USE
+%token WHILE
+%token CONTINUE
+%token PROC
+%token BOX
+%token CONST
+%token WHERE
+%token TYPEOF
+%token INNER_DOC_COMMENT
+%token OUTER_DOC_COMMENT
+
+%token SHEBANG
+%token SHEBANG_LINE
+%token STATIC_LIFETIME
+
+ /*
+   Quoting from the Bison manual:
+
+   "Finally, the resolution of conflicts works by comparing the precedence
+   of the rule being considered with that of the lookahead token. If the
+   token's precedence is higher, the choice is to shift. If the rule's
+   precedence is higher, the choice is to reduce. If they have equal
+   precedence, the choice is made based on the associativity of that
+   precedence level. The verbose output file made by ‘-v’ (see Invoking
+   Bison) says how each conflict was resolved"
+ */
+
+// We expect no shift/reduce or reduce/reduce conflicts in this grammar;
+// all potential ambiguities are scrutinized and eliminated manually.
+%expect 0
+
+// fake-precedence symbol to cause '|' bars in lambda context to parse
+// at low precedence, permit things like |x| foo = bar, where '=' is
+// otherwise lower-precedence than '|'. Also used for proc() to cause
+// things like proc() a + b to parse as proc() { a + b }.
+%precedence LAMBDA
+
+%precedence SELF
+
+// MUT should be lower precedence than IDENT so that in the pat rule,
+// "& MUT pat" has higher precedence than "binding_mode ident [@ pat]"
+%precedence MUT
+
+// IDENT needs to be lower than '{' so that 'foo {' is shifted when
+// trying to decide if we've got a struct-construction expr (esp. in
+// contexts like 'if foo { .')
+//
+// IDENT also needs to be lower precedence than '<' so that '<' in
+// 'foo:bar . <' is shifted (in a trait reference occurring in a
+// bounds list), parsing as foo:(bar<baz>) rather than (foo:bar)<baz>.
+%precedence IDENT
+
+// A couple fake-precedence symbols to use in rules associated with +
+// and < in trailing type contexts. These come up when you have a type
+// in the RHS of operator-AS, such as "foo as bar<baz>". The "<" there
+// has to be shifted so the parser keeps trying to parse a type, even
+// though it might well consider reducing the type "bar" and then
+// going on to "<" as a subsequent binop. The "+" case is with
+// trailing type-bounds ("foo as bar:A+B"), for the same reason.
+%precedence SHIFTPLUS
+
+%precedence MOD_SEP
+%precedence RARROW ':'
+
+// In where clauses, "for" should have greater precedence when used as
+// a higher ranked constraint than when used as the beginning of a
+// for_in_type (which is a ty)
+%precedence FORTYPE
+%precedence FOR
+
+// Binops & unops, and their precedences
+%precedence BOX
+%precedence BOXPLACE
+%nonassoc DOTDOT
+
+// RETURN needs to be lower-precedence than tokens that start
+// prefix_exprs
+%precedence RETURN
+
+%right '=' SHLEQ SHREQ MINUSEQ ANDEQ OREQ PLUSEQ STAREQ SLASHEQ CARETEQ PERCENTEQ
+%right LARROW
+%left OROR
+%left ANDAND
+%left EQEQ NE
+%left '<' '>' LE GE
+%left '|'
+%left '^'
+%left '&'
+%left SHL SHR
+%left '+' '-'
+%precedence AS
+%left '*' '/' '%'
+%precedence '!'
+
+%precedence '{' '[' '(' '.'
+
+%precedence RANGE
+
+%start crate
+
+%%
+
+////////////////////////////////////////////////////////////////////////
+// Part 1: Items and attributes
+////////////////////////////////////////////////////////////////////////
+
+crate
+: maybe_shebang inner_attrs maybe_mod_items  { mk_node("crate", 2, $2, $3); }
+| maybe_shebang maybe_mod_items  { mk_node("crate", 1, $2); }
+;
+
+maybe_shebang
+: SHEBANG_LINE
+| %empty
+;
+
+maybe_inner_attrs
+: inner_attrs
+| %empty                   { $$ = mk_none(); }
+;
+
+inner_attrs
+: inner_attr               { $$ = mk_node("InnerAttrs", 1, $1); }
+| inner_attrs inner_attr   { $$ = ext_node($1, 1, $2); }
+;
+
+inner_attr
+: SHEBANG '[' meta_item ']'   { $$ = mk_node("InnerAttr", 1, $3); }
+| INNER_DOC_COMMENT           { $$ = mk_node("InnerAttr", 1, mk_node("doc-comment", 1, mk_atom(yytext))); }
+;
+
+maybe_outer_attrs
+: outer_attrs
+| %empty                   { $$ = mk_none(); }
+;
+
+outer_attrs
+: outer_attr               { $$ = mk_node("OuterAttrs", 1, $1); }
+| outer_attrs outer_attr   { $$ = ext_node($1, 1, $2); }
+;
+
+outer_attr
+: '#' '[' meta_item ']'    { $$ = $3; }
+| OUTER_DOC_COMMENT        { $$ = mk_node("doc-comment", 1, mk_atom(yytext)); }
+;
+
+meta_item
+: ident                      { $$ = mk_node("MetaWord", 1, $1); }
+| ident '=' lit              { $$ = mk_node("MetaNameValue", 2, $1, $3); }
+| ident '(' meta_seq ')'     { $$ = mk_node("MetaList", 2, $1, $3); }
+| ident '(' meta_seq ',' ')' { $$ = mk_node("MetaList", 2, $1, $3); }
+;
+
+meta_seq
+: %empty                   { $$ = mk_none(); }
+| meta_item                { $$ = mk_node("MetaItems", 1, $1); }
+| meta_seq ',' meta_item   { $$ = ext_node($1, 1, $3); }
+;
+
+maybe_mod_items
+: mod_items
+| %empty             { $$ = mk_none(); }
+;
+
+mod_items
+: mod_item                               { $$ = mk_node("Items", 1, $1); }
+| mod_items mod_item                     { $$ = ext_node($1, 1, $2); }
+;
+
+attrs_and_vis
+: maybe_outer_attrs visibility           { $$ = mk_node("AttrsAndVis", 2, $1, $2); }
+;
+
+mod_item
+: attrs_and_vis item    { $$ = mk_node("Item", 2, $1, $2); }
+;
+
+// items that can appear outside of a fn block
+item
+: stmt_item
+| item_macro
+;
+
+// items that can appear in "stmts"
+stmt_item
+: item_static
+| item_const
+| item_type
+| block_item
+| view_item
+;
+
+item_static
+: STATIC ident ':' ty '=' expr ';'  { $$ = mk_node("ItemStatic", 3, $2, $4, $6); }
+| STATIC MUT ident ':' ty '=' expr ';'  { $$ = mk_node("ItemStatic", 3, $3, $5, $7); }
+;
+
+item_const
+: CONST ident ':' ty '=' expr ';'  { $$ = mk_node("ItemConst", 3, $2, $4, $6); }
+;
+
+item_macro
+: path_expr '!' maybe_ident parens_delimited_token_trees ';'  { $$ = mk_node("ItemMacro", 3, $1, $3, $4); }
+| path_expr '!' maybe_ident braces_delimited_token_trees      { $$ = mk_node("ItemMacro", 3, $1, $3, $4); }
+| path_expr '!' maybe_ident brackets_delimited_token_trees ';'{ $$ = mk_node("ItemMacro", 3, $1, $3, $4); }
+;
+
+view_item
+: use_item
+| extern_fn_item
+| EXTERN CRATE ident ';'                      { $$ = mk_node("ViewItemExternCrate", 1, $3); }
+| EXTERN CRATE ident AS ident ';'             { $$ = mk_node("ViewItemExternCrate", 2, $3, $5); }
+;
+
+extern_fn_item
+: EXTERN maybe_abi item_fn                    { $$ = mk_node("ViewItemExternFn", 2, $2, $3); }
+;
+
+use_item
+: USE view_path ';'                           { $$ = mk_node("ViewItemUse", 1, $2); }
+;
+
+view_path
+: path_no_types_allowed                                    { $$ = mk_node("ViewPathSimple", 1, $1); }
+| path_no_types_allowed MOD_SEP '{'                '}'     { $$ = mk_node("ViewPathList", 2, $1, mk_atom("ViewPathListEmpty")); }
+|                       MOD_SEP '{'                '}'     { $$ = mk_node("ViewPathList", 1, mk_atom("ViewPathListEmpty")); }
+| path_no_types_allowed MOD_SEP '{' idents_or_self '}'     { $$ = mk_node("ViewPathList", 2, $1, $4); }
+|                       MOD_SEP '{' idents_or_self '}'     { $$ = mk_node("ViewPathList", 1, $3); }
+| path_no_types_allowed MOD_SEP '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 2, $1, $4); }
+|                       MOD_SEP '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 1, $3); }
+| path_no_types_allowed MOD_SEP '*'                        { $$ = mk_node("ViewPathGlob", 1, $1); }
+|                               '{'                '}'     { $$ = mk_atom("ViewPathListEmpty"); }
+|                               '{' idents_or_self '}'     { $$ = mk_node("ViewPathList", 1, $2); }
+|                               '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 1, $2); }
+| path_no_types_allowed AS ident                           { $$ = mk_node("ViewPathSimple", 2, $1, $3); }
+;
+
+block_item
+: item_fn
+| item_unsafe_fn
+| item_mod
+| item_foreign_mod          { $$ = mk_node("ItemForeignMod", 1, $1); }
+| item_struct
+| item_enum
+| item_trait
+| item_impl
+;
+
+maybe_ty_ascription
+: ':' ty_sum { $$ = $2; }
+| %empty { $$ = mk_none(); }
+;
+
+maybe_init_expr
+: '=' expr { $$ = $2; }
+| %empty   { $$ = mk_none(); }
+;
+
+// structs
+item_struct
+: STRUCT ident generic_params maybe_where_clause struct_decl_args
+{
+  $$ = mk_node("ItemStruct", 4, $2, $3, $4, $5);
+}
+| STRUCT ident generic_params struct_tuple_args maybe_where_clause ';'
+{
+  $$ = mk_node("ItemStruct", 4, $2, $3, $4, $5);
+}
+| STRUCT ident generic_params maybe_where_clause ';'
+{
+  $$ = mk_node("ItemStruct", 3, $2, $3, $4);
+}
+;
+
+struct_decl_args
+: '{' struct_decl_fields '}'                  { $$ = $2; }
+| '{' struct_decl_fields ',' '}'              { $$ = $2; }
+;
+
+struct_tuple_args
+: '(' struct_tuple_fields ')'                 { $$ = $2; }
+| '(' struct_tuple_fields ',' ')'             { $$ = $2; }
+;
+
+struct_decl_fields
+: struct_decl_field                           { $$ = mk_node("StructFields", 1, $1); }
+| struct_decl_fields ',' struct_decl_field    { $$ = ext_node($1, 1, $3); }
+| %empty                                      { $$ = mk_none(); }
+;
+
+struct_decl_field
+: attrs_and_vis ident ':' ty_sum              { $$ = mk_node("StructField", 3, $1, $2, $4); }
+;
+
+struct_tuple_fields
+: struct_tuple_field                          { $$ = mk_node("StructFields", 1, $1); }
+| struct_tuple_fields ',' struct_tuple_field  { $$ = ext_node($1, 1, $3); }
+;
+
+struct_tuple_field
+: attrs_and_vis ty_sum                    { $$ = mk_node("StructField", 2, $1, $2); }
+;
+
+// enums
+item_enum
+: ENUM ident generic_params maybe_where_clause '{' enum_defs '}'     { $$ = mk_node("ItemEnum", 0); }
+| ENUM ident generic_params maybe_where_clause '{' enum_defs ',' '}' { $$ = mk_node("ItemEnum", 0); }
+;
+
+enum_defs
+: enum_def               { $$ = mk_node("EnumDefs", 1, $1); }
+| enum_defs ',' enum_def { $$ = ext_node($1, 1, $3); }
+| %empty                 { $$ = mk_none(); }
+;
+
+enum_def
+: attrs_and_vis ident enum_args { $$ = mk_node("EnumDef", 3, $1, $2, $3); }
+;
+
+enum_args
+: '{' struct_decl_fields '}'     { $$ = mk_node("EnumArgs", 1, $2); }
+| '{' struct_decl_fields ',' '}' { $$ = mk_node("EnumArgs", 1, $2); }
+| '(' maybe_ty_sums ')'          { $$ = mk_node("EnumArgs", 1, $2); }
+| '=' expr                       { $$ = mk_node("EnumArgs", 1, $2); }
+| %empty                         { $$ = mk_none(); }
+;
+
+item_mod
+: MOD ident ';'                                 { $$ = mk_node("ItemMod", 1, $2); }
+| MOD ident '{' maybe_mod_items '}'             { $$ = mk_node("ItemMod", 2, $2, $4); }
+| MOD ident '{' inner_attrs maybe_mod_items '}' { $$ = mk_node("ItemMod", 3, $2, $4, $5); }
+;
+
+item_foreign_mod
+: EXTERN maybe_abi '{' maybe_foreign_items '}'             { $$ = mk_node("ItemForeignMod", 1, $4); }
+| EXTERN maybe_abi '{' inner_attrs maybe_foreign_items '}' { $$ = mk_node("ItemForeignMod", 2, $4, $5); }
+;
+
+maybe_abi
+: str
+| %empty { $$ = mk_none(); }
+;
+
+maybe_foreign_items
+: foreign_items
+| %empty { $$ = mk_none(); }
+;
+
+foreign_items
+: foreign_item               { $$ = mk_node("ForeignItems", 1, $1); }
+| foreign_items foreign_item { $$ = ext_node($1, 1, $2); }
+;
+
+foreign_item
+: attrs_and_vis STATIC item_foreign_static { $$ = mk_node("ForeignItem", 2, $1, $3); }
+| attrs_and_vis item_foreign_fn            { $$ = mk_node("ForeignItem", 2, $1, $2); }
+| attrs_and_vis UNSAFE item_foreign_fn     { $$ = mk_node("ForeignItem", 2, $1, $3); }
+;
+
+item_foreign_static
+: maybe_mut ident ':' ty ';'               { $$ = mk_node("StaticItem", 3, $1, $2, $4); }
+;
+
+item_foreign_fn
+: FN ident generic_params fn_decl_allow_variadic maybe_where_clause ';' { $$ = mk_node("ForeignFn", 4, $2, $3, $4, $5); }
+;
+
+fn_decl_allow_variadic
+: fn_params_allow_variadic ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); }
+;
+
+fn_params_allow_variadic
+: '(' ')'                      { $$ = mk_none(); }
+| '(' params ')'               { $$ = $2; }
+| '(' params ',' ')'           { $$ = $2; }
+| '(' params ',' DOTDOTDOT ')' { $$ = $2; }
+;
+
+visibility
+: PUB      { $$ = mk_atom("Public"); }
+| %empty   { $$ = mk_atom("Inherited"); }
+;
+
+idents_or_self
+: ident_or_self                    { $$ = mk_node("IdentsOrSelf", 1, $1); }
+| ident_or_self AS ident           { $$ = mk_node("IdentsOrSelf", 2, $1, $3); }
+| idents_or_self ',' ident_or_self { $$ = ext_node($1, 1, $3); }
+;
+
+ident_or_self
+: ident
+| SELF  { $$ = mk_atom(yytext); }
+;
+
+item_type
+: TYPE ident generic_params maybe_where_clause '=' ty_sum ';'  { $$ = mk_node("ItemTy", 4, $2, $3, $4, $6); }
+;
+
+for_sized
+: FOR '?' ident { $$ = mk_node("ForSized", 1, $3); }
+| FOR ident '?' { $$ = mk_node("ForSized", 1, $2); }
+| %empty        { $$ = mk_none(); }
+;
+
+item_trait
+: maybe_unsafe TRAIT ident generic_params for_sized maybe_ty_param_bounds maybe_where_clause '{' maybe_trait_items '}'
+{
+  $$ = mk_node("ItemTrait", 7, $1, $3, $4, $5, $6, $7, $9);
+}
+;
+
+maybe_trait_items
+: trait_items
+| %empty { $$ = mk_none(); }
+;
+
+trait_items
+: trait_item               { $$ = mk_node("TraitItems", 1, $1); }
+| trait_items trait_item   { $$ = ext_node($1, 1, $2); }
+;
+
+trait_item
+: trait_const
+| trait_type
+| trait_method
+;
+
+trait_const
+: maybe_outer_attrs CONST ident maybe_ty_ascription maybe_const_default ';' { $$ = mk_node("ConstTraitItem", 4, $1, $3, $4, $5); }
+;
+
+maybe_const_default
+: '=' expr { $$ = mk_node("ConstDefault", 1, $2); }
+| %empty   { $$ = mk_none(); }
+;
+
+trait_type
+: maybe_outer_attrs TYPE ty_param ';' { $$ = mk_node("TypeTraitItem", 2, $1, $3); }
+;
+
+maybe_unsafe
+: UNSAFE { $$ = mk_atom("Unsafe"); }
+| %empty { $$ = mk_none(); }
+;
+
+maybe_default_maybe_unsafe
+: DEFAULT UNSAFE { $$ = mk_atom("DefaultUnsafe"); }
+| DEFAULT        { $$ = mk_atom("Default"); }
+|         UNSAFE { $$ = mk_atom("Unsafe"); }
+| %empty { $$ = mk_none(); }
+
+trait_method
+: type_method { $$ = mk_node("Required", 1, $1); }
+| method      { $$ = mk_node("Provided", 1, $1); }
+;
+
+type_method
+: attrs_and_vis maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';'
+{
+  $$ = mk_node("TypeMethod", 6, $1, $2, $4, $5, $6, $7);
+}
+| attrs_and_vis maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';'
+{
+  $$ = mk_node("TypeMethod", 7, $1, $2, $4, $6, $7, $8, $9);
+}
+;
+
+method
+: attrs_and_vis maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block
+{
+  $$ = mk_node("Method", 7, $1, $2, $4, $5, $6, $7, $8);
+}
+| attrs_and_vis maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block
+{
+  $$ = mk_node("Method", 8, $1, $2, $4, $6, $7, $8, $9, $10);
+}
+;
+
+impl_method
+: attrs_and_vis maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block
+{
+  $$ = mk_node("Method", 7, $1, $2, $4, $5, $6, $7, $8);
+}
+| attrs_and_vis maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block
+{
+  $$ = mk_node("Method", 8, $1, $2, $4, $6, $7, $8, $9, $10);
+}
+;
+
+// There are two forms of impl:
+//
+// impl (<...>)? TY { ... }
+// impl (<...>)? TRAIT for TY { ... }
+//
+// Unfortunately since TY can begin with '<' itself -- as part of a
+// TyQualifiedPath type -- there's an s/r conflict when we see '<' after IMPL:
+// should we reduce one of the early rules of TY (such as maybe_once)
+// or shall we continue shifting into the generic_params list for the
+// impl?
+//
+// The production parser disambiguates a different case here by
+// permitting / requiring the user to provide parens around types when
+// they are ambiguous with traits. We do the same here, regrettably,
+// by splitting ty into ty and ty_prim.
+item_impl
+: maybe_default_maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+{
+  $$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8);
+}
+| maybe_default_maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+{
+  $$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10);
+}
+| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+{
+  $$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10);
+}
+| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+{
+  $$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11);
+}
+| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}'
+{
+  $$ = mk_node("ItemImplDefault", 3, $1, $3, $4);
+}
+| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}'
+{
+  $$ = mk_node("ItemImplDefaultNeg", 3, $1, $3, $4);
+}
+;
+
+maybe_impl_items
+: impl_items
+| %empty { $$ = mk_none(); }
+;
+
+impl_items
+: impl_item               { $$ = mk_node("ImplItems", 1, $1); }
+| impl_item impl_items    { $$ = ext_node($1, 1, $2); }
+;
+
+impl_item
+: impl_method
+| attrs_and_vis item_macro { $$ = mk_node("ImplMacroItem", 2, $1, $2); }
+| impl_const
+| impl_type
+;
+
+impl_const
+: attrs_and_vis item_const { $$ = mk_node("ImplConst", 1, $1, $2); }
+;
+
+impl_type
+: attrs_and_vis TYPE ident generic_params '=' ty_sum ';'  { $$ = mk_node("ImplType", 4, $1, $3, $4, $6); }
+;
+
+item_fn
+: FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block
+{
+  $$ = mk_node("ItemFn", 5, $2, $3, $4, $5, $6);
+}
+;
+
+item_unsafe_fn
+: UNSAFE FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block
+{
+  $$ = mk_node("ItemUnsafeFn", 5, $3, $4, $5, $6, $7);
+}
+| UNSAFE EXTERN maybe_abi FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block
+{
+  $$ = mk_node("ItemUnsafeFn", 6, $3, $5, $6, $7, $8, $9);
+}
+;
+
+fn_decl
+: fn_params ret_ty   { $$ = mk_node("FnDecl", 2, $1, $2); }
+;
+
+fn_decl_with_self
+: fn_params_with_self ret_ty   { $$ = mk_node("FnDecl", 2, $1, $2); }
+;
+
+fn_decl_with_self_allow_anon_params
+: fn_anon_params_with_self ret_ty   { $$ = mk_node("FnDecl", 2, $1, $2); }
+;
+
+fn_params
+: '(' maybe_params ')'  { $$ = $2; }
+;
+
+fn_anon_params
+: '(' anon_param anon_params_allow_variadic_tail ')' { $$ = ext_node($2, 1, $3); }
+| '(' ')'                                            { $$ = mk_none(); }
+;
+
+fn_params_with_self
+: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')'              { $$ = mk_node("SelfValue", 3, $2, $4, $5); }
+| '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')'          { $$ = mk_node("SelfRegion", 3, $3, $5, $6); }
+| '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfRegion", 4, $3, $4, $6, $7); }
+| '(' maybe_params ')'                                                       { $$ = mk_node("SelfStatic", 1, $2); }
+;
+
+fn_anon_params_with_self
+: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')'              { $$ = mk_node("SelfValue", 3, $2, $4, $5); }
+| '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')'          { $$ = mk_node("SelfRegion", 3, $3, $5, $6); }
+| '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfRegion", 4, $3, $4, $6, $7); }
+| '(' maybe_anon_params ')'                                                       { $$ = mk_node("SelfStatic", 1, $2); }
+;
+
+maybe_params
+: params
+| params ','
+| %empty  { $$ = mk_none(); }
+;
+
+params
+: param                { $$ = mk_node("Args", 1, $1); }
+| params ',' param     { $$ = ext_node($1, 1, $3); }
+;
+
+param
+: pat ':' ty_sum   { $$ = mk_node("Arg", 2, $1, $3); }
+;
+
+inferrable_params
+: inferrable_param                       { $$ = mk_node("InferrableParams", 1, $1); }
+| inferrable_params ',' inferrable_param { $$ = ext_node($1, 1, $3); }
+;
+
+inferrable_param
+: pat maybe_ty_ascription { $$ = mk_node("InferrableParam", 2, $1, $2); }
+;
+
+maybe_unboxed_closure_kind
+: %empty
+| ':'
+| '&' maybe_mut ':'
+;
+
+maybe_comma_params
+: ','            { $$ = mk_none(); }
+| ',' params     { $$ = $2; }
+| ',' params ',' { $$ = $2; }
+| %empty         { $$ = mk_none(); }
+;
+
+maybe_comma_anon_params
+: ','                 { $$ = mk_none(); }
+| ',' anon_params     { $$ = $2; }
+| ',' anon_params ',' { $$ = $2; }
+| %empty              { $$ = mk_none(); }
+;
+
+maybe_anon_params
+: anon_params
+| anon_params ','
+| %empty      { $$ = mk_none(); }
+;
+
+anon_params
+: anon_param                 { $$ = mk_node("Args", 1, $1); }
+| anon_params ',' anon_param { $$ = ext_node($1, 1, $3); }
+;
+
+// anon means it's allowed to be anonymous (type-only), but it can
+// still have a name
+anon_param
+: named_arg ':' ty   { $$ = mk_node("Arg", 2, $1, $3); }
+| ty
+;
+
+anon_params_allow_variadic_tail
+: ',' DOTDOTDOT                                  { $$ = mk_none(); }
+| ',' anon_param anon_params_allow_variadic_tail { $$ = mk_node("Args", 2, $2, $3); }
+| %empty                                         { $$ = mk_none(); }
+;
+
+named_arg
+: ident
+| UNDERSCORE        { $$ = mk_atom("PatWild"); }
+| '&' ident         { $$ = $2; }
+| '&' UNDERSCORE    { $$ = mk_atom("PatWild"); }
+| ANDAND ident      { $$ = $2; }
+| ANDAND UNDERSCORE { $$ = mk_atom("PatWild"); }
+| MUT ident         { $$ = $2; }
+;
+
+ret_ty
+: RARROW '!'         { $$ = mk_none(); }
+| RARROW ty          { $$ = mk_node("ret-ty", 1, $2); }
+| %prec IDENT %empty { $$ = mk_none(); }
+;
+
+generic_params
+: '<' lifetimes '>'                   { $$ = mk_node("Generics", 2, $2, mk_none()); }
+| '<' lifetimes ',' '>'               { $$ = mk_node("Generics", 2, $2, mk_none()); }
+| '<' lifetimes SHR                   { push_back('>'); $$ = mk_node("Generics", 2, $2, mk_none()); }
+| '<' lifetimes ',' SHR               { push_back('>'); $$ = mk_node("Generics", 2, $2, mk_none()); }
+| '<' lifetimes ',' ty_params '>'     { $$ = mk_node("Generics", 2, $2, $4); }
+| '<' lifetimes ',' ty_params ',' '>' { $$ = mk_node("Generics", 2, $2, $4); }
+| '<' lifetimes ',' ty_params SHR     { push_back('>'); $$ = mk_node("Generics", 2, $2, $4); }
+| '<' lifetimes ',' ty_params ',' SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, $4); }
+| '<' ty_params '>'                   { $$ = mk_node("Generics", 2, mk_none(), $2); }
+| '<' ty_params ',' '>'               { $$ = mk_node("Generics", 2, mk_none(), $2); }
+| '<' ty_params SHR                   { push_back('>'); $$ = mk_node("Generics", 2, mk_none(), $2); }
+| '<' ty_params ',' SHR               { push_back('>'); $$ = mk_node("Generics", 2, mk_none(), $2); }
+| %empty                              { $$ = mk_none(); }
+;
+
+maybe_where_clause
+: %empty                              { $$ = mk_none(); }
+| where_clause
+;
+
+where_clause
+: WHERE where_predicates              { $$ = mk_node("WhereClause", 1, $2); }
+| WHERE where_predicates ','          { $$ = mk_node("WhereClause", 1, $2); }
+;
+
+where_predicates
+: where_predicate                      { $$ = mk_node("WherePredicates", 1, $1); }
+| where_predicates ',' where_predicate { $$ = ext_node($1, 1, $3); }
+;
+
+where_predicate
+: maybe_for_lifetimes lifetime ':' bounds    { $$ = mk_node("WherePredicate", 3, $1, $2, $4); }
+| maybe_for_lifetimes ty ':' ty_param_bounds { $$ = mk_node("WherePredicate", 3, $1, $2, $4); }
+;
+
+maybe_for_lifetimes
+: FOR '<' lifetimes '>' { $$ = mk_none(); }
+| %prec FORTYPE %empty  { $$ = mk_none(); }
+
+ty_params
+: ty_param               { $$ = mk_node("TyParams", 1, $1); }
+| ty_params ',' ty_param { $$ = ext_node($1, 1, $3); }
+;
+
+// A path with no type parameters; e.g. `foo::bar::Baz`
+//
+// These show up in 'use' view-items, because these are processed
+// without respect to types.
+path_no_types_allowed
+: ident                               { $$ = mk_node("ViewPath", 1, $1); }
+| MOD_SEP ident                       { $$ = mk_node("ViewPath", 1, $2); }
+| SELF                                { $$ = mk_node("ViewPath", 1, mk_atom("Self")); }
+| MOD_SEP SELF                        { $$ = mk_node("ViewPath", 1, mk_atom("Self")); }
+| path_no_types_allowed MOD_SEP ident { $$ = ext_node($1, 1, $3); }
+;
+
+// A path with a lifetime and type parameters, with no double colons
+// before the type parameters; e.g. `foo::bar<'a>::Baz<T>`
+//
+// These show up in "trait references", the components of
+// type-parameter bounds lists, as well as in the prefix of the
+// path_generic_args_and_bounds rule, which is the full form of a
+// named typed expression.
+//
+// They do not have (nor need) an extra '::' before '<' because
+// unlike in expr context, there are no "less-than" type exprs to
+// be ambiguous with.
+path_generic_args_without_colons
+: %prec IDENT
+  ident                                                                       { $$ = mk_node("components", 1, $1); }
+| %prec IDENT
+  ident generic_args                                                          { $$ = mk_node("components", 2, $1, $2); }
+| %prec IDENT
+  ident '(' maybe_ty_sums ')' ret_ty                                          { $$ = mk_node("components", 2, $1, $3); }
+| %prec IDENT
+  path_generic_args_without_colons MOD_SEP ident                              { $$ = ext_node($1, 1, $3); }
+| %prec IDENT
+  path_generic_args_without_colons MOD_SEP ident generic_args                 { $$ = ext_node($1, 2, $3, $4); }
+| %prec IDENT
+  path_generic_args_without_colons MOD_SEP ident '(' maybe_ty_sums ')' ret_ty { $$ = ext_node($1, 2, $3, $5); }
+;
+
+generic_args
+: '<' generic_values '>'   { $$ = $2; }
+| '<' generic_values SHR   { push_back('>'); $$ = $2; }
+| '<' generic_values GE    { push_back('='); $$ = $2; }
+| '<' generic_values SHREQ { push_back('>'); push_back('='); $$ = $2; }
+// If generic_args starts with "<<", the first arg must be a
+// TyQualifiedPath because that's the only type that can start with a
+// '<'. This rule parses that as the first ty_sum and then continues
+// with the rest of generic_values.
+| SHL ty_qualified_path_and_generic_values '>'   { $$ = $2; }
+| SHL ty_qualified_path_and_generic_values SHR   { push_back('>'); $$ = $2; }
+| SHL ty_qualified_path_and_generic_values GE    { push_back('='); $$ = $2; }
+| SHL ty_qualified_path_and_generic_values SHREQ { push_back('>'); push_back('='); $$ = $2; }
+;
+
+generic_values
+: maybe_lifetimes maybe_ty_sums_and_or_bindings { $$ = mk_node("GenericValues", 2, $1, $2); }
+;
+
+maybe_ty_sums_and_or_bindings
+: ty_sums
+| ty_sums ','
+| ty_sums ',' bindings { $$ = mk_node("TySumsAndBindings", 2, $1, $3); }
+| bindings
+| bindings ','
+| %empty               { $$ = mk_none(); }
+;
+
+maybe_bindings
+: ',' bindings { $$ = $2; }
+| %empty       { $$ = mk_none(); }
+;
+
+////////////////////////////////////////////////////////////////////////
+// Part 2: Patterns
+////////////////////////////////////////////////////////////////////////
+
+pat
+: UNDERSCORE                                      { $$ = mk_atom("PatWild"); }
+| '&' pat                                         { $$ = mk_node("PatRegion", 1, $2); }
+| '&' MUT pat                                     { $$ = mk_node("PatRegion", 1, $3); }
+| ANDAND pat                                      { $$ = mk_node("PatRegion", 1, mk_node("PatRegion", 1, $2)); }
+| '(' ')'                                         { $$ = mk_atom("PatUnit"); }
+| '(' pat_tup ')'                                 { $$ = mk_node("PatTup", 1, $2); }
+| '(' pat_tup ',' ')'                             { $$ = mk_node("PatTup", 1, $2); }
+| '[' pat_vec ']'                                 { $$ = mk_node("PatVec", 1, $2); }
+| lit_or_path
+| lit_or_path DOTDOTDOT lit_or_path               { $$ = mk_node("PatRange", 2, $1, $3); }
+| path_expr '{' pat_struct '}'                    { $$ = mk_node("PatStruct", 2, $1, $3); }
+| path_expr '(' DOTDOT ')'                        { $$ = mk_node("PatEnum", 1, $1); }
+| path_expr '(' pat_tup ')'                       { $$ = mk_node("PatEnum", 2, $1, $3); }
+| path_expr '!' maybe_ident delimited_token_trees { $$ = mk_node("PatMac", 3, $1, $3, $4); }
+| binding_mode ident                              { $$ = mk_node("PatIdent", 2, $1, $2); }
+|              ident '@' pat                      { $$ = mk_node("PatIdent", 3, mk_node("BindByValue", 1, mk_atom("MutImmutable")), $1, $3); }
+| binding_mode ident '@' pat                      { $$ = mk_node("PatIdent", 3, $1, $2, $4); }
+| BOX pat                                         { $$ = mk_node("PatUniq", 1, $2); }
+| '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node("PatQualifiedPath", 3, $2, $3, $6); }
+| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident
+{
+  $$ = mk_node("PatQualifiedPath", 3, mk_node("PatQualifiedPath", 3, $2, $3, $6), $7, $10);
+}
+;
+
+pats_or
+: pat              { $$ = mk_node("Pats", 1, $1); }
+| pats_or '|' pat  { $$ = ext_node($1, 1, $3); }
+;
+
+binding_mode
+: REF         { $$ = mk_node("BindByRef", 1, mk_atom("MutImmutable")); }
+| REF MUT     { $$ = mk_node("BindByRef", 1, mk_atom("MutMutable")); }
+| MUT         { $$ = mk_node("BindByValue", 1, mk_atom("MutMutable")); }
+;
+
+lit_or_path
+: path_expr    { $$ = mk_node("PatLit", 1, $1); }
+| lit          { $$ = mk_node("PatLit", 1, $1); }
+| '-' lit      { $$ = mk_node("PatLit", 1, $2); }
+;
+
+pat_field
+:                  ident        { $$ = mk_node("PatField", 1, $1); }
+|     binding_mode ident        { $$ = mk_node("PatField", 2, $1, $2); }
+| BOX              ident        { $$ = mk_node("PatField", 2, mk_atom("box"), $2); }
+| BOX binding_mode ident        { $$ = mk_node("PatField", 3, mk_atom("box"), $2, $3); }
+|              ident ':' pat    { $$ = mk_node("PatField", 2, $1, $3); }
+| binding_mode ident ':' pat    { $$ = mk_node("PatField", 3, $1, $2, $4); }
+;
+
+pat_fields
+: pat_field                  { $$ = mk_node("PatFields", 1, $1); }
+| pat_fields ',' pat_field   { $$ = ext_node($1, 1, $3); }
+;
+
+pat_struct
+: pat_fields                 { $$ = mk_node("PatStruct", 2, $1, mk_atom("false")); }
+| pat_fields ','             { $$ = mk_node("PatStruct", 2, $1, mk_atom("false")); }
+| pat_fields ',' DOTDOT      { $$ = mk_node("PatStruct", 2, $1, mk_atom("true")); }
+| DOTDOT                     { $$ = mk_node("PatStruct", 1, mk_atom("true")); }
+;
+
+pat_tup
+: pat               { $$ = mk_node("pat_tup", 1, $1); }
+| pat_tup ',' pat   { $$ = ext_node($1, 1, $3); }
+;
+
+pat_vec
+: pat_vec_elts                                  { $$ = mk_node("PatVec", 2, $1, mk_none()); }
+| pat_vec_elts                             ','  { $$ = mk_node("PatVec", 2, $1, mk_none()); }
+| pat_vec_elts     DOTDOT                       { $$ = mk_node("PatVec", 2, $1, mk_none()); }
+| pat_vec_elts ',' DOTDOT                       { $$ = mk_node("PatVec", 2, $1, mk_none()); }
+| pat_vec_elts     DOTDOT ',' pat_vec_elts      { $$ = mk_node("PatVec", 2, $1, $4); }
+| pat_vec_elts     DOTDOT ',' pat_vec_elts ','  { $$ = mk_node("PatVec", 2, $1, $4); }
+| pat_vec_elts ',' DOTDOT ',' pat_vec_elts      { $$ = mk_node("PatVec", 2, $1, $5); }
+| pat_vec_elts ',' DOTDOT ',' pat_vec_elts ','  { $$ = mk_node("PatVec", 2, $1, $5); }
+|                  DOTDOT ',' pat_vec_elts      { $$ = mk_node("PatVec", 2, mk_none(), $3); }
+|                  DOTDOT ',' pat_vec_elts ','  { $$ = mk_node("PatVec", 2, mk_none(), $3); }
+|                  DOTDOT                       { $$ = mk_node("PatVec", 2, mk_none(), mk_none()); }
+| %empty                                        { $$ = mk_node("PatVec", 2, mk_none(), mk_none()); }
+;
+
+pat_vec_elts
+: pat                    { $$ = mk_node("PatVecElts", 1, $1); }
+| pat_vec_elts ',' pat   { $$ = ext_node($1, 1, $3); }
+;
+
+////////////////////////////////////////////////////////////////////////
+// Part 3: Types
+////////////////////////////////////////////////////////////////////////
+
+ty
+: ty_prim
+| ty_closure
+| '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident                                      { $$ = mk_node("TyQualifiedPath", 3, $2, $3, $6); }
+| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node("TyQualifiedPath", 3, mk_node("TyQualifiedPath", 3, $2, $3, $6), $7, $10); }
+| '(' ty_sums ')'                                                                      { $$ = mk_node("TyTup", 1, $2); }
+| '(' ty_sums ',' ')'                                                                  { $$ = mk_node("TyTup", 1, $2); }
+| '(' ')'                                                                              { $$ = mk_atom("TyNil"); }
+;
+
+ty_prim
+: %prec IDENT path_generic_args_without_colons              { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("false")), $1); }
+| %prec IDENT MOD_SEP path_generic_args_without_colons      { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("true")), $2); }
+| %prec IDENT SELF MOD_SEP path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("self", 1, mk_atom("true")), $3); }
+| BOX ty                                                    { $$ = mk_node("TyBox", 1, $2); }
+| '*' maybe_mut_or_const ty                                 { $$ = mk_node("TyPtr", 2, $2, $3); }
+| '&' ty                                                    { $$ = mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2); }
+| '&' MUT ty                                                { $$ = mk_node("TyRptr", 2, mk_atom("MutMutable"), $3); }
+| ANDAND ty                                                 { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2)); }
+| ANDAND MUT ty                                             { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutMutable"), $3)); }
+| '&' lifetime maybe_mut ty                                 { $$ = mk_node("TyRptr", 3, $2, $3, $4); }
+| ANDAND lifetime maybe_mut ty                              { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 3, $2, $3, $4)); }
+| '[' ty ']'                                                { $$ = mk_node("TyVec", 1, $2); }
+| '[' ty ',' DOTDOT expr ']'                                { $$ = mk_node("TyFixedLengthVec", 2, $2, $5); }
+| '[' ty ';' expr ']'                                       { $$ = mk_node("TyFixedLengthVec", 2, $2, $4); }
+| TYPEOF '(' expr ')'                                       { $$ = mk_node("TyTypeof", 1, $3); }
+| UNDERSCORE                                                { $$ = mk_atom("TyInfer"); }
+| ty_bare_fn
+| ty_proc
+| for_in_type
+;
+
+ty_bare_fn
+:                         FN ty_fn_decl { $$ = $2; }
+| UNSAFE                  FN ty_fn_decl { $$ = $3; }
+|        EXTERN maybe_abi FN ty_fn_decl { $$ = $4; }
+| UNSAFE EXTERN maybe_abi FN ty_fn_decl { $$ = $5; }
+;
+
+ty_fn_decl
+: generic_params fn_anon_params ret_ty { $$ = mk_node("TyFnDecl", 3, $1, $2, $3); }
+;
+
+ty_closure
+: UNSAFE '|' anon_params '|' maybe_bounds ret_ty { $$ = mk_node("TyClosure", 3, $3, $5, $6); }
+|        '|' anon_params '|' maybe_bounds ret_ty { $$ = mk_node("TyClosure", 3, $2, $4, $5); }
+| UNSAFE OROR maybe_bounds ret_ty                { $$ = mk_node("TyClosure", 2, $3, $4); }
+|        OROR maybe_bounds ret_ty                { $$ = mk_node("TyClosure", 2, $2, $3); }
+;
+
+ty_proc
+: PROC generic_params fn_params maybe_bounds ret_ty { $$ = mk_node("TyProc", 4, $2, $3, $4, $5); }
+;
+
+for_in_type
+: FOR '<' maybe_lifetimes '>' for_in_type_suffix { $$ = mk_node("ForInType", 2, $3, $5); }
+;
+
+for_in_type_suffix
+: ty_proc
+| ty_bare_fn
+| trait_ref
+| ty_closure
+;
+
+maybe_mut
+: MUT              { $$ = mk_atom("MutMutable"); }
+| %prec MUT %empty { $$ = mk_atom("MutImmutable"); }
+;
+
+maybe_mut_or_const
+: MUT    { $$ = mk_atom("MutMutable"); }
+| CONST  { $$ = mk_atom("MutImmutable"); }
+| %empty { $$ = mk_atom("MutImmutable"); }
+;
+
+ty_qualified_path_and_generic_values
+: ty_qualified_path maybe_bindings
+{
+  $$ = mk_node("GenericValues", 3, mk_none(), mk_node("TySums", 1, mk_node("TySum", 1, $1)), $2);
+}
+| ty_qualified_path ',' ty_sums maybe_bindings
+{
+  $$ = mk_node("GenericValues", 3, mk_none(), mk_node("TySums", 2, $1, $3), $4);
+}
+;
+
+ty_qualified_path
+: ty_sum AS trait_ref '>' MOD_SEP ident                     { $$ = mk_node("TyQualifiedPath", 3, $1, $3, $6); }
+| ty_sum AS trait_ref '>' MOD_SEP ident '+' ty_param_bounds { $$ = mk_node("TyQualifiedPath", 3, $1, $3, $6); }
+;
+
+maybe_ty_sums
+: ty_sums
+| ty_sums ','
+| %empty { $$ = mk_none(); }
+;
+
+ty_sums
+: ty_sum             { $$ = mk_node("TySums", 1, $1); }
+| ty_sums ',' ty_sum { $$ = ext_node($1, 1, $3); }
+;
+
+ty_sum
+: ty                     { $$ = mk_node("TySum", 1, $1); }
+| ty '+' ty_param_bounds { $$ = mk_node("TySum", 2, $1, $3); }
+;
+
+ty_prim_sum
+: ty_prim                     { $$ = mk_node("TySum", 1, $1); }
+| ty_prim '+' ty_param_bounds { $$ = mk_node("TySum", 2, $1, $3); }
+;
+
+maybe_ty_param_bounds
+: ':' ty_param_bounds { $$ = $2; }
+| %empty              { $$ = mk_none(); }
+;
+
+ty_param_bounds
+: boundseq
+| %empty { $$ = mk_none(); }
+;
+
+boundseq
+: polybound
+| boundseq '+' polybound { $$ = ext_node($1, 1, $3); }
+;
+
+polybound
+: FOR '<' maybe_lifetimes '>' bound { $$ = mk_node("PolyBound", 2, $3, $5); }
+| bound
+| '?' bound { $$ = $2; }
+;
+
+bindings
+: binding              { $$ = mk_node("Bindings", 1, $1); }
+| bindings ',' binding { $$ = ext_node($1, 1, $3); }
+;
+
+binding
+: ident '=' ty { mk_node("Binding", 2, $1, $3); }
+;
+
+ty_param
+: ident maybe_ty_param_bounds maybe_ty_default           { $$ = mk_node("TyParam", 3, $1, $2, $3); }
+| ident '?' ident maybe_ty_param_bounds maybe_ty_default { $$ = mk_node("TyParam", 4, $1, $3, $4, $5); }
+;
+
+maybe_bounds
+: %prec SHIFTPLUS
+  ':' bounds             { $$ = $2; }
+| %prec SHIFTPLUS %empty { $$ = mk_none(); }
+;
+
+bounds
+: bound            { $$ = mk_node("bounds", 1, $1); }
+| bounds '+' bound { $$ = ext_node($1, 1, $3); }
+;
+
+bound
+: lifetime
+| trait_ref
+;
+
+maybe_ltbounds
+: %prec SHIFTPLUS
+  ':' ltbounds       { $$ = $2; }
+| %empty             { $$ = mk_none(); }
+;
+
+ltbounds
+: lifetime              { $$ = mk_node("ltbounds", 1, $1); }
+| ltbounds '+' lifetime { $$ = ext_node($1, 1, $3); }
+;
+
+maybe_ty_default
+: '=' ty_sum { $$ = mk_node("TyDefault", 1, $2); }
+| %empty     { $$ = mk_none(); }
+;
+
+maybe_lifetimes
+: lifetimes
+| lifetimes ','
+| %empty { $$ = mk_none(); }
+;
+
+lifetimes
+: lifetime_and_bounds               { $$ = mk_node("Lifetimes", 1, $1); }
+| lifetimes ',' lifetime_and_bounds { $$ = ext_node($1, 1, $3); }
+;
+
+lifetime_and_bounds
+: LIFETIME maybe_ltbounds         { $$ = mk_node("lifetime", 2, mk_atom(yytext), $2); }
+| STATIC_LIFETIME                 { $$ = mk_atom("static_lifetime"); }
+;
+
+lifetime
+: LIFETIME         { $$ = mk_node("lifetime", 1, mk_atom(yytext)); }
+| STATIC_LIFETIME  { $$ = mk_atom("static_lifetime"); }
+;
+
+trait_ref
+: %prec IDENT path_generic_args_without_colons
+| %prec IDENT MOD_SEP path_generic_args_without_colons { $$ = $2; }
+;
+
+////////////////////////////////////////////////////////////////////////
+// Part 4: Blocks, statements, and expressions
+////////////////////////////////////////////////////////////////////////
+
+inner_attrs_and_block
+: '{' maybe_inner_attrs maybe_stmts '}'        { $$ = mk_node("ExprBlock", 2, $2, $3); }
+;
+
+block
+: '{' maybe_stmts '}'                          { $$ = mk_node("ExprBlock", 1, $2); }
+;
+
+maybe_stmts
+: stmts
+| stmts nonblock_expr { $$ = ext_node($1, 1, $2); }
+| nonblock_expr
+| %empty              { $$ = mk_none(); }
+;
+
+// There are two sub-grammars within a "stmts: exprs" derivation
+// depending on whether each stmt-expr is a block-expr form; this is to
+// handle the "semicolon rule" for stmt sequencing that permits
+// writing
+//
+//     if foo { bar } 10
+//
+// as a sequence of two stmts (one if-expr stmt, one lit-10-expr
+// stmt). Unfortunately by permitting juxtaposition of exprs in
+// sequence like that, the non-block expr grammar has to have a
+// second limited sub-grammar that excludes the prefix exprs that
+// are ambiguous with binops. That is to say:
+//
+//     {10} - 1
+//
+// should parse as (progn (progn 10) (- 1)) not (- (progn 10) 1), that
+// is to say, two statements rather than one, at least according to
+// the mainline rust parser.
+//
+// So we wind up with a 3-way split in exprs that occur in stmt lists:
+// block, nonblock-prefix, and nonblock-nonprefix.
+//
+// In non-stmts contexts, expr can relax this trichotomy.
+//
+// There is also one other expr subtype: nonparen_expr disallows exprs
+// surrounded by parens (including tuple expressions), this is
+// necessary for BOX (place) expressions, so a parens expr following
+// the BOX is always parsed as the place.
+
+stmts
+: stmt           { $$ = mk_node("stmts", 1, $1); }
+| stmts stmt     { $$ = ext_node($1, 1, $2); }
+;
+
+stmt
+: let
+|                 stmt_item
+|             PUB stmt_item { $$ = $2; }
+| outer_attrs     stmt_item { $$ = $2; }
+| outer_attrs PUB stmt_item { $$ = $3; }
+| full_block_expr
+| block
+| nonblock_expr ';'
+| ';'                   { $$ = mk_none(); }
+;
+
+maybe_exprs
+: exprs
+| exprs ','
+| %empty { $$ = mk_none(); }
+;
+
+maybe_expr
+: expr
+| %empty { $$ = mk_none(); }
+;
+
+exprs
+: expr                                                        { $$ = mk_node("exprs", 1, $1); }
+| exprs ',' expr                                              { $$ = ext_node($1, 1, $3); }
+;
+
+path_expr
+: path_generic_args_with_colons
+| MOD_SEP path_generic_args_with_colons      { $$ = $2; }
+| SELF MOD_SEP path_generic_args_with_colons { $$ = mk_node("SelfPath", 1, $3); }
+;
+
+// A path with a lifetime and type parameters with double colons before
+// the type parameters; e.g. `foo::bar::<'a>::Baz::<T>`
+//
+// These show up in expr context, in order to disambiguate from "less-than"
+// expressions.
+path_generic_args_with_colons
+: ident                                              { $$ = mk_node("components", 1, $1); }
+| path_generic_args_with_colons MOD_SEP ident        { $$ = ext_node($1, 1, $3); }
+| path_generic_args_with_colons MOD_SEP generic_args { $$ = ext_node($1, 1, $3); }
+;
+
+// the braces-delimited macro is a block_expr so it doesn't appear here
+macro_expr
+: path_expr '!' maybe_ident parens_delimited_token_trees   { $$ = mk_node("MacroExpr", 3, $1, $3, $4); }
+| path_expr '!' maybe_ident brackets_delimited_token_trees { $$ = mk_node("MacroExpr", 3, $1, $3, $4); }
+;
+
+nonblock_expr
+: lit                                                           { $$ = mk_node("ExprLit", 1, $1); }
+| %prec IDENT
+  path_expr                                                     { $$ = mk_node("ExprPath", 1, $1); }
+| SELF                                                          { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); }
+| macro_expr                                                    { $$ = mk_node("ExprMac", 1, $1); }
+| path_expr '{' struct_expr_fields '}'                          { $$ = mk_node("ExprStruct", 2, $1, $3); }
+| nonblock_expr '.' path_generic_args_with_colons               { $$ = mk_node("ExprField", 2, $1, $3); }
+| nonblock_expr '.' LIT_INTEGER                                 { $$ = mk_node("ExprTupleIndex", 1, $1); }
+| nonblock_expr '[' maybe_expr ']'                              { $$ = mk_node("ExprIndex", 2, $1, $3); }
+| nonblock_expr '(' maybe_exprs ')'                             { $$ = mk_node("ExprCall", 2, $1, $3); }
+| '[' vec_expr ']'                                              { $$ = mk_node("ExprVec", 1, $2); }
+| '(' maybe_exprs ')'                                           { $$ = mk_node("ExprParen", 1, $2); }
+| CONTINUE                                                      { $$ = mk_node("ExprAgain", 0); }
+| CONTINUE lifetime                                             { $$ = mk_node("ExprAgain", 1, $2); }
+| RETURN                                                        { $$ = mk_node("ExprRet", 0); }
+| RETURN expr                                                   { $$ = mk_node("ExprRet", 1, $2); }
+| BREAK                                                         { $$ = mk_node("ExprBreak", 0); }
+| BREAK lifetime                                                { $$ = mk_node("ExprBreak", 1, $2); }
+| nonblock_expr LARROW expr                                     { $$ = mk_node("ExprInPlace", 2, $1, $3); }
+| nonblock_expr '=' expr                                        { $$ = mk_node("ExprAssign", 2, $1, $3); }
+| nonblock_expr SHLEQ expr                                      { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
+| nonblock_expr SHREQ expr                                      { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
+| nonblock_expr MINUSEQ expr                                    { $$ = mk_node("ExprAssignSub", 2, $1, $3); }
+| nonblock_expr ANDEQ expr                                      { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); }
+| nonblock_expr OREQ expr                                       { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); }
+| nonblock_expr PLUSEQ expr                                     { $$ = mk_node("ExprAssignAdd", 2, $1, $3); }
+| nonblock_expr STAREQ expr                                     { $$ = mk_node("ExprAssignMul", 2, $1, $3); }
+| nonblock_expr SLASHEQ expr                                    { $$ = mk_node("ExprAssignDiv", 2, $1, $3); }
+| nonblock_expr CARETEQ expr                                    { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); }
+| nonblock_expr PERCENTEQ expr                                  { $$ = mk_node("ExprAssignRem", 2, $1, $3); }
+| nonblock_expr OROR expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); }
+| nonblock_expr ANDAND expr                                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); }
+| nonblock_expr EQEQ expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); }
+| nonblock_expr NE expr                                         { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); }
+| nonblock_expr '<' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); }
+| nonblock_expr '>' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); }
+| nonblock_expr LE expr                                         { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); }
+| nonblock_expr GE expr                                         { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); }
+| nonblock_expr '|' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); }
+| nonblock_expr '^' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); }
+| nonblock_expr '&' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); }
+| nonblock_expr SHL expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); }
+| nonblock_expr SHR expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); }
+| nonblock_expr '+' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); }
+| nonblock_expr '-' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); }
+| nonblock_expr '*' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); }
+| nonblock_expr '/' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); }
+| nonblock_expr '%' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); }
+| nonblock_expr DOTDOT                                          { $$ = mk_node("ExprRange", 2, $1, mk_none()); }
+| nonblock_expr DOTDOT expr                                     { $$ = mk_node("ExprRange", 2, $1, $3); }
+|               DOTDOT expr                                     { $$ = mk_node("ExprRange", 2, mk_none(), $2); }
+|               DOTDOT                                          { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); }
+| nonblock_expr AS ty                                           { $$ = mk_node("ExprCast", 2, $1, $3); }
+| BOX nonparen_expr                                             { $$ = mk_node("ExprBox", 1, $2); }
+| %prec BOXPLACE BOX '(' maybe_expr ')' nonblock_expr           { $$ = mk_node("ExprBox", 2, $3, $5); }
+| expr_qualified_path
+| nonblock_prefix_expr
+;
+
+expr
+: lit                                                 { $$ = mk_node("ExprLit", 1, $1); }
+| %prec IDENT
+  path_expr                                           { $$ = mk_node("ExprPath", 1, $1); }
+| SELF                                                { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); }
+| macro_expr                                          { $$ = mk_node("ExprMac", 1, $1); }
+| path_expr '{' struct_expr_fields '}'                { $$ = mk_node("ExprStruct", 2, $1, $3); }
+| expr '.' path_generic_args_with_colons              { $$ = mk_node("ExprField", 2, $1, $3); }
+| expr '.' LIT_INTEGER                                { $$ = mk_node("ExprTupleIndex", 1, $1); }
+| expr '[' maybe_expr ']'                             { $$ = mk_node("ExprIndex", 2, $1, $3); }
+| expr '(' maybe_exprs ')'                            { $$ = mk_node("ExprCall", 2, $1, $3); }
+| '(' maybe_exprs ')'                                 { $$ = mk_node("ExprParen", 1, $2); }
+| '[' vec_expr ']'                                    { $$ = mk_node("ExprVec", 1, $2); }
+| CONTINUE                                            { $$ = mk_node("ExprAgain", 0); }
+| CONTINUE ident                                      { $$ = mk_node("ExprAgain", 1, $2); }
+| RETURN                                              { $$ = mk_node("ExprRet", 0); }
+| RETURN expr                                         { $$ = mk_node("ExprRet", 1, $2); }
+| BREAK                                               { $$ = mk_node("ExprBreak", 0); }
+| BREAK ident                                         { $$ = mk_node("ExprBreak", 1, $2); }
+| expr LARROW expr                                    { $$ = mk_node("ExprInPlace", 2, $1, $3); }
+| expr '=' expr                                       { $$ = mk_node("ExprAssign", 2, $1, $3); }
+| expr SHLEQ expr                                     { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
+| expr SHREQ expr                                     { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
+| expr MINUSEQ expr                                   { $$ = mk_node("ExprAssignSub", 2, $1, $3); }
+| expr ANDEQ expr                                     { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); }
+| expr OREQ expr                                      { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); }
+| expr PLUSEQ expr                                    { $$ = mk_node("ExprAssignAdd", 2, $1, $3); }
+| expr STAREQ expr                                    { $$ = mk_node("ExprAssignMul", 2, $1, $3); }
+| expr SLASHEQ expr                                   { $$ = mk_node("ExprAssignDiv", 2, $1, $3); }
+| expr CARETEQ expr                                   { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); }
+| expr PERCENTEQ expr                                 { $$ = mk_node("ExprAssignRem", 2, $1, $3); }
+| expr OROR expr                                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); }
+| expr ANDAND expr                                    { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); }
+| expr EQEQ expr                                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); }
+| expr NE expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); }
+| expr '<' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); }
+| expr '>' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); }
+| expr LE expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); }
+| expr GE expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); }
+| expr '|' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); }
+| expr '^' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); }
+| expr '&' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); }
+| expr SHL expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); }
+| expr SHR expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); }
+| expr '+' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); }
+| expr '-' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); }
+| expr '*' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); }
+| expr '/' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); }
+| expr '%' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); }
+| expr DOTDOT                                         { $$ = mk_node("ExprRange", 2, $1, mk_none()); }
+| expr DOTDOT expr                                    { $$ = mk_node("ExprRange", 2, $1, $3); }
+|      DOTDOT expr                                    { $$ = mk_node("ExprRange", 2, mk_none(), $2); }
+|      DOTDOT                                         { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); }
+| expr AS ty                                          { $$ = mk_node("ExprCast", 2, $1, $3); }
+| BOX nonparen_expr                                   { $$ = mk_node("ExprBox", 1, $2); }
+| %prec BOXPLACE BOX '(' maybe_expr ')' expr          { $$ = mk_node("ExprBox", 2, $3, $5); }
+| expr_qualified_path
+| block_expr
+| block
+| nonblock_prefix_expr
+;
+
+nonparen_expr
+: lit                                                 { $$ = mk_node("ExprLit", 1, $1); }
+| %prec IDENT
+  path_expr                                           { $$ = mk_node("ExprPath", 1, $1); }
+| SELF                                                { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); }
+| macro_expr                                          { $$ = mk_node("ExprMac", 1, $1); }
+| path_expr '{' struct_expr_fields '}'                { $$ = mk_node("ExprStruct", 2, $1, $3); }
+| nonparen_expr '.' path_generic_args_with_colons     { $$ = mk_node("ExprField", 2, $1, $3); }
+| nonparen_expr '.' LIT_INTEGER                       { $$ = mk_node("ExprTupleIndex", 1, $1); }
+| nonparen_expr '[' maybe_expr ']'                    { $$ = mk_node("ExprIndex", 2, $1, $3); }
+| nonparen_expr '(' maybe_exprs ')'                   { $$ = mk_node("ExprCall", 2, $1, $3); }
+| '[' vec_expr ']'                                    { $$ = mk_node("ExprVec", 1, $2); }
+| CONTINUE                                            { $$ = mk_node("ExprAgain", 0); }
+| CONTINUE ident                                      { $$ = mk_node("ExprAgain", 1, $2); }
+| RETURN                                              { $$ = mk_node("ExprRet", 0); }
+| RETURN expr                                         { $$ = mk_node("ExprRet", 1, $2); }
+| BREAK                                               { $$ = mk_node("ExprBreak", 0); }
+| BREAK ident                                         { $$ = mk_node("ExprBreak", 1, $2); }
+| nonparen_expr LARROW nonparen_expr                  { $$ = mk_node("ExprInPlace", 2, $1, $3); }
+| nonparen_expr '=' nonparen_expr                     { $$ = mk_node("ExprAssign", 2, $1, $3); }
+| nonparen_expr SHLEQ nonparen_expr                   { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
+| nonparen_expr SHREQ nonparen_expr                   { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
+| nonparen_expr MINUSEQ nonparen_expr                 { $$ = mk_node("ExprAssignSub", 2, $1, $3); }
+| nonparen_expr ANDEQ nonparen_expr                   { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); }
+| nonparen_expr OREQ nonparen_expr                    { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); }
+| nonparen_expr PLUSEQ nonparen_expr                  { $$ = mk_node("ExprAssignAdd", 2, $1, $3); }
+| nonparen_expr STAREQ nonparen_expr                  { $$ = mk_node("ExprAssignMul", 2, $1, $3); }
+| nonparen_expr SLASHEQ nonparen_expr                 { $$ = mk_node("ExprAssignDiv", 2, $1, $3); }
+| nonparen_expr CARETEQ nonparen_expr                 { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); }
+| nonparen_expr PERCENTEQ nonparen_expr               { $$ = mk_node("ExprAssignRem", 2, $1, $3); }
+| nonparen_expr OROR nonparen_expr                    { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); }
+| nonparen_expr ANDAND nonparen_expr                  { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); }
+| nonparen_expr EQEQ nonparen_expr                    { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); }
+| nonparen_expr NE nonparen_expr                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); }
+| nonparen_expr '<' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); }
+| nonparen_expr '>' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); }
+| nonparen_expr LE nonparen_expr                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); }
+| nonparen_expr GE nonparen_expr                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); }
+| nonparen_expr '|' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); }
+| nonparen_expr '^' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); }
+| nonparen_expr '&' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); }
+| nonparen_expr SHL nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); }
+| nonparen_expr SHR nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); }
+| nonparen_expr '+' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); }
+| nonparen_expr '-' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); }
+| nonparen_expr '*' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); }
+| nonparen_expr '/' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); }
+| nonparen_expr '%' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); }
+| nonparen_expr DOTDOT                                { $$ = mk_node("ExprRange", 2, $1, mk_none()); }
+| nonparen_expr DOTDOT nonparen_expr                  { $$ = mk_node("ExprRange", 2, $1, $3); }
+|               DOTDOT nonparen_expr                  { $$ = mk_node("ExprRange", 2, mk_none(), $2); }
+|               DOTDOT                                { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); }
+| nonparen_expr AS ty                                 { $$ = mk_node("ExprCast", 2, $1, $3); }
+| BOX nonparen_expr                                   { $$ = mk_node("ExprBox", 1, $2); }
+| %prec BOXPLACE BOX '(' maybe_expr ')' expr          { $$ = mk_node("ExprBox", 1, $3, $5); }
+| expr_qualified_path
+| block_expr
+| block
+| nonblock_prefix_expr
+;
+
+expr_nostruct
+: lit                                                 { $$ = mk_node("ExprLit", 1, $1); }
+| %prec IDENT
+  path_expr                                           { $$ = mk_node("ExprPath", 1, $1); }
+| SELF                                                { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); }
+| macro_expr                                          { $$ = mk_node("ExprMac", 1, $1); }
+| expr_nostruct '.' path_generic_args_with_colons     { $$ = mk_node("ExprField", 2, $1, $3); }
+| expr_nostruct '.' LIT_INTEGER                       { $$ = mk_node("ExprTupleIndex", 1, $1); }
+| expr_nostruct '[' maybe_expr ']'                    { $$ = mk_node("ExprIndex", 2, $1, $3); }
+| expr_nostruct '(' maybe_exprs ')'                   { $$ = mk_node("ExprCall", 2, $1, $3); }
+| '[' vec_expr ']'                                    { $$ = mk_node("ExprVec", 1, $2); }
+| '(' maybe_exprs ')'                                 { $$ = mk_node("ExprParen", 1, $2); }
+| CONTINUE                                            { $$ = mk_node("ExprAgain", 0); }
+| CONTINUE ident                                      { $$ = mk_node("ExprAgain", 1, $2); }
+| RETURN                                              { $$ = mk_node("ExprRet", 0); }
+| RETURN expr                                         { $$ = mk_node("ExprRet", 1, $2); }
+| BREAK                                               { $$ = mk_node("ExprBreak", 0); }
+| BREAK ident                                         { $$ = mk_node("ExprBreak", 1, $2); }
+| expr_nostruct LARROW expr_nostruct                  { $$ = mk_node("ExprInPlace", 2, $1, $3); }
+| expr_nostruct '=' expr_nostruct                     { $$ = mk_node("ExprAssign", 2, $1, $3); }
+| expr_nostruct SHLEQ expr_nostruct                   { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
+| expr_nostruct SHREQ expr_nostruct                   { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
+| expr_nostruct MINUSEQ expr_nostruct                 { $$ = mk_node("ExprAssignSub", 2, $1, $3); }
+| expr_nostruct ANDEQ expr_nostruct                   { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); }
+| expr_nostruct OREQ expr_nostruct                    { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); }
+| expr_nostruct PLUSEQ expr_nostruct                  { $$ = mk_node("ExprAssignAdd", 2, $1, $3); }
+| expr_nostruct STAREQ expr_nostruct                  { $$ = mk_node("ExprAssignMul", 2, $1, $3); }
+| expr_nostruct SLASHEQ expr_nostruct                 { $$ = mk_node("ExprAssignDiv", 2, $1, $3); }
+| expr_nostruct CARETEQ expr_nostruct                 { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); }
+| expr_nostruct PERCENTEQ expr_nostruct               { $$ = mk_node("ExprAssignRem", 2, $1, $3); }
+| expr_nostruct OROR expr_nostruct                    { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); }
+| expr_nostruct ANDAND expr_nostruct                  { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); }
+| expr_nostruct EQEQ expr_nostruct                    { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); }
+| expr_nostruct NE expr_nostruct                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); }
+| expr_nostruct '<' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); }
+| expr_nostruct '>' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); }
+| expr_nostruct LE expr_nostruct                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); }
+| expr_nostruct GE expr_nostruct                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); }
+| expr_nostruct '|' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); }
+| expr_nostruct '^' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); }
+| expr_nostruct '&' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); }
+| expr_nostruct SHL expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); }
+| expr_nostruct SHR expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); }
+| expr_nostruct '+' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); }
+| expr_nostruct '-' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); }
+| expr_nostruct '*' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); }
+| expr_nostruct '/' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); }
+| expr_nostruct '%' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); }
+| expr_nostruct DOTDOT               %prec RANGE      { $$ = mk_node("ExprRange", 2, $1, mk_none()); }
+| expr_nostruct DOTDOT expr_nostruct                  { $$ = mk_node("ExprRange", 2, $1, $3); }
+|               DOTDOT expr_nostruct                  { $$ = mk_node("ExprRange", 2, mk_none(), $2); }
+|               DOTDOT                                { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); }
+| expr_nostruct AS ty                                 { $$ = mk_node("ExprCast", 2, $1, $3); }
+| BOX nonparen_expr                                   { $$ = mk_node("ExprBox", 1, $2); }
+| %prec BOXPLACE BOX '(' maybe_expr ')' expr_nostruct { $$ = mk_node("ExprBox", 1, $3, $5); }
+| expr_qualified_path
+| block_expr
+| block
+| nonblock_prefix_expr_nostruct
+;
+
+nonblock_prefix_expr_nostruct
+: '-' expr_nostruct                         { $$ = mk_node("ExprUnary", 2, mk_atom("UnNeg"), $2); }
+| '!' expr_nostruct                         { $$ = mk_node("ExprUnary", 2, mk_atom("UnNot"), $2); }
+| '*' expr_nostruct                         { $$ = mk_node("ExprUnary", 2, mk_atom("UnDeref"), $2); }
+| '&' maybe_mut expr_nostruct               { $$ = mk_node("ExprAddrOf", 2, $2, $3); }
+| ANDAND maybe_mut expr_nostruct            { $$ = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, $2, $3)); }
+| lambda_expr_nostruct
+| MOVE lambda_expr_nostruct                 { $$ = $2; }
+| proc_expr_nostruct
+;
+
+nonblock_prefix_expr
+: '-' expr                         { $$ = mk_node("ExprUnary", 2, mk_atom("UnNeg"), $2); }
+| '!' expr                         { $$ = mk_node("ExprUnary", 2, mk_atom("UnNot"), $2); }
+| '*' expr                         { $$ = mk_node("ExprUnary", 2, mk_atom("UnDeref"), $2); }
+| '&' maybe_mut expr               { $$ = mk_node("ExprAddrOf", 2, $2, $3); }
+| ANDAND maybe_mut expr            { $$ = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, $2, $3)); }
+| lambda_expr
+| MOVE lambda_expr                 { $$ = $2; }
+| proc_expr
+;
+
+expr_qualified_path
+: '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_qpath_params
+{
+  $$ = mk_node("ExprQualifiedPath", 4, $2, $3, $6, $7);
+}
+| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident
+{
+  $$ = mk_node("ExprQualifiedPath", 3, mk_node("ExprQualifiedPath", 3, $2, $3, $6), $7, $10);
+}
+| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident generic_args maybe_as_trait_ref '>' MOD_SEP ident
+{
+  $$ = mk_node("ExprQualifiedPath", 3, mk_node("ExprQualifiedPath", 4, $2, $3, $6, $7), $8, $11);
+}
+| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident generic_args
+{
+  $$ = mk_node("ExprQualifiedPath", 4, mk_node("ExprQualifiedPath", 3, $2, $3, $6), $7, $10, $11);
+}
+| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident generic_args maybe_as_trait_ref '>' MOD_SEP ident generic_args
+{
+  $$ = mk_node("ExprQualifiedPath", 4, mk_node("ExprQualifiedPath", 4, $2, $3, $6, $7), $8, $11, $12);
+}
+
+maybe_qpath_params
+: MOD_SEP generic_args { $$ = $2; }
+| %empty               { $$ = mk_none(); }
+;
+
+maybe_as_trait_ref
+: AS trait_ref { $$ = $2; }
+| %empty       { $$ = mk_none(); }
+;
+
+lambda_expr
+: %prec LAMBDA
+  OROR ret_ty expr                                        { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); }
+| %prec LAMBDA
+  '|' maybe_unboxed_closure_kind '|' ret_ty expr          { $$ = mk_node("ExprFnBlock", 3, mk_none(), $4, $5); }
+| %prec LAMBDA
+  '|' inferrable_params '|' ret_ty expr                   { $$ = mk_node("ExprFnBlock", 3, $2, $4, $5); }
+| %prec LAMBDA
+  '|' '&' maybe_mut ':' inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $5, $7, $8); }
+| %prec LAMBDA
+  '|' ':' inferrable_params '|' ret_ty expr               { $$ = mk_node("ExprFnBlock", 3, $3, $5, $6); }
+;
+
+lambda_expr_nostruct
+: %prec LAMBDA
+  OROR expr_nostruct                                        { $$ = mk_node("ExprFnBlock", 2, mk_none(), $2); }
+| %prec LAMBDA
+  '|' maybe_unboxed_closure_kind '|'  expr_nostruct         { $$ = mk_node("ExprFnBlock", 2, mk_none(), $4); }
+| %prec LAMBDA
+  '|' inferrable_params '|' expr_nostruct                   { $$ = mk_node("ExprFnBlock", 2, $2, $4); }
+| %prec LAMBDA
+  '|' '&' maybe_mut ':' inferrable_params '|' expr_nostruct { $$ = mk_node("ExprFnBlock", 2, $5, $7); }
+| %prec LAMBDA
+  '|' ':' inferrable_params '|' expr_nostruct               { $$ = mk_node("ExprFnBlock", 2, $3, $5); }
+
+;
+
+proc_expr
+: %prec LAMBDA
+  PROC '(' ')' expr                         { $$ = mk_node("ExprProc", 2, mk_none(), $4); }
+| %prec LAMBDA
+  PROC '(' inferrable_params ')' expr       { $$ = mk_node("ExprProc", 2, $3, $5); }
+;
+
+proc_expr_nostruct
+: %prec LAMBDA
+  PROC '(' ')' expr_nostruct                     { $$ = mk_node("ExprProc", 2, mk_none(), $4); }
+| %prec LAMBDA
+  PROC '(' inferrable_params ')' expr_nostruct   { $$ = mk_node("ExprProc", 2, $3, $5); }
+;
+
+vec_expr
+: maybe_exprs
+| exprs ';' expr { $$ = mk_node("VecRepeat", 2, $1, $3); }
+;
+
+struct_expr_fields
+: field_inits
+| field_inits ','
+| maybe_field_inits default_field_init { $$ = ext_node($1, 1, $2); }
+;
+
+maybe_field_inits
+: field_inits
+| field_inits ','
+| %empty { $$ = mk_none(); }
+;
+
+field_inits
+: field_init                 { $$ = mk_node("FieldInits", 1, $1); }
+| field_inits ',' field_init { $$ = ext_node($1, 1, $3); }
+;
+
+field_init
+: ident ':' expr   { $$ = mk_node("FieldInit", 2, $1, $3); }
+;
+
+default_field_init
+: DOTDOT expr   { $$ = mk_node("DefaultFieldInit", 1, $2); }
+;
+
+block_expr
+: expr_match
+| expr_if
+| expr_if_let
+| expr_while
+| expr_while_let
+| expr_loop
+| expr_for
+| UNSAFE block                                           { $$ = mk_node("UnsafeBlock", 1, $2); }
+| path_expr '!' maybe_ident braces_delimited_token_trees { $$ = mk_node("Macro", 3, $1, $3, $4); }
+;
+
+full_block_expr
+: block_expr
+| full_block_expr '.' path_generic_args_with_colons %prec IDENT         { $$ = mk_node("ExprField", 2, $1, $3); }
+| full_block_expr '.' path_generic_args_with_colons '[' maybe_expr ']'  { $$ = mk_node("ExprIndex", 3, $1, $3, $5); }
+| full_block_expr '.' path_generic_args_with_colons '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 3, $1, $3, $5); }
+| full_block_expr '.' LIT_INTEGER                                       { $$ = mk_node("ExprTupleIndex", 1, $1); }
+;
+
+expr_match
+: MATCH expr_nostruct '{' '}'                                     { $$ = mk_node("ExprMatch", 1, $2); }
+| MATCH expr_nostruct '{' match_clauses                       '}' { $$ = mk_node("ExprMatch", 2, $2, $4); }
+| MATCH expr_nostruct '{' match_clauses nonblock_match_clause '}' { $$ = mk_node("ExprMatch", 2, $2, ext_node($4, 1, $5)); }
+| MATCH expr_nostruct '{'               nonblock_match_clause '}' { $$ = mk_node("ExprMatch", 2, $2, mk_node("Arms", 1, $4)); }
+;
+
+match_clauses
+: match_clause               { $$ = mk_node("Arms", 1, $1); }
+| match_clauses match_clause { $$ = ext_node($1, 1, $2); }
+;
+
+match_clause
+: nonblock_match_clause ','
+| block_match_clause
+| block_match_clause ','
+;
+
+nonblock_match_clause
+: maybe_outer_attrs pats_or maybe_guard FAT_ARROW nonblock_expr   { $$ = mk_node("Arm", 4, $1, $2, $3, $5); }
+| maybe_outer_attrs pats_or maybe_guard FAT_ARROW full_block_expr { $$ = mk_node("Arm", 4, $1, $2, $3, $5); }
+;
+
+block_match_clause
+: maybe_outer_attrs pats_or maybe_guard FAT_ARROW block { $$ = mk_node("Arm", 4, $1, $2, $3, $5); }
+;
+
+maybe_guard
+: IF expr_nostruct           { $$ = $2; }
+| %empty                     { $$ = mk_none(); }
+;
+
+expr_if
+: IF expr_nostruct block                              { $$ = mk_node("ExprIf", 2, $2, $3); }
+| IF expr_nostruct block ELSE block_or_if             { $$ = mk_node("ExprIf", 3, $2, $3, $5); }
+;
+
+expr_if_let
+: IF LET pat '=' expr_nostruct block                  { $$ = mk_node("ExprIfLet", 3, $3, $5, $6); }
+| IF LET pat '=' expr_nostruct block ELSE block_or_if { $$ = mk_node("ExprIfLet", 4, $3, $5, $6, $8); }
+;
+
+block_or_if
+: block
+| expr_if
+| expr_if_let
+;
+
+expr_while
+: maybe_label WHILE expr_nostruct block               { $$ = mk_node("ExprWhile", 3, $1, $3, $4); }
+;
+
+expr_while_let
+: maybe_label WHILE LET pat '=' expr_nostruct block   { $$ = mk_node("ExprWhileLet", 4, $1, $4, $6, $7); }
+;
+
+expr_loop
+: maybe_label LOOP block                              { $$ = mk_node("ExprLoop", 2, $1, $3); }
+;
+
+expr_for
+: maybe_label FOR pat IN expr_nostruct block          { $$ = mk_node("ExprForLoop", 4, $1, $3, $5, $6); }
+;
+
+maybe_label
+: lifetime ':'
+| %empty { $$ = mk_none(); }
+;
+
+let
+: LET pat maybe_ty_ascription maybe_init_expr ';' { $$ = mk_node("DeclLocal", 3, $2, $3, $4); }
+;
+
+////////////////////////////////////////////////////////////////////////
+// Part 5: Macros and misc. rules
+////////////////////////////////////////////////////////////////////////
+
+lit
+: LIT_BYTE                   { $$ = mk_node("LitByte", 1, mk_atom(yytext)); }
+| LIT_CHAR                   { $$ = mk_node("LitChar", 1, mk_atom(yytext)); }
+| LIT_INTEGER                { $$ = mk_node("LitInteger", 1, mk_atom(yytext)); }
+| LIT_FLOAT                  { $$ = mk_node("LitFloat", 1, mk_atom(yytext)); }
+| TRUE                       { $$ = mk_node("LitBool", 1, mk_atom(yytext)); }
+| FALSE                      { $$ = mk_node("LitBool", 1, mk_atom(yytext)); }
+| str
+;
+
+str
+: LIT_STR                    { $$ = mk_node("LitStr", 1, mk_atom(yytext), mk_atom("CookedStr")); }
+| LIT_STR_RAW                { $$ = mk_node("LitStr", 1, mk_atom(yytext), mk_atom("RawStr")); }
+| LIT_BYTE_STR                 { $$ = mk_node("LitByteStr", 1, mk_atom(yytext), mk_atom("ByteStr")); }
+| LIT_BYTE_STR_RAW             { $$ = mk_node("LitByteStr", 1, mk_atom(yytext), mk_atom("RawByteStr")); }
+;
+
+maybe_ident
+: %empty { $$ = mk_none(); }
+| ident
+;
+
+ident
+: IDENT                      { $$ = mk_node("ident", 1, mk_atom(yytext)); }
+;
+
+unpaired_token
+: SHL                        { $$ = mk_atom(yytext); }
+| SHR                        { $$ = mk_atom(yytext); }
+| LE                         { $$ = mk_atom(yytext); }
+| EQEQ                       { $$ = mk_atom(yytext); }
+| NE                         { $$ = mk_atom(yytext); }
+| GE                         { $$ = mk_atom(yytext); }
+| ANDAND                     { $$ = mk_atom(yytext); }
+| OROR                       { $$ = mk_atom(yytext); }
+| LARROW                     { $$ = mk_atom(yytext); }
+| SHLEQ                      { $$ = mk_atom(yytext); }
+| SHREQ                      { $$ = mk_atom(yytext); }
+| MINUSEQ                    { $$ = mk_atom(yytext); }
+| ANDEQ                      { $$ = mk_atom(yytext); }
+| OREQ                       { $$ = mk_atom(yytext); }
+| PLUSEQ                     { $$ = mk_atom(yytext); }
+| STAREQ                     { $$ = mk_atom(yytext); }
+| SLASHEQ                    { $$ = mk_atom(yytext); }
+| CARETEQ                    { $$ = mk_atom(yytext); }
+| PERCENTEQ                  { $$ = mk_atom(yytext); }
+| DOTDOT                     { $$ = mk_atom(yytext); }
+| DOTDOTDOT                  { $$ = mk_atom(yytext); }
+| MOD_SEP                    { $$ = mk_atom(yytext); }
+| RARROW                     { $$ = mk_atom(yytext); }
+| FAT_ARROW                  { $$ = mk_atom(yytext); }
+| LIT_BYTE                   { $$ = mk_atom(yytext); }
+| LIT_CHAR                   { $$ = mk_atom(yytext); }
+| LIT_INTEGER                { $$ = mk_atom(yytext); }
+| LIT_FLOAT                  { $$ = mk_atom(yytext); }
+| LIT_STR                    { $$ = mk_atom(yytext); }
+| LIT_STR_RAW                { $$ = mk_atom(yytext); }
+| LIT_BYTE_STR               { $$ = mk_atom(yytext); }
+| LIT_BYTE_STR_RAW           { $$ = mk_atom(yytext); }
+| IDENT                      { $$ = mk_atom(yytext); }
+| UNDERSCORE                 { $$ = mk_atom(yytext); }
+| LIFETIME                   { $$ = mk_atom(yytext); }
+| SELF                       { $$ = mk_atom(yytext); }
+| STATIC                     { $$ = mk_atom(yytext); }
+| AS                         { $$ = mk_atom(yytext); }
+| BREAK                      { $$ = mk_atom(yytext); }
+| CRATE                      { $$ = mk_atom(yytext); }
+| ELSE                       { $$ = mk_atom(yytext); }
+| ENUM                       { $$ = mk_atom(yytext); }
+| EXTERN                     { $$ = mk_atom(yytext); }
+| FALSE                      { $$ = mk_atom(yytext); }
+| FN                         { $$ = mk_atom(yytext); }
+| FOR                        { $$ = mk_atom(yytext); }
+| IF                         { $$ = mk_atom(yytext); }
+| IMPL                       { $$ = mk_atom(yytext); }
+| IN                         { $$ = mk_atom(yytext); }
+| LET                        { $$ = mk_atom(yytext); }
+| LOOP                       { $$ = mk_atom(yytext); }
+| MATCH                      { $$ = mk_atom(yytext); }
+| MOD                        { $$ = mk_atom(yytext); }
+| MOVE                       { $$ = mk_atom(yytext); }
+| MUT                        { $$ = mk_atom(yytext); }
+| PRIV                       { $$ = mk_atom(yytext); }
+| PUB                        { $$ = mk_atom(yytext); }
+| REF                        { $$ = mk_atom(yytext); }
+| RETURN                     { $$ = mk_atom(yytext); }
+| STRUCT                     { $$ = mk_atom(yytext); }
+| TRUE                       { $$ = mk_atom(yytext); }
+| TRAIT                      { $$ = mk_atom(yytext); }
+| TYPE                       { $$ = mk_atom(yytext); }
+| UNSAFE                     { $$ = mk_atom(yytext); }
+| USE                        { $$ = mk_atom(yytext); }
+| WHILE                      { $$ = mk_atom(yytext); }
+| CONTINUE                   { $$ = mk_atom(yytext); }
+| PROC                       { $$ = mk_atom(yytext); }
+| BOX                        { $$ = mk_atom(yytext); }
+| CONST                      { $$ = mk_atom(yytext); }
+| WHERE                      { $$ = mk_atom(yytext); }
+| TYPEOF                     { $$ = mk_atom(yytext); }
+| INNER_DOC_COMMENT          { $$ = mk_atom(yytext); }
+| OUTER_DOC_COMMENT          { $$ = mk_atom(yytext); }
+| SHEBANG                    { $$ = mk_atom(yytext); }
+| STATIC_LIFETIME            { $$ = mk_atom(yytext); }
+| ';'                        { $$ = mk_atom(yytext); }
+| ','                        { $$ = mk_atom(yytext); }
+| '.'                        { $$ = mk_atom(yytext); }
+| '@'                        { $$ = mk_atom(yytext); }
+| '#'                        { $$ = mk_atom(yytext); }
+| '~'                        { $$ = mk_atom(yytext); }
+| ':'                        { $$ = mk_atom(yytext); }
+| '$'                        { $$ = mk_atom(yytext); }
+| '='                        { $$ = mk_atom(yytext); }
+| '?'                        { $$ = mk_atom(yytext); }
+| '!'                        { $$ = mk_atom(yytext); }
+| '<'                        { $$ = mk_atom(yytext); }
+| '>'                        { $$ = mk_atom(yytext); }
+| '-'                        { $$ = mk_atom(yytext); }
+| '&'                        { $$ = mk_atom(yytext); }
+| '|'                        { $$ = mk_atom(yytext); }
+| '+'                        { $$ = mk_atom(yytext); }
+| '*'                        { $$ = mk_atom(yytext); }
+| '/'                        { $$ = mk_atom(yytext); }
+| '^'                        { $$ = mk_atom(yytext); }
+| '%'                        { $$ = mk_atom(yytext); }
+;
+
+token_trees
+: %empty                     { $$ = mk_node("TokenTrees", 0); }
+| token_trees token_tree     { $$ = ext_node($1, 1, $2); }
+;
+
+token_tree
+: delimited_token_trees
+| unpaired_token         { $$ = mk_node("TTTok", 1, $1); }
+;
+
+delimited_token_trees
+: parens_delimited_token_trees
+| braces_delimited_token_trees
+| brackets_delimited_token_trees
+;
+
+parens_delimited_token_trees
+: '(' token_trees ')'
+{
+  $$ = mk_node("TTDelim", 3,
+               mk_node("TTTok", 1, mk_atom("(")),
+               $2,
+               mk_node("TTTok", 1, mk_atom(")")));
+}
+;
+
+braces_delimited_token_trees
+: '{' token_trees '}'
+{
+  $$ = mk_node("TTDelim", 3,
+               mk_node("TTTok", 1, mk_atom("{")),
+               $2,
+               mk_node("TTTok", 1, mk_atom("}")));
+}
+;
+
+brackets_delimited_token_trees
+: '[' token_trees ']'
+{
+  $$ = mk_node("TTDelim", 3,
+               mk_node("TTTok", 1, mk_atom("[")),
+               $2,
+               mk_node("TTTok", 1, mk_atom("]")));
+}
+;
\ No newline at end of file
diff --git a/src/grammar/raw-string-literal-ambiguity.md b/src/grammar/raw-string-literal-ambiguity.md
new file mode 100644 (file)
index 0000000..c909f23
--- /dev/null
@@ -0,0 +1,64 @@
+Rust's lexical grammar is not context-free. Raw string literals are the source
+of the problem. Informally, a raw string literal is an `r`, followed by `N`
+hashes (where N can be zero), a quote, any characters, then a quote followed
+by `N` hashes. Critically, once inside the first pair of quotes,
+another quote cannot be followed by `N` consecutive hashes. e.g.
+`r###""###"###` is invalid.
+
+This grammar describes this as best possible:
+
+    R -> 'r' S
+    S -> '"' B '"'
+    S -> '#' S '#'
+    B -> . B
+    B -> ε
+
+Where `.` represents any character, and `ε` the empty string. Consider the
+string `r#""#"#`. This string is not a valid raw string literal, but can be
+accepted as one by the above grammar, using the derivation:
+
+    R : #""#"#
+    S : ""#"
+    S : "#
+    B : #
+    B : ε
+
+(Where `T : U` means the rule `T` is applied, and `U` is the remainder of the
+string.) The difficulty arises from the fact that it is fundamentally
+context-sensitive. In particular, the context needed is the number of hashes.
+
+To prove that Rust's string literals are not context-free, we will use
+the fact that context-free languages are closed under intersection with
+regular languages, and the
+[pumping lemma for context-free languages](https://en.wikipedia.org/wiki/Pumping_lemma_for_context-free_languages).
+
+Consider the regular language `R = r#+""#*"#+`. If Rust's raw string literals are
+context-free, then their intersection with `R`, `R'`, should also be context-free.
+Therefore, to prove that raw string literals are not context-free,
+it is sufficient to prove that `R'` is not context-free.
+
+The language `R'` is `{r#^n""#^m"#^n | m < n}`.
+
+Assume `R'` *is* context-free. Then `R'` has some pumping length `p > 0` for which
+the pumping lemma applies. Consider the following string `s` in `R'`:
+
+`r#^p""#^{p-1}"#^p`
+
+e.g. for `p = 2`: `s = r##""#"##`
+
+Then `s = uvwxy` for some choice of `uvwxy` such that `vx` is non-empty,
+`|vwx| < p+1`, and `uv^iwx^iy` is in `R'` for all `i >= 0`.
+
+Neither `v` nor `x` can contain a `"` or `r`, as the number of these characters
+in any string in `R'` is fixed. So `v` and `x` contain only hashes.
+Consequently, of the three sequences of hashes, `v` and `x` combined
+can only pump two of them.
+If we ever choose the central sequence of hashes, then one of the outer sequences
+will not grow when we pump, leading to an imbalance between the outer sequences.
+Therefore, we must pump both outer sequences of hashes. However,
+there are `p+2` characters between these two sequences of hashes, and `|vwx|` must
+be less than `p+1`. Therefore we have a contradiction, and `R'` must not be
+context-free.
+
+Since `R'` is not context-free, it follows that the Rust's raw string literals
+must not be context-free.
diff --git a/src/grammar/testparser.py b/src/grammar/testparser.py
new file mode 100755 (executable)
index 0000000..37be41b
--- /dev/null
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+#
+# 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.
+
+# ignore-tidy-linelength
+
+import sys
+
+import os
+import subprocess
+import argparse
+
+# usage: testparser.py [-h] [-p PARSER [PARSER ...]] -s SOURCE_DIR
+
+# Parsers should read from stdin and return exit status 0 for a
+# successful parse, and nonzero for an unsuccessful parse
+
+parser = argparse.ArgumentParser()
+parser.add_argument('-p', '--parser', nargs='+')
+parser.add_argument('-s', '--source-dir', nargs=1, required=True)
+args = parser.parse_args(sys.argv[1:])
+
+total = 0
+ok = {}
+bad = {}
+for parser in args.parser:
+    ok[parser] = 0
+    bad[parser] = []
+devnull = open(os.devnull, 'w')
+print("\n")
+
+for base, dirs, files in os.walk(args.source_dir[0]):
+    for f in filter(lambda p: p.endswith('.rs'), files):
+        p = os.path.join(base, f)
+        parse_fail = 'parse-fail' in p
+        if sys.version_info.major == 3:
+            lines = open(p, encoding='utf-8').readlines()
+        else:
+            lines = open(p).readlines()
+        if any('ignore-test' in line or 'ignore-lexer-test' in line for line in lines):
+            continue
+        total += 1
+        for parser in args.parser:
+            if subprocess.call(parser, stdin=open(p), stderr=subprocess.STDOUT, stdout=devnull) == 0:
+                if parse_fail:
+                    bad[parser].append(p)
+                else:
+                    ok[parser] += 1
+            else:
+                if parse_fail:
+                    ok[parser] += 1
+                else:
+                    bad[parser].append(p)
+        parser_stats = ', '.join(['{}: {}'.format(parser, ok[parser]) for parser in args.parser])
+        sys.stdout.write("\033[K\r total: {}, {}, scanned {}"
+                         .format(total, os.path.relpath(parser_stats), os.path.relpath(p)))
+
+devnull.close()
+
+print("\n")
+
+for parser in args.parser:
+    filename = os.path.basename(parser) + '.bad'
+    print("writing {} files that did not yield the correct result with {} to {}".format(len(bad[parser]), parser, filename))
+    with open(filename, "w") as f:
+        for p in bad[parser]:
+            f.write(p)
+            f.write("\n")
diff --git a/src/grammar/tokens.h b/src/grammar/tokens.h
new file mode 100644 (file)
index 0000000..081bd05
--- /dev/null
@@ -0,0 +1,91 @@
+// 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.
+
+enum Token {
+  SHL = 257, // Parser generators reserve 0-256 for char literals
+  SHR,
+  LE,
+  EQEQ,
+  NE,
+  GE,
+  ANDAND,
+  OROR,
+  SHLEQ,
+  SHREQ,
+  MINUSEQ,
+  ANDEQ,
+  OREQ,
+  PLUSEQ,
+  STAREQ,
+  SLASHEQ,
+  CARETEQ,
+  PERCENTEQ,
+  DOTDOT,
+  DOTDOTDOT,
+  MOD_SEP,
+  RARROW,
+  FAT_ARROW,
+  LIT_BYTE,
+  LIT_CHAR,
+  LIT_INTEGER,
+  LIT_FLOAT,
+  LIT_STR,
+  LIT_STR_RAW,
+  LIT_BYTE_STR,
+  LIT_BYTE_STR_RAW,
+  IDENT,
+  UNDERSCORE,
+  LIFETIME,
+
+  // keywords
+  SELF,
+  STATIC,
+  AS,
+  BREAK,
+  CRATE,
+  ELSE,
+  ENUM,
+  EXTERN,
+  FALSE,
+  FN,
+  FOR,
+  IF,
+  IMPL,
+  IN,
+  LET,
+  LOOP,
+  MATCH,
+  MOD,
+  MOVE,
+  MUT,
+  PRIV,
+  PUB,
+  REF,
+  RETURN,
+  STRUCT,
+  TRUE,
+  TRAIT,
+  TYPE,
+  UNSAFE,
+  USE,
+  WHILE,
+  CONTINUE,
+  PROC,
+  BOX,
+  CONST,
+  WHERE,
+  TYPEOF,
+  INNER_DOC_COMMENT,
+  OUTER_DOC_COMMENT,
+
+  SHEBANG,
+  SHEBANG_LINE,
+  STATIC_LIFETIME
+};
index 11bfb0dcf85f7aa92abd30524bb1e42e18d108c6..3288e0659c08fb5006f6d6dd4b5675ed0c2c432a 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 11bfb0dcf85f7aa92abd30524bb1e42e18d108c6
+Subproject commit 3288e0659c08fb5006f6d6dd4b5675ed0c2c432a
index 6d85183faf75d9867b2f54d531b74e30973b9a07..27ecefe043b1e333b7788a4444c74ff519c35be3 100644 (file)
 /// exception. If you need to mutate through an `Arc`, use [`Mutex`][mutex],
 /// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types.
 ///
-/// `Arc` uses atomic operations for reference counting, so `Arc`s can be
-/// sent between threads. In other words, `Arc<T>` implements [`Send`]
-/// as long as `T` implements [`Send`] and [`Sync`][sync]. The disadvantage is
-/// that atomic operations are more expensive than ordinary memory accesses.
-/// If you are not sharing reference-counted values between threads, consider
-/// using [`rc::Rc`][`Rc`] for lower overhead. [`Rc`] is a safe default, because
-/// the compiler will catch any attempt to send an [`Rc`] between threads.
-/// However, a library might choose `Arc` in order to give library consumers
+/// ## Thread Safety
+///
+/// Unlike [`Rc<T>`], `Arc<T>` uses atomic operations for its reference
+/// counting  This means that it is thread-safe. The disadvantage is that
+/// atomic operations are more expensive than ordinary memory accesses. If you
+/// are not sharing reference-counted values between threads, consider using
+/// [`Rc<T>`] for lower overhead. [`Rc<T>`] is a safe default, because the
+/// compiler will catch any attempt to send an [`Rc<T>`] between threads.
+/// However, a library might choose `Arc<T>` in order to give library consumers
 /// more flexibility.
 ///
+/// `Arc<T>` will implement [`Send`] and [`Sync`] as long as the `T` implements
+/// [`Send`] and [`Sync`]. Why can't you put a non-thread-safe type `T` in an
+/// `Arc<T>` to make it thread-safe? This may be a bit counter-intuitive at
+/// first: after all, isn't the point of `Arc<T>` thread safety? The key is
+/// this: `Arc<T>` makes it thread safe to have multiple ownership of the same
+/// data, but it  doesn't add thread safety to its data. Consider
+/// `Arc<RefCell<T>>`. `RefCell<T>` isn't [`Sync`], and if `Arc<T>` was always
+/// [`Send`], `Arc<RefCell<T>>` would be as well. But then we'd have a problem:
+/// `RefCell<T>` is not thread safe; it keeps track of the borrowing count using
+/// non-atomic operations.
+///
+/// In the end, this means that you may need to pair `Arc<T>` with some sort of
+/// `std::sync` type, usually `Mutex<T>`.
+///
+/// ## Breaking cycles with `Weak`
+///
 /// The [`downgrade`][downgrade] method can be used to create a non-owning
 /// [`Weak`][weak] pointer. A [`Weak`][weak] pointer can be [`upgrade`][upgrade]d
 /// to an `Arc`, but this will return [`None`] if the value has already been
@@ -74,6 +91,8 @@
 /// strong `Arc` pointers from parent nodes to children, and [`Weak`][weak]
 /// pointers from children back to their parents.
 ///
+/// ## `Deref` behavior
+///
 /// `Arc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait),
 /// so you can call `T`'s methods on a value of type `Arc<T>`. To avoid name
 /// clashes with `T`'s methods, the methods of `Arc<T>` itself are [associated
 ///
 /// [arc]: struct.Arc.html
 /// [weak]: struct.Weak.html
-/// [`Rc`]: ../../std/rc/struct.Rc.html
+/// [`Rc<T>`]: ../../std/rc/struct.Rc.html
 /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
 /// [mutex]: ../../std/sync/struct.Mutex.html
 /// [rwlock]: ../../std/sync/struct.RwLock.html
 /// [atomic]: ../../std/sync/atomic/index.html
 /// [`Send`]: ../../std/marker/trait.Send.html
-/// [sync]: ../../std/marker/trait.Sync.html
+/// [`Sync`]: ../../std/marker/trait.Sync.html
 /// [deref]: ../../std/ops/trait.Deref.html
 /// [downgrade]: struct.Arc.html#method.downgrade
 /// [upgrade]: struct.Weak.html#method.upgrade
index f3a0eebe6984d2a11ca73d93871b6c4314683c15..859e414a6fe7c18afc9789b77c0bc304f2b2c9d4 100644 (file)
@@ -93,29 +93,7 @@ fn main() {
        .env("AR", &ar)
        .env("RANLIB", format!("{} s", ar.display()));
 
-    if target.contains("windows") {
-        // A bit of history here, this used to be --enable-lazy-lock added in
-        // #14006 which was filed with jemalloc in jemalloc/jemalloc#83 which
-        // was also reported to MinGW:
-        //
-        //  http://sourceforge.net/p/mingw-w64/bugs/395/
-        //
-        // When updating jemalloc to 4.0, however, it was found that binaries
-        // would exit with the status code STATUS_RESOURCE_NOT_OWNED indicating
-        // that a thread was unlocking a mutex it never locked. Disabling this
-        // "lazy lock" option seems to fix the issue, but it was enabled by
-        // default for MinGW targets in 13473c7 for jemalloc.
-        //
-        // As a result of all that, force disabling lazy lock on Windows, and
-        // after reading some code it at least *appears* that the initialization
-        // of mutexes is otherwise ok in jemalloc, so shouldn't cause problems
-        // hopefully...
-        //
-        // tl;dr: make windows behave like other platforms by disabling lazy
-        //        locking, but requires passing an option due to a historical
-        //        default with jemalloc.
-        cmd.arg("--disable-lazy-lock");
-    } else if target.contains("ios") {
+    if target.contains("ios") {
         cmd.arg("--disable-tls");
     } else if target.contains("android") {
         // We force android to have prefixed symbols because apparently
index 321fa2edd56c7717e9bb2aaa243392d175b5feb1..c4c1635aa2a5a34cdfeae7b881536d008823f049 100644 (file)
@@ -19,7 +19,7 @@
 //! objects of a single type.
 
 #![crate_name = "arena"]
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -32,7 +32,7 @@
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
 #![feature(generic_param_attrs)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
 #![cfg_attr(test, feature(test))]
 
 #![allow(deprecated)]
index 42064e9ca575056b9811ce91cec267ac75ed055d..9f356e4b57912af410b56fcb4f4b7903a4c27c88 100644 (file)
@@ -10,7 +10,9 @@
 
 #![deny(warnings)]
 
+#![feature(i128_type)]
 #![feature(rand)]
+#![feature(repr_simd)]
 #![feature(sort_unstable)]
 #![feature(test)]
 
index 7195a9f9bf2c6ad53134af4398c2b92bb41b96f7..0079f2d01036cf76d5fa956a75ce7acdb0ec127f 100644 (file)
@@ -290,3 +290,28 @@ fn $name(b: &mut Bencher) {
 sort!(sort_unstable, sort_unstable_large_big_random, gen_big_random, 10000);
 sort!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000);
 sort_expensive!(sort_unstable_by, sort_unstable_large_random_expensive, gen_random, 10000);
+
+macro_rules! reverse {
+    ($name:ident, $ty:ty, $f:expr) => {
+        #[bench]
+        fn $name(b: &mut Bencher) {
+            // odd length and offset by 1 to be as unaligned as possible
+            let n = 0xFFFFF;
+            let mut v: Vec<_> =
+                (0..1+(n / mem::size_of::<$ty>() as u64))
+                .map($f)
+                .collect();
+            b.iter(|| black_box(&mut v[1..]).reverse());
+            b.bytes = n;
+        }
+    }
+}
+
+reverse!(reverse_u8, u8, |x| x as u8);
+reverse!(reverse_u16, u16, |x| x as u16);
+reverse!(reverse_u8x3, [u8;3], |x| [x as u8, (x>>8) as u8, (x>>16) as u8]);
+reverse!(reverse_u32, u32, |x| x as u32);
+reverse!(reverse_u64, u64, |x| x as u64);
+reverse!(reverse_u128, u128, |x| x as u128);
+#[repr(simd)] struct F64x4(f64, f64, f64, f64);
+reverse!(reverse_simd_f64x4, F64x4, |x| { let x = x as f64; F64x4(x,x,x,x) });
index 964660183e751c31f6a465e248c7e37b28ba74a3..5f4578bbeb36845ac862249368c73e4420e44063 100644 (file)
@@ -176,18 +176,6 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a> FusedIterator for EncodeUtf16<'a> {}
 
-// Return the initial codepoint accumulator for the first byte.
-// The first byte is special, only want bottom 5 bits for width 2, 4 bits
-// for width 3, and 3 bits for width 4
-macro_rules! utf8_first_byte {
-    ($byte:expr, $width:expr) => (($byte & (0x7F >> $width)) as u32)
-}
-
-// return the value of $ch updated with continuation byte $byte
-macro_rules! utf8_acc_cont_byte {
-    ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & 63) as u32)
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Borrow<str> for String {
     #[inline]
index c3e5304fb2b3544b855e7441d7ab32d88e0b7b09..1708f98b7ee47c2ab40ff0807fec183e09de2eea 100644 (file)
@@ -379,6 +379,16 @@ fn test_reverse() {
     let mut v3 = Vec::<i32>::new();
     v3.reverse();
     assert!(v3.is_empty());
+
+    // check the 1-byte-types path
+    let mut v = (-50..51i8).collect::<Vec<_>>();
+    v.reverse();
+    assert_eq!(v, (-50..51i8).rev().collect::<Vec<_>>());
+
+    // check the 2-byte-types path
+    let mut v = (-50..51i16).collect::<Vec<_>>();
+    v.reverse();
+    assert_eq!(v, (-50..51i16).rev().collect::<Vec<_>>());
 }
 
 #[test]
index 7ec5c29de6b4be49918d8bc5678f51a0ef665d29..1cf713290d8e8b7e7ea65b6b9af21f961a73c337 100644 (file)
@@ -1220,11 +1220,14 @@ pub fn split_off(&mut self, at: usize) -> Self {
 }
 
 impl<T: Clone> Vec<T> {
-    /// Resizes the `Vec` in-place so that `len()` is equal to `new_len`.
+    /// Resizes the `Vec` in-place so that `len` is equal to `new_len`.
     ///
-    /// If `new_len` is greater than `len()`, the `Vec` is extended by the
+    /// If `new_len` is greater than `len`, the `Vec` is extended by the
     /// difference, with each additional slot filled with `value`.
-    /// If `new_len` is less than `len()`, the `Vec` is simply truncated.
+    /// If `new_len` is less than `len`, the `Vec` is simply truncated.
+    ///
+    /// This method requires `Clone` to clone the passed value. If you'd
+    /// rather create a value with `Default` instead, see [`resize_default`].
     ///
     /// # Examples
     ///
@@ -1237,19 +1240,100 @@ impl<T: Clone> Vec<T> {
     /// vec.resize(2, 0);
     /// assert_eq!(vec, [1, 2]);
     /// ```
+    ///
+    /// [`resize_default`]: #method.resize_default
     #[stable(feature = "vec_resize", since = "1.5.0")]
     pub fn resize(&mut self, new_len: usize, value: T) {
         let len = self.len();
 
         if new_len > len {
-            self.extend_with_element(new_len - len, value);
+            self.extend_with(new_len - len, ExtendElement(value))
+        } else {
+            self.truncate(new_len);
+        }
+    }
+
+    /// Clones and appends all elements in a slice to the `Vec`.
+    ///
+    /// Iterates over the slice `other`, clones each element, and then appends
+    /// it to this `Vec`. The `other` vector is traversed in-order.
+    ///
+    /// Note that this function is same as `extend` except that it is
+    /// specialized to work with slices instead. If and when Rust gets
+    /// specialization this function will likely be deprecated (but still
+    /// available).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut vec = vec![1];
+    /// vec.extend_from_slice(&[2, 3, 4]);
+    /// assert_eq!(vec, [1, 2, 3, 4]);
+    /// ```
+    #[stable(feature = "vec_extend_from_slice", since = "1.6.0")]
+    pub fn extend_from_slice(&mut self, other: &[T]) {
+        self.spec_extend(other.iter())
+    }
+}
+
+impl<T: Default> Vec<T> {
+    /// Resizes the `Vec` in-place so that `len` is equal to `new_len`.
+    ///
+    /// If `new_len` is greater than `len`, the `Vec` is extended by the
+    /// difference, with each additional slot filled with `Default::default()`.
+    /// If `new_len` is less than `len`, the `Vec` is simply truncated.
+    ///
+    /// This method uses `Default` to create new values on every push. If
+    /// you'd rather `Clone` a given value, use [`resize`].
+    ///
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(vec_resize_default)]
+    ///
+    /// let mut vec = vec![1, 2, 3];
+    /// vec.resize_default(5);
+    /// assert_eq!(vec, [1, 2, 3, 0, 0]);
+    ///
+    /// let mut vec = vec![1, 2, 3, 4];
+    /// vec.resize_default(2);
+    /// assert_eq!(vec, [1, 2]);
+    /// ```
+    ///
+    /// [`resize`]: #method.resize
+    #[unstable(feature = "vec_resize_default", issue = "41758")]
+    pub fn resize_default(&mut self, new_len: usize) {
+        let len = self.len();
+
+        if new_len > len {
+            self.extend_with(new_len - len, ExtendDefault);
         } else {
             self.truncate(new_len);
         }
     }
+}
 
-    /// Extend the vector by `n` additional clones of `value`.
-    fn extend_with_element(&mut self, n: usize, value: T) {
+// This code generalises `extend_with_{element,default}`.
+trait ExtendWith<T> {
+    fn next(&self) -> T;
+    fn last(self) -> T;
+}
+
+struct ExtendElement<T>(T);
+impl<T: Clone> ExtendWith<T> for ExtendElement<T> {
+    fn next(&self) -> T { self.0.clone() }
+    fn last(self) -> T { self.0 }
+}
+
+struct ExtendDefault;
+impl<T: Default> ExtendWith<T> for ExtendDefault {
+    fn next(&self) -> T { Default::default() }
+    fn last(self) -> T { Default::default() }
+}
+impl<T> Vec<T> {
+    /// Extend the vector by `n` values, using the given generator.
+    fn extend_with<E: ExtendWith<T>>(&mut self, n: usize, value: E) {
         self.reserve(n);
 
         unsafe {
@@ -1261,43 +1345,21 @@ fn extend_with_element(&mut self, n: usize, value: T) {
 
             // Write all elements except the last one
             for _ in 1..n {
-                ptr::write(ptr, value.clone());
+                ptr::write(ptr, value.next());
                 ptr = ptr.offset(1);
-                // Increment the length in every step in case clone() panics
+                // Increment the length in every step in case next() panics
                 local_len.increment_len(1);
             }
 
             if n > 0 {
                 // We can write the last element directly without cloning needlessly
-                ptr::write(ptr, value);
+                ptr::write(ptr, value.last());
                 local_len.increment_len(1);
             }
 
             // len set by scope guard
         }
     }
-
-    /// Clones and appends all elements in a slice to the `Vec`.
-    ///
-    /// Iterates over the slice `other`, clones each element, and then appends
-    /// it to this `Vec`. The `other` vector is traversed in-order.
-    ///
-    /// Note that this function is same as `extend` except that it is
-    /// specialized to work with slices instead. If and when Rust gets
-    /// specialization this function will likely be deprecated (but still
-    /// available).
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut vec = vec![1];
-    /// vec.extend_from_slice(&[2, 3, 4]);
-    /// assert_eq!(vec, [1, 2, 3, 4]);
-    /// ```
-    #[stable(feature = "vec_extend_from_slice", since = "1.6.0")]
-    pub fn extend_from_slice(&mut self, other: &[T]) {
-        self.spec_extend(other.iter())
-    }
 }
 
 // Set the length of the vec when the `SetLenOnDrop` value goes out of scope.
@@ -1389,7 +1451,7 @@ trait SpecFromElem: Sized {
 impl<T: Clone> SpecFromElem for T {
     default fn from_elem(elem: Self, n: usize) -> Vec<Self> {
         let mut v = Vec::with_capacity(n);
-        v.extend_with_element(n, elem);
+        v.extend_with(n, ExtendElement(elem));
         v
     }
 }
@@ -1424,7 +1486,7 @@ fn from_elem(elem: $t, n: usize) -> Vec<$t> {
                     }
                 }
                 let mut v = Vec::with_capacity(n);
-                v.extend_with_element(n, elem);
+                v.extend_with(n, ExtendElement(elem));
                 v
             }
         }
index 87def375b202b17e2e38c85cc62453e911b7992d..4825c2aa132640abc14c27cc5e2f7ce040ed3928 100644 (file)
@@ -21,7 +21,7 @@ fn float_to_decimal_common_exact<T>(fmt: &mut Formatter, num: &T,
 {
     unsafe {
         let mut buf: [u8; 1024] = mem::uninitialized(); // enough for f32 and f64
-        let mut parts: [flt2dec::Part; 5] = mem::uninitialized();
+        let mut parts: [flt2dec::Part; 4] = mem::uninitialized();
         let formatted = flt2dec::to_exact_fixed_str(flt2dec::strategy::grisu::format_exact,
                                                     *num, sign, precision,
                                                     false, &mut buf, &mut parts);
@@ -39,7 +39,7 @@ fn float_to_decimal_common_shortest<T>(fmt: &mut Formatter,
     unsafe {
         // enough for f32 and f64
         let mut buf: [u8; flt2dec::MAX_SIG_DIGITS] = mem::uninitialized();
-        let mut parts: [flt2dec::Part; 5] = mem::uninitialized();
+        let mut parts: [flt2dec::Part; 4] = mem::uninitialized();
         let formatted = flt2dec::to_shortest_str(flt2dec::strategy::grisu::format_shortest,
                                                  *num, sign, 0, false, &mut buf, &mut parts);
         fmt.pad_formatted_parts(&formatted)
@@ -75,7 +75,7 @@ fn float_to_exponential_common_exact<T>(fmt: &mut Formatter, num: &T,
 {
     unsafe {
         let mut buf: [u8; 1024] = mem::uninitialized(); // enough for f32 and f64
-        let mut parts: [flt2dec::Part; 7] = mem::uninitialized();
+        let mut parts: [flt2dec::Part; 6] = mem::uninitialized();
         let formatted = flt2dec::to_exact_exp_str(flt2dec::strategy::grisu::format_exact,
                                                   *num, sign, precision,
                                                   upper, &mut buf, &mut parts);
@@ -94,7 +94,7 @@ fn float_to_exponential_common_shortest<T>(fmt: &mut Formatter,
     unsafe {
         // enough for f32 and f64
         let mut buf: [u8; flt2dec::MAX_SIG_DIGITS] = mem::uninitialized();
-        let mut parts: [flt2dec::Part; 7] = mem::uninitialized();
+        let mut parts: [flt2dec::Part; 6] = mem::uninitialized();
         let formatted = flt2dec::to_shortest_exp_str(flt2dec::strategy::grisu::format_shortest,
                                                      *num, sign, (0, 0), upper,
                                                      &mut buf, &mut parts);
index b3f4d75c4da617d61e5d6443ec479016e1ffc466..67b97afb9769a33e9379ed9cf6255a0875bba515 100644 (file)
@@ -119,7 +119,7 @@ pub trait Iterator {
     /// // exactly wouldn't be possible without executing filter().
     /// assert_eq!((0, Some(10)), iter.size_hint());
     ///
-    /// // Let's add one five more numbers with chain()
+    /// // Let's add five more numbers with chain()
     /// let iter = (0..10).filter(|x| x % 2 == 0).chain(15..20);
     ///
     /// // now both bounds are increased by five
index 80c2221ce641617c5be116dfe255f1bf1c0c8da6..b6ab1ecaf4e65643a88f325fadd305fe2428f0b1 100644 (file)
 #[macro_use]
 mod internal_macros;
 
-#[path = "num/float_macros.rs"]
-#[macro_use]
-mod float_macros;
-
 #[path = "num/int_macros.rs"]
 #[macro_use]
 mod int_macros;
diff --git a/src/libcore/num/float_macros.rs b/src/libcore/num/float_macros.rs
deleted file mode 100644 (file)
index b3adef5..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![doc(hidden)]
-
-macro_rules! assert_approx_eq {
-    ($a:expr, $b:expr) => ({
-        use num::Float;
-        let (a, b) = (&$a, &$b);
-        assert!((*a - *b).abs() < 1.0e-6,
-                "{} is not approximately equal to {}", *a, *b);
-    })
-}
index 5123e42df61ca8e013943c5d2be7f1f561d57299..74b9e7bf37d5110a754d51a532d2eef5e9ea8d00 100644 (file)
@@ -410,8 +410,8 @@ fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static
 /// it will only print given digits and nothing else.
 ///
 /// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long.
-/// There should be at least 5 parts available, due to the worst case like
-/// `[+][0.][0000][45][0000]` with `frac_digits = 10`.
+/// There should be at least 4 parts available, due to the worst case like
+/// `[+][0.][0000][2][0000]` with `frac_digits = 10`.
 pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T,
                                  sign: Sign, frac_digits: usize, _upper: bool,
                                  buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
@@ -465,8 +465,8 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T,
 /// cannot be in this range, avoiding any confusion.
 ///
 /// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long.
-/// There should be at least 7 parts available, due to the worst case like
-/// `[+][1][.][2345][e][-][67]`.
+/// There should be at least 6 parts available, due to the worst case like
+/// `[+][1][.][2345][e][-][6]`.
 pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T,
                                      sign: Sign, dec_bounds: (i16, i16), upper: bool,
                                      buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
@@ -544,8 +544,8 @@ fn estimate_max_buf_len(exp: i16) -> usize {
 /// The byte buffer should be at least `ndigits` bytes long unless `ndigits` is
 /// so large that only the fixed number of digits will be ever written.
 /// (The tipping point for `f64` is about 800, so 1000 bytes should be enough.)
-/// There should be at least 7 parts available, due to the worst case like
-/// `[+][1][.][2345][e][-][67]`.
+/// There should be at least 6 parts available, due to the worst case like
+/// `[+][1][.][2345][e][-][6]`.
 pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T,
                                   sign: Sign, ndigits: usize, upper: bool,
                                   buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
@@ -600,8 +600,8 @@ pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T,
 /// The byte buffer should be enough for the output unless `frac_digits` is
 /// so large that only the fixed number of digits will be ever written.
 /// (The tipping point for `f64` is about 800, and 1000 bytes should be enough.)
-/// There should be at least 5 parts available, due to the worst case like
-/// `[+][0.][0000][45][0000]` with `frac_digits = 10`.
+/// There should be at least 4 parts available, due to the worst case like
+/// `[+][0.][0000][2][0000]` with `frac_digits = 10`.
 pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T,
                                     sign: Sign, frac_digits: usize, _upper: bool,
                                     buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
index 18e2c1d5c73fd84cf1b1f1d6630e5133342979b7..8b4002fe9af244e585adc451e65c8ffdbae26406 100644 (file)
@@ -96,13 +96,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 pub mod bignum;
 pub mod diy_float;
 
-macro_rules! checked_op {
-    ($U:ty, $op:path, $x:expr, $y:expr) => {{
-        let (result, overflowed) = unsafe { $op($x as $U, $y as $U) };
-        if overflowed { None } else { Some(result as Self) }
-    }}
-}
-
 // `Int` + `SignedInt` implemented for signed integers
 macro_rules! int_impl {
     ($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr,
index 013f02685bad117149951d86e56b9c3f662d6f71..6cc374b13b7b3042257f13190f47f0bf95bdbd08 100644 (file)
@@ -12,6 +12,7 @@
 
 use ops::*;
 
+#[allow(unused_macros)]
 macro_rules! sh_impl_signed {
     ($t:ident, $f:ident) => (
         #[stable(feature = "rust1", since = "1.0.0")]
index 391b606f613f288970e7b74544d4e20e840eacb5..fc3af096b183880c4b3a61910e4fe5eae73e904d 100644 (file)
@@ -235,6 +235,42 @@ pub trait Drop {
 /// }
 /// ```
 ///
+/// Here is an example of the same `Point` struct implementing the `Add` trait
+/// using generics.
+///
+/// ```
+/// use std::ops::Add;
+///
+/// #[derive(Debug)]
+/// struct Point<T> {
+///     x: T,
+///     y: T,
+/// }
+///
+/// // Notice that the implementation uses the `Output` associated type
+/// impl<T: Add<Output=T>> Add for Point<T> {
+///     type Output = Point<T>;
+///
+///     fn add(self, other: Point<T>) -> Point<T> {
+///         Point {
+///             x: self.x + other.x,
+///             y: self.y + other.y,
+///         }
+///     }
+/// }
+///
+/// impl<T: PartialEq> PartialEq for Point<T> {
+///     fn eq(&self, other: &Self) -> bool {
+///         self.x == other.x && self.y == other.y
+///     }
+/// }
+///
+/// fn main() {
+///     assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
+///                Point { x: 3, y: 3 });
+/// }
+/// ```
+///
 /// Note that `RHS = Self` by default, but this is not mandatory. For example,
 /// [std::time::SystemTime] implements `Add<Duration>`, which permits
 /// operations of the form `SystemTime = SystemTime + Duration`.
@@ -763,6 +799,7 @@ macro_rules! neg_impl_numeric {
     ($($t:ty)*) => { neg_impl_core!{ x => -x, $($t)*} }
 }
 
+#[allow(unused_macros)]
 macro_rules! neg_impl_unsigned {
     ($($t:ty)*) => {
         neg_impl_core!{ x => {
index a60abefc076504027bdc99141b9add789bda7060..f89f86e18a149554d09dbf34f6f736ab22b93356 100644 (file)
@@ -56,7 +56,6 @@
 /// invalid pointers, types, and double drops.
 #[stable(feature = "drop_in_place", since = "1.8.0")]
 #[lang="drop_in_place"]
-#[inline]
 #[allow(unconditional_recursion)]
 pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
     // Code here does not matter - this is replaced by the
@@ -1005,7 +1004,7 @@ unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
 
 #[unstable(feature = "unique", issue = "27730")]
 impl<T: Sized> Unique<T> {
-    /// Creates a new `Shared` that is dangling, but well-aligned.
+    /// Creates a new `Unique` that is dangling, but well-aligned.
     ///
     /// This is useful for initializing types which lazily allocate, like
     /// `Vec::new` does.
index 9e3bd9115468ab22b8645ab1b14bb522da4c542d..e15eb8f24440956b5e1ff88e48b794ecca1194c6 100644 (file)
@@ -539,6 +539,55 @@ fn swap(&mut self, a: usize, b: usize) {
     fn reverse(&mut self) {
         let mut i: usize = 0;
         let ln = self.len();
+
+        // For very small types, all the individual reads in the normal
+        // path perform poorly.  We can do better, given efficient unaligned
+        // load/store, by loading a larger chunk and reversing a register.
+
+        // Ideally LLVM would do this for us, as it knows better than we do
+        // whether unaligned reads are efficient (since that changes between
+        // different ARM versions, for example) and what the best chunk size
+        // would be.  Unfortunately, as of LLVM 4.0 (2017-05) it only unrolls
+        // the loop, so we need to do this ourselves.  (Hypothesis: reverse
+        // is troublesome because the sides can be aligned differently --
+        // will be, when the length is odd -- so there's no way of emitting
+        // pre- and postludes to use fully-aligned SIMD in the middle.)
+
+        let fast_unaligned =
+            cfg!(any(target_arch = "x86", target_arch = "x86_64"));
+
+        if fast_unaligned && mem::size_of::<T>() == 1 {
+            // Use the llvm.bswap intrinsic to reverse u8s in a usize
+            let chunk = mem::size_of::<usize>();
+            while i + chunk - 1 < ln / 2 {
+                unsafe {
+                    let pa: *mut T = self.get_unchecked_mut(i);
+                    let pb: *mut T = self.get_unchecked_mut(ln - i - chunk);
+                    let va = ptr::read_unaligned(pa as *mut usize);
+                    let vb = ptr::read_unaligned(pb as *mut usize);
+                    ptr::write_unaligned(pa as *mut usize, vb.swap_bytes());
+                    ptr::write_unaligned(pb as *mut usize, va.swap_bytes());
+                }
+                i += chunk;
+            }
+        }
+
+        if fast_unaligned && mem::size_of::<T>() == 2 {
+            // Use rotate-by-16 to reverse u16s in a u32
+            let chunk = mem::size_of::<u32>() / 2;
+            while i + chunk - 1 < ln / 2 {
+                unsafe {
+                    let pa: *mut T = self.get_unchecked_mut(i);
+                    let pb: *mut T = self.get_unchecked_mut(ln - i - chunk);
+                    let va = ptr::read_unaligned(pa as *mut u32);
+                    let vb = ptr::read_unaligned(pb as *mut u32);
+                    ptr::write_unaligned(pa as *mut u32, vb.rotate_left(16));
+                    ptr::write_unaligned(pb as *mut u32, va.rotate_left(16));
+                }
+                i += chunk;
+            }
+        }
+
         while i < ln / 2 {
             // Unsafe swap to avoid the bounds check in safe swap.
             unsafe {
index 3619be82829cade3559577dd57a0f9fe71da2d52..e0bea884f31c5a667245b373ffcc8744261f0fbb 100644 (file)
@@ -15,7 +15,7 @@
 //! [mz]: https://code.google.com/p/miniz/
 
 #![crate_name = "flate"]
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -25,7 +25,7 @@
 #![deny(warnings)]
 
 #![feature(libc)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
 #![feature(unique)]
 #![cfg_attr(test, feature(rand))]
 
index f5a687de64e486866ebf5dc9d519de567bca09f8..641a42b08188f8f64b9abfc3e8ee71e2dd798765 100644 (file)
@@ -15,7 +15,7 @@
 //! generated instead.
 
 #![crate_name = "fmt_macros"]
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -25,7 +25,7 @@
        test(attr(deny(warnings))))]
 #![deny(warnings)]
 
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
 #![feature(unicode)]
 
 pub use self::Piece::*;
index a5cd9fab2cf4bca92f621174243f803c904c6b0d..c69c68ba59c011a65e6b3aaa873f4fdb690d584e 100644 (file)
@@ -78,9 +78,9 @@
 //! ```
 
 #![crate_name = "getopts"]
-#![unstable(feature = "rustc_private",
+#![cfg_attr(stage0, unstable(feature = "rustc_private",
             reason = "use the crates.io `getopts` library instead",
-            issue = "27812")]
+            issue = "27812"))]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -91,7 +91,7 @@
 
 #![deny(missing_docs)]
 #![deny(warnings)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
 
 use self::Name::*;
 use self::HasArg::*;
index 1b2c7775185f78d9dbf9e318236f8d3e4e5c0426..2c6744e7c90533d7cf045c9fab97b9e294e3fb2c 100644 (file)
 //! * [DOT language](http://www.graphviz.org/doc/info/lang.html)
 
 #![crate_name = "graphviz"]
-#![unstable(feature = "rustc_private", issue = "27812")]
-#![feature(staged_api)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(staged_api))]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
index a6dad64125331cc4c6ab5d903615fffbe8be4389..68c5d49591839216c8e4dec12b29b084ea7529d0 100644 (file)
@@ -72,7 +72,7 @@
 //! }
 //! ```
 #![crate_name = "proc_macro_plugin"]
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
 #![feature(plugin_registrar)]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
@@ -81,9 +81,9 @@
        html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![deny(warnings)]
 
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
 #![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
+#![cfg_attr(stage0, feature(rustc_private))]
 
 extern crate rustc_plugin;
 extern crate syntax;
index ad71584b61a0fbf611965a1bc8af7758494f7073..09675564291a248b4ded93dddccee6aa6371a73f 100644 (file)
@@ -133,6 +133,14 @@ fn quote(&self) -> TokenStream {
     }
 }
 
+impl Quote for usize {
+    fn quote(&self) -> TokenStream {
+        let integer_symbol = Symbol::intern(&self.to_string());
+        TokenTree::Token(DUMMY_SP, Token::Literal(token::Lit::Integer(integer_symbol), None))
+            .into()
+    }
+}
+
 impl Quote for Ident {
     fn quote(&self) -> TokenStream {
         // FIXME(jseyfried) quote hygiene
@@ -193,15 +201,17 @@ macro_rules! gen_match {
 impl Quote for Lit {
     fn quote(&self) -> TokenStream {
         macro_rules! gen_match {
-            ($($i:ident),*) => {
+            ($($i:ident),*; $($raw:ident),*) => {
                 match *self {
                     $( Lit::$i(lit) => quote!(::syntax::parse::token::Lit::$i((quote lit))), )*
-                    _ => panic!("Unsupported literal"),
+                    $( Lit::$raw(lit, n) => {
+                        quote!(::syntax::parse::token::Lit::$raw((quote lit), (quote n)))
+                    })*
                 }
             }
         }
 
-        gen_match!(Byte, Char, Float, Str_, Integer, ByteStr)
+        gen_match!(Byte, Char, Float, Str_, Integer, ByteStr; StrRaw, ByteStrRaw)
     }
 }
 
index fa217acd9f9bf5e4eed1ea2feaede465f4450cbd..9d64f511914d6d3c2ec5b16a95a28886a2f3c8ba 100644 (file)
@@ -13,12 +13,12 @@ arena = { path = "../libarena" }
 fmt_macros = { path = "../libfmt_macros" }
 graphviz = { path = "../libgraphviz" }
 log = "0.3"
+owning_ref = "0.3.3"
 rustc_back = { path = "../librustc_back" }
 rustc_bitflags = { path = "../librustc_bitflags" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
-rustc_llvm = { path = "../librustc_llvm" }
 serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
index a8ad49c6582d4f14cc56311bcec6c57716a53d87..c1c195852f9492bddfe2406446ce1a4b78698b22 100644 (file)
@@ -10,6 +10,7 @@
 
 use rustc_data_structures::graph;
 use cfg::*;
+use middle::region::CodeExtent;
 use ty::{self, TyCtxt};
 use syntax::ast;
 use syntax::ptr::P;
@@ -586,8 +587,8 @@ fn add_exiting_edge(&mut self,
                         scope_id: ast::NodeId,
                         to_index: CFGIndex) {
         let mut data = CFGEdgeData { exiting_scopes: vec![] };
-        let mut scope = self.tcx.node_extent(from_expr.id);
-        let target_scope = self.tcx.node_extent(scope_id);
+        let mut scope = CodeExtent::Misc(from_expr.id);
+        let target_scope = CodeExtent::Misc(scope_id);
         let region_maps = self.tcx.region_maps(self.owner_def_id);
         while scope != target_scope {
             data.exiting_scopes.push(scope.node_id());
index 12e0d4d3ea26cf6907a7d608098d34b4abb543e0..15c4469b74694c98d3108c0002a9840329f6b53f 100644 (file)
@@ -51,6 +51,9 @@ pub enum DepNode<D: Clone + Debug> {
     // in an extern crate.
     MetaData(D),
 
+    // Represents some piece of metadata global to its crate.
+    GlobalMetaData(D, GlobalMetaDataKind),
+
     // Represents some artifact that we save to disk. Note that these
     // do not have a def-id as part of their identifier.
     WorkProduct(Arc<WorkProductId>),
@@ -79,7 +82,6 @@ pub enum DepNode<D: Clone + Debug> {
     MirKeys,
     LateLintCheck,
     TransCrateItem(D),
-    TransInlinedItem(D),
     TransWriteMetadata,
     CrateVariances,
 
@@ -104,6 +106,8 @@ pub enum DepNode<D: Clone + Debug> {
     UsedTraitImports(D),
     ConstEval(D),
     SymbolName(D),
+    SpecializationGraph(D),
+    ObjectSafety(D),
 
     // The set of impls for a given trait. Ultimately, it would be
     // nice to get more fine-grained here (e.g., to include a
@@ -114,6 +118,8 @@ pub enum DepNode<D: Clone + Debug> {
     // than changes in the impl body.
     TraitImpls(D),
 
+    AllLocalTraitImpls,
+
     // Nodes representing caches. To properly handle a true cache, we
     // don't use a DepTrackingMap, but rather we push a task node.
     // Otherwise the write into the map would be incorrectly
@@ -157,6 +163,15 @@ pub enum DepNode<D: Clone + Debug> {
     DefSpan(D),
     Stability(D),
     Deprecation(D),
+    ItemBodyNestedBodies(D),
+    ConstIsRvaluePromotableToStatic(D),
+    ImplParent(D),
+    TraitOfItem(D),
+    IsExportedSymbol(D),
+    IsMirAvailable(D),
+    ItemAttrs(D),
+    FnArgNames(D),
+    FileMap(D, Arc<String>),
 }
 
 impl<D: Clone + Debug> DepNode<D> {
@@ -234,7 +249,6 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             RegionMaps(ref d) => op(d).map(RegionMaps),
             RvalueCheck(ref d) => op(d).map(RvalueCheck),
             TransCrateItem(ref d) => op(d).map(TransCrateItem),
-            TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
             AssociatedItems(ref d) => op(d).map(AssociatedItems),
             ItemSignature(ref d) => op(d).map(ItemSignature),
             ItemVariances(ref d) => op(d).map(ItemVariances),
@@ -252,7 +266,10 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             UsedTraitImports(ref d) => op(d).map(UsedTraitImports),
             ConstEval(ref d) => op(d).map(ConstEval),
             SymbolName(ref d) => op(d).map(SymbolName),
+            SpecializationGraph(ref d) => op(d).map(SpecializationGraph),
+            ObjectSafety(ref d) => op(d).map(ObjectSafety),
             TraitImpls(ref d) => op(d).map(TraitImpls),
+            AllLocalTraitImpls => Some(AllLocalTraitImpls),
             TraitItems(ref d) => op(d).map(TraitItems),
             ReprHints(ref d) => op(d).map(ReprHints),
             TraitSelect { ref trait_def_id, ref input_def_id } => {
@@ -271,6 +288,16 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             DefSpan(ref d) => op(d).map(DefSpan),
             Stability(ref d) => op(d).map(Stability),
             Deprecation(ref d) => op(d).map(Deprecation),
+            ItemAttrs(ref d) => op(d).map(ItemAttrs),
+            FnArgNames(ref d) => op(d).map(FnArgNames),
+            ImplParent(ref d) => op(d).map(ImplParent),
+            TraitOfItem(ref d) => op(d).map(TraitOfItem),
+            IsExportedSymbol(ref d) => op(d).map(IsExportedSymbol),
+            ItemBodyNestedBodies(ref d) => op(d).map(ItemBodyNestedBodies),
+            ConstIsRvaluePromotableToStatic(ref d) => op(d).map(ConstIsRvaluePromotableToStatic),
+            IsMirAvailable(ref d) => op(d).map(IsMirAvailable),
+            GlobalMetaData(ref d, kind) => op(d).map(|d| GlobalMetaData(d, kind)),
+            FileMap(ref d, ref file_name) => op(d).map(|d| FileMap(d, file_name.clone())),
         }
     }
 }
@@ -282,3 +309,16 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
 /// them even in the absence of a tcx.)
 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
 pub struct WorkProductId(pub String);
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+pub enum GlobalMetaDataKind {
+    Krate,
+    CrateDeps,
+    DylibDependencyFormats,
+    LangItems,
+    LangItemsMissing,
+    NativeLibraries,
+    CodeMap,
+    Impls,
+    ExportedSymbols,
+}
index 809bed939f54ca4bcb78e102d33077f0ba4499f7..822b61df7a489ae7b2c11677b341343a46585fb6 100644 (file)
@@ -22,6 +22,7 @@
 pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
 pub use self::dep_node::DepNode;
 pub use self::dep_node::WorkProductId;
+pub use self::dep_node::GlobalMetaDataKind;
 pub use self::graph::DepGraph;
 pub use self::graph::WorkProduct;
 pub use self::query::DepGraphQuery;
index 8ef42826faca5cc2d00043951c4a785f67c5f886..470dcb4bd61e10e431bf8e3392e3734c288081c7 100644 (file)
@@ -409,6 +409,67 @@ impl Quux for Foo { }
 [iss15872]: https://github.com/rust-lang/rust/issues/15872
 "##,
 
+E0119: r##"
+There are conflicting trait implementations for the same type.
+Example of erroneous code:
+
+```compile_fail,E0119
+trait MyTrait {
+    fn get(&self) -> usize;
+}
+
+impl<T> MyTrait for T {
+    fn get(&self) -> usize { 0 }
+}
+
+struct Foo {
+    value: usize
+}
+
+impl MyTrait for Foo { // error: conflicting implementations of trait
+                       //        `MyTrait` for type `Foo`
+    fn get(&self) -> usize { self.value }
+}
+```
+
+When looking for the implementation for the trait, the compiler finds
+both the `impl<T> MyTrait for T` where T is all types and the `impl
+MyTrait for Foo`. Since a trait cannot be implemented multiple times,
+this is an error. So, when you write:
+
+```
+trait MyTrait {
+    fn get(&self) -> usize;
+}
+
+impl<T> MyTrait for T {
+    fn get(&self) -> usize { 0 }
+}
+```
+
+This makes the trait implemented on all types in the scope. So if you
+try to implement it on another one after that, the implementations will
+conflict. Example:
+
+```
+trait MyTrait {
+    fn get(&self) -> usize;
+}
+
+impl<T> MyTrait for T {
+    fn get(&self) -> usize { 0 }
+}
+
+struct Foo;
+
+fn main() {
+    let f = Foo;
+
+    f.get(); // the trait is implemented so we can use it
+}
+```
+"##,
+
 E0133: r##"
 Unsafe code was used outside of an unsafe function or block.
 
index bf292ccb8d86d064212c1d33c40e56b90c0c144a..f553c03d09bd680e683243f3bc57a1171640dd22 100644 (file)
@@ -43,7 +43,7 @@ impl<'a> CheckAttrVisitor<'a> {
     fn check_inline(&self, attr: &ast::Attribute, target: Target) {
         if target != Target::Fn {
             struct_span_err!(self.sess, attr.span, E0518, "attribute should be applied to function")
-                .span_label(attr.span, &format!("requires a function"))
+                .span_label(attr.span, "requires a function")
                 .emit();
         }
     }
@@ -123,7 +123,7 @@ fn check_repr(&self, attr: &ast::Attribute, target: Target) {
                 _ => continue,
             };
             struct_span_err!(self.sess, attr.span, E0517, "{}", message)
-                .span_label(attr.span, &format!("requires {}", label))
+                .span_label(attr.span, format!("requires {}", label))
                 .emit();
         }
         if conflicting_reprs > 1 {
index a6b18ac10a79074bb35d0c3e39a5c590fce391f5..47604b961ae4ac04f505fe9b013d504575cfaee6 100644 (file)
@@ -36,7 +36,10 @@ fn index(self) -> usize {
 
 /// Virtual crate for builtin macros
 // FIXME(jseyfried): this is also used for custom derives until proc-macro crates get `CrateNum`s.
-pub const BUILTIN_MACROS_CRATE: CrateNum = CrateNum(!0);
+pub const BUILTIN_MACROS_CRATE: CrateNum = CrateNum(u32::MAX);
+
+/// A CrateNum value that indicates that something is wrong.
+pub const INVALID_CRATE: CrateNum = CrateNum(u32::MAX - 1);
 
 impl CrateNum {
     pub fn new(x: usize) -> CrateNum {
index def6b2b3421f6f4135e0741b575506381f5a2e10..836d9775a3f69b7f5292897801ec0eb30b85310d 100644 (file)
@@ -140,23 +140,6 @@ pub fn inter(self) -> Option<&'this Map<'tcx>> {
 /// to monitor future changes to `Visitor` in case a new method with a
 /// new default implementation gets introduced.)
 pub trait Visitor<'v> : Sized {
-    /// Invokes the suitable visitor method for the given `Node`
-    /// extracted from the hir map.
-    fn visit_hir_map_node(&mut self, node: map::Node<'v>) {
-        match node {
-            map::NodeItem(a) => self.visit_item(a),
-            map::NodeForeignItem(a) => self.visit_foreign_item(a),
-            map::NodeTraitItem(a) => self.visit_trait_item(a),
-            map::NodeImplItem(a) => self.visit_impl_item(a),
-            map::NodeExpr(a) => self.visit_expr(a),
-            map::NodeStmt(a) => self.visit_stmt(a),
-            map::NodeTy(a) => self.visit_ty(a),
-            map::NodePat(a) => self.visit_pat(a),
-            map::NodeBlock(a) => self.visit_block(a),
-            _ => bug!("Visitor::visit_hir_map_node() not yet impl for node `{:?}`", node)
-        }
-    }
-
     ///////////////////////////////////////////////////////////////////////////
     // Nested items.
 
index abc967dec905c23459cfc9fc567679316d5467af..868730edfedda83b1d4d10ef586ca3f37b75dc58 100644 (file)
@@ -442,20 +442,21 @@ pub fn body_owner_def_id(&self, id: BodyId) -> DefId {
         self.local_def_id(self.body_owner(id))
     }
 
-    /// Given a body owner's id, returns the `BodyId` associated with it.
-    pub fn body_owned_by(&self, id: NodeId) -> BodyId {
+    /// Given a node id, returns the `BodyId` associated with it,
+    /// if the node is a body owner, otherwise returns `None`.
+    pub fn maybe_body_owned_by(&self, id: NodeId) -> Option<BodyId> {
         if let Some(entry) = self.find_entry(id) {
             if let Some(body_id) = entry.associated_body() {
                 // For item-like things and closures, the associated
                 // body has its own distinct id, and that is returned
                 // by `associated_body`.
-                body_id
+                Some(body_id)
             } else {
                 // For some expressions, the expression is its own body.
                 if let EntryExpr(_, expr) = entry {
-                    BodyId { node_id: expr.id }
+                    Some(BodyId { node_id: expr.id })
                 } else {
-                    span_bug!(self.span(id), "id `{}` has no associated body: {:?}", id, entry);
+                    None
                 }
             }
         } else {
@@ -463,6 +464,14 @@ pub fn body_owned_by(&self, id: NodeId) -> BodyId {
         }
     }
 
+    /// Given a body owner's id, returns the `BodyId` associated with it.
+    pub fn body_owned_by(&self, id: NodeId) -> BodyId {
+        self.maybe_body_owned_by(id).unwrap_or_else(|| {
+            span_bug!(self.span(id), "body_owned_by: {} has no associated body",
+                      self.node_to_string(id));
+        })
+    }
+
     pub fn ty_param_owner(&self, id: NodeId) -> NodeId {
         match self.get(id) {
             NodeItem(&Item { node: ItemTrait(..), .. }) => id,
@@ -488,7 +497,7 @@ pub fn ty_param_name(&self, id: NodeId) -> Name {
     }
 
     pub fn trait_impls(&self, trait_did: DefId) -> &'hir [NodeId] {
-        self.dep_graph.read(DepNode::TraitImpls(trait_did));
+        self.dep_graph.read(DepNode::AllLocalTraitImpls);
 
         // NB: intentionally bypass `self.forest.krate()` so that we
         // do not trigger a read of the whole krate here
@@ -496,7 +505,7 @@ pub fn trait_impls(&self, trait_did: DefId) -> &'hir [NodeId] {
     }
 
     pub fn trait_default_impl(&self, trait_did: DefId) -> Option<NodeId> {
-        self.dep_graph.read(DepNode::TraitImpls(trait_did));
+        self.dep_graph.read(DepNode::AllLocalTraitImpls);
 
         // NB: intentionally bypass `self.forest.krate()` so that we
         // do not trigger a read of the whole krate here
index ae1f9d3028c2c08075934fc18654d212bb7decaa..a6cfcb710edad6919ec68c2c32008f38c95681d7 100644 (file)
@@ -66,3 +66,7 @@ fn decode<D: Decoder>(d: &mut D) -> Result<Svh, D::Error> {
          .map(Svh::new)
     }
 }
+
+impl_stable_hash_for!(struct Svh {
+    hash
+});
index 1278d9f5171b3be590be3880fd4804a4d6f7242a..b21c3a2b216000e4072b3e2b11dbcccc637c6345 100644 (file)
@@ -8,10 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ty::TyCtxt;
+use dep_graph::{DepGraph, DepNode};
+use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
+use rustc_data_structures::bitvec::BitVector;
 use std::rc::Rc;
+use std::sync::Arc;
 use syntax::codemap::CodeMap;
 use syntax_pos::{BytePos, FileMap};
+use ty::TyCtxt;
 
 #[derive(Clone)]
 struct CacheEntry {
@@ -20,30 +24,37 @@ struct CacheEntry {
     line_start: BytePos,
     line_end: BytePos,
     file: Rc<FileMap>,
+    file_index: usize,
 }
 
 pub struct CachingCodemapView<'tcx> {
     codemap: &'tcx CodeMap,
     line_cache: [CacheEntry; 3],
     time_stamp: usize,
+    dep_graph: DepGraph,
+    dep_tracking_reads: BitVector,
 }
 
 impl<'tcx> CachingCodemapView<'tcx> {
     pub fn new<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CachingCodemapView<'tcx> {
         let codemap = tcx.sess.codemap();
-        let first_file = codemap.files.borrow()[0].clone();
+        let files = codemap.files_untracked();
+        let first_file = files[0].clone();
         let entry = CacheEntry {
             time_stamp: 0,
             line_number: 0,
             line_start: BytePos(0),
             line_end: BytePos(0),
             file: first_file,
+            file_index: 0,
         };
 
         CachingCodemapView {
+            dep_graph: tcx.dep_graph.clone(),
             codemap: codemap,
             line_cache: [entry.clone(), entry.clone(), entry.clone()],
             time_stamp: 0,
+            dep_tracking_reads: BitVector::new(files.len()),
         }
     }
 
@@ -56,6 +67,10 @@ pub fn byte_pos_to_line_and_col(&mut self,
         for cache_entry in self.line_cache.iter_mut() {
             if pos >= cache_entry.line_start && pos < cache_entry.line_end {
                 cache_entry.time_stamp = self.time_stamp;
+                if self.dep_tracking_reads.insert(cache_entry.file_index) {
+                    self.dep_graph.read(dep_node(cache_entry));
+                }
+
                 return Some((cache_entry.file.clone(),
                              cache_entry.line_number,
                              pos - cache_entry.line_start));
@@ -75,7 +90,7 @@ pub fn byte_pos_to_line_and_col(&mut self,
         // If the entry doesn't point to the correct file, fix it up
         if pos < cache_entry.file.start_pos || pos >= cache_entry.file.end_pos {
             let file_valid;
-            let files = self.codemap.files.borrow();
+            let files = self.codemap.files_untracked();
 
             if files.len() > 0 {
                 let file_index = self.codemap.lookup_filemap_idx(pos);
@@ -83,6 +98,7 @@ pub fn byte_pos_to_line_and_col(&mut self,
 
                 if pos >= file.start_pos && pos < file.end_pos {
                     cache_entry.file = file;
+                    cache_entry.file_index = file_index;
                     file_valid = true;
                 } else {
                     file_valid = false;
@@ -104,8 +120,21 @@ pub fn byte_pos_to_line_and_col(&mut self,
         cache_entry.line_end = line_bounds.1;
         cache_entry.time_stamp = self.time_stamp;
 
+        if self.dep_tracking_reads.insert(cache_entry.file_index) {
+            self.dep_graph.read(dep_node(cache_entry));
+        }
+
         return Some((cache_entry.file.clone(),
                      cache_entry.line_number,
                      pos - cache_entry.line_start));
     }
 }
+
+fn dep_node(cache_entry: &CacheEntry) -> DepNode<DefId> {
+    let def_id = DefId {
+        krate: CrateNum::from_u32(cache_entry.file.crate_of_origin),
+        index: CRATE_DEF_INDEX,
+    };
+    let name = Arc::new(cache_entry.file.name.clone());
+    DepNode::FileMap(def_id, name)
+}
index e760f7efc93d912645454213f9b42b5707836261..ccdbab88b8b9c17e9e9916804d194c2d953392ae 100644 (file)
@@ -94,3 +94,11 @@ fn finish(mut hasher: stable_hasher::StableHasher<Self>) -> Self {
         fingerprint
     }
 }
+
+impl<CTX> stable_hasher::HashStable<CTX> for Fingerprint {
+    fn hash_stable<W: stable_hasher::StableHasherResult>(&self,
+                                          _: &mut CTX,
+                                          hasher: &mut stable_hasher::StableHasher<W>) {
+        ::std::hash::Hash::hash(&self.0, hasher);
+    }
+}
index 3a6367c353c1eec7cdcc32a756281ef81c8f528e..786d1c5035d96fa388278aa906c362e2c6467ffa 100644 (file)
@@ -16,7 +16,7 @@
 use util::nodemap::NodeMap;
 
 use std::hash as std_hash;
-use std::collections::{HashMap, HashSet};
+use std::collections::{HashMap, HashSet, BTreeMap};
 
 use syntax::ast;
 use syntax::attr;
@@ -348,3 +348,25 @@ pub fn hash_stable_nodemap<'a, 'tcx, V, W>(hcx: &mut StableHashingContext<'a, 't
         hcx.tcx.hir.definitions().node_to_hir_id(*node_id).local_id
     });
 }
+
+
+pub fn hash_stable_btreemap<'a, 'tcx, K, V, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>,
+                                                      hasher: &mut StableHasher<W>,
+                                                      map: &BTreeMap<K, V>,
+                                                      extract_stable_key: F)
+    where K: Eq + Ord,
+          V: HashStable<StableHashingContext<'a, 'tcx>>,
+          SK: HashStable<StableHashingContext<'a, 'tcx>> + Ord + Clone,
+          F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK,
+          W: StableHasherResult,
+{
+    let mut keys: Vec<_> = map.keys()
+                              .map(|k| (extract_stable_key(hcx, k), k))
+                              .collect();
+    keys.sort_unstable_by_key(|&(ref stable_key, _)| stable_key.clone());
+    keys.len().hash_stable(hcx, hasher);
+    for (stable_key, key) in keys {
+        stable_key.hash_stable(hcx, hasher);
+        map[key].hash_stable(hcx, hasher);
+    }
+}
diff --git a/src/librustc/ich/impls_cstore.rs b/src/librustc/ich/impls_cstore.rs
new file mode 100644 (file)
index 0000000..e95dbdd
--- /dev/null
@@ -0,0 +1,40 @@
+// 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.
+
+//! This module contains `HashStable` implementations for various data types
+//! from rustc::middle::cstore in no particular order.
+
+use middle;
+
+impl_stable_hash_for!(enum middle::cstore::DepKind {
+    UnexportedMacrosOnly,
+    MacrosOnly,
+    Implicit,
+    Explicit
+});
+
+impl_stable_hash_for!(enum middle::cstore::NativeLibraryKind {
+    NativeStatic,
+    NativeStaticNobundle,
+    NativeFramework,
+    NativeUnknown
+});
+
+impl_stable_hash_for!(struct middle::cstore::NativeLibrary {
+    kind,
+    name,
+    cfg,
+    foreign_items
+});
+
+impl_stable_hash_for!(enum middle::cstore::LinkagePreference {
+    RequireDynamic,
+    RequireStatic
+});
index 3aeee1c1b981f4e861213579e7fa23a2f6a83641..abc51601b6ecef814c2ea2e95da8e37739367521 100644 (file)
@@ -1120,3 +1120,11 @@ fn hash_stable<W: StableHasherResult>(&self,
     def,
     span
 });
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::lang_items::LangItem {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          _: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        ::std::hash::Hash::hash(self, hasher);
+    }
+}
index 26734500001f6d772327d64f712d074ab21d7c02..7138db01339f6a89489a6204526c24fb26c96b87 100644 (file)
@@ -19,7 +19,9 @@
 use syntax::ast;
 use syntax::parse::token;
 use syntax::tokenstream;
-use syntax_pos::Span;
+use syntax_pos::{Span, FileMap};
+
+use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
@@ -299,3 +301,79 @@ fn hash_token<'a, 'tcx, W: StableHasherResult>(token: &token::Token,
         token::Token::Shebang(val) => val.hash_stable(hcx, hasher),
     }
 }
+
+impl_stable_hash_for_spanned!(::syntax::ast::NestedMetaItemKind);
+
+impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItemKind {
+    MetaItem(meta_item),
+    Literal(lit)
+});
+
+impl_stable_hash_for!(struct ::syntax::ast::MetaItem {
+    name,
+    node,
+    span
+});
+
+impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
+    Word,
+    List(nested_items),
+    NameValue(lit)
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for FileMap {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let FileMap {
+            ref name,
+            name_was_remapped,
+            crate_of_origin,
+            // Do not hash the source as it is not encoded
+            src: _,
+            start_pos,
+            end_pos: _,
+            ref lines,
+            ref multibyte_chars,
+        } = *self;
+
+        name.hash_stable(hcx, hasher);
+        name_was_remapped.hash_stable(hcx, hasher);
+
+        DefId {
+            krate: CrateNum::from_u32(crate_of_origin),
+            index: CRATE_DEF_INDEX,
+        }.hash_stable(hcx, hasher);
+
+        // We only hash the relative position within this filemap
+        let lines = lines.borrow();
+        lines.len().hash_stable(hcx, hasher);
+        for &line in lines.iter() {
+            stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
+        }
+
+        // We only hash the relative position within this filemap
+        let multibyte_chars = multibyte_chars.borrow();
+        multibyte_chars.len().hash_stable(hcx, hasher);
+        for &char_pos in multibyte_chars.iter() {
+            stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
+        }
+    }
+}
+
+fn stable_byte_pos(pos: ::syntax_pos::BytePos,
+                   filemap_start: ::syntax_pos::BytePos)
+                   -> u32 {
+    pos.0 - filemap_start.0
+}
+
+fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar,
+                         filemap_start: ::syntax_pos::BytePos)
+                         -> (u32, u32) {
+    let ::syntax_pos::MultiByteChar {
+        pos,
+        bytes,
+    } = mbc;
+
+    (pos.0 - filemap_start.0, bytes as u32)
+}
index 52bdb5d02406e4f79a6f8a3bce9ef39fe111cbd0..3bbac8d6a64259ec513d70afbccb2dd5cc27c0b6 100644 (file)
@@ -39,7 +39,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
-impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::RegionKind<'tcx> {
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::RegionKind {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
@@ -54,7 +54,8 @@ fn hash_stable<W: StableHasherResult>(&self,
                 db.depth.hash_stable(hcx, hasher);
                 i.hash_stable(hcx, hasher);
             }
-            ty::ReEarlyBound(ty::EarlyBoundRegion { index, name }) => {
+            ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {
+                def_id.hash_stable(hcx, hasher);
                 index.hash_stable(hcx, hasher);
                 name.hash_stable(hcx, hasher);
             }
@@ -409,11 +410,6 @@ fn hash_stable<W: StableHasherResult>(&self,
     Free(call_site_scope_data, decl)
 });
 
-impl_stable_hash_for!(struct ::middle::region::CallSiteScopeData {
-    fn_id,
-    body_id
-});
-
 impl_stable_hash_for!(struct ty::DebruijnIndex {
     depth
 });
@@ -432,25 +428,24 @@ fn hash_stable<W: StableHasherResult>(&self,
     FnPtrAddrCast
 });
 
-impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtentData
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtent
 {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
-        use middle::region::CodeExtentData;
+        use middle::region::CodeExtent;
 
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
-            CodeExtentData::Misc(node_id) |
-            CodeExtentData::DestructionScope(node_id) => {
+            CodeExtent::Misc(node_id) |
+            CodeExtent::DestructionScope(node_id) => {
                 node_id.hash_stable(hcx, hasher);
             }
-            CodeExtentData::CallSiteScope { fn_id, body_id } |
-            CodeExtentData::ParameterScope { fn_id, body_id } => {
-                fn_id.hash_stable(hcx, hasher);
+            CodeExtent::CallSiteScope(body_id) |
+            CodeExtent::ParameterScope(body_id) => {
                 body_id.hash_stable(hcx, hasher);
             }
-            CodeExtentData::Remainder(block_remainder) => {
+            CodeExtent::Remainder(block_remainder) => {
                 block_remainder.hash_stable(hcx, hasher);
             }
         }
@@ -466,7 +461,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     custom_kind
 });
 
-impl_stable_hash_for!(struct ty::FreeRegion<'tcx> {
+impl_stable_hash_for!(struct ty::FreeRegion {
     scope,
     bound_region
 });
index d70ed051ac4107ad2d3b31ca3d8fc2c1ed6183ac..5b23809085053d09b2cf6a821a25140dc9315602 100644 (file)
 pub use self::fingerprint::Fingerprint;
 pub use self::caching_codemap_view::CachingCodemapView;
 pub use self::hcx::{StableHashingContext, NodeIdHashingMode, hash_stable_hashmap,
-                    hash_stable_hashset, hash_stable_nodemap};
+                    hash_stable_hashset, hash_stable_nodemap,
+                    hash_stable_btreemap};
 mod fingerprint;
 mod caching_codemap_view;
 mod hcx;
 
 mod impls_const_math;
+mod impls_cstore;
 mod impls_hir;
 mod impls_mir;
 mod impls_ty;
index 1bac512e20977b087d4fdd09b35e336bbf8e8e9b..aabb6aff55140c4138efecfa741db1245b2e0e4b 100644 (file)
 use super::InferCtxt;
 use super::{MiscVariable, TypeTrace};
 
+use hir::def_id::DefId;
 use ty::{IntType, UintType};
 use ty::{self, Ty, TyCtxt};
 use ty::error::TypeError;
-use ty::fold::TypeFoldable;
-use ty::relate::{RelateResult, TypeRelation};
-use traits::PredicateObligations;
+use ty::relate::{self, Relate, RelateResult, TypeRelation};
+use ty::subst::Substs;
+use traits::{Obligation, PredicateObligations};
 
 use syntax::ast;
 use syntax_pos::Span;
@@ -207,11 +208,16 @@ pub fn instantiate(&mut self,
         // `'?2` and `?3` are fresh region/type inference
         // variables. (Down below, we will relate `a_ty <: b_ty`,
         // adding constraints like `'x: '?2` and `?1 <: ?3`.)
-        let b_ty = self.generalize(a_ty, b_vid, dir == EqTo)?;
+        let Generalization { ty: b_ty, needs_wf } = self.generalize(a_ty, b_vid, dir)?;
         debug!("instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})",
                a_ty, dir, b_vid, b_ty);
         self.infcx.type_variables.borrow_mut().instantiate(b_vid, b_ty);
 
+        if needs_wf {
+            self.obligations.push(Obligation::new(self.trace.cause.clone(),
+                                                  ty::Predicate::WellFormed(b_ty)));
+        }
+
         // Finally, relate `b_ty` to `a_ty`, as described in previous comment.
         //
         // FIXME(#16847): This code is non-ideal because all these subtype
@@ -230,10 +236,9 @@ pub fn instantiate(&mut self,
 
     /// Attempts to generalize `ty` for the type variable `for_vid`.
     /// This checks for cycle -- that is, whether the type `ty`
-    /// references `for_vid`. If `is_eq_relation` is false, it will
-    /// also replace all regions/unbound-type-variables with fresh
-    /// variables. Returns `TyError` in the case of a cycle, `Ok`
-    /// otherwise.
+    /// references `for_vid`. The `dir` is the "direction" for which we
+    /// a performing the generalization (i.e., are we producing a type
+    /// that can be used as a supertype etc).
     ///
     /// Preconditions:
     ///
@@ -241,22 +246,33 @@ pub fn instantiate(&mut self,
     fn generalize(&self,
                   ty: Ty<'tcx>,
                   for_vid: ty::TyVid,
-                  is_eq_relation: bool)
-                  -> RelateResult<'tcx, Ty<'tcx>>
+                  dir: RelationDir)
+                  -> RelateResult<'tcx, Generalization<'tcx>>
     {
+        // Determine the ambient variance within which `ty` appears.
+        // The surrounding equation is:
+        //
+        //     ty [op] ty2
+        //
+        // where `op` is either `==`, `<:`, or `:>`. This maps quite
+        // naturally.
+        let ambient_variance = match dir {
+            RelationDir::EqTo => ty::Invariant,
+            RelationDir::SubtypeOf => ty::Covariant,
+            RelationDir::SupertypeOf => ty::Contravariant,
+        };
+
         let mut generalize = Generalizer {
             infcx: self.infcx,
             span: self.trace.cause.span,
             for_vid_sub_root: self.infcx.type_variables.borrow_mut().sub_root_var(for_vid),
-            is_eq_relation: is_eq_relation,
-            cycle_detected: false
+            ambient_variance: ambient_variance,
+            needs_wf: false,
         };
-        let u = ty.fold_with(&mut generalize);
-        if generalize.cycle_detected {
-            Err(TypeError::CyclicTy)
-        } else {
-            Ok(u)
-        }
+
+        let ty = generalize.relate(&ty, &ty)?;
+        let needs_wf = generalize.needs_wf;
+        Ok(Generalization { ty, needs_wf })
     }
 }
 
@@ -264,16 +280,98 @@ struct Generalizer<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
     infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
     span: Span,
     for_vid_sub_root: ty::TyVid,
-    is_eq_relation: bool,
-    cycle_detected: bool,
+    ambient_variance: ty::Variance,
+    needs_wf: bool, // see the field `needs_wf` in `Generalization`
 }
 
-impl<'cx, 'gcx, 'tcx> ty::fold::TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx, 'tcx> {
-    fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> {
+/// Result from a generalization operation. This includes
+/// not only the generalized type, but also a bool flag
+/// indicating whether further WF checks are needed.q
+struct Generalization<'tcx> {
+    ty: Ty<'tcx>,
+
+    /// If true, then the generalized type may not be well-formed,
+    /// even if the source type is well-formed, so we should add an
+    /// additional check to enforce that it is. This arises in
+    /// particular around 'bivariant' type parameters that are only
+    /// constrained by a where-clause. As an example, imagine a type:
+    ///
+    ///     struct Foo<A, B> where A: Iterator<Item=B> {
+    ///         data: A
+    ///     }
+    ///
+    /// here, `A` will be covariant, but `B` is
+    /// unconstrained. However, whatever it is, for `Foo` to be WF, it
+    /// must be equal to `A::Item`. If we have an input `Foo<?A, ?B>`,
+    /// then after generalization we will wind up with a type like
+    /// `Foo<?C, ?D>`. When we enforce that `Foo<?A, ?B> <: Foo<?C,
+    /// ?D>` (or `>:`), we will wind up with the requirement that `?A
+    /// <: ?C`, but no particular relationship between `?B` and `?D`
+    /// (after all, we do not know the variance of the normalized form
+    /// of `A::Item` with respect to `A`). If we do nothing else, this
+    /// may mean that `?D` goes unconstrained (as in #41677).  So, in
+    /// this scenario where we create a new type variable in a
+    /// bivariant context, we set the `needs_wf` flag to true. This
+    /// will force the calling code to check that `WF(Foo<?C, ?D>)`
+    /// holds, which in turn implies that `?C::Item == ?D`. So once
+    /// `?C` is constrained, that should suffice to restrict `?D`.
+    needs_wf: bool,
+}
+
+impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> {
         self.infcx.tcx
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn tag(&self) -> &'static str {
+        "Generalizer"
+    }
+
+    fn a_is_expected(&self) -> bool {
+        true
+    }
+
+    fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
+                  -> RelateResult<'tcx, ty::Binder<T>>
+        where T: Relate<'tcx>
+    {
+        Ok(ty::Binder(self.relate(a.skip_binder(), b.skip_binder())?))
+    }
+
+    fn relate_item_substs(&mut self,
+                          item_def_id: DefId,
+                          a_subst: &'tcx Substs<'tcx>,
+                          b_subst: &'tcx Substs<'tcx>)
+                          -> RelateResult<'tcx, &'tcx Substs<'tcx>>
+    {
+        if self.ambient_variance == ty::Variance::Invariant {
+            // Avoid fetching the variance if we are in an invariant
+            // context; no need, and it can induce dependency cycles
+            // (e.g. #41849).
+            relate::relate_substs(self, None, a_subst, b_subst)
+        } else {
+            let opt_variances = self.tcx().variances_of(item_def_id);
+            relate::relate_substs(self, Some(&opt_variances), a_subst, b_subst)
+        }
+    }
+
+    fn relate_with_variance<T: Relate<'tcx>>(&mut self,
+                                             variance: ty::Variance,
+                                             a: &T,
+                                             b: &T)
+                                             -> RelateResult<'tcx, T>
+    {
+        let old_ambient_variance = self.ambient_variance;
+        self.ambient_variance = self.ambient_variance.xform(variance);
+
+        let result = self.relate(a, b);
+        self.ambient_variance = old_ambient_variance;
+        result
+    }
+
+    fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
+
         // Check to see whether the type we are genealizing references
         // any other type variable related to `vid` via
         // subtyping. This is basically our "occurs check", preventing
@@ -286,49 +384,62 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                 if sub_vid == self.for_vid_sub_root {
                     // If sub-roots are equal, then `for_vid` and
                     // `vid` are related via subtyping.
-                    self.cycle_detected = true;
-                    self.tcx().types.err
+                    return Err(TypeError::CyclicTy);
                 } else {
                     match variables.probe_root(vid) {
                         Some(u) => {
                             drop(variables);
-                            self.fold_ty(u)
+                            self.relate(&u, &u)
                         }
                         None => {
-                            if !self.is_eq_relation {
-                                let origin = variables.origin(vid);
-                                let new_var_id = variables.new_var(false, origin, None);
-                                let u = self.tcx().mk_var(new_var_id);
-                                debug!("generalize: replacing original vid={:?} with new={:?}",
-                                       vid, u);
-                                u
-                            } else {
-                                t
+                            match self.ambient_variance {
+                                // Invariant: no need to make a fresh type variable.
+                                ty::Invariant => return Ok(t),
+
+                                // Bivariant: make a fresh var, but we
+                                // may need a WF predicate. See
+                                // comment on `needs_wf` field for
+                                // more info.
+                                ty::Bivariant => self.needs_wf = true,
+
+                                // Co/contravariant: this will be
+                                // sufficiently constrained later on.
+                                ty::Covariant | ty::Contravariant => (),
                             }
+
+                            let origin = variables.origin(vid);
+                            let new_var_id = variables.new_var(false, origin, None);
+                            let u = self.tcx().mk_var(new_var_id);
+                            debug!("generalize: replacing original vid={:?} with new={:?}",
+                                   vid, u);
+                            return Ok(u);
                         }
                     }
                 }
             }
+            ty::TyInfer(ty::IntVar(_)) |
+            ty::TyInfer(ty::FloatVar(_)) => {
+                // No matter what mode we are in,
+                // integer/floating-point types must be equal to be
+                // relatable.
+                Ok(t)
+            }
             _ => {
-                t.super_fold_with(self)
+                relate::super_relate_tys(self, t, t)
             }
         }
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn regions(&mut self, r: ty::Region<'tcx>, r2: ty::Region<'tcx>)
+               -> RelateResult<'tcx, ty::Region<'tcx>> {
+        assert_eq!(r, r2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
+
         match *r {
             // Never make variables for regions bound within the type itself,
             // nor for erased regions.
             ty::ReLateBound(..) |
-            ty::ReErased => { return r; }
-
-            // Early-bound regions should really have been substituted away before
-            // we get to this point.
-            ty::ReEarlyBound(..) => {
-                span_bug!(
-                    self.span,
-                    "Encountered early bound region when generalizing: {:?}",
-                    r);
+            ty::ReErased => {
+                return Ok(r);
             }
 
             // Always make a fresh region variable for skolemized regions;
@@ -341,16 +452,18 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
             ty::ReStatic |
             ty::ReScope(..) |
             ty::ReVar(..) |
+            ty::ReEarlyBound(..) |
             ty::ReFree(..) => {
-                if self.is_eq_relation {
-                    return r;
+                match self.ambient_variance {
+                    ty::Invariant => return Ok(r),
+                    ty::Bivariant | ty::Covariant | ty::Contravariant => (),
                 }
             }
         }
 
         // FIXME: This is non-ideal because we don't give a
         // very descriptive origin for this region variable.
-        self.infcx.next_region_var(MiscVariable(self.span))
+        Ok(self.infcx.next_region_var(MiscVariable(self.span)))
     }
 }
 
index f0b179fa2e4205ac2d8b5f6b1818b71e3d193308..f9ffaee81f1573de6c636e685d0418c45f0e9e33 100644 (file)
 use super::combine::{CombineFields, RelationDir};
 use super::{Subtype};
 
+use hir::def_id::DefId;
+
 use ty::{self, Ty, TyCtxt};
 use ty::TyVar;
-use ty::relate::{Relate, RelateResult, TypeRelation};
+use ty::subst::Substs;
+use ty::relate::{self, Relate, RelateResult, TypeRelation};
 
 /// Ensures `a` is made equal to `b`. Returns `a` on success.
 pub struct Equate<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
@@ -38,6 +41,22 @@ fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
 
     fn a_is_expected(&self) -> bool { self.a_is_expected }
 
+    fn relate_item_substs(&mut self,
+                          _item_def_id: DefId,
+                          a_subst: &'tcx Substs<'tcx>,
+                          b_subst: &'tcx Substs<'tcx>)
+                          -> RelateResult<'tcx, &'tcx Substs<'tcx>>
+    {
+        // NB: Once we are equating types, we don't care about
+        // variance, so don't try to lookup the variance here. This
+        // also avoids some cycles (e.g. #41849) since looking up
+        // variance requires computing types which can require
+        // performing trait matching (which then performs equality
+        // unification).
+
+        relate::relate_substs(self, None, a_subst, b_subst)
+    }
+
     fn relate_with_variance<T: Relate<'tcx>>(&mut self,
                                              _: ty::Variance,
                                              a: &T,
index 8f2bdd4e85c77ac725745b0724b8f6ef90a0a8fd..c07b3b3c4be90bd445a407d1d901ef1289ce843b 100644 (file)
@@ -151,19 +151,19 @@ fn explain_span<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                         return;
                     }
                 };
-                let scope_decorated_tag = match *scope {
-                    region::CodeExtentData::Misc(_) => tag,
-                    region::CodeExtentData::CallSiteScope { .. } => {
+                let scope_decorated_tag = match scope {
+                    region::CodeExtent::Misc(_) => tag,
+                    region::CodeExtent::CallSiteScope(_) => {
                         "scope of call-site for function"
                     }
-                    region::CodeExtentData::ParameterScope { .. } => {
+                    region::CodeExtent::ParameterScope(_) => {
                         "scope of function body"
                     }
-                    region::CodeExtentData::DestructionScope(_) => {
+                    region::CodeExtent::DestructionScope(_) => {
                         new_string = format!("destruction scope surrounding {}", tag);
                         &new_string[..]
                     }
-                    region::CodeExtentData::Remainder(r) => {
+                    region::CodeExtent::Remainder(r) => {
                         new_string = format!("block suffix following statement {}",
                                              r.first_statement_index);
                         &new_string[..]
@@ -172,19 +172,35 @@ fn explain_span<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                 explain_span(self, scope_decorated_tag, span)
             }
 
-            ty::ReFree(ref fr) => {
-                let prefix = match fr.bound_region {
-                    ty::BrAnon(idx) => {
-                        format!("the anonymous lifetime #{} defined on", idx + 1)
+            ty::ReEarlyBound(_) |
+            ty::ReFree(_) => {
+                let scope = match *region {
+                    ty::ReEarlyBound(ref br) => {
+                        self.parent_def_id(br.def_id).unwrap()
                     }
-                    ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
-                    _ => {
-                        format!("the lifetime {} as defined on",
-                                fr.bound_region)
+                    ty::ReFree(ref fr) => fr.scope,
+                    _ => bug!()
+                };
+                let prefix = match *region {
+                    ty::ReEarlyBound(ref br) => {
+                        format!("the lifetime {} as defined on", br.name)
+                    }
+                    ty::ReFree(ref fr) => {
+                        match fr.bound_region {
+                            ty::BrAnon(idx) => {
+                                format!("the anonymous lifetime #{} defined on", idx + 1)
+                            }
+                            ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
+                            _ => {
+                                format!("the lifetime {} as defined on",
+                                        fr.bound_region)
+                            }
+                        }
                     }
+                    _ => bug!()
                 };
 
-                let node = fr.scope.map(|s| s.node_id())
+                let node = self.hir.as_local_node_id(scope)
                                    .unwrap_or(DUMMY_NODE_ID);
                 let unknown;
                 let tag = match self.hir.find(node) {
@@ -199,12 +215,12 @@ fn explain_span<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                     Some(_) => {
                         unknown = format!("unexpected node ({}) for scope {:?}.  \
                                            Please report a bug.",
-                                          self.hir.node_to_string(node), fr.scope);
+                                          self.hir.node_to_string(node), scope);
                         &unknown
                     }
                     None => {
                         unknown = format!("unknown node for scope {:?}.  \
-                                           Please report a bug.", fr.scope);
+                                           Please report a bug.", scope);
                         &unknown
                     }
                 };
@@ -216,8 +232,6 @@ fn explain_span<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 
             ty::ReEmpty => ("the empty lifetime".to_owned(), None),
 
-            ty::ReEarlyBound(ref data) => (data.name.to_string(), None),
-
             // FIXME(#13998) ReSkolemized should probably print like
             // ReFree rather than dumping Debug output on the user.
             //
@@ -668,9 +682,9 @@ pub fn note_type_err(&self,
             }
         }
 
-        diag.span_label(span, &terr);
+        diag.span_label(span, terr.to_string());
         if let Some((sp, msg)) = secondary_span {
-            diag.span_label(sp, &msg);
+            diag.span_label(sp, msg);
         }
 
         self.note_error_origin(diag, &cause);
@@ -797,6 +811,7 @@ fn report_generic_bound_failure(&self,
         }
 
         let mut err = match *sub {
+            ty::ReEarlyBound(_) |
             ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
                 // Does the required lifetime have a nice name we can print?
                 let mut err = struct_span_err!(self.tcx.sess,
index 49952d81cbb0b8918bffae54a5b2769205506924..963c14c48c82947d834ce678414af72817c5fcfc 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use infer::{self, InferCtxt, SubregionOrigin};
-use ty::Region;
+use ty::{self, Region};
 use ty::error::TypeError;
 use errors::DiagnosticBuilder;
 
@@ -262,7 +262,14 @@ pub(super) fn report_concrete_failure(&self,
                                                "the type `{}` does not fulfill the required \
                                                 lifetime",
                                                self.ty_to_string(ty));
-                self.tcx.note_and_explain_region(&mut err, "type must outlive ", sub, "");
+                match *sub {
+                    ty::ReStatic => {
+                        self.tcx.note_and_explain_region(&mut err, "type must satisfy ", sub, "")
+                    }
+                    _ => {
+                        self.tcx.note_and_explain_region(&mut err, "type must outlive ", sub, "")
+                    }
+                }
                 err
             }
             infer::RelateRegionParamBound(span) => {
index ad67ef9a127d8fd79d6bf38be40afdc95dfe6531..a0ef1f65f52eac661ca0000eaed6e99251194426 100644 (file)
@@ -85,13 +85,13 @@ fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match *r {
-            ty::ReEarlyBound(..) |
             ty::ReLateBound(..) => {
                 // leave bound regions alone
                 r
             }
 
             ty::ReStatic |
+            ty::ReEarlyBound(..) |
             ty::ReFree(_) |
             ty::ReScope(_) |
             ty::ReVar(_) |
index 09f909ef399d1652d130eaabc80901cb2b2f2694..dbbcc6cfbec6b0048cce15c8af31a37110873133 100644 (file)
@@ -274,7 +274,7 @@ fn generalize_region<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                              -> ty::Region<'tcx> {
             // Regions that pre-dated the LUB computation stay as they are.
             if !is_var_in_set(new_vars, r0) {
-                assert!(!r0.is_bound());
+                assert!(!r0.is_late_bound());
                 debug!("generalize_region(r0={:?}): not new variable", r0);
                 return r0;
             }
@@ -288,7 +288,7 @@ fn generalize_region<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                 debug!("generalize_region(r0={:?}): \
                         non-new-variables found in {:?}",
                        r0, tainted);
-                assert!(!r0.is_bound());
+                assert!(!r0.is_late_bound());
                 return r0;
             }
 
@@ -371,7 +371,7 @@ fn generalize_region<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                              r0: ty::Region<'tcx>)
                                              -> ty::Region<'tcx> {
             if !is_var_in_set(new_vars, r0) {
-                assert!(!r0.is_bound());
+                assert!(!r0.is_late_bound());
                 return r0;
             }
 
@@ -424,7 +424,7 @@ fn generalize_region<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                 return rev_lookup(infcx, span, a_map, a_r.unwrap());
             } else if a_r.is_none() && b_r.is_none() {
                 // Not related to bound variables from either fn:
-                assert!(!r0.is_bound());
+                assert!(!r0.is_late_bound());
                 return r0;
             } else {
                 // Other:
index e91af21c6db2c3d7acc6085b0aff8c13afb61a2b..1ecc277c7ca4d27dd407cfc9ff39b1f910c5ecdb 100644 (file)
@@ -450,10 +450,10 @@ fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
                 -> (Option<&'a ty::TypeckTables<'tcx>>,
                     Option<ty::TypeckTables<'tcx>>,
                     Option<ty::ParameterEnvironment<'tcx>>) {
-        let item_id = tcx.hir.body_owner(self);
-        (Some(tcx.typeck_tables_of(tcx.hir.local_def_id(item_id))),
+        let def_id = tcx.hir.body_owner_def_id(self);
+        (Some(tcx.typeck_tables_of(def_id)),
          None,
-         Some(ty::ParameterEnvironment::for_item(tcx, item_id)))
+         Some(tcx.parameter_environment(def_id)))
     }
 }
 
@@ -1009,7 +1009,7 @@ pub fn probe<R, F>(&self, f: F) -> R where
     }
 
     pub fn add_given(&self,
-                     sub: ty::FreeRegion<'tcx>,
+                     sub: ty::Region<'tcx>,
                      sup: ty::RegionVid)
     {
         self.region_vars.add_given(sub, sup);
@@ -1324,7 +1324,7 @@ pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> {
 
     pub fn resolve_regions_and_report_errors(&self,
                                              region_context: DefId,
-                                             region_map: &RegionMaps<'tcx>,
+                                             region_map: &RegionMaps,
                                              free_regions: &FreeRegionMap<'tcx>) {
         let region_rels = RegionRelations::new(self.tcx,
                                                region_context,
index c48b8f610a2b735eea07a629d42b5d9e38d926d0..cce253c1a1a43b8e77b73e5d5e66bf02e005d25b 100644 (file)
@@ -124,20 +124,20 @@ struct ConstraintGraph<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     graph_name: String,
     region_rels: &'a RegionRelations<'a, 'gcx, 'tcx>,
     map: &'a FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
-    node_ids: FxHashMap<Node<'tcx>, usize>,
+    node_ids: FxHashMap<Node, usize>,
 }
 
 #[derive(Clone, Hash, PartialEq, Eq, Debug, Copy)]
-enum Node<'tcx> {
+enum Node {
     RegionVid(ty::RegionVid),
-    Region(ty::RegionKind<'tcx>),
+    Region(ty::RegionKind),
 }
 
 // type Edge = Constraint;
 #[derive(Clone, PartialEq, Eq, Debug, Copy)]
 enum Edge<'tcx> {
     Constraint(Constraint<'tcx>),
-    EnclScope(CodeExtent<'tcx>, CodeExtent<'tcx>),
+    EnclScope(CodeExtent, CodeExtent),
 }
 
 impl<'a, 'gcx, 'tcx> ConstraintGraph<'a, 'gcx, 'tcx> {
@@ -176,7 +176,7 @@ fn new(name: String,
 }
 
 impl<'a, 'gcx, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
-    type Node = Node<'tcx>;
+    type Node = Node;
     type Edge = Edge<'tcx>;
     fn graph_id(&self) -> dot::Id {
         dot::Id::new(&*self.graph_name).unwrap()
@@ -209,7 +209,7 @@ fn edge_label(&self, e: &Edge) -> dot::LabelText {
     }
 }
 
-fn constraint_to_nodes<'tcx>(c: &Constraint<'tcx>) -> (Node<'tcx>, Node<'tcx>) {
+fn constraint_to_nodes(c: &Constraint) -> (Node, Node) {
     match *c {
         Constraint::ConstrainVarSubVar(rv_1, rv_2) =>
             (Node::RegionVid(rv_1), Node::RegionVid(rv_2)),
@@ -222,7 +222,7 @@ fn constraint_to_nodes<'tcx>(c: &Constraint<'tcx>) -> (Node<'tcx>, Node<'tcx>) {
     }
 }
 
-fn edge_to_nodes<'tcx>(e: &Edge<'tcx>) -> (Node<'tcx>, Node<'tcx>) {
+fn edge_to_nodes(e: &Edge) -> (Node, Node) {
     match *e {
         Edge::Constraint(ref c) => constraint_to_nodes(c),
         Edge::EnclScope(sub, sup) => {
@@ -233,9 +233,9 @@ fn edge_to_nodes<'tcx>(e: &Edge<'tcx>) -> (Node<'tcx>, Node<'tcx>) {
 }
 
 impl<'a, 'gcx, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
-    type Node = Node<'tcx>;
+    type Node = Node;
     type Edge = Edge<'tcx>;
-    fn nodes(&self) -> dot::Nodes<Node<'tcx>> {
+    fn nodes(&self) -> dot::Nodes<Node> {
         let mut set = FxHashSet();
         for node in self.node_ids.keys() {
             set.insert(*node);
@@ -250,12 +250,12 @@ fn edges(&self) -> dot::Edges<Edge<'tcx>> {
         debug!("region graph has {} edges", v.len());
         Cow::Owned(v)
     }
-    fn source(&self, edge: &Edge<'tcx>) -> Node<'tcx> {
+    fn source(&self, edge: &Edge<'tcx>) -> Node {
         let (n1, _) = edge_to_nodes(edge);
         debug!("edge {:?} has source {:?}", edge, n1);
         n1
     }
-    fn target(&self, edge: &Edge<'tcx>) -> Node<'tcx> {
+    fn target(&self, edge: &Edge<'tcx>) -> Node {
         let (_, n2) = edge_to_nodes(edge);
         debug!("edge {:?} has target {:?}", edge, n2);
         n2
index 39554d1fa3a3ae77cce418d08d76881bcc838c33..2e3c2443544f649601743c9174465d7d2a1e5a54 100644 (file)
@@ -29,7 +29,6 @@
 use ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
 
 use std::cell::{Cell, RefCell};
-use std::cmp::Ordering::{self, Less, Greater, Equal};
 use std::fmt;
 use std::mem;
 use std::u32;
@@ -127,7 +126,7 @@ pub enum UndoLogEntry<'tcx> {
     AddVerify(usize),
 
     /// We added the given `given`
-    AddGiven(ty::FreeRegion<'tcx>, ty::RegionVid),
+    AddGiven(Region<'tcx>, ty::RegionVid),
 
     /// We added a GLB/LUB "combinaton variable"
     AddCombination(CombineMapType, TwoRegions<'tcx>),
@@ -213,7 +212,7 @@ pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     // record the fact that `'a <= 'b` is implied by the fn signature,
     // and then ignore the constraint when solving equations. This is
     // a bit of a hack but seems to work.
-    givens: RefCell<FxHashSet<(ty::FreeRegion<'tcx>, ty::RegionVid)>>,
+    givens: RefCell<FxHashSet<(Region<'tcx>, ty::RegionVid)>>,
 
     lubs: RefCell<CombineMap<'tcx>>,
     glbs: RefCell<CombineMap<'tcx>>,
@@ -309,8 +308,7 @@ fn fixed_point(&mut self,
                         self.add_edge(a, b);
                     }
                     &AddGiven(a, b) => {
-                        self.add_edge(tcx.mk_region(ReFree(a)),
-                                      tcx.mk_region(ReVar(b)));
+                        self.add_edge(a, tcx.mk_region(ReVar(b)));
                     }
                     &AddVerify(i) => {
                         verifys[i].bound.for_each_region(&mut |b| {
@@ -661,7 +659,7 @@ fn add_verify(&self, verify: Verify<'tcx>) {
         }
     }
 
-    pub fn add_given(&self, sub: ty::FreeRegion<'tcx>, sup: ty::RegionVid) {
+    pub fn add_given(&self, sub: Region<'tcx>, sup: ty::RegionVid) {
         // cannot add givens once regions are resolved
         assert!(self.values_are_none());
 
@@ -702,9 +700,7 @@ pub fn make_subregion(&self,
                origin);
 
         match (sub, sup) {
-            (&ReEarlyBound(..), _) |
             (&ReLateBound(..), _) |
-            (_, &ReEarlyBound(..)) |
             (_, &ReLateBound(..)) => {
                 span_bug!(origin.span(),
                           "cannot relate bound region: {:?} <= {:?}",
@@ -908,8 +904,6 @@ fn lub_concrete_regions(&self,
         match (a, b) {
             (&ReLateBound(..), _) |
             (_, &ReLateBound(..)) |
-            (&ReEarlyBound(..), _) |
-            (_, &ReEarlyBound(..)) |
             (&ReErased, _) |
             (_, &ReErased) => {
                 bug!("cannot relate region: LUB({:?}, {:?})", a, b);
@@ -931,18 +925,31 @@ fn lub_concrete_regions(&self,
                           b);
             }
 
-            (&ReFree(fr), &ReScope(s_id)) |
-            (&ReScope(s_id), &ReFree(fr)) => {
+            (&ReEarlyBound(_), &ReScope(s_id)) |
+            (&ReScope(s_id), &ReEarlyBound(_)) |
+            (&ReFree(_), &ReScope(s_id)) |
+            (&ReScope(s_id), &ReFree(_)) => {
                 // A "free" region can be interpreted as "some region
-                // at least as big as the block fr.scope_id".  So, we can
+                // at least as big as fr.scope".  So, we can
                 // reasonably compare free regions and scopes:
-                if let Some(fr_scope) = fr.scope {
-                    let r_id = region_rels.region_maps.nearest_common_ancestor(fr_scope, s_id);
-                    if r_id == fr_scope {
-                        // if the free region's scope `fr.scope_id` is bigger than
-                        // the scope region `s_id`, then the LUB is the free
-                        // region itself:
-                        return self.tcx.mk_region(ReFree(fr));
+                let fr_scope = match (a, b) {
+                    (&ReEarlyBound(ref br), _) | (_, &ReEarlyBound(ref br)) => {
+                        region_rels.region_maps.early_free_extent(self.tcx, br)
+                    }
+                    (&ReFree(ref fr), _) | (_, &ReFree(ref fr)) => {
+                        region_rels.region_maps.free_extent(self.tcx, fr)
+                    }
+                    _ => bug!()
+                };
+                let r_id = region_rels.region_maps.nearest_common_ancestor(fr_scope, s_id);
+                if r_id == fr_scope {
+                    // if the free region's scope `fr.scope` is bigger than
+                    // the scope region `s_id`, then the LUB is the free
+                    // region itself:
+                    match (a, b) {
+                        (_, &ReScope(_)) => return a,
+                        (&ReScope(_), _) => return b,
+                        _ => bug!()
                     }
                 }
 
@@ -959,6 +966,9 @@ fn lub_concrete_regions(&self,
                 self.tcx.mk_region(ReScope(lub))
             }
 
+            (&ReEarlyBound(_), &ReEarlyBound(_)) |
+            (&ReFree(_), &ReEarlyBound(_)) |
+            (&ReEarlyBound(_), &ReFree(_)) |
             (&ReFree(_), &ReFree(_)) => {
                 region_rels.lub_free_regions(a, b)
             }
@@ -1041,13 +1051,13 @@ fn expand_givens(&self, graph: &RegionGraph) {
 
         let mut givens = self.givens.borrow_mut();
         let seeds: Vec<_> = givens.iter().cloned().collect();
-        for (fr, vid) in seeds {
+        for (r, vid) in seeds {
             let seed_index = NodeIndex(vid.index as usize);
             for succ_index in graph.depth_traverse(seed_index, OUTGOING) {
                 let succ_index = succ_index.0 as u32;
                 if succ_index < self.num_vars() {
                     let succ_vid = RegionVid { index: succ_index };
-                    givens.insert((fr, succ_vid));
+                    givens.insert((r, succ_vid));
                 }
             }
         }
@@ -1096,8 +1106,9 @@ fn expand_node(&self,
 
         // Check if this relationship is implied by a given.
         match *a_region {
-            ty::ReFree(fr) => {
-                if self.givens.borrow().contains(&(fr, b_vid)) {
+            ty::ReEarlyBound(_) |
+            ty::ReFree(_) => {
+                if self.givens.borrow().contains(&(a_region, b_vid)) {
                     debug!("given");
                     return false;
                 }
@@ -1333,16 +1344,15 @@ fn collect_error_for_expanding_node(&self,
         // We place free regions first because we are special casing
         // SubSupConflict(ReFree, ReFree) when reporting error, and so
         // the user will more likely get a specific suggestion.
-        fn free_regions_first(a: &RegionAndOrigin, b: &RegionAndOrigin) -> Ordering {
-            match (a.region, b.region) {
-                (&ReFree(..), &ReFree(..)) => Equal,
-                (&ReFree(..), _) => Less,
-                (_, &ReFree(..)) => Greater,
-                (..) => Equal,
+        fn region_order_key(x: &RegionAndOrigin) -> u8 {
+            match *x.region {
+                ReEarlyBound(_) => 0,
+                ReFree(_) => 1,
+                _ => 2
             }
         }
-        lower_bounds.sort_by(|a, b| free_regions_first(a, b));
-        upper_bounds.sort_by(|a, b| free_regions_first(a, b));
+        lower_bounds.sort_by_key(region_order_key);
+        upper_bounds.sort_by_key(region_order_key);
 
         for lower_bound in &lower_bounds {
             for upper_bound in &upper_bounds {
index d3954326e7b721c28586f0c001bbc82d3e703a6c..f32ee7900646b0e4f1c82e9b415362e85dbc533d 100644 (file)
@@ -15,7 +15,6 @@
 //! This API is completely unstable and subject to change.
 
 #![crate_name = "rustc"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 #![feature(nonzero)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
 #![feature(slice_patterns)]
 #![feature(specialization)]
-#![feature(staged_api)]
 #![feature(unboxed_closures)]
 #![feature(discriminant_value)]
 #![feature(sort_unstable)]
 #![feature(trace_macros)]
 
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
 #![recursion_limit="128"]
 
 extern crate arena;
@@ -53,7 +54,7 @@
 extern crate getopts;
 extern crate graphviz;
 extern crate libc;
-extern crate rustc_llvm as llvm;
+extern crate owning_ref;
 extern crate rustc_back;
 extern crate rustc_data_structures;
 extern crate serialize;
index e681d55cf94b893db2fd37f65eb7e5a422bc4dda..07140f71aebaa1b68253f71e3aef28372800d397 100644 (file)
     "detects unreachable patterns"
 }
 
+declare_lint! {
+    pub UNUSED_MACROS,
+    Warn,
+    "detects macros that were not used"
+}
+
 declare_lint! {
     pub WARNINGS,
     Warn,
@@ -259,6 +265,7 @@ fn get_lints(&self) -> LintArray {
             DEAD_CODE,
             UNREACHABLE_CODE,
             UNREACHABLE_PATTERNS,
+            UNUSED_MACROS,
             WARNINGS,
             UNUSED_FEATURES,
             STABLE_FEATURES,
index 6947e7c3f4085ce579d75f7a32f1bfd86f07bb3b..9d5ba2c8f950101547a810d5ea2a398f044249f0 100644 (file)
@@ -49,6 +49,7 @@
 use hir::def_id::LOCAL_CRATE;
 use hir::intravisit as hir_visit;
 use syntax::visit as ast_visit;
+use syntax::tokenstream::ThinTokenStream;
 
 /// Information about the registered lints.
 ///
@@ -680,12 +681,12 @@ fn with_lint_attrs<F>(&mut self,
                                                             "{}({}) overruled by outer forbid({})",
                                                             level.as_str(), lint_name,
                                                             lint_name);
-                    diag_builder.span_label(span, &format!("overruled by previous forbid"));
+                    diag_builder.span_label(span, "overruled by previous forbid");
                     match now_source {
                         LintSource::Default => &mut diag_builder,
                         LintSource::Node(_, forbid_source_span) => {
                             diag_builder.span_label(forbid_source_span,
-                                                    &format!("`forbid` level set here"))
+                                                    "`forbid` level set here")
                         },
                         LintSource::CommandLine(_) => {
                             diag_builder.note("`forbid` lint level was set on command line")
@@ -1055,7 +1056,7 @@ fn visit_ident(&mut self, sp: Span, id: ast::Ident) {
         run_lints!(self, check_ident, early_passes, sp, id);
     }
 
-    fn visit_mod(&mut self, m: &'a ast::Mod, s: Span, n: ast::NodeId) {
+    fn visit_mod(&mut self, m: &'a ast::Mod, s: Span, _a: &[ast::Attribute], n: ast::NodeId) {
         run_lints!(self, check_mod, early_passes, m, s, n);
         ast_visit::walk_mod(self, m);
         run_lints!(self, check_mod_post, early_passes, m, s, n);
@@ -1125,6 +1126,13 @@ fn visit_path_list_item(&mut self, prefix: &'a ast::Path, item: &'a ast::PathLis
     fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
         run_lints!(self, check_attribute, early_passes, attr);
     }
+
+    fn visit_mac_def(&mut self, _mac: &'a ThinTokenStream, id: ast::NodeId) {
+        let lints = self.sess.lints.borrow_mut().take(id);
+        for early_lint in lints {
+            self.early_lint(&early_lint);
+        }
+    }
 }
 
 enum CheckLintNameResult {
index 74026abe64db2fd1c27a0b4a000bfbc490e04c5b..3bbaf5c9299f8945e301378c874a15cd57473c52 100644 (file)
@@ -197,7 +197,7 @@ pub fn note(&self,
     {
         match self.description() {
             ConstEvalErrDescription::Simple(message) => {
-                diag.span_label(self.span, &message);
+                diag.span_label(self.span, message);
             }
         }
 
index 303c5059e7cf3d6136445d2a076dbe601243aeb4..a68aca4600054ac2ba3e9d87b7df727ad2d0f09b 100644 (file)
@@ -23,6 +23,7 @@
 // probably get a better home if someone can find one.
 
 use hir::def;
+use dep_graph::DepNode;
 use hir::def_id::{CrateNum, DefId, DefIndex};
 use hir::map as hir_map;
 use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData};
@@ -35,8 +36,9 @@
 use util::nodemap::{NodeSet, DefIdMap};
 
 use std::any::Any;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::rc::Rc;
+use owning_ref::ErasedBoxRef;
 use syntax::ast;
 use syntax::ext::base::SyntaxExtension;
 use syntax::symbol::Symbol;
@@ -161,7 +163,16 @@ pub struct ExternCrate {
 
 pub struct EncodedMetadata {
     pub raw_data: Vec<u8>,
-    pub hashes: Vec<EncodedMetadataHash>,
+    pub hashes: EncodedMetadataHashes,
+}
+
+impl EncodedMetadata {
+    pub fn new() -> EncodedMetadata {
+        EncodedMetadata {
+            raw_data: Vec::new(),
+            hashes: EncodedMetadataHashes::new(),
+        }
+    }
 }
 
 /// The hash for some metadata that (when saving) will be exported
@@ -173,36 +184,70 @@ pub struct EncodedMetadataHash {
     pub hash: ich::Fingerprint,
 }
 
+/// The hash for some metadata that (when saving) will be exported
+/// from this crate, or which (when importing) was exported by an
+/// upstream crate.
+#[derive(Debug, RustcEncodable, RustcDecodable, Clone)]
+pub struct EncodedMetadataHashes {
+    pub entry_hashes: Vec<EncodedMetadataHash>,
+    pub global_hashes: Vec<(DepNode<()>, ich::Fingerprint)>,
+}
+
+impl EncodedMetadataHashes {
+    pub fn new() -> EncodedMetadataHashes {
+        EncodedMetadataHashes {
+            entry_hashes: Vec::new(),
+            global_hashes: Vec::new(),
+        }
+    }
+}
+
+/// The backend's way to give the crate store access to the metadata in a library.
+/// Note that it returns the raw metadata bytes stored in the library file, whether
+/// it is compressed, uncompressed, some weird mix, etc.
+/// rmeta files are backend independent and not handled here.
+///
+/// At the time of this writing, there is only one backend and one way to store
+/// metadata in library -- this trait just serves to decouple rustc_metadata from
+/// the archive reader, which depends on LLVM.
+pub trait MetadataLoader {
+    fn get_rlib_metadata(&self,
+                         target: &Target,
+                         filename: &Path)
+                         -> Result<ErasedBoxRef<[u8]>, String>;
+    fn get_dylib_metadata(&self,
+                          target: &Target,
+                          filename: &Path)
+                          -> Result<ErasedBoxRef<[u8]>, String>;
+}
+
 /// A store of Rust crates, through with their metadata
 /// can be accessed.
 pub trait CrateStore {
     fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any>;
 
+    // access to the metadata loader
+    fn metadata_loader(&self) -> &MetadataLoader;
+
     // item info
     fn visibility(&self, def: DefId) -> ty::Visibility;
     fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>>;
     fn item_generics_cloned(&self, def: DefId) -> ty::Generics;
-    fn item_attrs(&self, def_id: DefId) -> Rc<[ast::Attribute]>;
-    fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name>;
 
     // trait info
     fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>;
 
     // impl info
     fn impl_defaultness(&self, def: DefId) -> hir::Defaultness;
-    fn impl_parent(&self, impl_def_id: DefId) -> Option<DefId>;
 
     // trait/impl-item info
-    fn trait_of_item(&self, def_id: DefId) -> Option<DefId>;
     fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem;
 
     // flags
     fn is_const_fn(&self, did: DefId) -> bool;
     fn is_default_impl(&self, impl_did: DefId) -> bool;
-    fn is_foreign_item(&self, did: DefId) -> bool;
     fn is_dllimport_foreign_item(&self, def: DefId) -> bool;
     fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool;
-    fn is_exported_symbol(&self, def_id: DefId) -> bool;
 
     // crate metadata
     fn dylib_dependency_formats(&self, cnum: CrateNum)
@@ -211,7 +256,6 @@ fn dylib_dependency_formats(&self, cnum: CrateNum)
     fn export_macros(&self, cnum: CrateNum);
     fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>;
     fn missing_lang_items(&self, cnum: CrateNum) -> Vec<lang_items::LangItem>;
-    fn is_staged_api(&self, cnum: CrateNum) -> bool;
     fn is_allocator(&self, cnum: CrateNum) -> bool;
     fn is_panic_runtime(&self, cnum: CrateNum) -> bool;
     fn is_compiler_builtins(&self, cnum: CrateNum) -> bool;
@@ -254,8 +298,6 @@ fn item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
     fn used_link_args(&self) -> Vec<String>;
 
     // utility functions
-    fn metadata_filename(&self) -> &str;
-    fn metadata_section_name(&self, target: &Target) -> &str;
     fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>;
     fn used_crate_source(&self, cnum: CrateNum) -> CrateSource;
     fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
@@ -309,28 +351,22 @@ fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>> {
     }
     fn item_generics_cloned(&self, def: DefId) -> ty::Generics
         { bug!("item_generics_cloned") }
-    fn item_attrs(&self, def_id: DefId) -> Rc<[ast::Attribute]> { bug!("item_attrs") }
-    fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name> { bug!("fn_arg_names") }
 
     // trait info
     fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId> { vec![] }
 
     // impl info
     fn impl_defaultness(&self, def: DefId) -> hir::Defaultness { bug!("impl_defaultness") }
-    fn impl_parent(&self, def: DefId) -> Option<DefId> { bug!("impl_parent") }
 
     // trait/impl-item info
-    fn trait_of_item(&self, def_id: DefId) -> Option<DefId> { bug!("trait_of_item") }
     fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem
         { bug!("associated_item_cloned") }
 
     // flags
     fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") }
     fn is_default_impl(&self, impl_did: DefId) -> bool { bug!("is_default_impl") }
-    fn is_foreign_item(&self, did: DefId) -> bool { bug!("is_foreign_item") }
     fn is_dllimport_foreign_item(&self, id: DefId) -> bool { false }
     fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool { false }
-    fn is_exported_symbol(&self, def_id: DefId) -> bool { false }
 
     // crate metadata
     fn dylib_dependency_formats(&self, cnum: CrateNum)
@@ -340,7 +376,6 @@ fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>
         { bug!("lang_items") }
     fn missing_lang_items(&self, cnum: CrateNum) -> Vec<lang_items::LangItem>
         { bug!("missing_lang_items") }
-    fn is_staged_api(&self, cnum: CrateNum) -> bool { bug!("is_staged_api") }
     fn dep_kind(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") }
     fn export_macros(&self, cnum: CrateNum) { bug!("export_macros") }
     fn is_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") }
@@ -399,8 +434,6 @@ fn used_libraries(&self) -> Vec<NativeLibrary> { vec![] }
     fn used_link_args(&self) -> Vec<String> { vec![] }
 
     // utility functions
-    fn metadata_filename(&self) -> &str { bug!("metadata_filename") }
-    fn metadata_section_name(&self, target: &Target) -> &str { bug!("metadata_section_name") }
     fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
         { vec![] }
     fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { bug!("used_crate_source") }
@@ -413,6 +446,9 @@ fn encode_metadata<'a, 'tcx>(&self,
         bug!("encode_metadata")
     }
     fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
+
+    // access to the metadata loader
+    fn metadata_loader(&self) -> &MetadataLoader { bug!("metadata_loader") }
 }
 
 pub trait CrateLoader {
index d2b8ed8c2970770250d35fe78699d06d548d4316..5360a86560d399235a660c877c47090fea23bf3f 100644 (file)
@@ -74,7 +74,7 @@ fn require_unsafe_ext(&mut self, node_id: ast::NodeId, span: Span,
                     struct_span_err!(
                         self.tcx.sess, span, E0133,
                         "{} requires unsafe function or block", description)
-                        .span_label(span, &description)
+                        .span_label(span, description)
                         .emit();
                 }
             }
@@ -205,7 +205,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
                     } else if match self.tcx.hir.get_if_local(def_id) {
                         Some(hir::map::NodeForeignItem(..)) => true,
                         Some(..) => false,
-                        None => self.tcx.sess.cstore.is_foreign_item(def_id),
+                        None => self.tcx.is_foreign_item(def_id),
                     } {
                         self.require_unsafe_ext(expr.id, expr.span, "use of extern static", true);
                     }
index 8da7560387f879d3794ad17068c760e4bcac60bf..24748b6cf65b8aab05159071a883fcd4821885b4 100644 (file)
@@ -128,8 +128,8 @@ fn find_item(item: &Item, ctxt: &mut EntryContext, at_root: bool) {
             } else {
                 struct_span_err!(ctxt.session, item.span, E0137,
                           "multiple functions with a #[main] attribute")
-                .span_label(item.span, &format!("additional #[main] function"))
-                .span_label(ctxt.attr_main_fn.unwrap().1, &format!("first #[main] function"))
+                .span_label(item.span, "additional #[main] function")
+                .span_label(ctxt.attr_main_fn.unwrap().1, "first #[main] function")
                 .emit();
             }
         },
@@ -141,8 +141,8 @@ fn find_item(item: &Item, ctxt: &mut EntryContext, at_root: bool) {
                     ctxt.session, item.span, E0138,
                     "multiple 'start' functions")
                     .span_label(ctxt.start_fn.unwrap().1,
-                                &format!("previous `start` function here"))
-                    .span_label(item.span, &format!("multiple `start` functions"))
+                                "previous `start` function here")
+                    .span_label(item.span, "multiple `start` functions")
                     .emit();
             }
         },
index 41f9311dd809bf5bf09c5b9590763776c5a2cd09..99b140f690a4848cda6ee003634a45f7cb321ed9 100644 (file)
@@ -271,7 +271,7 @@ enum PassArgs {
 
 impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
     pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
-               region_maps: &'a RegionMaps<'tcx>,
+               region_maps: &'a RegionMaps,
                infcx: &'a InferCtxt<'a, 'gcx, 'tcx>)
                -> Self
     {
@@ -283,7 +283,7 @@ pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
 
     pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a),
                         infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-                        region_maps: &'a RegionMaps<'tcx>,
+                        region_maps: &'a RegionMaps,
                         options: mc::MemCategorizationOptions)
                -> Self
     {
index 2dc7aac04aede4bc53413f5fefd0d65cb9b6ec13..6a21bdc19e0915b2ade6bf1ebb69e59a0e9a8d92 100644 (file)
@@ -35,7 +35,7 @@ pub struct RegionRelations<'a, 'gcx: 'tcx, 'tcx: 'a> {
     pub context: DefId,
 
     /// region maps for the given context
-    pub region_maps: &'a RegionMaps<'tcx>,
+    pub region_maps: &'a RegionMaps,
 
     /// free-region relationships
     pub free_regions: &'a FreeRegionMap<'tcx>,
@@ -45,7 +45,7 @@ impl<'a, 'gcx, 'tcx> RegionRelations<'a, 'gcx, 'tcx> {
     pub fn new(
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
         context: DefId,
-        region_maps: &'a RegionMaps<'tcx>,
+        region_maps: &'a RegionMaps,
         free_regions: &'a FreeRegionMap<'tcx>,
     ) -> Self {
         Self {
@@ -71,26 +71,27 @@ pub fn is_subregion_of(&self,
                 (&ty::ReScope(sub_scope), &ty::ReScope(super_scope)) =>
                     self.region_maps.is_subscope_of(sub_scope, super_scope),
 
-                (&ty::ReScope(sub_scope), &ty::ReFree(fr)) => {
-                    // 1. It is safe to unwrap `fr.scope` because we
-                    // should only ever wind up comparing against
-                    // `ReScope` in the context of a method or
-                    // body, where `fr.scope` should be `Some`.
-                    self.region_maps.is_subscope_of(sub_scope, fr.scope.unwrap() /*1*/) ||
-                        self.is_static(super_region)
+                (&ty::ReScope(sub_scope), &ty::ReEarlyBound(ref br)) => {
+                    let fr_scope = self.region_maps.early_free_extent(self.tcx, br);
+                    self.region_maps.is_subscope_of(sub_scope, fr_scope)
                 }
 
-                (&ty::ReFree(_), &ty::ReFree(_)) =>
-                    self.free_regions.relation.contains(&sub_region, &super_region) ||
-                        self.is_static(super_region),
+                (&ty::ReScope(sub_scope), &ty::ReFree(ref fr)) => {
+                    let fr_scope = self.region_maps.free_extent(self.tcx, fr);
+                    self.region_maps.is_subscope_of(sub_scope, fr_scope)
+                }
 
-                (&ty::ReStatic, &ty::ReFree(_)) =>
-                    self.is_static(super_region),
+                (&ty::ReEarlyBound(_), &ty::ReEarlyBound(_)) |
+                (&ty::ReFree(_), &ty::ReEarlyBound(_)) |
+                (&ty::ReEarlyBound(_), &ty::ReFree(_)) |
+                (&ty::ReFree(_), &ty::ReFree(_)) =>
+                    self.free_regions.relation.contains(&sub_region, &super_region),
 
                 _ =>
                     false,
             }
         };
+        let result = result || self.is_static(super_region);
         debug!("is_subregion_of(sub_region={:?}, super_region={:?}) = {:?}",
                sub_region, super_region, result);
         result
@@ -101,11 +102,11 @@ fn is_static(&self, super_region: ty::Region<'tcx>) -> bool {
         debug!("is_static(super_region={:?})", super_region);
         match *super_region {
             ty::ReStatic => true,
-            ty::ReFree(_) => {
+            ty::ReEarlyBound(_) | ty::ReFree(_) => {
                 let re_static = self.tcx.mk_region(ty::ReStatic);
                 self.free_regions.relation.contains(&re_static, &super_region)
             }
-            _ => bug!("only free regions should be given to `is_static`")
+            _ => false
         }
     }
 
@@ -142,11 +143,9 @@ pub fn relate_free_regions_from_implied_bounds(&mut self,
         for implied_bound in implied_bounds {
             debug!("implied bound: {:?}", implied_bound);
             match *implied_bound {
-                ImpliedBound::RegionSubRegion(a @ &ty::ReFree(_), b @ &ty::ReFree(_)) |
-                ImpliedBound::RegionSubRegion(a @ &ty::ReStatic, b @ &ty::ReFree(_)) => {
+                ImpliedBound::RegionSubRegion(a, b) => {
                     self.relate_regions(a, b);
                 }
-                ImpliedBound::RegionSubRegion(..) |
                 ImpliedBound::RegionSubParam(..) |
                 ImpliedBound::RegionSubProjection(..) => {
                 }
@@ -170,32 +169,18 @@ pub fn relate_free_regions_from_predicates(&mut self,
                     // No region bounds here
                 }
                 ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r_a, r_b))) => {
-                    match (r_a, r_b) {
-                        // `'static: 'x` is not notable
-                        (&ty::ReStatic, &ty::ReFree(_)) => {},
-
-                        (&ty::ReFree(_), &ty::ReStatic) |
-                        (&ty::ReFree(_), &ty::ReFree(_)) => {
-                            // Record that `'a:'b`. Or, put another way, `'b <= 'a`.
-                            self.relate_regions(r_b, r_a);
-                        }
-
-                        _ => {
-                            // All named regions are instantiated with free regions.
-                            bug!("record_region_bounds: non free region: {:?} / {:?}",
-                                 r_a,
-                                 r_b);
-                        }
-                    }
+                    self.relate_regions(r_b, r_a);
                 }
             }
         }
     }
 
+    // Record that `'sup:'sub`. Or, put another way, `'sub <= 'sup`.
+    // (with the exception that `'static: 'x` is not notable)
     fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) {
-        assert!(match *sub { ty::ReFree(_) | ty::ReStatic => true, _ => false });
-        assert!(match *sup { ty::ReFree(_) | ty::ReStatic => true, _ => false });
-        self.relation.add(sub, sup)
+        if (is_free(sub) || *sub == ty::ReStatic) && is_free(sup) {
+            self.relation.add(sub, sup)
+        }
     }
 
     pub fn lub_free_regions<'a, 'gcx>(&self,
@@ -203,8 +188,8 @@ pub fn lub_free_regions<'a, 'gcx>(&self,
                                       r_a: Region<'tcx>,
                                       r_b: Region<'tcx>)
                                       -> Region<'tcx> {
-        assert!(match *r_a { ty::ReFree(_) => true, _ => false });
-        assert!(match *r_b { ty::ReFree(_) => true, _ => false });
+        assert!(is_free(r_a));
+        assert!(is_free(r_b));
         let result = if r_a == r_b { r_a } else {
             match self.relation.postdom_upper_bound(&r_a, &r_b) {
                 None => tcx.mk_region(ty::ReStatic),
@@ -216,6 +201,13 @@ pub fn lub_free_regions<'a, 'gcx>(&self,
     }
 }
 
+fn is_free(r: Region) -> bool {
+    match *r {
+        ty::ReEarlyBound(_) | ty::ReFree(_) => true,
+        _ => false
+    }
+}
+
 impl_stable_hash_for!(struct FreeRegionMap<'tcx> {
     relation
 });
index 435dd05358d47e11162b8248ce191666a1e7b452..a759a9061f8428874475d8a2f61be1e8426d6057 100644 (file)
@@ -92,7 +92,7 @@ fn check_transmute(&self, span: Span, from: Ty<'gcx>, to: Ty<'gcx>) {
                     struct_span_err!(self.infcx.tcx.sess, span, E0591,
                                      "`{}` is zero-sized and can't be transmuted to `{}`",
                                      from, to)
-                        .span_note(span, &format!("cast with `as` to a pointer instead"))
+                        .span_note(span, "cast with `as` to a pointer instead")
                         .emit();
                     return;
                 }
@@ -126,7 +126,7 @@ fn check_transmute(&self, span: Span, from: Ty<'gcx>, to: Ty<'gcx>) {
                   from, skeleton_string(from, sk_from),
                   to, skeleton_string(to, sk_to))
             .span_label(span,
-                &format!("transmuting between {} and {}",
+                format!("transmuting between {} and {}",
                     skeleton_string(from, sk_from),
                     skeleton_string(to, sk_to)))
             .emit();
index 1ea87cc0a4568347e15d1c11dc266c845f1a7c73..ecd350d12736897799a3a78d6cfbbf01274db79a 100644 (file)
@@ -96,9 +96,6 @@
 //!
 //! - `fallthrough_ln`: a live node that represents a fallthrough
 //!
-//! - `no_ret_var`: a synthetic variable that is only 'read' from, the
-//!   fallthrough node.  This allows us to detect functions where we fail
-//!   to return explicitly.
 //! - `clean_exit_var`: a synthetic variable that is only 'read' from the
 //!   fallthrough node.  It is only live if the function could converge
 //!   via means other than an explicit `return` expression. That is, it is
 use self::VarKind::*;
 
 use hir::def::*;
-use ty::{self, TyCtxt, ParameterEnvironment};
-use traits::{self, Reveal};
-use ty::subst::Subst;
+use ty::{self, TyCtxt};
 use lint;
 use util::nodemap::NodeMap;
 
@@ -256,7 +251,6 @@ struct LocalInfo {
 enum VarKind {
     Arg(NodeId, ast::Name),
     Local(LocalInfo),
-    ImplicitRet,
     CleanExit
 }
 
@@ -313,7 +307,7 @@ fn add_variable(&mut self, vk: VarKind) -> Variable {
             Local(LocalInfo { id: node_id, .. }) | Arg(node_id, _) => {
                 self.variable_map.insert(node_id, v);
             },
-            ImplicitRet | CleanExit => {}
+            CleanExit => {}
         }
 
         debug!("{:?} is {:?}", v, vk);
@@ -335,7 +329,6 @@ fn variable_name(&self, var: Variable) -> String {
             Local(LocalInfo { name, .. }) | Arg(_, name) => {
                 name.to_string()
             },
-            ImplicitRet => "<implicit-ret>".to_string(),
             CleanExit => "<clean-exit>".to_string()
         }
     }
@@ -382,7 +375,6 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
 
     // check for various error conditions
     lsets.visit_body(body);
-    lsets.check_ret(id, sp, entry_ln, body);
     lsets.warn_about_unused_args(body, entry_ln);
 }
 
@@ -500,7 +492,6 @@ fn invalid_users() -> Users {
 struct Specials {
     exit_ln: LiveNode,
     fallthrough_ln: LiveNode,
-    no_ret_var: Variable,
     clean_exit_var: Variable
 }
 
@@ -534,7 +525,6 @@ fn new(ir: &'a mut IrMaps<'a, 'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> {
         let specials = Specials {
             exit_ln: ir.add_live_node(ExitNode),
             fallthrough_ln: ir.add_live_node(ExitNode),
-            no_ret_var: ir.add_variable(ImplicitRet),
             clean_exit_var: ir.add_variable(CleanExit)
         };
 
@@ -1420,45 +1410,6 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) {
 }
 
 impl<'a, 'tcx> Liveness<'a, 'tcx> {
-    fn check_ret(&self,
-                 id: NodeId,
-                 sp: Span,
-                 entry_ln: LiveNode,
-                 body: &hir::Body)
-    {
-        let fn_ty = self.ir.tcx.type_of(self.ir.tcx.hir.local_def_id(id));
-        let fn_sig = match fn_ty.sty {
-            ty::TyClosure(closure_def_id, substs) => {
-                self.ir.tcx.closure_type(closure_def_id)
-                    .subst(self.ir.tcx, substs.substs)
-            }
-            _ => fn_ty.fn_sig()
-        };
-
-        let fn_ret = fn_sig.output();
-
-        // within the fn body, late-bound regions are liberated
-        // and must outlive the *call-site* of the function.
-        let fn_ret =
-            self.ir.tcx.liberate_late_bound_regions(
-                Some(self.ir.tcx.call_site_extent(id, body.value.id)),
-                &fn_ret);
-
-        if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() {
-            let param_env = ParameterEnvironment::for_item(self.ir.tcx, id);
-            let t_ret_subst = fn_ret.subst(self.ir.tcx, &param_env.free_substs);
-            let is_nil = self.ir.tcx.infer_ctxt(param_env, Reveal::All).enter(|infcx| {
-                let cause = traits::ObligationCause::dummy();
-                traits::fully_normalize(&infcx, cause, &t_ret_subst).unwrap().is_nil()
-            });
-
-            // for nil return types, it is ok to not return a value expl.
-            if !is_nil {
-                span_bug!(sp, "not all control paths return a value");
-            }
-        }
-    }
-
     fn check_lvalue(&mut self, expr: &'tcx Expr) {
         match expr.node {
             hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
index 11a364f92c316858538f83518a1aaef00d171bf2..d0adf51d79e68675a59672003c9c96b4d31a54f6 100644 (file)
@@ -290,7 +290,7 @@ fn span(&self) -> Span { self.span }
 #[derive(Clone)]
 pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-    pub region_maps: &'a RegionMaps<'tcx>,
+    pub region_maps: &'a RegionMaps,
     options: MemCategorizationOptions,
 }
 
@@ -406,7 +406,7 @@ pub fn to_user_str(&self) -> &'static str {
 impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
     /// Context should be the `DefId` we use to fetch region-maps.
     pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-               region_maps: &'a RegionMaps<'tcx>)
+               region_maps: &'a RegionMaps)
                -> MemCategorizationContext<'a, 'gcx, 'tcx> {
         MemCategorizationContext::with_options(infcx,
                                                region_maps,
@@ -414,7 +414,7 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     }
 
     pub fn with_options(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-                        region_maps: &'a RegionMaps<'tcx>,
+                        region_maps: &'a RegionMaps,
                         options: MemCategorizationOptions)
                         -> MemCategorizationContext<'a, 'gcx, 'tcx> {
         MemCategorizationContext {
@@ -785,26 +785,12 @@ fn env_deref(&self,
                  cmt_result: cmt_<'tcx>)
                  -> cmt_<'tcx>
     {
-        // Look up the node ID of the closure body so we can construct
-        // a free region within it
-        let fn_body_id = {
-            let fn_expr = match self.tcx().hir.find(upvar_id.closure_expr_id) {
-                Some(hir_map::NodeExpr(e)) => e,
-                _ => bug!()
-            };
-
-            match fn_expr.node {
-                hir::ExprClosure(.., body_id, _) => body_id,
-                _ => bug!()
-            }
-        };
-
         // Region of environment pointer
         let env_region = self.tcx().mk_region(ty::ReFree(ty::FreeRegion {
             // The environment of a closure is guaranteed to
             // outlive any bindings introduced in the body of the
             // closure itself.
-            scope: Some(self.tcx().item_extent(fn_body_id.node_id)),
+            scope: self.tcx().hir.local_def_id(upvar_id.closure_expr_id),
             bound_region: ty::BrEnv
         }));
 
@@ -853,7 +839,7 @@ fn env_deref(&self,
     pub fn temporary_scope(&self, id: ast::NodeId) -> (ty::Region<'tcx>, ty::Region<'tcx>)
     {
         let (scope, old_scope) =
-            self.region_maps.old_and_new_temporary_scope(self.tcx(), id);
+            self.region_maps.old_and_new_temporary_scope(id);
         (self.tcx().mk_region(match scope {
             Some(scope) => ty::ReScope(scope),
             None => ty::ReStatic
index d1d5e9d6cb18f78b52fea08b19b6a6dbc17afda8..2d632e3feb5457de6b463f62e84160cb362f19ce 100644 (file)
 
 use std::mem;
 use std::rc::Rc;
-use serialize;
 use syntax::codemap;
-use syntax::ast::{self, NodeId};
+use syntax::ast;
 use syntax_pos::Span;
 use ty::TyCtxt;
 use ty::maps::Providers;
 
-use hir; use hir::def_id::DefId;
-use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
-use hir::{Block, Item, FnDecl, Arm, Pat, PatKind, Stmt, Expr, Local};
-
-pub type CodeExtent<'tcx> = &'tcx CodeExtentData;
-
-impl<'tcx> serialize::UseSpecializedEncodable for CodeExtent<'tcx> {}
-impl<'tcx> serialize::UseSpecializedDecodable for CodeExtent<'tcx> {}
+use hir;
+use hir::def_id::DefId;
+use hir::intravisit::{self, Visitor, NestedVisitorMap};
+use hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local};
+use mir::transform::MirSource;
 
 /// CodeExtent represents a statically-describable extent that can be
 /// used to bound the lifetime/region for values.
@@ -100,16 +96,16 @@ impl<'tcx> serialize::UseSpecializedDecodable for CodeExtent<'tcx> {}
 /// actually attach a more meaningful ordering to scopes than the one
 /// generated via deriving here.
 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)]
-pub enum CodeExtentData {
+pub enum CodeExtent {
     Misc(ast::NodeId),
 
     // extent of the call-site for a function or closure (outlives
     // the parameters as well as the body).
-    CallSiteScope { fn_id: ast::NodeId, body_id: ast::NodeId },
+    CallSiteScope(hir::BodyId),
 
     // extent of parameters passed to a function or closure (they
     // outlive its body)
-    ParameterScope { fn_id: ast::NodeId, body_id: ast::NodeId },
+    ParameterScope(hir::BodyId),
 
     // extent of destructors for temporaries of node-id
     DestructionScope(ast::NodeId),
@@ -118,23 +114,6 @@ pub enum CodeExtentData {
     Remainder(BlockRemainder)
 }
 
-/// extent of call-site for a function/method.
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable,
-           RustcDecodable, Debug, Copy)]
-pub struct CallSiteScopeData {
-    pub fn_id: ast::NodeId, pub body_id: ast::NodeId,
-}
-
-impl CallSiteScopeData {
-    pub fn to_code_extent<'a, 'tcx, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> CodeExtent<'tcx> {
-        tcx.intern_code_extent(
-            match *self {
-                CallSiteScopeData { fn_id, body_id } =>
-                    CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id },
-            })
-    }
-}
-
 /// Represents a subscope of `block` for a binding that is introduced
 /// by `block.stmts[first_statement_index]`. Such subscopes represent
 /// a suffix of the block. Note that each subscope does not include
@@ -146,9 +125,9 @@ pub fn to_code_extent<'a, 'tcx, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Cod
 /// * the subscope with `first_statement_index == 0` is scope of both
 ///   `a` and `b`; it does not include EXPR_1, but does include
 ///   everything after that first `let`. (If you want a scope that
-///   includes EXPR_1 as well, then do not use `CodeExtentData::Remainder`,
+///   includes EXPR_1 as well, then do not use `CodeExtent::Remainder`,
 ///   but instead another `CodeExtent` that encompasses the whole block,
-///   e.g. `CodeExtentData::Misc`.
+///   e.g. `CodeExtent::Misc`.
 ///
 /// * the subscope with `first_statement_index == 1` is scope of `c`,
 ///   and thus does not include EXPR_2, but covers the `...`.
@@ -159,21 +138,21 @@ pub struct BlockRemainder {
     pub first_statement_index: u32,
 }
 
-impl CodeExtentData {
+impl CodeExtent {
     /// Returns a node id associated with this scope.
     ///
     /// NB: likely to be replaced as API is refined; e.g. pnkfelix
     /// anticipates `fn entry_node_id` and `fn each_exit_node_id`.
     pub fn node_id(&self) -> ast::NodeId {
         match *self {
-            CodeExtentData::Misc(node_id) => node_id,
+            CodeExtent::Misc(node_id) => node_id,
 
             // These cases all return rough approximations to the
             // precise extent denoted by `self`.
-            CodeExtentData::Remainder(br) => br.block,
-            CodeExtentData::DestructionScope(node_id) => node_id,
-            CodeExtentData::CallSiteScope { fn_id: _, body_id } |
-            CodeExtentData::ParameterScope { fn_id: _, body_id } => body_id,
+            CodeExtent::Remainder(br) => br.block,
+            CodeExtent::DestructionScope(node_id) => node_id,
+            CodeExtent::CallSiteScope(body_id) |
+            CodeExtent::ParameterScope(body_id) => body_id.node_id,
         }
     }
 
@@ -184,12 +163,12 @@ pub fn span(&self, hir_map: &hir_map::Map) -> Option<Span> {
         match hir_map.find(self.node_id()) {
             Some(hir_map::NodeBlock(ref blk)) => {
                 match *self {
-                    CodeExtentData::CallSiteScope { .. } |
-                    CodeExtentData::ParameterScope { .. } |
-                    CodeExtentData::Misc(_) |
-                    CodeExtentData::DestructionScope(_) => Some(blk.span),
+                    CodeExtent::CallSiteScope(_) |
+                    CodeExtent::ParameterScope(_) |
+                    CodeExtent::Misc(_) |
+                    CodeExtent::DestructionScope(_) => Some(blk.span),
 
-                    CodeExtentData::Remainder(r) => {
+                    CodeExtent::Remainder(r) => {
                         assert_eq!(r.block, blk.id);
                         // Want span for extent starting after the
                         // indexed statement and ending at end of
@@ -212,21 +191,29 @@ pub fn span(&self, hir_map: &hir_map::Map) -> Option<Span> {
 }
 
 /// The region maps encode information about region relationships.
-pub struct RegionMaps<'tcx> {
+pub struct RegionMaps {
+    /// If not empty, this body is the root of this region hierarchy.
+    root_body: Option<hir::BodyId>,
+
+    /// The parent of the root body owner, if the latter is an
+    /// an associated const or method, as impls/traits can also
+    /// have lifetime parameters free in this body.
+    root_parent: Option<ast::NodeId>,
+
     /// `scope_map` maps from a scope id to the enclosing scope id;
     /// this is usually corresponding to the lexical nesting, though
     /// in the case of closures the parent scope is the innermost
     /// conditional expression or repeating block. (Note that the
     /// enclosing scope id for the block associated with a closure is
     /// the closure itself.)
-    scope_map: FxHashMap<CodeExtent<'tcx>, CodeExtent<'tcx>>,
+    scope_map: FxHashMap<CodeExtent, CodeExtent>,
 
     /// `var_map` maps from a variable or binding id to the block in
     /// which that variable is declared.
-    var_map: NodeMap<CodeExtent<'tcx>>,
+    var_map: NodeMap<CodeExtent>,
 
     /// maps from a node-id to the associated destruction scope (if any)
-    destruction_scopes: NodeMap<CodeExtent<'tcx>>,
+    destruction_scopes: NodeMap<CodeExtent>,
 
     /// `rvalue_scopes` includes entries for those expressions whose cleanup scope is
     /// larger than the default. The map goes from the expression id
@@ -234,14 +221,14 @@ pub struct RegionMaps<'tcx> {
     /// table, the appropriate cleanup scope is the innermost
     /// enclosing statement, conditional expression, or repeating
     /// block (see `terminating_scopes`).
-    rvalue_scopes: NodeMap<CodeExtent<'tcx>>,
+    rvalue_scopes: NodeMap<CodeExtent>,
 
     /// Records the value of rvalue scopes before they were shrunk by
     /// #36082, for error reporting.
     ///
     /// FIXME: this should be temporary. Remove this by 1.18.0 or
     /// so.
-    shrunk_rvalue_scopes: NodeMap<CodeExtent<'tcx>>,
+    shrunk_rvalue_scopes: NodeMap<CodeExtent>,
 
     /// Encodes the hierarchy of fn bodies. Every fn body (including
     /// closures) forms its own distinct region hierarchy, rooted in
@@ -257,7 +244,7 @@ pub struct RegionMaps<'tcx> {
 }
 
 #[derive(Debug, Copy, Clone)]
-pub struct Context<'tcx> {
+pub struct Context {
     /// the root of the current region tree. This is typically the id
     /// of the innermost fn body. Each fn forms its own disjoint tree
     /// in the region hierarchy. These fn bodies are themselves
@@ -267,21 +254,19 @@ pub struct Context<'tcx> {
     root_id: Option<ast::NodeId>,
 
     /// the scope that contains any new variables declared
-    var_parent: Option<CodeExtent<'tcx>>,
+    var_parent: Option<CodeExtent>,
 
     /// region parent of expressions etc
-    parent: Option<CodeExtent<'tcx>>,
+    parent: Option<CodeExtent>,
 }
 
 struct RegionResolutionVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     // Generated maps:
-    region_maps: &'a mut RegionMaps<'tcx>,
-
-    cx: Context<'tcx>,
+    region_maps: RegionMaps,
 
-    map: &'a hir_map::Map<'tcx>,
+    cx: Context,
 
     /// `terminating_scopes` is a set containing the ids of each
     /// statement, or conditional/repeating expression. These scopes
@@ -307,9 +292,11 @@ struct RegionResolutionVisitor<'a, 'tcx: 'a> {
 }
 
 
-impl<'tcx> RegionMaps<'tcx> {
+impl<'tcx> RegionMaps {
     pub fn new() -> Self {
         RegionMaps {
+            root_body: None,
+            root_parent: None,
             scope_map: FxHashMap(),
             destruction_scopes: FxHashMap(),
             var_map: NodeMap(),
@@ -320,8 +307,8 @@ pub fn new() -> Self {
     }
 
     pub fn record_code_extent(&mut self,
-                              child: CodeExtent<'tcx>,
-                              parent: Option<CodeExtent<'tcx>>) {
+                              child: CodeExtent,
+                              parent: Option<CodeExtent>) {
         debug!("{:?}.parent = {:?}", child, parent);
 
         if let Some(p) = parent {
@@ -330,24 +317,24 @@ pub fn record_code_extent(&mut self,
         }
 
         // record the destruction scopes for later so we can query them
-        if let &CodeExtentData::DestructionScope(n) = child {
+        if let CodeExtent::DestructionScope(n) = child {
             self.destruction_scopes.insert(n, child);
         }
     }
 
-    pub fn each_encl_scope<E>(&self, mut e:E) where E: FnMut(CodeExtent<'tcx>, CodeExtent<'tcx>) {
+    pub fn each_encl_scope<E>(&self, mut e:E) where E: FnMut(CodeExtent, CodeExtent) {
         for (&child, &parent) in &self.scope_map {
             e(child, parent)
         }
     }
 
-    pub fn each_var_scope<E>(&self, mut e:E) where E: FnMut(&ast::NodeId, CodeExtent<'tcx>) {
-        for (child, parent) in self.var_map.iter() {
+    pub fn each_var_scope<E>(&self, mut e:E) where E: FnMut(&ast::NodeId, CodeExtent) {
+        for (child, &parent) in self.var_map.iter() {
             e(child, parent)
         }
     }
 
-    pub fn opt_destruction_extent(&self, n: ast::NodeId) -> Option<CodeExtent<'tcx>> {
+    pub fn opt_destruction_extent(&self, n: ast::NodeId) -> Option<CodeExtent> {
         self.destruction_scopes.get(&n).cloned()
     }
 
@@ -371,48 +358,46 @@ fn fn_is_enclosed_by(&self, mut sub_fn: ast::NodeId, sup_fn: ast::NodeId) -> boo
         }
     }
 
-    fn record_var_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent<'tcx>) {
+    fn record_var_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) {
         debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime);
         assert!(var != lifetime.node_id());
         self.var_map.insert(var, lifetime);
     }
 
-    fn record_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent<'tcx>) {
+    fn record_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) {
         debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime);
         assert!(var != lifetime.node_id());
         self.rvalue_scopes.insert(var, lifetime);
     }
 
-    fn record_shrunk_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent<'tcx>) {
+    fn record_shrunk_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) {
         debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime);
         assert!(var != lifetime.node_id());
         self.shrunk_rvalue_scopes.insert(var, lifetime);
     }
 
-    pub fn opt_encl_scope(&self, id: CodeExtent<'tcx>) -> Option<CodeExtent<'tcx>> {
+    pub fn opt_encl_scope(&self, id: CodeExtent) -> Option<CodeExtent> {
         //! Returns the narrowest scope that encloses `id`, if any.
         self.scope_map.get(&id).cloned()
     }
 
     #[allow(dead_code)] // used in cfg
-    pub fn encl_scope(&self, id: CodeExtent<'tcx>) -> CodeExtent<'tcx> {
+    pub fn encl_scope(&self, id: CodeExtent) -> CodeExtent {
         //! Returns the narrowest scope that encloses `id`, if any.
         self.opt_encl_scope(id).unwrap()
     }
 
     /// Returns the lifetime of the local variable `var_id`
-    pub fn var_scope(&self, var_id: ast::NodeId) -> CodeExtent<'tcx> {
+    pub fn var_scope(&self, var_id: ast::NodeId) -> CodeExtent {
         match self.var_map.get(&var_id) {
             Some(&r) => r,
             None => { bug!("no enclosing scope for id {:?}", var_id); }
         }
     }
 
-    pub fn temporary_scope2<'a, 'gcx: 'tcx>(&self,
-                                            tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                            expr_id: ast::NodeId)
-                                            -> (Option<CodeExtent<'tcx>>, bool) {
-        let temporary_scope = self.temporary_scope(tcx, expr_id);
+    pub fn temporary_scope2(&self, expr_id: ast::NodeId)
+                            -> (Option<CodeExtent>, bool) {
+        let temporary_scope = self.temporary_scope(expr_id);
         let was_shrunk = match self.shrunk_rvalue_scopes.get(&expr_id) {
             Some(&s) => {
                 info!("temporary_scope2({:?}, scope={:?}, shrunk={:?})",
@@ -425,23 +410,18 @@ pub fn temporary_scope2<'a, 'gcx: 'tcx>(&self,
         (temporary_scope, was_shrunk)
     }
 
-    pub fn old_and_new_temporary_scope<'a, 'gcx: 'tcx>(&self,
-                                                       tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                                       expr_id: ast::NodeId)
-                                                       -> (Option<CodeExtent<'tcx>>,
-                                                           Option<CodeExtent<'tcx>>)
+    pub fn old_and_new_temporary_scope(&self, expr_id: ast::NodeId)
+                                       -> (Option<CodeExtent>,
+                                           Option<CodeExtent>)
     {
-        let temporary_scope = self.temporary_scope(tcx, expr_id);
+        let temporary_scope = self.temporary_scope(expr_id);
         (temporary_scope,
          self.shrunk_rvalue_scopes
              .get(&expr_id).cloned()
              .or(temporary_scope))
     }
 
-    pub fn temporary_scope<'a, 'gcx: 'tcx>(&self,
-                                           tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                           expr_id: ast::NodeId)
-                                           -> Option<CodeExtent<'tcx>> {
+    pub fn temporary_scope(&self, expr_id: ast::NodeId) -> Option<CodeExtent> {
         //! Returns the scope when temp created by expr_id will be cleaned up
 
         // check for a designated rvalue scope
@@ -454,11 +434,11 @@ pub fn temporary_scope<'a, 'gcx: 'tcx>(&self,
         // if there's one. Static items, for instance, won't
         // have an enclosing scope, hence no scope will be
         // returned.
-        let mut id = tcx.node_extent(expr_id);
+        let mut id = CodeExtent::Misc(expr_id);
 
-        while let Some(&p) = self.scope_map.get(id) {
-            match *p {
-                CodeExtentData::DestructionScope(..) => {
+        while let Some(&p) = self.scope_map.get(&id) {
+            match p {
+                CodeExtent::DestructionScope(..) => {
                     debug!("temporary_scope({:?}) = {:?} [enclosing]",
                            expr_id, id);
                     return Some(id);
@@ -471,7 +451,7 @@ pub fn temporary_scope<'a, 'gcx: 'tcx>(&self,
         return None;
     }
 
-    pub fn var_region(&self, id: ast::NodeId) -> ty::RegionKind<'tcx> {
+    pub fn var_region(&self, id: ast::NodeId) -> ty::RegionKind {
         //! Returns the lifetime of the variable `id`.
 
         let scope = ty::ReScope(self.var_scope(id));
@@ -513,9 +493,9 @@ pub fn is_subscope_of(&self,
     /// Finds the nearest common ancestor (if any) of two scopes.  That is, finds the smallest
     /// scope which is greater than or equal to both `scope_a` and `scope_b`.
     pub fn nearest_common_ancestor(&self,
-                                   scope_a: CodeExtent<'tcx>,
-                                   scope_b: CodeExtent<'tcx>)
-                                   -> CodeExtent<'tcx> {
+                                   scope_a: CodeExtent,
+                                   scope_b: CodeExtent)
+                                   -> CodeExtent {
         if scope_a == scope_b { return scope_a; }
 
         /// [1] The initial values for `a_buf` and `b_buf` are not used.
@@ -523,9 +503,9 @@ pub fn nearest_common_ancestor(&self,
         /// is re-initialized with new values (or else fallback to a
         /// heap-allocated vector).
         let mut a_buf: [CodeExtent; 32] = [scope_a /* [1] */; 32];
-        let mut a_vec: Vec<CodeExtent<'tcx>> = vec![];
+        let mut a_vec: Vec<CodeExtent> = vec![];
         let mut b_buf: [CodeExtent; 32] = [scope_b /* [1] */; 32];
-        let mut b_vec: Vec<CodeExtent<'tcx>> = vec![];
+        let mut b_vec: Vec<CodeExtent> = vec![];
         let scope_map = &self.scope_map;
         let a_ancestors = ancestors_of(scope_map, scope_a, &mut a_buf, &mut a_vec);
         let b_ancestors = ancestors_of(scope_map, scope_b, &mut b_buf, &mut b_vec);
@@ -549,8 +529,8 @@ pub fn nearest_common_ancestor(&self,
             let a_root_scope = a_ancestors[a_index];
             let b_root_scope = a_ancestors[a_index];
             return match (a_root_scope, b_root_scope) {
-                (&CodeExtentData::DestructionScope(a_root_id),
-                 &CodeExtentData::DestructionScope(b_root_id)) => {
+                (CodeExtent::DestructionScope(a_root_id),
+                 CodeExtent::DestructionScope(b_root_id)) => {
                     if self.fn_is_enclosed_by(a_root_id, b_root_id) {
                         // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a`
                         scope_b
@@ -581,11 +561,11 @@ pub fn nearest_common_ancestor(&self,
             }
         }
 
-        fn ancestors_of<'a, 'tcx>(scope_map: &FxHashMap<CodeExtent<'tcx>, CodeExtent<'tcx>>,
-                                  scope: CodeExtent<'tcx>,
-                                  buf: &'a mut [CodeExtent<'tcx>; 32],
-                                  vec: &'a mut Vec<CodeExtent<'tcx>>)
-                                  -> &'a [CodeExtent<'tcx>] {
+        fn ancestors_of<'a, 'tcx>(scope_map: &FxHashMap<CodeExtent, CodeExtent>,
+                                  scope: CodeExtent,
+                                  buf: &'a mut [CodeExtent; 32],
+                                  vec: &'a mut Vec<CodeExtent>)
+                                  -> &'a [CodeExtent] {
             // debug!("ancestors_of(scope={:?})", scope);
             let mut scope = scope;
 
@@ -593,7 +573,7 @@ fn ancestors_of<'a, 'tcx>(scope_map: &FxHashMap<CodeExtent<'tcx>, CodeExtent<'tc
             while i < 32 {
                 buf[i] = scope;
                 match scope_map.get(&scope) {
-                    Some(superscope) => scope = superscope,
+                    Some(&superscope) => scope = superscope,
                     _ => return &buf[..i+1]
                 }
                 i += 1;
@@ -604,12 +584,55 @@ fn ancestors_of<'a, 'tcx>(scope_map: &FxHashMap<CodeExtent<'tcx>, CodeExtent<'tc
             loop {
                 vec.push(scope);
                 match scope_map.get(&scope) {
-                    Some(superscope) => scope = superscope,
+                    Some(&superscope) => scope = superscope,
                     _ => return &*vec
                 }
             }
         }
     }
+
+    /// Assuming that the provided region was defined within this `RegionMaps`,
+    /// returns the outermost `CodeExtent` that the region outlives.
+    pub fn early_free_extent<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                       br: &ty::EarlyBoundRegion)
+                                       -> CodeExtent {
+        let param_owner = tcx.parent_def_id(br.def_id).unwrap();
+
+        let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap();
+        let body_id = tcx.hir.maybe_body_owned_by(param_owner_id).unwrap_or_else(|| {
+            // The lifetime was defined on node that doesn't own a body,
+            // which in practice can only mean a trait or an impl, that
+            // is the parent of a method, and that is enforced below.
+            assert_eq!(Some(param_owner_id), self.root_parent,
+                       "free_extent: {:?} not recognized by the region maps for {:?}",
+                       param_owner,
+                       self.root_body.map(|body| tcx.hir.body_owner_def_id(body)));
+
+            // The trait/impl lifetime is in scope for the method's body.
+            self.root_body.unwrap()
+        });
+
+        CodeExtent::CallSiteScope(body_id)
+    }
+
+    /// Assuming that the provided region was defined within this `RegionMaps`,
+    /// returns the outermost `CodeExtent` that the region outlives.
+    pub fn free_extent<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, fr: &ty::FreeRegion)
+                                 -> CodeExtent {
+        let param_owner = match fr.bound_region {
+            ty::BoundRegion::BrNamed(def_id, _) => {
+                tcx.parent_def_id(def_id).unwrap()
+            }
+            _ => fr.scope
+        };
+
+        // Ensure that the named late-bound lifetimes were defined
+        // on the same function that they ended up being freed in.
+        assert_eq!(param_owner, fr.scope);
+
+        let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap();
+        CodeExtent::CallSiteScope(tcx.hir.body_owned_by(param_owner_id))
+    }
 }
 
 /// Records the lifetime of a local variable as `cx.var_parent`
@@ -631,7 +654,6 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk:
     debug!("resolve_block(blk.id={:?})", blk.id);
 
     let prev_cx = visitor.cx;
-    let block_extent = visitor.new_node_extent_with_dtor(blk.id);
 
     // We treat the tail expression in the block (if any) somewhat
     // differently from the statements. The issue has to do with
@@ -658,11 +680,8 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk:
     // `other_argument()` has run and also the call to `quux(..)`
     // itself has returned.
 
-    visitor.cx = Context {
-        root_id: prev_cx.root_id,
-        var_parent: Some(block_extent),
-        parent: Some(block_extent),
-    };
+    visitor.enter_node_extent_with_dtor(blk.id);
+    visitor.cx.var_parent = visitor.cx.parent;
 
     {
         // This block should be kept approximately in sync with
@@ -678,17 +697,13 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk:
                 // has the previous subscope in the block as a parent,
                 // except for the first such subscope, which has the
                 // block itself as a parent.
-                let stmt_extent = visitor.new_code_extent(
-                    CodeExtentData::Remainder(BlockRemainder {
+                visitor.enter_code_extent(
+                    CodeExtent::Remainder(BlockRemainder {
                         block: blk.id,
                         first_statement_index: i as u32
                     })
                 );
-                visitor.cx = Context {
-                    root_id: prev_cx.root_id,
-                    var_parent: Some(stmt_extent),
-                    parent: Some(stmt_extent),
-                };
+                visitor.cx.var_parent = visitor.cx.parent;
             }
             visitor.visit_stmt(statement)
         }
@@ -709,7 +724,7 @@ fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, arm: &
 }
 
 fn resolve_pat<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, pat: &'tcx hir::Pat) {
-    visitor.new_node_extent(pat.id);
+    visitor.record_code_extent(CodeExtent::Misc(pat.id));
 
     // If this is a binding then record the lifetime of that binding.
     if let PatKind::Binding(..) = pat.node {
@@ -729,20 +744,20 @@ fn resolve_stmt<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, stmt:
     // statement plus its destructors, and thus the extent for which
     // regions referenced by the destructors need to survive.
     visitor.terminating_scopes.insert(stmt_id);
-    let stmt_extent = visitor.new_node_extent_with_dtor(stmt_id);
 
     let prev_parent = visitor.cx.parent;
-    visitor.cx.parent = Some(stmt_extent);
+    visitor.enter_node_extent_with_dtor(stmt_id);
+
     intravisit::walk_stmt(visitor, stmt);
+
     visitor.cx.parent = prev_parent;
 }
 
 fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: &'tcx hir::Expr) {
     debug!("resolve_expr(expr.id={:?})", expr.id);
 
-    let expr_extent = visitor.new_node_extent_with_dtor(expr.id);
     let prev_cx = visitor.cx;
-    visitor.cx.parent = Some(expr_extent);
+    visitor.enter_node_extent_with_dtor(expr.id);
 
     {
         let terminating_scopes = &mut visitor.terminating_scopes;
@@ -782,7 +797,7 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr:
             }
 
             hir::ExprMatch(..) => {
-                visitor.cx.var_parent = Some(expr_extent);
+                visitor.cx.var_parent = visitor.cx.parent;
             }
 
             hir::ExprAssignOp(..) | hir::ExprIndex(..) |
@@ -811,7 +826,17 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr:
         }
     }
 
-    intravisit::walk_expr(visitor, expr);
+    match expr.node {
+        // Manually recurse over closures, because they are the only
+        // case of nested bodies that share the parent environment.
+        hir::ExprClosure(.., body, _) => {
+            let body = visitor.tcx.hir.body(body);
+            visitor.visit_body(body);
+        }
+
+        _ => intravisit::walk_expr(visitor, expr)
+    }
+
     visitor.cx = prev_cx;
 }
 
@@ -959,7 +984,7 @@ fn is_borrowed_ty(ty: &hir::Ty) -> bool {
     fn record_rvalue_scope_if_borrow_expr<'a, 'tcx>(
         visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
         expr: &hir::Expr,
-        blk_id: CodeExtent<'tcx>)
+        blk_id: CodeExtent)
     {
         match expr.node {
             hir::ExprAddrOf(_, ref subexpr) => {
@@ -1009,7 +1034,7 @@ fn record_rvalue_scope_if_borrow_expr<'a, 'tcx>(
     /// Note: ET is intended to match "rvalues or lvalues based on rvalues".
     fn record_rvalue_scope<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
                                      expr: &hir::Expr,
-                                     blk_scope: CodeExtent<'tcx>,
+                                     blk_scope: CodeExtent,
                                      is_shrunk: bool) {
         let mut expr = expr;
         loop {
@@ -1041,140 +1066,83 @@ fn record_rvalue_scope<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>
     }
 }
 
-fn resolve_item_like<'a, 'tcx, F>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, walk: F)
-    where F: FnOnce(&mut RegionResolutionVisitor<'a, 'tcx>)
-{
-    // Items create a new outer block scope as far as we're concerned.
-    let prev_cx = visitor.cx;
-    let prev_ts = mem::replace(&mut visitor.terminating_scopes, NodeSet());
-    visitor.cx = Context {
-        root_id: None,
-        var_parent: None,
-        parent: None,
-    };
-    walk(visitor);
-    visitor.cx = prev_cx;
-    visitor.terminating_scopes = prev_ts;
-}
-
-fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
-                        kind: FnKind<'tcx>,
-                        decl: &'tcx hir::FnDecl,
-                        body_id: hir::BodyId,
-                        sp: Span,
-                        id: ast::NodeId) {
-    visitor.cx.parent = Some(visitor.new_code_extent(
-        CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id }));
-
-    debug!("region::resolve_fn(id={:?}, \
-            span={:?}, \
-            body.id={:?}, \
-            cx.parent={:?})",
-           id,
-           visitor.tcx.sess.codemap().span_to_string(sp),
-           body_id,
-           visitor.cx.parent);
-
-    let fn_decl_scope = visitor.new_code_extent(
-        CodeExtentData::ParameterScope { fn_id: id, body_id: body_id.node_id });
-
-    if let Some(root_id) = visitor.cx.root_id {
-        visitor.region_maps.record_fn_parent(body_id.node_id, root_id);
-    }
-
-    let outer_cx = visitor.cx;
-    let outer_ts = mem::replace(&mut visitor.terminating_scopes, NodeSet());
-    visitor.terminating_scopes.insert(body_id.node_id);
-
-    // The arguments and `self` are parented to the fn.
-    visitor.cx = Context {
-        root_id: Some(body_id.node_id),
-        parent: None,
-        var_parent: Some(fn_decl_scope),
-    };
-
-    intravisit::walk_fn_decl(visitor, decl);
-    intravisit::walk_fn_kind(visitor, kind);
-
-    // The body of the every fn is a root scope.
-    visitor.cx = Context {
-        root_id: Some(body_id.node_id),
-        parent: Some(fn_decl_scope),
-        var_parent: Some(fn_decl_scope),
-    };
-    visitor.visit_nested_body(body_id);
-
-    // Restore context we had at the start.
-    visitor.cx = outer_cx;
-    visitor.terminating_scopes = outer_ts;
-}
-
 impl<'a, 'tcx> RegionResolutionVisitor<'a, 'tcx> {
-    pub fn intern_code_extent(&mut self,
-                              data: CodeExtentData,
-                              parent: Option<CodeExtent<'tcx>>)
-                              -> CodeExtent<'tcx> {
-        let code_extent = self.tcx.intern_code_extent(data);
-        self.region_maps.record_code_extent(code_extent, parent);
-        code_extent
-    }
-
-    pub fn intern_node(&mut self,
-                       n: ast::NodeId,
-                       parent: Option<CodeExtent<'tcx>>) -> CodeExtent<'tcx> {
-        self.intern_code_extent(CodeExtentData::Misc(n), parent)
-    }
-
     /// Records the current parent (if any) as the parent of `child_scope`.
-    fn new_code_extent(&mut self, child_scope: CodeExtentData) -> CodeExtent<'tcx> {
+    fn record_code_extent(&mut self, child_scope: CodeExtent) {
         let parent = self.cx.parent;
-        self.intern_code_extent(child_scope, parent)
+        self.region_maps.record_code_extent(child_scope, parent);
     }
 
-    fn new_node_extent(&mut self, child_scope: ast::NodeId) -> CodeExtent<'tcx> {
-        self.new_code_extent(CodeExtentData::Misc(child_scope))
+    /// Records the current parent (if any) as the parent of `child_scope`,
+    /// and sets `child_scope` as the new current parent.
+    fn enter_code_extent(&mut self, child_scope: CodeExtent) {
+        self.record_code_extent(child_scope);
+        self.cx.parent = Some(child_scope);
     }
 
-    fn new_node_extent_with_dtor(&mut self, id: ast::NodeId) -> CodeExtent<'tcx> {
+    fn enter_node_extent_with_dtor(&mut self, id: ast::NodeId) {
         // If node was previously marked as a terminating scope during the
         // recursive visit of its parent node in the AST, then we need to
         // account for the destruction scope representing the extent of
         // the destructors that run immediately after it completes.
         if self.terminating_scopes.contains(&id) {
-            let ds = self.new_code_extent(
-                CodeExtentData::DestructionScope(id));
-            self.intern_node(id, Some(ds))
-        } else {
-            self.new_node_extent(id)
+            self.enter_code_extent(CodeExtent::DestructionScope(id));
         }
+        self.enter_code_extent(CodeExtent::Misc(id));
     }
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::OnlyBodies(&self.map)
+        NestedVisitorMap::None
     }
 
     fn visit_block(&mut self, b: &'tcx Block) {
         resolve_block(self, b);
     }
 
-    fn visit_item(&mut self, i: &'tcx Item) {
-        resolve_item_like(self, |this| intravisit::walk_item(this, i));
-    }
+    fn visit_body(&mut self, body: &'tcx hir::Body) {
+        let body_id = body.id();
+        let owner_id = self.tcx.hir.body_owner(body_id);
 
-    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
-        resolve_item_like(self, |this| intravisit::walk_impl_item(this, ii));
-    }
+        debug!("visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})",
+               owner_id,
+               self.tcx.sess.codemap().span_to_string(body.value.span),
+               body_id,
+               self.cx.parent);
 
-    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
-        resolve_item_like(self, |this| intravisit::walk_trait_item(this, ti));
-    }
+        let outer_cx = self.cx;
+        let outer_ts = mem::replace(&mut self.terminating_scopes, NodeSet());
+
+        // Only functions have an outer terminating (drop) scope,
+        // while temporaries in constant initializers are 'static.
+        if let MirSource::Fn(_) = MirSource::from_node(self.tcx, owner_id) {
+            self.terminating_scopes.insert(body_id.node_id);
+        }
+
+        if let Some(root_id) = self.cx.root_id {
+            self.region_maps.record_fn_parent(body_id.node_id, root_id);
+        }
+        self.cx.root_id = Some(body_id.node_id);
 
-    fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx FnDecl,
-                b: hir::BodyId, s: Span, n: NodeId) {
-        resolve_fn(self, fk, fd, b, s, n);
+        self.enter_code_extent(CodeExtent::CallSiteScope(body_id));
+        self.enter_code_extent(CodeExtent::ParameterScope(body_id));
+
+        // The arguments and `self` are parented to the fn.
+        self.cx.var_parent = self.cx.parent.take();
+        for argument in &body.arguments {
+            self.visit_pat(&argument.pat);
+        }
+
+        // The body of the every fn is a root scope.
+        self.cx.parent = self.cx.var_parent;
+        self.visit_expr(&body.value);
+
+        // Restore context we had at the start.
+        self.cx = outer_cx;
+        self.terminating_scopes = outer_ts;
     }
+
     fn visit_arm(&mut self, a: &'tcx Arm) {
         resolve_arm(self, a);
     }
@@ -1192,25 +1160,19 @@ fn visit_local(&mut self, l: &'tcx Local) {
     }
 }
 
-fn region_maps<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_id: DefId)
-    -> Rc<RegionMaps<'tcx>>
+fn region_maps<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+    -> Rc<RegionMaps>
 {
-    let closure_base_def_id = tcx.closure_base_def_id(fn_id);
-    if closure_base_def_id != fn_id {
+    let closure_base_def_id = tcx.closure_base_def_id(def_id);
+    if closure_base_def_id != def_id {
         return tcx.region_maps(closure_base_def_id);
     }
 
-    let mut maps = RegionMaps::new();
-
-    let fn_node_id = tcx.hir.as_local_node_id(fn_id)
-                            .expect("fn DefId should be for LOCAL_CRATE");
-    let node = tcx.hir.get(fn_node_id);
-
-    {
+    let id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let maps = if let Some(body) = tcx.hir.maybe_body_owned_by(id) {
         let mut visitor = RegionResolutionVisitor {
-            tcx: tcx,
-            region_maps: &mut maps,
-            map: &tcx.hir,
+            tcx,
+            region_maps: RegionMaps::new(),
             cx: Context {
                 root_id: None,
                 parent: None,
@@ -1218,8 +1180,26 @@ fn region_maps<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_id: DefId)
             },
             terminating_scopes: NodeSet(),
         };
-        visitor.visit_hir_map_node(node);
-    }
+
+        visitor.region_maps.root_body = Some(body);
+
+        // If the item is an associated const or a method,
+        // record its impl/trait parent, as it can also have
+        // lifetime parameters free in this body.
+        match tcx.hir.get(id) {
+            hir::map::NodeImplItem(_) |
+            hir::map::NodeTraitItem(_) => {
+                visitor.region_maps.root_parent = Some(tcx.hir.get_parent(id));
+            }
+            _ => {}
+        }
+
+        visitor.visit_body(tcx.hir.body(body));
+
+        visitor.region_maps
+    } else {
+        RegionMaps::new()
+    };
 
     Rc::new(maps)
 }
index a8ba708cc2cd41427904d4fdb279b3a53efd2f8b..7d7308d73bb048a2b5ed81d8e1166d4606e1788b 100644 (file)
@@ -19,7 +19,6 @@
 use session::Session;
 use hir::def::Def;
 use hir::def_id::DefId;
-use middle::region;
 use ty;
 
 use std::cell::Cell;
@@ -42,7 +41,7 @@ pub enum Region {
     EarlyBound(/* index */ u32, /* lifetime decl */ ast::NodeId),
     LateBound(ty::DebruijnIndex, /* lifetime decl */ ast::NodeId),
     LateBoundAnon(ty::DebruijnIndex, /* anon index */ u32),
-    Free(region::CallSiteScopeData, /* lifetime decl */ ast::NodeId),
+    Free(DefId, /* lifetime decl */ ast::NodeId),
 }
 
 impl Region {
@@ -574,9 +573,9 @@ fn signal_shadowing_problem(sess: &Session, name: ast::Name, orig: Original, sha
                                         {} name that is already in scope",
                                        shadower.kind.desc(), name, orig.kind.desc()))
     };
-    err.span_label(orig.span, &"first declared here");
+    err.span_label(orig.span, "first declared here");
     err.span_label(shadower.span,
-                   &format!("lifetime {} already in scope", name));
+                   format!("lifetime {} already in scope", name));
     err.emit();
 }
 
@@ -895,11 +894,10 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
         };
 
         if let Some(mut def) = result {
-            if let Some(body_id) = outermost_body {
+            if let Region::EarlyBound(..) = def {
+                // Do not free early-bound regions, only late-bound ones.
+            } else if let Some(body_id) = outermost_body {
                 let fn_id = self.hir_map.body_owner(body_id);
-                let scope_data = region::CallSiteScopeData {
-                    fn_id: fn_id, body_id: body_id.node_id
-                };
                 match self.hir_map.get(fn_id) {
                     hir::map::NodeItem(&hir::Item {
                         node: hir::ItemFn(..), ..
@@ -910,7 +908,8 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
                     hir::map::NodeImplItem(&hir::ImplItem {
                         node: hir::ImplItemKind::Method(..), ..
                     }) => {
-                        def = Region::Free(scope_data, def.id().unwrap());
+                        let scope = self.hir_map.local_def_id(fn_id);
+                        def = Region::Free(scope, def.id().unwrap());
                     }
                     _ => {}
                 }
@@ -919,7 +918,7 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
         } else {
             struct_span_err!(self.sess, lifetime_ref.span, E0261,
                 "use of undeclared lifetime name `{}`", lifetime_ref.name)
-                .span_label(lifetime_ref.span, &format!("undeclared lifetime"))
+                .span_label(lifetime_ref.span, "undeclared lifetime")
                 .emit();
         }
     }
@@ -1328,7 +1327,7 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[hir::Lifetime]) {
         } else {
             format!("expected lifetime parameter")
         };
-        err.span_label(span, &msg);
+        err.span_label(span, msg);
 
         if let Some(params) = error {
             if lifetime_refs.len() == 1 {
@@ -1438,7 +1437,7 @@ fn check_lifetime_defs(&mut self, old_scope: ScopeRef, lifetimes: &[hir::Lifetim
                     let mut err = struct_span_err!(self.sess, lifetime.span, E0262,
                                   "invalid lifetime parameter name: `{}`", lifetime.name);
                     err.span_label(lifetime.span,
-                                   &format!("{} is a reserved lifetime name", lifetime.name));
+                                   format!("{} is a reserved lifetime name", lifetime.name));
                     err.emit();
                 }
             }
@@ -1452,9 +1451,9 @@ fn check_lifetime_defs(&mut self, old_scope: ScopeRef, lifetimes: &[hir::Lifetim
                                      "lifetime name `{}` declared twice in the same scope",
                                      lifetime_j.lifetime.name)
                         .span_label(lifetime_j.lifetime.span,
-                                    &format!("declared twice"))
+                                    "declared twice")
                         .span_label(lifetime_i.lifetime.span,
-                                   &format!("previous declaration here"))
+                                   "previous declaration here")
                         .emit();
                 }
             }
index 198f7420f5d2b7af19a79a06ccb481ff2e5c1522..d74877e355a7946c0d1bed885a397e2ce9b68908 100644 (file)
 
 pub use self::StabilityLevel::*;
 
-use hir::map as hir_map;
 use lint;
 use hir::def::Def;
 use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, DefIndex, LOCAL_CRATE};
 use ty::{self, TyCtxt};
 use middle::privacy::AccessLevels;
+use session::Session;
 use syntax::symbol::Symbol;
 use syntax_pos::{Span, DUMMY_SP};
 use syntax::ast;
@@ -123,7 +123,7 @@ fn annotate<F>(&mut self, id: NodeId, attrs: &[Attribute],
                    item_sp: Span, kind: AnnotationKind, visit_children: F)
         where F: FnOnce(&mut Self)
     {
-        if self.index.staged_api[&LOCAL_CRATE] && self.tcx.sess.features.borrow().staged_api {
+        if self.index.staged_api[&LOCAL_CRATE] {
             debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
             if let Some(..) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) {
                 self.tcx.sess.span_err(item_sp, "`#[deprecated]` cannot be used in staged api, \
@@ -390,20 +390,36 @@ pub fn build(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
             parent_depr: None,
             in_trait_impl: false,
         };
+
+        // If the `-Z force-unstable-if-unmarked` flag is passed then we provide
+        // a parent stability annotation which indicates that this is private
+        // with the `rustc_private` feature. This is intended for use when
+        // compiling librustc crates themselves so we can leverage crates.io
+        // while maintaining the invariant that all sysroot crates are unstable
+        // by default and are unable to be used.
+        if tcx.sess.opts.debugging_opts.force_unstable_if_unmarked {
+            let reason = "this crate is being loaded from the sysroot, and \
+                          unstable location; did you mean to load this crate \
+                          from crates.io via `Cargo.toml` instead?";
+            let stability = tcx.intern_stability(Stability {
+                level: attr::StabilityLevel::Unstable {
+                    reason: Some(Symbol::intern(reason)),
+                    issue: 27812,
+                },
+                feature: Symbol::intern("rustc_private"),
+                rustc_depr: None,
+            });
+            annotator.parent_stab = Some(stability);
+        }
+
         annotator.annotate(ast::CRATE_NODE_ID, &krate.attrs, krate.span, AnnotationKind::Required,
                            |v| intravisit::walk_crate(v, krate));
     }
 
-    pub fn new(hir_map: &hir_map::Map) -> Index<'tcx> {
-        let krate = hir_map.krate();
-
-        let mut is_staged_api = false;
-        for attr in &krate.attrs {
-            if attr.path == "stable" || attr.path == "unstable" {
-                is_staged_api = true;
-                break
-            }
-        }
+    pub fn new(sess: &Session) -> Index<'tcx> {
+        let is_staged_api =
+            sess.opts.debugging_opts.force_unstable_if_unmarked ||
+            sess.features.borrow().staged_api;
 
         let mut staged_api = FxHashMap();
         staged_api.insert(LOCAL_CRATE, is_staged_api);
@@ -496,8 +512,10 @@ pub fn check_stability(self, def_id: DefId, id: NodeId, span: Span) {
             }
         }
 
-        let is_staged_api = *self.stability.borrow_mut().staged_api.entry(def_id.krate)
-            .or_insert_with(|| self.sess.cstore.is_staged_api(def_id.krate));
+        let is_staged_api = self.lookup_stability(DefId {
+            index: CRATE_DEF_INDEX,
+            ..def_id
+        }).is_some();
         if !is_staged_api {
             return;
         }
@@ -530,15 +548,32 @@ pub fn check_stability(self, def_id: DefId, id: NodeId, span: Span) {
 
         match stability {
             Some(&Stability { level: attr::Unstable {ref reason, issue}, ref feature, .. }) => {
-                if !self.stability.borrow().active_features.contains(feature) {
-                    let msg = match *reason {
-                        Some(ref r) => format!("use of unstable library feature '{}': {}",
-                                               feature.as_str(), &r),
-                        None => format!("use of unstable library feature '{}'", &feature)
-                    };
-                    emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span,
-                                     GateIssue::Library(Some(issue)), &msg);
+                if self.stability.borrow().active_features.contains(feature) {
+                    return
                 }
+
+                // When we're compiling the compiler itself we may pull in
+                // crates from crates.io, but those crates may depend on other
+                // crates also pulled in from crates.io. We want to ideally be
+                // able to compile everything without requiring upstream
+                // modifications, so in the case that this looks like a
+                // rustc_private crate (e.g. a compiler crate) and we also have
+                // the `-Z force-unstable-if-unmarked` flag present (we're
+                // compiling a compiler crate), then let this missing feature
+                // annotation slide.
+                if *feature == "rustc_private" && issue == 27812 {
+                    if self.sess.opts.debugging_opts.force_unstable_if_unmarked {
+                        return
+                    }
+                }
+
+                let msg = match *reason {
+                    Some(ref r) => format!("use of unstable library feature '{}': {}",
+                                           feature.as_str(), &r),
+                    None => format!("use of unstable library feature '{}'", &feature)
+                };
+                emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span,
+                                 GateIssue::Library(Some(issue)), &msg);
             }
             Some(_) => {
                 // Stable APIs are always ok to call and deprecated APIs are
@@ -658,7 +693,7 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 
     let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
 
-    if tcx.stability.borrow().staged_api[&LOCAL_CRATE] && tcx.sess.features.borrow().staged_api {
+    if tcx.stability.borrow().staged_api[&LOCAL_CRATE] {
         let krate = tcx.hir.krate();
         let mut missing = MissingStabilityAnnotations {
             tcx: tcx,
index b517ebabbe767622e9b4ab7e1b1e099a328bf3f1..fe2ad498e99610635faf0a4889717dc7a7422904 100644 (file)
@@ -799,7 +799,7 @@ pub enum StatementKind<'tcx> {
     StorageDead(Lvalue<'tcx>),
 
     InlineAsm {
-        asm: InlineAsm,
+        asm: Box<InlineAsm>,
         outputs: Vec<Lvalue<'tcx>>,
         inputs: Vec<Operand<'tcx>>
     },
@@ -995,7 +995,7 @@ pub struct VisibilityScopeData {
 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
 pub enum Operand<'tcx> {
     Consume(Lvalue<'tcx>),
-    Constant(Constant<'tcx>),
+    Constant(Box<Constant<'tcx>>),
 }
 
 impl<'tcx> Debug for Operand<'tcx> {
@@ -1015,7 +1015,7 @@ pub fn function_handle<'a>(
         substs: &'tcx Substs<'tcx>,
         span: Span,
     ) -> Self {
-        Operand::Constant(Constant {
+        Operand::Constant(box Constant {
             span: span,
             ty: tcx.type_of(def_id).subst(tcx, substs),
             literal: Literal::Value { value: ConstVal::Function(def_id, substs) },
@@ -1062,7 +1062,7 @@ pub enum Rvalue<'tcx> {
     /// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case
     /// that `Foo` has a destructor. These rvalues can be optimized
     /// away after type-checking and before lowering.
-    Aggregate(AggregateKind<'tcx>, Vec<Operand<'tcx>>),
+    Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
@@ -1185,7 +1185,7 @@ fn fmt_tuple(fmt: &mut Formatter, lvs: &[Operand]) -> fmt::Result {
                     tuple_fmt.finish()
                 }
 
-                match *kind {
+                match **kind {
                     AggregateKind::Array(_) => write!(fmt, "{:?}", lvs),
 
                     AggregateKind::Tuple => {
@@ -1603,7 +1603,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
             Discriminant(ref lval) => Discriminant(lval.fold_with(folder)),
             Box(ty) => Box(ty.fold_with(folder)),
             Aggregate(ref kind, ref fields) => {
-                let kind = match *kind {
+                let kind = box match **kind {
                     AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
                     AggregateKind::Tuple => AggregateKind::Tuple,
                     AggregateKind::Adt(def, v, substs, n) =>
@@ -1631,7 +1631,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
             Discriminant(ref lval) => lval.visit_with(visitor),
             Box(ty) => ty.visit_with(visitor),
             Aggregate(ref kind, ref fields) => {
-                (match *kind {
+                (match **kind {
                     AggregateKind::Array(ty) => ty.visit_with(visitor),
                     AggregateKind::Tuple => false,
                     AggregateKind::Adt(_, _, substs, _) => substs.visit_with(visitor),
index b6020df072853631ce43cfa14d2e01403ed8f9f4..7bc1dc58c29d298ed84a42b603973487732efef2 100644 (file)
@@ -183,7 +183,7 @@ pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'
                 tcx.mk_box(t)
             }
             Rvalue::Aggregate(ref ak, ref ops) => {
-                match *ak {
+                match **ak {
                     AggregateKind::Array(ty) => {
                         tcx.mk_array(ty, ops.len())
                     }
index 31bdd99ef32210abb0e85e91221396ab14d2e355..557fedadeba62155cb0a6cb1ce5767b68f76b35b 100644 (file)
@@ -515,6 +515,7 @@ fn super_rvalue(&mut self,
 
                     Rvalue::Aggregate(ref $($mutability)* kind,
                                       ref $($mutability)* operands) => {
+                        let kind = &$($mutability)* **kind;
                         match *kind {
                             AggregateKind::Array(ref $($mutability)* ty) => {
                                 self.visit_ty(ty);
index 75bc940625d82d58b8701606c7557af5443b820c..7cb5f2510d5c7acdc363048165bca73f44d2d85d 100644 (file)
@@ -328,7 +328,7 @@ pub struct Options {
     }
 );
 
-#[derive(Clone, PartialEq, Eq)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum PrintRequest {
     FileNames,
     Sysroot,
@@ -824,9 +824,9 @@ fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) ->
     linker: Option<String> = (None, parse_opt_string, [UNTRACKED],
         "system linker to link outputs with"),
     link_arg: Vec<String> = (vec![], parse_string_push, [UNTRACKED],
-        "a single extra argument to pass to the linker (can be used several times)"),
+        "a single extra argument to append to the linker invocation (can be used several times)"),
     link_args: Option<Vec<String>> = (None, parse_opt_list, [UNTRACKED],
-        "extra arguments to pass to the linker (space separated)"),
+        "extra arguments to append to the linker invocation (space separated)"),
     link_dead_code: bool = (false, parse_bool, [UNTRACKED],
         "don't let linker strip dead code (turning it on can be used for code coverage)"),
     lto: bool = (false, parse_bool, [TRACKED],
@@ -963,7 +963,7 @@ fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) ->
           "attempt to recover from parse errors (experimental)"),
     incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
           "enable incremental compilation (experimental)"),
-    incremental_cc: bool = (false, parse_bool, [UNTRACKED],
+    incremental_cc: bool = (true, parse_bool, [UNTRACKED],
           "enable cross-crate incremental compilation (even more experimental)"),
     incremental_info: bool = (false, parse_bool, [UNTRACKED],
         "print high-level information about incremental reuse (or the lack thereof)"),
@@ -1027,6 +1027,12 @@ fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) ->
         "add a source pattern to the file path remapping config"),
     remap_path_prefix_to: Vec<String> = (vec![], parse_string_push, [TRACKED],
         "add a mapping target to the file path remapping config"),
+    force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED],
+        "force all crates to be `rustc_private` unstable"),
+    pre_link_arg: Vec<String> = (vec![], parse_string_push, [UNTRACKED],
+        "a single extra argument to prepend the linker invocation (can be used several times)"),
+    pre_link_args: Option<Vec<String>> = (None, parse_opt_list, [UNTRACKED],
+        "extra arguments to prepend to the linker invocation (space separated)"),
 }
 
 pub fn default_lib_output() -> CrateType {
index ec3eaa124c3078a253f804317843f0451aa16dda..814246330a4c2f7b8da5e640ebbb536c83910423 100644 (file)
@@ -11,8 +11,8 @@
 pub use self::code_stats::{CodeStats, DataTypeKind, FieldInfo};
 pub use self::code_stats::{SizeKind, TypeSizeInfo, VariantInfo};
 
-use dep_graph::DepGraph;
-use hir::def_id::{CrateNum, DefIndex};
+use dep_graph::{DepGraph, DepNode};
+use hir::def_id::{DefId, CrateNum, DefIndex, CRATE_DEF_INDEX};
 use lint;
 use middle::cstore::CrateStore;
 use middle::dependency_format;
 use syntax::symbol::Symbol;
 use syntax::{ast, codemap};
 use syntax::feature_gate::AttributeType;
-use syntax_pos::{Span, MultiSpan};
+use syntax_pos::{Span, MultiSpan, FileMap};
 
 use rustc_back::{LinkerFlavor, PanicStrategy};
 use rustc_back::target::Target;
 use rustc_data_structures::flock;
-use llvm;
 
 use std::path::{Path, PathBuf};
 use std::cell::{self, Cell, RefCell};
 use std::collections::HashMap;
 use std::env;
-use std::ffi::CString;
 use std::io::Write;
 use std::rc::Rc;
 use std::fmt;
 use std::time::Duration;
-use libc::c_int;
+use std::sync::Arc;
 
 mod code_stats;
 pub mod config;
@@ -627,6 +625,22 @@ pub fn build_session_(sopts: config::Options,
         }
     };
     let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
+
+    // Hook up the codemap with a callback that allows it to register FileMap
+    // accesses with the dependency graph.
+    let cm_depgraph = dep_graph.clone();
+    let codemap_dep_tracking_callback = Box::new(move |filemap: &FileMap| {
+        let def_id = DefId {
+            krate: CrateNum::from_u32(filemap.crate_of_origin),
+            index: CRATE_DEF_INDEX,
+        };
+        let name = Arc::new(filemap.name.clone());
+        let dep_node = DepNode::FileMap(def_id, name);
+
+        cm_depgraph.read(dep_node);
+    });
+    codemap.set_dep_tracking_callback(codemap_dep_tracking_callback);
+
     let p_s = parse::ParseSess::with_span_handler(span_diagnostic, codemap);
     let default_sysroot = match sopts.maybe_sysroot {
         Some(_) => None,
@@ -696,8 +710,6 @@ pub fn build_session_(sopts: config::Options,
         out_of_fuel: Cell::new(false),
     };
 
-    init_llvm(&sess);
-
     sess
 }
 
@@ -726,55 +738,6 @@ pub enum IncrCompSession {
     }
 }
 
-fn init_llvm(sess: &Session) {
-    unsafe {
-        // Before we touch LLVM, make sure that multithreading is enabled.
-        use std::sync::Once;
-        static INIT: Once = Once::new();
-        static mut POISONED: bool = false;
-        INIT.call_once(|| {
-            if llvm::LLVMStartMultithreaded() != 1 {
-                // use an extra bool to make sure that all future usage of LLVM
-                // cannot proceed despite the Once not running more than once.
-                POISONED = true;
-            }
-
-            configure_llvm(sess);
-        });
-
-        if POISONED {
-            bug!("couldn't enable multi-threaded LLVM");
-        }
-    }
-}
-
-unsafe fn configure_llvm(sess: &Session) {
-    let mut llvm_c_strs = Vec::new();
-    let mut llvm_args = Vec::new();
-
-    {
-        let mut add = |arg: &str| {
-            let s = CString::new(arg).unwrap();
-            llvm_args.push(s.as_ptr());
-            llvm_c_strs.push(s);
-        };
-        add("rustc"); // fake program name
-        if sess.time_llvm_passes() { add("-time-passes"); }
-        if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
-
-        for arg in &sess.opts.cg.llvm_args {
-            add(&(*arg));
-        }
-    }
-
-    llvm::LLVMInitializePasses();
-
-    llvm::initialize_available_targets();
-
-    llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
-                                 llvm_args.as_ptr());
-}
-
 pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
     let emitter: Box<Emitter> = match output {
         config::ErrorOutputType::HumanReadable(color_config) => {
index e846d74febfb7af6f7a83fe6710ce9d8abd2f30e..152e3353994b3b32315d8591d4e482f2792b461d 100644 (file)
@@ -484,12 +484,12 @@ pub fn report_extra_impl_obligation(&self,
 
         if let Some(trait_item_span) = self.tcx.hir.span_if_local(trait_item_def_id) {
             let span = self.tcx.sess.codemap().def_span(trait_item_span);
-            err.span_label(span, &format!("definition of `{}` from trait", item_name));
+            err.span_label(span, format!("definition of `{}` from trait", item_name));
         }
 
         err.span_label(
             error_span,
-            &format!("impl has extra requirement {}", requirement));
+            format!("impl has extra requirement {}", requirement));
 
         if let Some(node_id) = lint_id {
             self.tcx.sess.add_lint_diagnostic(EXTRA_REQUIREMENT_IN_IMPL,
@@ -582,7 +582,7 @@ pub fn report_selection_error(&self,
                         }
 
                         err.span_label(span,
-                                       &format!("{}the trait `{}` is not implemented for `{}`",
+                                       format!("{}the trait `{}` is not implemented for `{}`",
                                                 pre_message,
                                                 trait_ref,
                                                 trait_ref.self_ty()));
@@ -738,11 +738,11 @@ fn report_type_argument_mismatch(&self,
             expected_ref,
             found_ref);
 
-        err.span_label(span, &format!("{}", type_error));
+        err.span_label(span, format!("{}", type_error));
 
         if let Some(sp) = found_span {
-            err.span_label(span, &format!("requires `{}`", found_ref));
-            err.span_label(sp, &format!("implements `{}`", expected_ref));
+            err.span_label(span, format!("requires `{}`", found_ref));
+            err.span_label(sp, format!("implements `{}`", expected_ref));
         }
 
         err
@@ -765,12 +765,12 @@ fn report_arg_count_mismatch(&self,
             if expected == 1 { "" } else { "s" },
             if expected == 1 { "is" } else { "are" });
 
-        err.span_label(span, &format!("expected {} that takes {} argument{}",
+        err.span_label(span, format!("expected {} that takes {} argument{}",
                                       if is_closure { "closure" } else { "function" },
                                       expected,
                                       if expected == 1 { "" } else { "s" }));
         if let Some(span) = found_span {
-            err.span_label(span, &format!("takes {} argument{}",
+            err.span_label(span, format!("takes {} argument{}",
                                           found,
                                           if found == 1 { "" } else { "s" }));
         }
@@ -789,7 +789,7 @@ pub fn recursive_type_with_infinite_size_error(self,
         let mut err = struct_span_err!(self.sess, span, E0072,
                                        "recursive type `{}` has infinite size",
                                        self.item_path_str(type_def_id));
-        err.span_label(span, &format!("recursive type has infinite size"));
+        err.span_label(span, "recursive type has infinite size");
         err.help(&format!("insert indirection (e.g., a `Box`, `Rc`, or `&`) \
                            at some point to make `{}` representable",
                           self.item_path_str(type_def_id)));
@@ -808,7 +808,7 @@ pub fn report_object_safety_error(self,
             self.sess, span, E0038,
             "the trait `{}` cannot be made into an object",
             trait_str);
-        err.span_label(span, &format!("the trait `{}` cannot be made into an object", trait_str));
+        err.span_label(span, format!("the trait `{}` cannot be made into an object", trait_str));
 
         let mut reported_violations = FxHashSet();
         for violation in violations {
@@ -1043,7 +1043,7 @@ pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) {
                                        "type annotations needed");
 
         for (target_span, label_message) in labels {
-            err.span_label(target_span, &label_message);
+            err.span_label(target_span, label_message);
         }
 
         err.emit();
index 2f525e1b8b45c5afcba01f3f6fc720c09ecd81e5..1823373348badfb8ef177602d852f4ed29ff0217 100644 (file)
@@ -619,8 +619,6 @@ pub fn get_vtable_methods<'a, 'tcx>(
     debug!("get_vtable_methods({:?})", trait_ref);
 
     supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
-        tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
-
         let trait_methods = tcx.associated_items(trait_ref.def_id())
             .filter(|item| item.kind == ty::AssociatedKind::Method);
 
@@ -782,3 +780,19 @@ fn self_ty(&self) -> ty::Binder<Ty<'tcx>> {
         ty::Binder(self.predicate.skip_binder().self_ty())
     }
 }
+
+pub fn provide(providers: &mut ty::maps::Providers) {
+    *providers = ty::maps::Providers {
+        is_object_safe: object_safety::is_object_safe_provider,
+        specialization_graph_of: specialize::specialization_graph_provider,
+        ..*providers
+    };
+}
+
+pub fn provide_extern(providers: &mut ty::maps::Providers) {
+    *providers = ty::maps::Providers {
+        is_object_safe: object_safety::is_object_safe_provider,
+        specialization_graph_of: specialize::specialization_graph_provider,
+        ..*providers
+    };
+}
index ea1a2f9a982c93d51322d2bb361b4f44faa9b533..0e3a53129d157fe2af455cacd25a59597c87b22f 100644 (file)
@@ -77,25 +77,6 @@ pub enum MethodViolationCode {
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-    pub fn is_object_safe(self, trait_def_id: DefId) -> bool {
-        // Because we query yes/no results frequently, we keep a cache:
-        let def = self.trait_def(trait_def_id);
-
-        let result = def.object_safety().unwrap_or_else(|| {
-            let result = self.object_safety_violations(trait_def_id).is_empty();
-
-            // Record just a yes/no result in the cache; this is what is
-            // queried most frequently. Note that this may overwrite a
-            // previous result, but always with the same thing.
-            def.set_object_safety(result);
-
-            result
-        });
-
-        debug!("is_object_safe({:?}) = {}", trait_def_id, result);
-
-        result
-    }
 
     /// Returns the object safety violations that affect
     /// astconv - currently, Self in supertraits. This is needed
@@ -206,9 +187,8 @@ fn generics_require_sized_self(self, def_id: DefId) -> bool {
         };
 
         // Search for a predicate like `Self : Sized` amongst the trait bounds.
-        let free_substs = self.construct_free_substs(def_id, None);
         let predicates = self.predicates_of(def_id);
-        let predicates = predicates.instantiate(self, free_substs).predicates;
+        let predicates = predicates.instantiate_identity(self).predicates;
         elaborate_predicates(self, predicates)
             .any(|predicate| {
                 match predicate {
@@ -392,3 +372,9 @@ fn contains_illegal_self_type_reference(self,
         error
     }
 }
+
+pub(super) fn is_object_safe_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                         trait_def_id: DefId)
+                                         -> bool {
+    tcx.object_safety_violations(trait_def_id).is_empty()
+}
index e01f97eb1f3a0340dbe635139ed7985becf977b6..d7911870f391a541dfd36297c3437999350603b1 100644 (file)
@@ -900,96 +900,50 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
                 // In either case, we handle this by not adding a
                 // candidate for an impl if it contains a `default`
                 // type.
-                let opt_node_item = assoc_ty_def(selcx,
-                                                 impl_data.impl_def_id,
-                                                 obligation.predicate.item_name);
-                let new_candidate = if let Some(node_item) = opt_node_item {
-                    let is_default = if node_item.node.is_from_trait() {
-                        // If true, the impl inherited a `type Foo = Bar`
-                        // given in the trait, which is implicitly default.
-                        // Otherwise, the impl did not specify `type` and
-                        // neither did the trait:
-                        //
-                        // ```rust
-                        // trait Foo { type T; }
-                        // impl Foo for Bar { }
-                        // ```
-                        //
-                        // This is an error, but it will be
-                        // reported in `check_impl_items_against_trait`.
-                        // We accept it here but will flag it as
-                        // an error when we confirm the candidate
-                        // (which will ultimately lead to `normalize_to_error`
-                        // being invoked).
-                        node_item.item.defaultness.has_value()
-                    } else {
-                        node_item.item.defaultness.is_default() ||
-                        selcx.tcx().impl_is_default(node_item.node.def_id())
-                    };
-
-                    // Only reveal a specializable default if we're past type-checking
-                    // and the obligations is monomorphic, otherwise passes such as
-                    // transmute checking and polymorphic MIR optimizations could
-                    // get a result which isn't correct for all monomorphizations.
-                    if !is_default {
+                let node_item = assoc_ty_def(selcx,
+                                             impl_data.impl_def_id,
+                                             obligation.predicate.item_name);
+
+                let is_default = if node_item.node.is_from_trait() {
+                    // If true, the impl inherited a `type Foo = Bar`
+                    // given in the trait, which is implicitly default.
+                    // Otherwise, the impl did not specify `type` and
+                    // neither did the trait:
+                    //
+                    // ```rust
+                    // trait Foo { type T; }
+                    // impl Foo for Bar { }
+                    // ```
+                    //
+                    // This is an error, but it will be
+                    // reported in `check_impl_items_against_trait`.
+                    // We accept it here but will flag it as
+                    // an error when we confirm the candidate
+                    // (which will ultimately lead to `normalize_to_error`
+                    // being invoked).
+                    node_item.item.defaultness.has_value()
+                } else {
+                    node_item.item.defaultness.is_default() ||
+                    selcx.tcx().impl_is_default(node_item.node.def_id())
+                };
+
+                // Only reveal a specializable default if we're past type-checking
+                // and the obligations is monomorphic, otherwise passes such as
+                // transmute checking and polymorphic MIR optimizations could
+                // get a result which isn't correct for all monomorphizations.
+                let new_candidate = if !is_default {
+                    Some(ProjectionTyCandidate::Select)
+                } else if selcx.projection_mode() == Reveal::All {
+                    assert!(!poly_trait_ref.needs_infer());
+                    if !poly_trait_ref.needs_subst() {
                         Some(ProjectionTyCandidate::Select)
-                    } else if selcx.projection_mode() == Reveal::All {
-                        assert!(!poly_trait_ref.needs_infer());
-                        if !poly_trait_ref.needs_subst() {
-                            Some(ProjectionTyCandidate::Select)
-                        } else {
-                            None
-                        }
                     } else {
                         None
                     }
                 } else {
-                    // This is saying that neither the trait nor
-                    // the impl contain a definition for this
-                    // associated type.  Normally this situation
-                    // could only arise through a compiler bug --
-                    // if the user wrote a bad item name, it
-                    // should have failed in astconv. **However**,
-                    // at coherence-checking time, we only look at
-                    // the topmost impl (we don't even consider
-                    // the trait itself) for the definition -- and
-                    // so in that case it may be that the trait
-                    // *DOES* have a declaration, but we don't see
-                    // it, and we end up in this branch.
-                    //
-                    // This is kind of tricky to handle actually.
-                    // For now, we just unconditionally ICE,
-                    // because otherwise, examples like the
-                    // following will succeed:
-                    //
-                    // ```
-                    // trait Assoc {
-                    //     type Output;
-                    // }
-                    //
-                    // impl<T> Assoc for T {
-                    //     default type Output = bool;
-                    // }
-                    //
-                    // impl Assoc for u8 {}
-                    // impl Assoc for u16 {}
-                    //
-                    // trait Foo {}
-                    // impl Foo for <u8 as Assoc>::Output {}
-                    // impl Foo for <u16 as Assoc>::Output {}
-                    //     return None;
-                    // }
-                    // ```
-                    //
-                    // The essential problem here is that the
-                    // projection fails, leaving two unnormalized
-                    // types, which appear not to unify -- so the
-                    // overlap check succeeds, when it should
-                    // fail.
-                    span_bug!(obligation.cause.span,
-                              "Tried to project an inherited associated type during \
-                               coherence checking, which is currently not supported.");
+                    None
                 };
+
                 candidate_set.vec.extend(new_candidate);
             }
             super::VtableParam(..) => {
@@ -1274,35 +1228,25 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
     let VtableImplData { substs, nested, impl_def_id } = impl_vtable;
 
     let tcx = selcx.tcx();
-    let trait_ref = obligation.predicate.trait_ref;
     let assoc_ty = assoc_ty_def(selcx, impl_def_id, obligation.predicate.item_name);
 
-    match assoc_ty {
-        Some(node_item) => {
-            let ty = if !node_item.item.defaultness.has_value() {
-                // This means that the impl is missing a definition for the
-                // associated type. This error will be reported by the type
-                // checker method `check_impl_items_against_trait`, so here we
-                // just return TyError.
-                debug!("confirm_impl_candidate: no associated type {:?} for {:?}",
-                       node_item.item.name,
-                       obligation.predicate.trait_ref);
-                tcx.types.err
-            } else {
-                tcx.type_of(node_item.item.def_id)
-            };
-            let substs = translate_substs(selcx.infcx(), impl_def_id, substs, node_item.node);
-            Progress {
-                ty: ty.subst(tcx, substs),
-                obligations: nested,
-                cacheable: true
-            }
-        }
-        None => {
-            span_bug!(obligation.cause.span,
-                      "No associated type for {:?}",
-                      trait_ref);
-        }
+    let ty = if !assoc_ty.item.defaultness.has_value() {
+        // This means that the impl is missing a definition for the
+        // associated type. This error will be reported by the type
+        // checker method `check_impl_items_against_trait`, so here we
+        // just return TyError.
+        debug!("confirm_impl_candidate: no associated type {:?} for {:?}",
+               assoc_ty.item.name,
+               obligation.predicate.trait_ref);
+        tcx.types.err
+    } else {
+        tcx.type_of(assoc_ty.item.def_id)
+    };
+    let substs = translate_substs(selcx.infcx(), impl_def_id, substs, assoc_ty.node);
+    Progress {
+        ty: ty.subst(tcx, substs),
+        obligations: nested,
+        cacheable: true
     }
 }
 
@@ -1315,27 +1259,43 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>(
     selcx: &SelectionContext<'cx, 'gcx, 'tcx>,
     impl_def_id: DefId,
     assoc_ty_name: ast::Name)
-    -> Option<specialization_graph::NodeItem<ty::AssociatedItem>>
+    -> specialization_graph::NodeItem<ty::AssociatedItem>
 {
-    let trait_def_id = selcx.tcx().impl_trait_ref(impl_def_id).unwrap().def_id;
-    let trait_def = selcx.tcx().trait_def(trait_def_id);
-
-    if !trait_def.is_complete(selcx.tcx()) {
-        let impl_node = specialization_graph::Node::Impl(impl_def_id);
-        for item in impl_node.items(selcx.tcx()) {
-            if item.kind == ty::AssociatedKind::Type && item.name == assoc_ty_name {
-                return Some(specialization_graph::NodeItem {
-                    node: specialization_graph::Node::Impl(impl_def_id),
-                    item: item,
-                });
-            }
+    let tcx = selcx.tcx();
+    let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
+    let trait_def = tcx.trait_def(trait_def_id);
+
+    // This function may be called while we are still building the
+    // specialization graph that is queried below (via TraidDef::ancestors()),
+    // so, in order to avoid unnecessary infinite recursion, we manually look
+    // for the associated item at the given impl.
+    // If there is no such item in that impl, this function will fail with a
+    // cycle error if the specialization graph is currently being built.
+    let impl_node = specialization_graph::Node::Impl(impl_def_id);
+    for item in impl_node.items(tcx) {
+        if item.kind == ty::AssociatedKind::Type && item.name == assoc_ty_name {
+            return specialization_graph::NodeItem {
+                node: specialization_graph::Node::Impl(impl_def_id),
+                item: item,
+            };
         }
-        None
+    }
+
+    if let Some(assoc_item) = trait_def
+        .ancestors(tcx, impl_def_id)
+        .defs(tcx, assoc_ty_name, ty::AssociatedKind::Type)
+        .next() {
+        assoc_item
     } else {
-        trait_def
-            .ancestors(impl_def_id)
-            .defs(selcx.tcx(), assoc_ty_name, ty::AssociatedKind::Type)
-            .next()
+        // This is saying that neither the trait nor
+        // the impl contain a definition for this
+        // associated type.  Normally this situation
+        // could only arise through a compiler bug --
+        // if the user wrote a bad item name, it
+        // should have failed in astconv.
+        bug!("No associated type `{}` for {}",
+             assoc_ty_name,
+             tcx.item_path_str(impl_def_id))
     }
 }
 
index d5d17e3c81214901b8f3a6b7cbb9fabced4d7f54..0e5779f9d17935b291fc1d72aec74fd879166c0f 100644 (file)
@@ -27,6 +27,7 @@
 use traits::{self, Reveal, ObligationCause};
 use ty::{self, TyCtxt, TypeFoldable};
 use syntax_pos::DUMMY_SP;
+use std::rc::Rc;
 
 pub mod specialization_graph;
 
@@ -118,7 +119,7 @@ pub fn find_associated_item<'a, 'tcx>(
     let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
     let trait_def = tcx.trait_def(trait_def_id);
 
-    let ancestors = trait_def.ancestors(impl_data.impl_def_id);
+    let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id);
     match ancestors.defs(tcx, item.name, item.kind).next() {
         Some(node_item) => {
             let substs = tcx.infer_ctxt((), Reveal::All).enter(|infcx| {
@@ -179,12 +180,8 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     // create a parameter environment corresponding to a (skolemized) instantiation of impl1
-    let penv = tcx.construct_parameter_environment(DUMMY_SP,
-                                                   impl1_def_id,
-                                                   None);
-    let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id)
-                             .unwrap()
-                             .subst(tcx, &penv.free_substs);
+    let penv = tcx.parameter_environment(impl1_def_id);
+    let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
 
     // Create a infcx, taking the predicates of impl1 as assumptions:
     let result = tcx.infer_ctxt(penv, Reveal::UserFacing).enter(|infcx| {
@@ -289,3 +286,62 @@ pub fn insert(&mut self, a: DefId, b: DefId, result: bool) {
         self.map.insert((a, b), result);
     }
 }
+
+// Query provider for `specialization_graph_of`.
+pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                                      trait_id: DefId)
+                                                      -> Rc<specialization_graph::Graph> {
+    let mut sg = specialization_graph::Graph::new();
+
+    let mut trait_impls: Vec<DefId> = tcx.trait_impls_of(trait_id).iter().collect();
+
+    // The coherence checking implementation seems to rely on impls being
+    // iterated over (roughly) in definition order, so we are sorting by
+    // negated CrateNum (so remote definitions are visited first) and then
+    // by a flattend version of the DefIndex.
+    trait_impls.sort_unstable_by_key(|def_id| {
+        (-(def_id.krate.as_u32() as i64),
+         def_id.index.address_space().index(),
+         def_id.index.as_array_index())
+    });
+
+    for impl_def_id in trait_impls {
+        if impl_def_id.is_local() {
+            // This is where impl overlap checking happens:
+            let insert_result = sg.insert(tcx, impl_def_id);
+            // Report error if there was one.
+            if let Err(overlap) = insert_result {
+                let mut err = struct_span_err!(tcx.sess,
+                                               tcx.span_of_impl(impl_def_id).unwrap(),
+                                               E0119,
+                                               "conflicting implementations of trait `{}`{}:",
+                                               overlap.trait_desc,
+                                               overlap.self_desc.clone().map_or(String::new(),
+                                                                                |ty| {
+                    format!(" for type `{}`", ty)
+                }));
+
+                match tcx.span_of_impl(overlap.with_impl) {
+                    Ok(span) => {
+                        err.span_label(span, format!("first implementation here"));
+                        err.span_label(tcx.span_of_impl(impl_def_id).unwrap(),
+                                       format!("conflicting implementation{}",
+                                                overlap.self_desc
+                                                    .map_or(String::new(),
+                                                            |ty| format!(" for `{}`", ty))));
+                    }
+                    Err(cname) => {
+                        err.note(&format!("conflicting implementation in crate `{}`", cname));
+                    }
+                }
+
+                err.emit();
+            }
+        } else {
+            let parent = tcx.impl_parent(impl_def_id).unwrap_or(trait_id);
+            sg.record_impl_from_cstore(tcx, parent, impl_def_id)
+        }
+    }
+
+    Rc::new(sg)
+}
index 6e2c16c82aeb42274fd30c21a4a058a66d607e00..87c98a0ef0ed6daf16839d7a96f712dd99bde1f4 100644 (file)
@@ -12,8 +12,9 @@
 
 use hir::def_id::DefId;
 use traits::{self, Reveal};
-use ty::{self, TyCtxt, TraitDef, TypeFoldable};
+use ty::{self, TyCtxt, TypeFoldable};
 use ty::fast_reject::{self, SimplifiedType};
+use std::rc::Rc;
 use syntax::ast::Name;
 use util::nodemap::{DefIdMap, FxHashMap};
 
@@ -301,18 +302,19 @@ pub fn def_id(&self) -> DefId {
     }
 }
 
-pub struct Ancestors<'a> {
-    trait_def: &'a TraitDef,
+pub struct Ancestors {
+    trait_def_id: DefId,
+    specialization_graph: Rc<Graph>,
     current_source: Option<Node>,
 }
 
-impl<'a> Iterator for Ancestors<'a> {
+impl Iterator for Ancestors {
     type Item = Node;
     fn next(&mut self) -> Option<Node> {
         let cur = self.current_source.take();
         if let Some(Node::Impl(cur_impl)) = cur {
-            let parent = self.trait_def.specialization_graph.borrow().parent(cur_impl);
-            if parent == self.trait_def.def_id {
+            let parent = self.specialization_graph.parent(cur_impl);
+            if parent == self.trait_def_id {
                 self.current_source = Some(Node::Trait(parent));
             } else {
                 self.current_source = Some(Node::Impl(parent));
@@ -336,7 +338,7 @@ pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> NodeItem<U> {
     }
 }
 
-impl<'a, 'gcx, 'tcx> Ancestors<'a> {
+impl<'a, 'gcx, 'tcx> Ancestors {
     /// Search the items from the given ancestors, returning each definition
     /// with the given name and the given kind.
     #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
@@ -351,9 +353,14 @@ pub fn defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, name: Name, kind: ty::AssociatedK
 
 /// Walk up the specialization ancestors of a given impl, starting with that
 /// impl itself.
-pub fn ancestors<'a>(trait_def: &'a TraitDef, start_from_impl: DefId) -> Ancestors<'a> {
+pub fn ancestors(tcx: TyCtxt,
+                 trait_def_id: DefId,
+                 start_from_impl: DefId)
+                 -> Ancestors {
+    let specialization_graph = tcx.specialization_graph_of(trait_def_id);
     Ancestors {
-        trait_def: trait_def,
+        trait_def_id,
+        specialization_graph,
         current_source: Some(Node::Impl(start_from_impl)),
     }
 }
index 1d10c3a969509cacff5f5508bb35cdbc38b3300a..3f5cf7eca53077bd48c8900e3093d33b3b9799b2 100644 (file)
@@ -197,7 +197,7 @@ fn push(&mut self, predicate: &ty::Predicate<'tcx>) {
                 // I want to be conservative. --nmatsakis
                 let ty_max = data.skip_binder().0;
                 let r_min = data.skip_binder().1;
-                if r_min.is_bound() {
+                if r_min.is_late_bound() {
                     return;
                 }
 
@@ -206,7 +206,7 @@ fn push(&mut self, predicate: &ty::Predicate<'tcx>) {
                     tcx.outlives_components(ty_max)
                        .into_iter()
                        .filter_map(|component| match component {
-                           Component::Region(r) => if r.is_bound() {
+                           Component::Region(r) => if r.is_late_bound() {
                                None
                            } else {
                                Some(ty::Predicate::RegionOutlives(
index 74aac7b788b26263580a72d2043dcfb098bf090c..b9355c264b3ef49d85c7f1d392645d7b3c6ef3ee 100644 (file)
@@ -21,7 +21,6 @@
 use hir::map::DisambiguatedDefPathData;
 use middle::free_region::FreeRegionMap;
 use middle::lang_items;
-use middle::region::{CodeExtent, CodeExtentData};
 use middle::resolve_lifetime;
 use middle::stability;
 use mir::Mir;
@@ -99,7 +98,7 @@ pub struct CtxtInterners<'tcx> {
     type_: RefCell<FxHashSet<Interned<'tcx, TyS<'tcx>>>>,
     type_list: RefCell<FxHashSet<Interned<'tcx, Slice<Ty<'tcx>>>>>,
     substs: RefCell<FxHashSet<Interned<'tcx, Substs<'tcx>>>>,
-    region: RefCell<FxHashSet<Interned<'tcx, RegionKind<'tcx>>>>,
+    region: RefCell<FxHashSet<Interned<'tcx, RegionKind>>>,
     existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
     predicates: RefCell<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
 }
@@ -548,8 +547,6 @@ pub struct GlobalCtxt<'tcx> {
 
     layout_interner: RefCell<FxHashSet<&'tcx Layout>>,
 
-    code_extent_interner: RefCell<FxHashSet<CodeExtent<'tcx>>>,
-
     /// A vector of every trait accessible in the whole crate
     /// (i.e. including those from subcrates). This is used only for
     /// error reporting, and so is lazily initialised and generally
@@ -651,32 +648,6 @@ pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability {
         interned
     }
 
-    pub fn node_extent(self, n: ast::NodeId) -> CodeExtent<'gcx> {
-        self.intern_code_extent(CodeExtentData::Misc(n))
-    }
-
-    // Returns the code extent for an item - the destruction scope.
-    pub fn item_extent(self, n: ast::NodeId) -> CodeExtent<'gcx> {
-        self.intern_code_extent(CodeExtentData::DestructionScope(n))
-    }
-
-    pub fn call_site_extent(self, fn_id: ast::NodeId, body_id: ast::NodeId) -> CodeExtent<'gcx> {
-        assert!(fn_id != body_id);
-        self.intern_code_extent(CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id })
-    }
-
-    pub fn intern_code_extent(self, data: CodeExtentData) -> CodeExtent<'gcx> {
-        if let Some(st) = self.code_extent_interner.borrow().get(&data) {
-            return st;
-        }
-
-        let interned = self.global_interners.arena.alloc(data);
-        if let Some(prev) = self.code_extent_interner.borrow_mut().replace(interned) {
-            bug!("Tried to overwrite interned code-extent: {:?}", prev)
-        }
-        interned
-    }
-
     pub fn intern_layout(self, layout: Layout) -> &'gcx Layout {
         if let Some(layout) = self.layout_interner.borrow().get(&layout) {
             return layout;
@@ -764,7 +735,6 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             data_layout: data_layout,
             layout_cache: RefCell::new(FxHashMap()),
             layout_interner: RefCell::new(FxHashSet()),
-            code_extent_interner: RefCell::new(FxHashSet()),
             layout_depth: Cell::new(0),
             derive_macros: RefCell::new(NodeMap()),
             stability_interner: RefCell::new(FxHashSet()),
@@ -843,15 +813,6 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Sub
     }
 }
 
-impl<'a, 'tcx> Lift<'tcx> for ty::FreeRegion<'a> {
-    type Lifted = ty::FreeRegion<'tcx>;
-    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
-        let scope = self.scope.map(|code_extent| tcx.intern_code_extent(*code_extent));
-        let bound_region = self.bound_region;
-        Some(ty::FreeRegion { scope, bound_region })
-    }
-}
-
 impl<'a, 'tcx> Lift<'tcx> for Region<'a> {
     type Lifted = Region<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Region<'tcx>> {
@@ -1115,8 +1076,8 @@ fn borrow<'a>(&'a self) -> &'a [Kind<'lcx>] {
     }
 }
 
-impl<'tcx> Borrow<RegionKind<'tcx>> for Interned<'tcx, RegionKind<'tcx>> {
-    fn borrow<'a>(&'a self) -> &'a RegionKind<'tcx> {
+impl<'tcx> Borrow<RegionKind> for Interned<'tcx, RegionKind> {
+    fn borrow<'a>(&'a self) -> &'a RegionKind {
         &self.0
     }
 }
@@ -1215,7 +1176,7 @@ fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool {
             &ty::ReVar(_) | &ty::ReSkolemized(..) => true,
             _ => false
         }
-    }) -> RegionKind<'tcx>
+    }) -> RegionKind
 );
 
 macro_rules! slice_interners {
index 21ccf6f987b8952307460ee07a4db31d310e9785..6de3c018bda0ebe8223760d6d7eb282553712540 100644 (file)
@@ -39,7 +39,6 @@
 //! These methods return true to indicate that the visitor has found what it is looking for
 //! and does not need to visit anything else.
 
-use middle::region;
 use ty::subst::Substs;
 use ty::adjustment;
 use ty::{self, Binder, Ty, TyCtxt, TypeFlags};
@@ -326,23 +325,6 @@ pub fn replace_late_bound_regions<T,F>(self,
         (result, replacer.map)
     }
 
-
-    /// Replace any late-bound regions bound in `value` with free variants attached to scope-id
-    /// `scope_id`.
-    pub fn liberate_late_bound_regions<T>(self,
-        all_outlive_scope: Option<region::CodeExtent<'tcx>>,
-        value: &Binder<T>)
-        -> T
-        where T : TypeFoldable<'tcx>
-    {
-        self.replace_late_bound_regions(value, |br| {
-            self.mk_region(ty::ReFree(ty::FreeRegion {
-                scope: all_outlive_scope,
-                bound_region: br
-            }))
-        }).0
-    }
-
     /// Flattens two binding levels into one. So `for<'a> for<'b> Foo`
     /// becomes `for<'a,'b> Foo`.
     pub fn flatten_late_bound_regions<T>(self, bound2_value: &Binder<Binder<T>>)
@@ -554,7 +536,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
 // regions. See comment on `shift_regions_through_binders` method in
 // `subst.rs` for more details.
 
-pub fn shift_region<'tcx>(region: ty::RegionKind<'tcx>, amount: u32) -> ty::RegionKind<'tcx> {
+pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind {
     match region {
         ty::ReLateBound(debruijn, br) => {
             ty::ReLateBound(debruijn.shifted(amount), br)
index 480b8967a79e9e907ac44964f5cfbfbdc01933b2..bd38a6c3fd39a6edad843f3053b95fe8b4325ea4 100644 (file)
@@ -1268,11 +1268,10 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                     let kind = if def.is_enum() || def.variants[0].fields.len() == 0{
                         StructKind::AlwaysSizedUnivariant
                     } else {
-                        let param_env = tcx.construct_parameter_environment(DUMMY_SP,
-                          def.did, None);
+                        let param_env = tcx.parameter_environment(def.did);
                         let fields = &def.variants[0].fields;
                         let last_field = &fields[fields.len()-1];
-                        let always_sized = last_field.ty(tcx, param_env.free_substs)
+                        let always_sized = tcx.type_of(last_field.did)
                           .is_sized(tcx, &param_env, DUMMY_SP);
                         if !always_sized { StructKind::MaybeUnsizedUnivariant }
                         else { StructKind::AlwaysSizedUnivariant }
index a737e7caa3e59dc7639d69b49ec702d2134530bc..85462bd9b1273ca2a40946ace10c0355abcb9212 100644 (file)
 use mir;
 use mir::transform::{MirSuite, MirPassIndex};
 use session::CompileResult;
+use traits::specialization_graph;
 use ty::{self, CrateInherentImpls, Ty, TyCtxt};
 use ty::item_path;
 use ty::steal::Steal;
 use ty::subst::Substs;
+use ty::fast_reject::SimplifiedType;
 use util::nodemap::{DefIdSet, NodeSet};
 
 use rustc_data_structures::indexed_vec::IndexVec;
@@ -34,6 +36,7 @@
 use std::rc::Rc;
 use syntax_pos::{Span, DUMMY_SP};
 use syntax::attr;
+use syntax::ast;
 use syntax::symbol::Symbol;
 
 pub trait Key: Clone + Hash + Eq + Debug {
@@ -97,6 +100,15 @@ fn default_span(&self, tcx: TyCtxt) -> Span {
     }
 }
 
+impl Key for (DefId, SimplifiedType) {
+    fn map_crate(&self) -> CrateNum {
+        self.0.krate
+    }
+    fn default_span(&self, tcx: TyCtxt) -> Span {
+        self.0.default_span(tcx)
+    }
+}
+
 impl<'tcx> Key for (DefId, &'tcx Substs<'tcx>) {
     fn map_crate(&self) -> CrateNum {
         self.0.krate
@@ -181,7 +193,7 @@ pub fn report_cycle(self, CycleError { span, cycle }: CycleError) {
             let mut err =
                 struct_span_err!(self.sess, span, E0391,
                                  "unsupported cyclic reference between types/traits detected");
-            err.span_label(span, &format!("cyclic reference"));
+            err.span_label(span, "cyclic reference");
 
             err.span_note(stack[0].0, &format!("the cycle begins when {}...",
                                                stack[0].1.describe(self)));
@@ -340,6 +352,36 @@ fn describe(_: TyCtxt, _: DefId) -> String {
     }
 }
 
+impl<'tcx> QueryDescription for queries::item_attrs<'tcx> {
+    fn describe(_: TyCtxt, _: DefId) -> String {
+        bug!("item_attrs")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::is_exported_symbol<'tcx> {
+    fn describe(_: TyCtxt, _: DefId) -> String {
+        bug!("is_exported_symbol")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::fn_arg_names<'tcx> {
+    fn describe(_: TyCtxt, _: DefId) -> String {
+        bug!("fn_arg_names")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::impl_parent<'tcx> {
+    fn describe(_: TyCtxt, _: DefId) -> String {
+        bug!("impl_parent")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::trait_of_item<'tcx> {
+    fn describe(_: TyCtxt, _: DefId) -> String {
+        bug!("trait_of_item")
+    }
+}
+
 impl<'tcx> QueryDescription for queries::item_body_nested_bodies<'tcx> {
     fn describe(tcx: TyCtxt, def_id: DefId) -> String {
         format!("nested item bodies of `{}`", tcx.item_path_str(def_id))
@@ -360,6 +402,24 @@ fn describe(tcx: TyCtxt, def_id: DefId) -> String {
     }
 }
 
+impl<'tcx> QueryDescription for queries::trait_impls_of<'tcx> {
+    fn describe(tcx: TyCtxt, def_id: DefId) -> String {
+        format!("trait impls of `{}`", tcx.item_path_str(def_id))
+    }
+}
+
+impl<'tcx> QueryDescription for queries::relevant_trait_impls_for<'tcx> {
+    fn describe(tcx: TyCtxt, (def_id, ty): (DefId, SimplifiedType)) -> String {
+        format!("relevant impls for: `({}, {:?})`", tcx.item_path_str(def_id), ty)
+    }
+}
+
+impl<'tcx> QueryDescription for queries::is_object_safe<'tcx> {
+    fn describe(tcx: TyCtxt, def_id: DefId) -> String {
+        format!("determine object safety of trait `{}`", tcx.item_path_str(def_id))
+    }
+}
+
 macro_rules! define_maps {
     (<$tcx:tt>
      $($(#[$attr:meta])*
@@ -561,7 +621,7 @@ pub struct Maps<$tcx> {
      output: $output:tt) => {
         define_map_struct! {
             tcx: $tcx,
-            ready: ([pub] $attrs $name),
+            ready: ([] $attrs $name),
             input: ($($input)*),
             output: $output
         }
@@ -770,7 +830,7 @@ fn default() -> Self {
     /// Per-function `RegionMaps`. The `DefId` should be the owner-def-id for the fn body;
     /// in the case of closures or "inline" expressions, this will be redirected to the enclosing
     /// fn item.
-    [] region_maps: RegionMaps(DefId) -> Rc<RegionMaps<'tcx>>,
+    [] region_maps: RegionMaps(DefId) -> Rc<RegionMaps>,
 
     [] mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx mir::Mir<'tcx>,
 
@@ -781,9 +841,21 @@ fn default() -> Self {
     [] def_span: DefSpan(DefId) -> Span,
     [] stability: Stability(DefId) -> Option<attr::Stability>,
     [] deprecation: Deprecation(DefId) -> Option<attr::Deprecation>,
-    [] item_body_nested_bodies: metadata_dep_node(DefId) -> Rc<BTreeMap<hir::BodyId, hir::Body>>,
-    [] const_is_rvalue_promotable_to_static: metadata_dep_node(DefId) -> bool,
-    [] is_mir_available: metadata_dep_node(DefId) -> bool,
+    [] item_attrs: ItemAttrs(DefId) -> Rc<[ast::Attribute]>,
+    [] fn_arg_names: FnArgNames(DefId) -> Vec<ast::Name>,
+    [] impl_parent: ImplParent(DefId) -> Option<DefId>,
+    [] trait_of_item: TraitOfItem(DefId) -> Option<DefId>,
+    [] is_exported_symbol: IsExportedSymbol(DefId) -> bool,
+    [] item_body_nested_bodies: ItemBodyNestedBodies(DefId) -> Rc<BTreeMap<hir::BodyId, hir::Body>>,
+    [] const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool,
+    [] is_mir_available: IsMirAvailable(DefId) -> bool,
+
+    [] trait_impls_of: TraitImpls(DefId) -> ty::trait_def::TraitImpls,
+    // Note that TraitDef::for_each_relevant_impl() will do type simplication for you.
+    [] relevant_trait_impls_for: relevant_trait_impls_for((DefId, SimplifiedType))
+        -> ty::trait_def::TraitImpls,
+    [] specialization_graph_of: SpecializationGraph(DefId) -> Rc<specialization_graph::Graph>,
+    [] is_object_safe: ObjectSafety(DefId) -> bool,
 }
 
 fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
@@ -798,10 +870,6 @@ fn reachability_dep_node(_: CrateNum) -> DepNode<DefId> {
     DepNode::Reachability
 }
 
-fn metadata_dep_node(def_id: DefId) -> DepNode<DefId> {
-    DepNode::MetaData(def_id)
-}
-
 fn mir_shim_dep_node(instance: ty::InstanceDef) -> DepNode<DefId> {
     instance.dep_node()
 }
@@ -827,3 +895,7 @@ fn mir_keys(_: CrateNum) -> DepNode<DefId> {
 fn crate_variances(_: CrateNum) -> DepNode<DefId> {
     DepNode::CrateVariances
 }
+
+fn relevant_trait_impls_for((def_id, _): (DefId, SimplifiedType)) -> DepNode<DefId> {
+    DepNode::TraitImpls(def_id)
+}
index a361c80a2529f34090920688e728b255a6ffb2da..a86d7351ef472be7116ff228da20fcfc47d54c53 100644 (file)
@@ -23,8 +23,8 @@
 use middle::const_val::ConstVal;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
 use middle::privacy::AccessLevels;
-use middle::region::CodeExtent;
 use middle::resolve_lifetime::ObjectLifetimeDefault;
+use middle::region::CodeExtent;
 use mir::Mir;
 use traits;
 use ty;
@@ -80,7 +80,7 @@
 
 pub use self::instance::{Instance, InstanceDef};
 
-pub use self::trait_def::{TraitDef, TraitFlags};
+pub use self::trait_def::TraitDef;
 
 pub use self::maps::queries;
 
@@ -330,6 +330,66 @@ pub struct CrateVariancesMap {
     pub empty_variance: Rc<Vec<ty::Variance>>,
 }
 
+impl Variance {
+    /// `a.xform(b)` combines the variance of a context with the
+    /// variance of a type with the following meaning.  If we are in a
+    /// context with variance `a`, and we encounter a type argument in
+    /// a position with variance `b`, then `a.xform(b)` is the new
+    /// variance with which the argument appears.
+    ///
+    /// Example 1:
+    ///
+    ///     *mut Vec<i32>
+    ///
+    /// Here, the "ambient" variance starts as covariant. `*mut T` is
+    /// invariant with respect to `T`, so the variance in which the
+    /// `Vec<i32>` appears is `Covariant.xform(Invariant)`, which
+    /// yields `Invariant`. Now, the type `Vec<T>` is covariant with
+    /// respect to its type argument `T`, and hence the variance of
+    /// the `i32` here is `Invariant.xform(Covariant)`, which results
+    /// (again) in `Invariant`.
+    ///
+    /// Example 2:
+    ///
+    ///     fn(*const Vec<i32>, *mut Vec<i32)
+    ///
+    /// The ambient variance is covariant. A `fn` type is
+    /// contravariant with respect to its parameters, so the variance
+    /// within which both pointer types appear is
+    /// `Covariant.xform(Contravariant)`, or `Contravariant`.  `*const
+    /// T` is covariant with respect to `T`, so the variance within
+    /// which the first `Vec<i32>` appears is
+    /// `Contravariant.xform(Covariant)` or `Contravariant`.  The same
+    /// is true for its `i32` argument. In the `*mut T` case, the
+    /// variance of `Vec<i32>` is `Contravariant.xform(Invariant)`,
+    /// and hence the outermost type is `Invariant` with respect to
+    /// `Vec<i32>` (and its `i32` argument).
+    ///
+    /// Source: Figure 1 of "Taming the Wildcards:
+    /// Combining Definition- and Use-Site Variance" published in PLDI'11.
+    pub fn xform(self, v: ty::Variance) -> ty::Variance {
+        match (self, v) {
+            // Figure 1, column 1.
+            (ty::Covariant, ty::Covariant) => ty::Covariant,
+            (ty::Covariant, ty::Contravariant) => ty::Contravariant,
+            (ty::Covariant, ty::Invariant) => ty::Invariant,
+            (ty::Covariant, ty::Bivariant) => ty::Bivariant,
+
+            // Figure 1, column 2.
+            (ty::Contravariant, ty::Covariant) => ty::Contravariant,
+            (ty::Contravariant, ty::Contravariant) => ty::Covariant,
+            (ty::Contravariant, ty::Invariant) => ty::Invariant,
+            (ty::Contravariant, ty::Bivariant) => ty::Bivariant,
+
+            // Figure 1, column 3.
+            (ty::Invariant, _) => ty::Invariant,
+
+            // Figure 1, column 4.
+            (ty::Bivariant, _) => ty::Bivariant,
+        }
+    }
+}
+
 #[derive(Clone, Copy, Debug, RustcDecodable, RustcEncodable)]
 pub struct MethodCallee<'tcx> {
     /// Impl method ID, for inherent methods, or trait method ID, otherwise.
@@ -672,11 +732,18 @@ pub struct RegionParameterDef {
 impl RegionParameterDef {
     pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
         ty::EarlyBoundRegion {
+            def_id: self.def_id,
             index: self.index,
             name: self.name,
         }
     }
 
+    pub fn to_bound_region(&self) -> ty::BoundRegion {
+        self.to_early_bound_region_data().to_bound_region()
+    }
+}
+
+impl ty::EarlyBoundRegion {
     pub fn to_bound_region(&self) -> ty::BoundRegion {
         ty::BoundRegion::BrNamed(self.def_id, self.name)
     }
@@ -756,6 +823,21 @@ fn instantiate_into(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
         instantiated.predicates.extend(self.predicates.iter().map(|p| p.subst(tcx, substs)))
     }
 
+    pub fn instantiate_identity(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
+                                -> InstantiatedPredicates<'tcx> {
+        let mut instantiated = InstantiatedPredicates::empty();
+        self.instantiate_identity_into(tcx, &mut instantiated);
+        instantiated
+    }
+
+    fn instantiate_identity_into(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                 instantiated: &mut InstantiatedPredicates<'tcx>) {
+        if let Some(def_id) = self.parent {
+            tcx.predicates_of(def_id).instantiate_identity_into(tcx, instantiated);
+        }
+        instantiated.predicates.extend(&self.predicates)
+    }
+
     pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                   poly_trait_ref: &ty::PolyTraitRef<'tcx>)
                                   -> InstantiatedPredicates<'tcx>
@@ -1181,31 +1263,11 @@ pub fn is_empty(&self) -> bool {
 /// more distinctions clearer.
 #[derive(Clone)]
 pub struct ParameterEnvironment<'tcx> {
-    /// See `construct_free_substs` for details.
-    pub free_substs: &'tcx Substs<'tcx>,
-
-    /// Each type parameter has an implicit region bound that
-    /// indicates it must outlive at least the function body (the user
-    /// may specify stronger requirements). This field indicates the
-    /// region of the callee. If it is `None`, then the parameter
-    /// environment is for an item or something where the "callee" is
-    /// not clear.
-    pub implicit_region_bound: Option<ty::Region<'tcx>>,
-
     /// Obligations that the caller must satisfy. This is basically
     /// the set of bounds on the in-scope type parameters, translated
     /// into Obligations, and elaborated and normalized.
     pub caller_bounds: &'tcx [ty::Predicate<'tcx>],
 
-    /// Scope that is attached to free regions for this scope. This is
-    /// usually the id of the fn body, but for more abstract scopes
-    /// like structs we use None or the item extent.
-    ///
-    /// FIXME(#3696). It would be nice to refactor so that free
-    /// regions don't have this implicit scope and instead introduce
-    /// relationships in the environment.
-    pub free_id_outlive: Option<CodeExtent<'tcx>>,
-
     /// A cache for `moves_by_default`.
     pub is_copy_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
 
@@ -1222,138 +1284,12 @@ pub fn with_caller_bounds(&self,
                               -> ParameterEnvironment<'tcx>
     {
         ParameterEnvironment {
-            free_substs: self.free_substs,
-            implicit_region_bound: self.implicit_region_bound,
             caller_bounds: caller_bounds,
-            free_id_outlive: self.free_id_outlive,
             is_copy_cache: RefCell::new(FxHashMap()),
             is_sized_cache: RefCell::new(FxHashMap()),
             is_freeze_cache: RefCell::new(FxHashMap()),
         }
     }
-
-    /// Construct a parameter environment given an item, impl item, or trait item
-    pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
-                    -> ParameterEnvironment<'tcx> {
-        match tcx.hir.find(id) {
-            Some(hir_map::NodeImplItem(ref impl_item)) => {
-                match impl_item.node {
-                    hir::ImplItemKind::Type(_) | hir::ImplItemKind::Const(..) => {
-                        // associated types don't have their own entry (for some reason),
-                        // so for now just grab environment for the impl
-                        let impl_id = tcx.hir.get_parent(id);
-                        let impl_def_id = tcx.hir.local_def_id(impl_id);
-                        tcx.construct_parameter_environment(impl_item.span,
-                                                            impl_def_id,
-                                                            Some(tcx.item_extent(id)))
-                    }
-                    hir::ImplItemKind::Method(_, ref body) => {
-                        tcx.construct_parameter_environment(
-                            impl_item.span,
-                            tcx.hir.local_def_id(id),
-                            Some(tcx.call_site_extent(id, body.node_id)))
-                    }
-                }
-            }
-            Some(hir_map::NodeTraitItem(trait_item)) => {
-                match trait_item.node {
-                    hir::TraitItemKind::Type(..) | hir::TraitItemKind::Const(..) => {
-                        // associated types don't have their own entry (for some reason),
-                        // so for now just grab environment for the trait
-                        let trait_id = tcx.hir.get_parent(id);
-                        let trait_def_id = tcx.hir.local_def_id(trait_id);
-                        tcx.construct_parameter_environment(trait_item.span,
-                                                            trait_def_id,
-                                                            Some(tcx.item_extent(id)))
-                    }
-                    hir::TraitItemKind::Method(_, ref body) => {
-                        // Use call-site for extent (unless this is a
-                        // trait method with no default; then fallback
-                        // to the method id).
-                        let extent = if let hir::TraitMethod::Provided(body_id) = *body {
-                            // default impl: use call_site extent as free_id_outlive bound.
-                            tcx.call_site_extent(id, body_id.node_id)
-                        } else {
-                            // no default impl: use item extent as free_id_outlive bound.
-                            tcx.item_extent(id)
-                        };
-                        tcx.construct_parameter_environment(
-                            trait_item.span,
-                            tcx.hir.local_def_id(id),
-                            Some(extent))
-                    }
-                }
-            }
-            Some(hir_map::NodeItem(item)) => {
-                match item.node {
-                    hir::ItemFn(.., body_id) => {
-                        // We assume this is a function.
-                        let fn_def_id = tcx.hir.local_def_id(id);
-
-                        tcx.construct_parameter_environment(
-                            item.span,
-                            fn_def_id,
-                            Some(tcx.call_site_extent(id, body_id.node_id)))
-                    }
-                    hir::ItemEnum(..) |
-                    hir::ItemStruct(..) |
-                    hir::ItemUnion(..) |
-                    hir::ItemTy(..) |
-                    hir::ItemImpl(..) |
-                    hir::ItemConst(..) |
-                    hir::ItemStatic(..) => {
-                        let def_id = tcx.hir.local_def_id(id);
-                        tcx.construct_parameter_environment(item.span,
-                                                            def_id,
-                                                            Some(tcx.item_extent(id)))
-                    }
-                    hir::ItemTrait(..) => {
-                        let def_id = tcx.hir.local_def_id(id);
-                        tcx.construct_parameter_environment(item.span,
-                                                            def_id,
-                                                            Some(tcx.item_extent(id)))
-                    }
-                    _ => {
-                        span_bug!(item.span,
-                                  "ParameterEnvironment::for_item():
-                                   can't create a parameter \
-                                   environment for this kind of item")
-                    }
-                }
-            }
-            Some(hir_map::NodeExpr(expr)) => {
-                // This is a convenience to allow closures to work.
-                if let hir::ExprClosure(.., body, _) = expr.node {
-                    let def_id = tcx.hir.local_def_id(id);
-                    let base_def_id = tcx.closure_base_def_id(def_id);
-                    tcx.construct_parameter_environment(
-                        expr.span,
-                        base_def_id,
-                        Some(tcx.call_site_extent(id, body.node_id)))
-                } else {
-                    tcx.empty_parameter_environment()
-                }
-            }
-            Some(hir_map::NodeForeignItem(item)) => {
-                let def_id = tcx.hir.local_def_id(id);
-                tcx.construct_parameter_environment(item.span,
-                                                    def_id,
-                                                    None)
-            }
-            Some(hir_map::NodeStructCtor(..)) |
-            Some(hir_map::NodeVariant(..)) => {
-                let def_id = tcx.hir.local_def_id(id);
-                tcx.construct_parameter_environment(tcx.hir.span(id),
-                                                    def_id,
-                                                    None)
-            }
-            it => {
-                bug!("ParameterEnvironment::from_item(): \
-                      `{}` = {:?} is unsupported",
-                     tcx.hir.node_to_string(id), it)
-            }
-        }
-    }
 }
 
 #[derive(Copy, Clone, Debug)]
@@ -2378,7 +2314,7 @@ pub fn get_attrs(self, did: DefId) -> Attributes<'gcx> {
         if let Some(id) = self.hir.as_local_node_id(did) {
             Attributes::Borrowed(self.hir.attrs(id))
         } else {
-            Attributes::Owned(self.sess.cstore.item_attrs(did))
+            Attributes::Owned(self.item_attrs(did))
         }
     }
 
@@ -2388,37 +2324,7 @@ pub fn has_attr(self, did: DefId, attr: &str) -> bool {
     }
 
     pub fn trait_has_default_impl(self, trait_def_id: DefId) -> bool {
-        let def = self.trait_def(trait_def_id);
-        def.flags.get().intersects(TraitFlags::HAS_DEFAULT_IMPL)
-    }
-
-    /// Populates the type context with all the implementations for the given
-    /// trait if necessary.
-    pub fn populate_implementations_for_trait_if_necessary(self, trait_id: DefId) {
-        if trait_id.is_local() {
-            return
-        }
-
-        // The type is not local, hence we are reading this out of
-        // metadata and don't need to track edges.
-        let _ignore = self.dep_graph.in_ignore();
-
-        let def = self.trait_def(trait_id);
-        if def.flags.get().intersects(TraitFlags::HAS_REMOTE_IMPLS) {
-            return;
-        }
-
-        debug!("populate_implementations_for_trait_if_necessary: searching for {:?}", def);
-
-        for impl_def_id in self.sess.cstore.implementations_of_trait(Some(trait_id)) {
-            let trait_ref = self.impl_trait_ref(impl_def_id).unwrap();
-
-            // Record the trait->implementation mapping.
-            let parent = self.sess.cstore.impl_parent(impl_def_id).unwrap_or(trait_id);
-            def.record_remote_impl(self, impl_def_id, trait_ref, parent);
-        }
-
-        def.flags.set(def.flags.get() | TraitFlags::HAS_REMOTE_IMPLS);
+        self.trait_def(trait_def_id).has_default_impl
     }
 
     /// Given the def_id of an impl, return the def_id of the trait it implements.
@@ -2451,84 +2357,25 @@ pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
         }
     }
 
-    /// If the given def ID describes an item belonging to a trait,
-    /// return the ID of the trait that the trait item belongs to.
-    /// Otherwise, return `None`.
-    pub fn trait_of_item(self, def_id: DefId) -> Option<DefId> {
-        if def_id.krate != LOCAL_CRATE {
-            return self.sess.cstore.trait_of_item(def_id);
-        }
-        self.opt_associated_item(def_id)
-            .and_then(|associated_item| {
-                match associated_item.container {
-                    TraitContainer(def_id) => Some(def_id),
-                    ImplContainer(_) => None
-                }
-            })
-    }
-
     /// Construct a parameter environment suitable for static contexts or other contexts where there
     /// are no free type/lifetime parameters in scope.
     pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
         ty::ParameterEnvironment {
-            free_substs: self.intern_substs(&[]),
             caller_bounds: Slice::empty(),
-            implicit_region_bound: None,
-            free_id_outlive: None,
             is_copy_cache: RefCell::new(FxHashMap()),
             is_sized_cache: RefCell::new(FxHashMap()),
             is_freeze_cache: RefCell::new(FxHashMap()),
         }
     }
 
-    /// Constructs and returns a substitution that can be applied to move from
-    /// the "outer" view of a type or method to the "inner" view.
-    /// In general, this means converting from bound parameters to
-    /// free parameters. Since we currently represent bound/free type
-    /// parameters in the same way, this only has an effect on regions.
-    pub fn construct_free_substs(self,
-                                 def_id: DefId,
-                                 free_id_outlive: Option<CodeExtent<'gcx>>)
-                                 -> &'gcx Substs<'gcx> {
-
-        let substs = Substs::for_item(self.global_tcx(), def_id, |def, _| {
-            // map bound 'a => free 'a
-            self.global_tcx().mk_region(ReFree(FreeRegion {
-                scope: free_id_outlive,
-                bound_region: def.to_bound_region()
-            }))
-        }, |def, _| {
-            // map T => T
-            self.global_tcx().mk_param_from_def(def)
-        });
-
-        debug!("construct_parameter_environment: {:?}", substs);
-        substs
-    }
-
     /// See `ParameterEnvironment` struct def'n for details.
-    /// If you were using `free_id: NodeId`, you might try `self.region_maps().item_extent(free_id)`
-    /// for the `free_id_outlive` parameter. (But note that this is not always quite right.)
-    pub fn construct_parameter_environment(self,
-                                           span: Span,
-                                           def_id: DefId,
-                                           free_id_outlive: Option<CodeExtent<'gcx>>)
-                                           -> ParameterEnvironment<'gcx>
-    {
-        //
-        // Construct the free substs.
-        //
-
-        let free_substs = self.construct_free_substs(def_id, free_id_outlive);
-
+    pub fn parameter_environment(self, def_id: DefId) -> ParameterEnvironment<'gcx> {
         //
         // Compute the bounds on Self and the type parameters.
         //
 
         let tcx = self.global_tcx();
-        let generic_predicates = tcx.predicates_of(def_id);
-        let bounds = generic_predicates.instantiate(tcx, free_substs);
-        let bounds = tcx.liberate_late_bound_regions(free_id_outlive, &ty::Binder(bounds));
+        let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
         let predicates = bounds.predicates;
 
         // Finally, we have to normalize the bounds in the environment, in
@@ -2545,23 +2392,21 @@ pub fn construct_parameter_environment(self,
         //
 
         let unnormalized_env = ty::ParameterEnvironment {
-            free_substs: free_substs,
-            implicit_region_bound: free_id_outlive.map(|f| tcx.mk_region(ty::ReScope(f))),
             caller_bounds: tcx.intern_predicates(&predicates),
-            free_id_outlive: free_id_outlive,
             is_copy_cache: RefCell::new(FxHashMap()),
             is_sized_cache: RefCell::new(FxHashMap()),
             is_freeze_cache: RefCell::new(FxHashMap()),
         };
 
-        let body_id = free_id_outlive.map(|f| f.node_id())
-                                     .unwrap_or(DUMMY_NODE_ID);
-        let cause = traits::ObligationCause::misc(span, body_id);
+        let body_id = self.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| {
+            self.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id)
+        });
+        let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
         traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
     }
 
     pub fn node_scope_region(self, id: NodeId) -> Region<'tcx> {
-        self.mk_region(ty::ReScope(self.node_extent(id)))
+        self.mk_region(ty::ReScope(CodeExtent::Misc(id)))
     }
 
     /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err`
@@ -2706,6 +2551,20 @@ fn def_span<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Span {
     tcx.hir.span_if_local(def_id).unwrap()
 }
 
+/// If the given def ID describes an item belonging to a trait,
+/// return the ID of the trait that the trait item belongs to.
+/// Otherwise, return `None`.
+fn trait_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option<DefId> {
+    tcx.opt_associated_item(def_id)
+        .and_then(|associated_item| {
+            match associated_item.container {
+                TraitContainer(def_id) => Some(def_id),
+                ImplContainer(_) => None
+            }
+        })
+}
+
+
 pub fn provide(providers: &mut ty::maps::Providers) {
     *providers = ty::maps::Providers {
         associated_item,
@@ -2713,6 +2572,9 @@ pub fn provide(providers: &mut ty::maps::Providers) {
         adt_sized_constraint,
         adt_dtorck_constraint,
         def_span,
+        trait_of_item,
+        trait_impls_of: trait_def::trait_impls_of_provider,
+        relevant_trait_impls_for: trait_def::relevant_trait_impls_provider,
         ..*providers
     };
 }
@@ -2721,6 +2583,8 @@ pub fn provide_extern(providers: &mut ty::maps::Providers) {
     *providers = ty::maps::Providers {
         adt_sized_constraint,
         adt_dtorck_constraint,
+        trait_impls_of: trait_def::trait_impls_of_provider,
+        relevant_trait_impls_for: trait_def::relevant_trait_impls_provider,
         ..*providers
     };
 }
index a544b2dd3991bf1e95a6faa13ab24281f09024bb..ab1b1b3857d0035c81695027d48a439a2cc86813 100644 (file)
@@ -204,7 +204,7 @@ fn capture_components(&self, ty: Ty<'tcx>) -> Vec<Component<'tcx>> {
 
 fn push_region_constraints<'tcx>(out: &mut Vec<Component<'tcx>>, regions: Vec<ty::Region<'tcx>>) {
     for r in regions {
-        if !r.is_bound() {
+        if !r.is_late_bound() {
             out.push(Component::Region(r));
         }
     }
index dfa11b9c71a04c6c038621d4dc63330310fa986b..bbe682e74bc04b6dcfe920808d1faae0df10b883 100644 (file)
@@ -51,6 +51,24 @@ fn relate<T: Relate<'tcx>>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> {
         Relate::relate(self, a, b)
     }
 
+    /// Relate the two substitutions for the given item. The default
+    /// is to look up the variance for the item and proceed
+    /// accordingly.
+    fn relate_item_substs(&mut self,
+                          item_def_id: DefId,
+                          a_subst: &'tcx Substs<'tcx>,
+                          b_subst: &'tcx Substs<'tcx>)
+                          -> RelateResult<'tcx, &'tcx Substs<'tcx>>
+    {
+        debug!("relate_item_substs(item_def_id={:?}, a_subst={:?}, b_subst={:?})",
+               item_def_id,
+               a_subst,
+               b_subst);
+
+        let opt_variances = self.tcx().variances_of(item_def_id);
+        relate_substs(self, Some(&opt_variances), a_subst, b_subst)
+    }
+
     /// Switch variance for the purpose of relating `a` and `b`.
     fn relate_with_variance<T: Relate<'tcx>>(&mut self,
                                              variance: ty::Variance,
@@ -109,25 +127,6 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
     }
 }
 
-// substitutions are not themselves relatable without more context,
-// but they is an important subroutine for things that ARE relatable,
-// like traits etc.
-fn relate_item_substs<'a, 'gcx, 'tcx, R>(relation: &mut R,
-                                         item_def_id: DefId,
-                                         a_subst: &'tcx Substs<'tcx>,
-                                         b_subst: &'tcx Substs<'tcx>)
-                                         -> RelateResult<'tcx, &'tcx Substs<'tcx>>
-    where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
-{
-    debug!("substs: item_def_id={:?} a_subst={:?} b_subst={:?}",
-           item_def_id,
-           a_subst,
-           b_subst);
-
-    let opt_variances = relation.tcx().variances_of(item_def_id);
-    relate_substs(relation, Some(&opt_variances), a_subst, b_subst)
-}
-
 pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R,
                                         variances: Option<&Vec<ty::Variance>>,
                                         a_subst: &'tcx Substs<'tcx>,
@@ -291,7 +290,7 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
         if a.def_id != b.def_id {
             Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
         } else {
-            let substs = relate_item_substs(relation, a.def_id, a.substs, b.substs)?;
+            let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?;
             Ok(ty::TraitRef { def_id: a.def_id, substs: substs })
         }
     }
@@ -308,7 +307,7 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
         if a.def_id != b.def_id {
             Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
         } else {
-            let substs = relate_item_substs(relation, a.def_id, a.substs, b.substs)?;
+            let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?;
             Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs })
         }
     }
@@ -372,7 +371,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
         (&ty::TyAdt(a_def, a_substs), &ty::TyAdt(b_def, b_substs))
             if a_def == b_def =>
         {
-            let substs = relate_item_substs(relation, a_def.did, a_substs, b_substs)?;
+            let substs = relation.relate_item_substs(a_def.did, a_substs, b_substs)?;
             Ok(tcx.mk_adt(a_def, substs))
         }
 
index 630e4a239cc65d953d0395b0421567094196f758..cfbf1244db3ad70202effe2891a277185b44150f 100644 (file)
@@ -43,12 +43,8 @@ pub struct TypeAndMut<'tcx> {
          RustcEncodable, RustcDecodable, Copy)]
 /// A "free" region `fr` can be interpreted as "some region
 /// at least as big as the scope `fr.scope`".
-///
-/// If `fr.scope` is None, then this is in some context (e.g., an
-/// impl) where lifetimes are more abstract and the notion of the
-/// caller/callee stack frames are not applicable.
-pub struct FreeRegion<'tcx> {
-    pub scope: Option<region::CodeExtent<'tcx>>,
+pub struct FreeRegion {
+    pub scope: DefId,
     pub bound_region: BoundRegion,
 }
 
@@ -67,8 +63,8 @@ pub enum BoundRegion {
     /// Fresh bound identifiers created during GLB computations.
     BrFresh(u32),
 
-    // Anonymous region for the implicit env pointer parameter
-    // to a closure
+    /// Anonymous region for the implicit env pointer parameter
+    /// to a closure
     BrEnv,
 }
 
@@ -95,8 +91,8 @@ pub struct Issue32330 {
     pub region_name: ast::Name,
 }
 
-// NB: If you change this, you'll probably want to change the corresponding
-// AST structure in libsyntax/ast.rs as well.
+/// NB: If you change this, you'll probably want to change the corresponding
+/// AST structure in libsyntax/ast.rs as well.
 #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub enum TypeVariants<'tcx> {
     /// The primitive boolean type. Written as `bool`.
@@ -283,11 +279,11 @@ impl Iterator<Item=Ty<'tcx>> + 'tcx
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub enum ExistentialPredicate<'tcx> {
-    // e.g. Iterator
+    /// e.g. Iterator
     Trait(ExistentialTraitRef<'tcx>),
-    // e.g. Iterator::Item = T
+    /// e.g. Iterator::Item = T
     Projection(ExistentialProjection<'tcx>),
-    // e.g. Send
+    /// e.g. Send
     AutoTrait(DefId),
 }
 
@@ -683,12 +679,12 @@ pub fn is_self(&self) -> bool {
 /// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
 #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy)]
 pub struct DebruijnIndex {
-    // We maintain the invariant that this is never 0. So 1 indicates
-    // the innermost binder. To ensure this, create with `DebruijnIndex::new`.
+    /// We maintain the invariant that this is never 0. So 1 indicates
+    /// the innermost binder. To ensure this, create with `DebruijnIndex::new`.
     pub depth: u32,
 }
 
-pub type Region<'tcx> = &'tcx RegionKind<'tcx>;
+pub type Region<'tcx> = &'tcx RegionKind;
 
 /// Representation of regions.
 ///
@@ -747,7 +743,7 @@ pub struct DebruijnIndex {
 /// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
 /// [2] http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
 #[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable)]
-pub enum RegionKind<'tcx> {
+pub enum RegionKind {
     // Region bound in a type or fn declaration which will be
     // substituted 'early' -- that is, at the same time when type
     // parameters are substituted.
@@ -760,12 +756,12 @@ pub enum RegionKind<'tcx> {
     /// When checking a function body, the types of all arguments and so forth
     /// that refer to bound region parameters are modified to refer to free
     /// region parameters.
-    ReFree(FreeRegion<'tcx>),
+    ReFree(FreeRegion),
 
     /// A concrete region naming some statically determined extent
     /// (e.g. an expression or sequence of statements) within the
     /// current function.
-    ReScope(region::CodeExtent<'tcx>),
+    ReScope(region::CodeExtent),
 
     /// Static data that has an "infinite" lifetime. Top in the region lattice.
     ReStatic,
@@ -794,6 +790,7 @@ impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {}
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
 pub struct EarlyBoundRegion {
+    pub def_id: DefId,
     pub index: u32,
     pub name: Name,
 }
@@ -908,11 +905,10 @@ pub fn shifted(&self, amount: u32) -> DebruijnIndex {
     }
 }
 
-// Region utilities
-impl<'tcx> RegionKind<'tcx> {
-    pub fn is_bound(&self) -> bool {
+/// Region utilities
+impl RegionKind {
+    pub fn is_late_bound(&self) -> bool {
         match *self {
-            ty::ReEarlyBound(..) => true,
             ty::ReLateBound(..) => true,
             _ => false,
         }
@@ -933,7 +929,7 @@ pub fn escapes_depth(&self, depth: u32) -> bool {
     }
 
     /// Returns the depth of `self` from the (1-based) binding level `depth`
-    pub fn from_depth(&self, depth: u32) -> RegionKind<'tcx> {
+    pub fn from_depth(&self, depth: u32) -> RegionKind {
         match *self {
             ty::ReLateBound(debruijn, r) => ty::ReLateBound(DebruijnIndex {
                 depth: debruijn.depth - (depth - 1)
@@ -972,7 +968,7 @@ pub fn type_flags(&self) -> TypeFlags {
     }
 }
 
-// Type utilities
+/// Type utilities
 impl<'a, 'gcx, 'tcx> TyS<'tcx> {
     pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> {
         match self.sty {
@@ -995,8 +991,8 @@ pub fn is_never(&self) -> bool {
         }
     }
 
-    // Test whether this is a `()` which was produced by defaulting a
-    // diverging type variable with feature(never_type) disabled.
+    /// Test whether this is a `()` which was produced by defaulting a
+    /// diverging type variable with feature(never_type) disabled.
     pub fn is_defaulted_unit(&self) -> bool {
         match self.sty {
             TyTuple(_, true) => true,
@@ -1171,6 +1167,7 @@ pub fn is_box(&self) -> bool {
         }
     }
 
+    /// panics if called on any type other than `Box<T>`
     pub fn boxed_ty(&self) -> Ty<'tcx> {
         match self.sty {
             TyAdt(def, substs) if def.is_box() => substs.type_at(0),
@@ -1178,11 +1175,9 @@ pub fn boxed_ty(&self) -> Ty<'tcx> {
         }
     }
 
-    /*
-     A scalar type is one that denotes an atomic datum, with no sub-components.
-     (A TyRawPtr is scalar because it represents a non-managed pointer, so its
-     contents are abstract to rustc.)
-    */
+    /// A scalar type is one that denotes an atomic datum, with no sub-components.
+    /// (A TyRawPtr is scalar because it represents a non-managed pointer, so its
+    /// contents are abstract to rustc.)
     pub fn is_scalar(&self) -> bool {
         match self.sty {
             TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) |
@@ -1278,10 +1273,10 @@ pub fn has_concrete_skeleton(&self) -> bool {
         }
     }
 
-    // Returns the type and mutability of *ty.
-    //
-    // The parameter `explicit` indicates if this is an *explicit* dereference.
-    // Some types---notably unsafe ptrs---can only be dereferenced explicitly.
+    /// Returns the type and mutability of *ty.
+    ///
+    /// The parameter `explicit` indicates if this is an *explicit* dereference.
+    /// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
     pub fn builtin_deref(&self, explicit: bool, pref: ty::LvaluePreference)
         -> Option<TypeAndMut<'tcx>>
     {
@@ -1302,7 +1297,7 @@ pub fn builtin_deref(&self, explicit: bool, pref: ty::LvaluePreference)
         }
     }
 
-    // Returns the type of ty[i]
+    /// Returns the type of ty[i]
     pub fn builtin_index(&self) -> Option<Ty<'tcx>> {
         match self.sty {
             TyArray(ty, _) | TySlice(ty) => Some(ty),
@@ -1317,7 +1312,7 @@ pub fn fn_sig(&self) -> PolyFnSig<'tcx> {
         }
     }
 
-    // Type accessors for substructures of types
+    /// Type accessors for substructures of types
     pub fn fn_args(&self) -> ty::Binder<&'tcx [Ty<'tcx>]> {
         self.fn_sig().inputs()
     }
index c9ffcee51c20ad1e346b54109a98949c174d8112..e23003bf772f2d284b33ad59ca63db7d16ddcd9d 100644 (file)
@@ -102,7 +102,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         } else if let Some(r) = self.as_region() {
             write!(f, "{:?}", r)
         } else {
-            write!(f, "<unknwon @ {:p}>", self.ptr.get() as *const ())
+            write!(f, "<unknown @ {:p}>", self.ptr.get() as *const ())
         }
     }
 }
index 097b596c5ebb6b6c9e08219168643855605b265a..865297c7ecbfd5fa67ec69dac06e3b609133e9df 100644 (file)
@@ -8,18 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use dep_graph::DepNode;
-use hir::def_id::{DefId, LOCAL_CRATE};
-use traits::{self, specialization_graph};
-use ty;
+use hir::def_id::DefId;
+use traits::specialization_graph;
 use ty::fast_reject;
-use ty::{Ty, TyCtxt, TraitRef};
-use std::cell::{Cell, RefCell};
+use ty::fold::TypeFoldable;
+use ty::{Ty, TyCtxt};
+use std::rc::Rc;
 use hir;
-use util::nodemap::FxHashMap;
-
-use syntax::ast;
-use syntax_pos::DUMMY_SP;
 
 /// A trait's definition with type information.
 pub struct TraitDef {
@@ -33,237 +28,93 @@ pub struct TraitDef {
     /// be usable with the sugar (or without it).
     pub paren_sugar: bool,
 
-    // Impls of a trait. To allow for quicker lookup, the impls are indexed by a
-    // simplified version of their `Self` type: impls with a simplifiable `Self`
-    // are stored in `nonblanket_impls` keyed by it, while all other impls are
-    // stored in `blanket_impls`.
-    //
-    // A similar division is used within `specialization_graph`, but the ones
-    // here are (1) stored as a flat list for the trait and (2) populated prior
-    // to -- and used while -- determining specialization order.
-    //
-    // FIXME: solve the reentrancy issues and remove these lists in favor of the
-    // ones in `specialization_graph`.
-    //
-    // These lists are tracked by `DepNode::TraitImpls`; we don't use
-    // a DepTrackingMap but instead have the `TraitDef` insert the
-    // required reads/writes.
-
-    /// Impls of the trait.
-    nonblanket_impls: RefCell<
-        FxHashMap<fast_reject::SimplifiedType, Vec<DefId>>
-    >,
-
-    /// Blanket impls associated with the trait.
-    blanket_impls: RefCell<Vec<DefId>>,
-
-    /// The specialization order for impls of this trait.
-    pub specialization_graph: RefCell<traits::specialization_graph::Graph>,
-
-    /// Various flags
-    pub flags: Cell<TraitFlags>,
-
-    /// The number of impls we've added from the local crate.
-    /// When this number matches up the list in the HIR map,
-    /// we're done, and the specialization graph is correct.
-    local_impl_count: Cell<usize>,
+    pub has_default_impl: bool,
 
     /// The ICH of this trait's DefPath, cached here so it doesn't have to be
     /// recomputed all the time.
     pub def_path_hash: u64,
 }
 
-impl<'a, 'gcx, 'tcx> TraitDef {
-    pub fn new(def_id: DefId,
-               unsafety: hir::Unsafety,
-               paren_sugar: bool,
-               def_path_hash: u64)
-               -> TraitDef {
-        TraitDef {
-            def_id: def_id,
-            paren_sugar: paren_sugar,
-            unsafety: unsafety,
-            nonblanket_impls: RefCell::new(FxHashMap()),
-            blanket_impls: RefCell::new(vec![]),
-            flags: Cell::new(ty::TraitFlags::NO_TRAIT_FLAGS),
-            local_impl_count: Cell::new(0),
-            specialization_graph: RefCell::new(traits::specialization_graph::Graph::new()),
-            def_path_hash: def_path_hash,
-        }
-    }
+// We don't store the list of impls in a flat list because each cached list of
+// `relevant_impls_for` we would then duplicate all blanket impls. By keeping
+// blanket and non-blanket impls separate, we can share the list of blanket
+// impls.
+#[derive(Clone)]
+pub struct TraitImpls {
+    blanket_impls: Rc<Vec<DefId>>,
+    non_blanket_impls: Rc<Vec<DefId>>,
+}
 
-    // returns None if not yet calculated
-    pub fn object_safety(&self) -> Option<bool> {
-        if self.flags.get().intersects(TraitFlags::OBJECT_SAFETY_VALID) {
-            Some(self.flags.get().intersects(TraitFlags::IS_OBJECT_SAFE))
-        } else {
-            None
+impl TraitImpls {
+    pub fn iter(&self) -> TraitImplsIter {
+        TraitImplsIter {
+            blanket_impls: self.blanket_impls.clone(),
+            non_blanket_impls: self.non_blanket_impls.clone(),
+            index: 0
         }
     }
+}
 
-    pub fn set_object_safety(&self, is_safe: bool) {
-        assert!(self.object_safety().map(|cs| cs == is_safe).unwrap_or(true));
-        self.flags.set(
-            self.flags.get() | if is_safe {
-                TraitFlags::OBJECT_SAFETY_VALID | TraitFlags::IS_OBJECT_SAFE
-            } else {
-                TraitFlags::OBJECT_SAFETY_VALID
-            }
-        );
-    }
-
-    fn write_trait_impls(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) {
-        tcx.dep_graph.write(DepNode::TraitImpls(self.def_id));
-    }
-
-    fn read_trait_impls(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) {
-        tcx.dep_graph.read(DepNode::TraitImpls(self.def_id));
-    }
-
-    /// Records a basic trait-to-implementation mapping.
-    ///
-    /// Returns `true` iff the impl has not previously been recorded.
-    fn record_impl(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                   impl_def_id: DefId,
-                   impl_trait_ref: TraitRef<'tcx>)
-                   -> bool {
-        debug!("TraitDef::record_impl for {:?}, from {:?}",
-               self, impl_trait_ref);
+#[derive(Clone)]
+pub struct TraitImplsIter {
+    blanket_impls: Rc<Vec<DefId>>,
+    non_blanket_impls: Rc<Vec<DefId>>,
+    index: usize,
+}
 
-        // Record the write into the impl set, but only for local
-        // impls: external impls are handled differently.
-        if impl_def_id.is_local() {
-            self.write_trait_impls(tcx);
-        }
+impl Iterator for TraitImplsIter {
+    type Item = DefId;
 
-        // We don't want to borrow_mut after we already populated all impls,
-        // so check if an impl is present with an immutable borrow first.
-        if let Some(sty) = fast_reject::simplify_type(tcx,
-                                                      impl_trait_ref.self_ty(), false) {
-            if let Some(is) = self.nonblanket_impls.borrow().get(&sty) {
-                if is.contains(&impl_def_id) {
-                    return false; // duplicate - skip
-                }
-            }
-
-            self.nonblanket_impls.borrow_mut().entry(sty).or_insert(vec![]).push(impl_def_id)
+    fn next(&mut self) -> Option<DefId> {
+        if self.index < self.blanket_impls.len() {
+            let bi_index = self.index;
+            self.index += 1;
+            Some(self.blanket_impls[bi_index])
         } else {
-            if self.blanket_impls.borrow().contains(&impl_def_id) {
-                return false; // duplicate - skip
+            let nbi_index = self.index - self.blanket_impls.len();
+            if nbi_index < self.non_blanket_impls.len() {
+                self.index += 1;
+                Some(self.non_blanket_impls[nbi_index])
+            } else {
+                None
             }
-            self.blanket_impls.borrow_mut().push(impl_def_id)
         }
-
-        true
-    }
-
-    /// Records a trait-to-implementation mapping for a crate-local impl.
-    pub fn record_local_impl(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                             impl_def_id: DefId,
-                             impl_trait_ref: TraitRef<'tcx>) {
-        assert!(impl_def_id.is_local());
-        let was_new = self.record_impl(tcx, impl_def_id, impl_trait_ref);
-        assert!(was_new);
-
-        self.local_impl_count.set(self.local_impl_count.get() + 1);
     }
 
-    /// Records a trait-to-implementation mapping.
-    pub fn record_has_default_impl(&self) {
-        self.flags.set(self.flags.get() | TraitFlags::HAS_DEFAULT_IMPL);
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let items_left = (self.blanket_impls.len() + self.non_blanket_impls.len()) - self.index;
+        (items_left, Some(items_left))
     }
+}
 
-    /// Records a trait-to-implementation mapping for a non-local impl.
-    ///
-    /// The `parent_impl` is the immediately-less-specialized impl, or the
-    /// trait's def ID if the impl is not a specialization -- information that
-    /// should be pulled from the metadata.
-    pub fn record_remote_impl(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                              impl_def_id: DefId,
-                              impl_trait_ref: TraitRef<'tcx>,
-                              parent_impl: DefId) {
-        assert!(!impl_def_id.is_local());
+impl ExactSizeIterator for TraitImplsIter {}
 
-        // if the impl has not previously been recorded
-        if self.record_impl(tcx, impl_def_id, impl_trait_ref) {
-            // if the impl is non-local, it's placed directly into the
-            // specialization graph using parent information drawn from metadata.
-            self.specialization_graph.borrow_mut()
-                .record_impl_from_cstore(tcx, parent_impl, impl_def_id)
+impl<'a, 'gcx, 'tcx> TraitDef {
+    pub fn new(def_id: DefId,
+               unsafety: hir::Unsafety,
+               paren_sugar: bool,
+               has_default_impl: bool,
+               def_path_hash: u64)
+               -> TraitDef {
+        TraitDef {
+            def_id,
+            paren_sugar,
+            unsafety,
+            has_default_impl,
+            def_path_hash,
         }
     }
 
-    /// Adds a local impl into the specialization graph, returning an error with
-    /// overlap information if the impl overlaps but does not specialize an
-    /// existing impl.
-    pub fn add_impl_for_specialization(&self,
-                                       tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                       impl_def_id: DefId)
-                                       -> Result<(), traits::OverlapError> {
-        assert!(impl_def_id.is_local());
-
-        self.specialization_graph.borrow_mut()
-            .insert(tcx, impl_def_id)
-    }
-
-    pub fn ancestors(&'a self, of_impl: DefId) -> specialization_graph::Ancestors<'a> {
-        specialization_graph::ancestors(self, of_impl)
-    }
-
-    /// Whether the impl set and specialization graphs are complete.
-    pub fn is_complete(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
-        tcx.populate_implementations_for_trait_if_necessary(self.def_id);
-        ty::queries::coherent_trait::try_get(tcx, DUMMY_SP, (LOCAL_CRATE, self.def_id)).is_ok()
-    }
-
-    /// If any local impls haven't been added yet, returns
-    /// Some(list of local impls for this trait).
-    fn missing_local_impls(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
-                           -> Option<&'gcx [ast::NodeId]> {
-        if self.flags.get().intersects(TraitFlags::HAS_LOCAL_IMPLS) {
-            return None;
-        }
-
-        if self.is_complete(tcx) {
-            self.flags.set(self.flags.get() | TraitFlags::HAS_LOCAL_IMPLS);
-            return None;
-        }
-
-        let impls = tcx.hir.trait_impls(self.def_id);
-        assert!(self.local_impl_count.get() <= impls.len());
-        if self.local_impl_count.get() == impls.len() {
-            self.flags.set(self.flags.get() | TraitFlags::HAS_LOCAL_IMPLS);
-            return None;
-        }
-
-        Some(impls)
+    pub fn ancestors(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                     of_impl: DefId)
+                     -> specialization_graph::Ancestors {
+        specialization_graph::ancestors(tcx, self.def_id, of_impl)
     }
 
     pub fn for_each_impl<F: FnMut(DefId)>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, mut f: F) {
-        self.read_trait_impls(tcx);
-        tcx.populate_implementations_for_trait_if_necessary(self.def_id);
-
-        let local_impls = self.missing_local_impls(tcx);
-        if let Some(impls) = local_impls {
-            for &id in impls {
-                f(tcx.hir.local_def_id(id));
-            }
-        }
-        let mut f = |def_id: DefId| {
-            if !(local_impls.is_some() && def_id.is_local()) {
-                f(def_id);
-            }
-        };
-
-        for &impl_def_id in self.blanket_impls.borrow().iter() {
+        for impl_def_id in tcx.trait_impls_of(self.def_id).iter() {
             f(impl_def_id);
         }
-
-        for v in self.nonblanket_impls.borrow().values() {
-            for &impl_def_id in v {
-                f(impl_def_id);
-            }
-        }
     }
 
     /// Iterate over every impl that could possibly match the
@@ -273,25 +124,6 @@ pub fn for_each_relevant_impl<F: FnMut(DefId)>(&self,
                                                    self_ty: Ty<'tcx>,
                                                    mut f: F)
     {
-        self.read_trait_impls(tcx);
-        tcx.populate_implementations_for_trait_if_necessary(self.def_id);
-
-        let local_impls = self.missing_local_impls(tcx);
-        if let Some(impls) = local_impls {
-            for &id in impls {
-                f(tcx.hir.local_def_id(id));
-            }
-        }
-        let mut f = |def_id: DefId| {
-            if !(local_impls.is_some() && def_id.is_local()) {
-                f(def_id);
-            }
-        };
-
-        for &impl_def_id in self.blanket_impls.borrow().iter() {
-            f(impl_def_id);
-        }
-
         // simplify_type(.., false) basically replaces type parameters and
         // projections with infer-variables. This is, of course, done on
         // the impl trait-ref when it is instantiated, but not on the
@@ -304,29 +136,86 @@ pub fn for_each_relevant_impl<F: FnMut(DefId)>(&self,
         // replace `S` with anything - this impl of course can't be
         // selected, and as there are hundreds of similar impls,
         // considering them would significantly harm performance.
-        if let Some(simp) = fast_reject::simplify_type(tcx, self_ty, true) {
-            if let Some(impls) = self.nonblanket_impls.borrow().get(&simp) {
-                for &impl_def_id in impls {
-                    f(impl_def_id);
-                }
-            }
+        let relevant_impls = if let Some(simplified_self_ty) =
+                fast_reject::simplify_type(tcx, self_ty, true) {
+            tcx.relevant_trait_impls_for((self.def_id, simplified_self_ty))
         } else {
-            for v in self.nonblanket_impls.borrow().values() {
-                for &impl_def_id in v {
-                    f(impl_def_id);
-                }
-            }
+            tcx.trait_impls_of(self.def_id)
+        };
+
+        for impl_def_id in relevant_impls.iter() {
+            f(impl_def_id);
         }
     }
 }
 
-bitflags! {
-    flags TraitFlags: u32 {
-        const NO_TRAIT_FLAGS        = 0,
-        const HAS_DEFAULT_IMPL      = 1 << 0,
-        const IS_OBJECT_SAFE        = 1 << 1,
-        const OBJECT_SAFETY_VALID   = 1 << 2,
-        const HAS_REMOTE_IMPLS      = 1 << 3,
-        const HAS_LOCAL_IMPLS       = 1 << 4,
+// Query provider for `trait_impls_of`.
+pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                                trait_id: DefId)
+                                                -> TraitImpls {
+    let remote_impls = if trait_id.is_local() {
+        // Traits defined in the current crate can't have impls in upstream
+        // crates, so we don't bother querying the cstore.
+        Vec::new()
+    } else {
+        tcx.sess.cstore.implementations_of_trait(Some(trait_id))
+    };
+
+    let mut blanket_impls = Vec::new();
+    let mut non_blanket_impls = Vec::new();
+
+    let local_impls = tcx.hir
+                         .trait_impls(trait_id)
+                         .into_iter()
+                         .map(|&node_id| tcx.hir.local_def_id(node_id));
+
+     for impl_def_id in local_impls.chain(remote_impls.into_iter()) {
+        let impl_self_ty = tcx.type_of(impl_def_id);
+        if impl_def_id.is_local() && impl_self_ty.references_error() {
+            continue
+        }
+
+        if fast_reject::simplify_type(tcx, impl_self_ty, false).is_some() {
+            non_blanket_impls.push(impl_def_id);
+        } else {
+            blanket_impls.push(impl_def_id);
+        }
+    }
+
+    TraitImpls {
+        blanket_impls: Rc::new(blanket_impls),
+        non_blanket_impls: Rc::new(non_blanket_impls),
+    }
+}
+
+// Query provider for `relevant_trait_impls_for`.
+pub(super) fn relevant_trait_impls_provider<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    (trait_id, self_ty): (DefId, fast_reject::SimplifiedType))
+    -> TraitImpls
+{
+    let all_trait_impls = tcx.trait_impls_of(trait_id);
+
+    let relevant: Vec<DefId> = all_trait_impls
+        .non_blanket_impls
+        .iter()
+        .cloned()
+        .filter(|&impl_def_id| {
+            let impl_self_ty = tcx.type_of(impl_def_id);
+            let impl_simple_self_ty = fast_reject::simplify_type(tcx,
+                                                                 impl_self_ty,
+                                                                 false).unwrap();
+            impl_simple_self_ty == self_ty
+        })
+        .collect();
+
+    if all_trait_impls.non_blanket_impls.len() == relevant.len() {
+        // If we didn't filter anything out, re-use the existing vec.
+        all_trait_impls
+    } else {
+        TraitImpls {
+            blanket_impls: all_trait_impls.blanket_impls.clone(),
+            non_blanket_impls: Rc::new(relevant),
+        }
     }
 }
index 06d09bd350a4c8eab5002311887379924ba4bdfd..c6c6a0e47003dbb40777d056b2ade638c6259eb7 100644 (file)
@@ -688,9 +688,8 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
                 self.hash(db.depth);
                 self.hash(i);
             }
-            ty::ReEarlyBound(ty::EarlyBoundRegion { index, name }) => {
-                self.hash(index);
-                self.hash(name.as_str());
+            ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. }) => {
+                self.def_id(def_id);
             }
             ty::ReLateBound(..) |
             ty::ReFree(..) |
index 7b5e2253109aa01c1d49d0fdc8152ed8cc618aab..17564671a1e364f45eed26442e33e6b9e8231b06 100644 (file)
@@ -116,6 +116,7 @@ pub fn record_time<T, F>(accu: &Cell<Duration>, f: F) -> T where
 }
 
 // Like std::macros::try!, but for Option<>.
+#[cfg(unix)]
 macro_rules! option_try(
     ($e:expr) => (match $e { Some(e) => e, None => return None })
 );
index d773bb2da0898b6b30d0cdd07698bfa8395a90b1..8ca699339d36ecedca7a92a3e785b51fffb248bf 100644 (file)
@@ -458,7 +458,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-impl<'tcx> fmt::Debug for ty::RegionKind<'tcx> {
+impl fmt::Debug for ty::RegionKind {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             ty::ReEarlyBound(ref data) => {
@@ -506,17 +506,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 impl<'tcx> fmt::Debug for ty::ParameterEnvironment<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "ParameterEnvironment(\
-            free_substs={:?}, \
-            implicit_region_bound={:?}, \
-            caller_bounds={:?})",
-            self.free_substs,
-            self.implicit_region_bound,
-            self.caller_bounds)
+        write!(f, "ParameterEnvironment({:?})", self.caller_bounds)
     }
 }
 
-impl<'tcx> fmt::Display for ty::RegionKind<'tcx> {
+impl<'tcx> fmt::Display for ty::RegionKind {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if verbose() {
             return write!(f, "{:?}", *self);
@@ -544,7 +538,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-impl<'tcx> fmt::Debug for ty::FreeRegion<'tcx> {
+impl fmt::Debug for ty::FreeRegion {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "ReFree({:?}, {:?})",
                self.scope, self.bound_region)
index 6679cc73029c7e119edd15ff81fdb00f36d5c52d..69eabfe2ac0bf70c176f02e5fb23b59e1817142b 100644 (file)
@@ -22,7 +22,6 @@
 //! build speedups.
 
 #![crate_name = "rustc_back"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 #![feature(const_fn)]
 #![feature(libc)]
 #![feature(rand)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
 #![cfg_attr(test, feature(rand))]
 
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
 extern crate syntax;
 extern crate libc;
 extern crate serialize;
index edd474b2e9edc441992e141c77a7254dc3404468..23558d82883423266f399ad98173c0f78f8cb21a 100644 (file)
 
 #![crate_name = "rustc_bitflags"]
 #![feature(associated_consts)]
-#![feature(staged_api)]
 #![crate_type = "rlib"]
 #![no_std]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![deny(warnings)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(staged_api))]
 
 //! A typesafe bitmask flag generator.
 
index 1c5a6c3985cfc43f92b1b06b9f33c0b6813317b2..eeb5a3fb957fa481f7a2ad4dc15f80b77f529950 100644 (file)
@@ -232,7 +232,7 @@ pub fn each_issued_loan<F>(&self, node: ast::NodeId, mut op: F) -> bool where
         })
     }
 
-    pub fn each_in_scope_loan<F>(&self, scope: region::CodeExtent<'tcx>, mut op: F) -> bool where
+    pub fn each_in_scope_loan<F>(&self, scope: region::CodeExtent, mut op: F) -> bool where
         F: FnMut(&Loan<'tcx>) -> bool,
     {
         //! Like `each_issued_loan()`, but only considers loans that are
@@ -248,7 +248,7 @@ pub fn each_in_scope_loan<F>(&self, scope: region::CodeExtent<'tcx>, mut op: F)
     }
 
     fn each_in_scope_loan_affecting_path<F>(&self,
-                                            scope: region::CodeExtent<'tcx>,
+                                            scope: region::CodeExtent,
                                             loan_path: &LoanPath<'tcx>,
                                             mut op: F)
                                             -> bool where
@@ -469,13 +469,13 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
                                                   nl, new_loan_msg);
                     err.span_label(
                             old_loan.span,
-                            &format!("first mutable borrow occurs here{}", old_loan_msg));
+                            format!("first mutable borrow occurs here{}", old_loan_msg));
                     err.span_label(
                             new_loan.span,
-                            &format!("second mutable borrow occurs here{}", new_loan_msg));
+                            format!("second mutable borrow occurs here{}", new_loan_msg));
                     err.span_label(
                             previous_end_span,
-                            &format!("first borrow ends here"));
+                            "first borrow ends here");
                     err
                 }
 
@@ -486,13 +486,13 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
                                      nl);
                     err.span_label(
                             old_loan.span,
-                            &format!("first closure is constructed here"));
+                            "first closure is constructed here");
                     err.span_label(
                             new_loan.span,
-                            &format!("second closure is constructed here"));
+                            "second closure is constructed here");
                     err.span_label(
                             previous_end_span,
-                            &format!("borrow from first closure ends here"));
+                            "borrow from first closure ends here");
                     err
                 }
 
@@ -503,13 +503,13 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
                                                    nl, ol_pronoun, old_loan_msg);
                     err.span_label(
                             new_loan.span,
-                            &format!("closure construction occurs here{}", new_loan_msg));
+                            format!("closure construction occurs here{}", new_loan_msg));
                     err.span_label(
                             old_loan.span,
-                            &format!("borrow occurs here{}", old_loan_msg));
+                            format!("borrow occurs here{}", old_loan_msg));
                     err.span_label(
                             previous_end_span,
-                            &format!("borrow ends here"));
+                            "borrow ends here");
                     err
                 }
 
@@ -520,13 +520,13 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
                                                    nl, new_loan_msg, new_loan.kind.to_user_str());
                     err.span_label(
                             new_loan.span,
-                            &format!("borrow occurs here{}", new_loan_msg));
+                            format!("borrow occurs here{}", new_loan_msg));
                     err.span_label(
                             old_loan.span,
-                            &format!("closure construction occurs here{}", old_loan_msg));
+                            format!("closure construction occurs here{}", old_loan_msg));
                     err.span_label(
                             previous_end_span,
-                            &format!("borrow from closure ends here"));
+                            "borrow from closure ends here");
                     err
                 }
 
@@ -542,17 +542,17 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
                                                    old_loan_msg);
                     err.span_label(
                             new_loan.span,
-                            &format!("{} borrow occurs here{}",
+                            format!("{} borrow occurs here{}",
                                      new_loan.kind.to_user_str(),
                                      new_loan_msg));
                     err.span_label(
                             old_loan.span,
-                            &format!("{} borrow occurs here{}",
+                            format!("{} borrow occurs here{}",
                                      old_loan.kind.to_user_str(),
                                      old_loan_msg));
                     err.span_label(
                             previous_end_span,
-                            &format!("{} borrow ends here",
+                            format!("{} borrow ends here",
                                      old_loan.kind.to_user_str()));
                     err
                 }
@@ -562,7 +562,7 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
                 euv::ClosureCapture(span) => {
                     err.span_label(
                         span,
-                        &format!("borrow occurs due to use of `{}` in closure", nl));
+                        format!("borrow occurs due to use of `{}` in closure", nl));
                 }
                 _ => { }
             }
@@ -571,7 +571,7 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
                 euv::ClosureCapture(span) => {
                     err.span_label(
                         span,
-                        &format!("previous borrow occurs due to use of `{}` in closure",
+                        format!("previous borrow occurs due to use of `{}` in closure",
                                  ol));
                 }
                 _ => { }
@@ -633,11 +633,11 @@ fn check_for_copy_of_frozen_path(&self,
                                  "cannot use `{}` because it was mutably borrowed",
                                  &self.bccx.loan_path_to_string(copy_path))
                     .span_label(loan_span,
-                               &format!("borrow of `{}` occurs here",
+                               format!("borrow of `{}` occurs here",
                                        &self.bccx.loan_path_to_string(&loan_path))
                                )
                     .span_label(span,
-                               &format!("use of borrowed `{}`",
+                               format!("use of borrowed `{}`",
                                         &self.bccx.loan_path_to_string(&loan_path)))
                     .emit();
             }
@@ -662,12 +662,12 @@ fn check_for_move_of_borrowed_path(&self,
                                          &self.bccx.loan_path_to_string(move_path));
                         err.span_label(
                             loan_span,
-                            &format!("borrow of `{}` occurs here",
+                            format!("borrow of `{}` occurs here",
                                     &self.bccx.loan_path_to_string(&loan_path))
                             );
                         err.span_label(
                             span,
-                            &format!("move into closure occurs here")
+                            "move into closure occurs here"
                             );
                         err
                     }
@@ -679,12 +679,12 @@ fn check_for_move_of_borrowed_path(&self,
                                          &self.bccx.loan_path_to_string(move_path));
                         err.span_label(
                             loan_span,
-                            &format!("borrow of `{}` occurs here",
+                            format!("borrow of `{}` occurs here",
                                     &self.bccx.loan_path_to_string(&loan_path))
                             );
                         err.span_label(
                             span,
-                            &format!("move out of `{}` occurs here",
+                            format!("move out of `{}` occurs here",
                                 &self.bccx.loan_path_to_string(move_path))
                             );
                         err
@@ -708,7 +708,7 @@ pub fn analyze_restrictions_on_use(&self,
         let mut ret = UseOk;
 
         self.each_in_scope_loan_affecting_path(
-            self.tcx().node_extent(expr_id), use_path, |loan| {
+            region::CodeExtent::Misc(expr_id), use_path, |loan| {
             if !compatible_borrow_kinds(loan.kind, borrow_kind) {
                 ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span);
                 false
@@ -822,7 +822,7 @@ fn check_assignment(&self,
 
         // Check that we don't invalidate any outstanding loans
         if let Some(loan_path) = opt_loan_path(&assignee_cmt) {
-            let scope = self.tcx().node_extent(assignment_id);
+            let scope = region::CodeExtent::Misc(assignment_id);
             self.each_in_scope_loan_affecting_path(scope, &loan_path, |loan| {
                 self.report_illegal_mutation(assignment_span, &loan_path, loan);
                 false
@@ -857,10 +857,10 @@ pub fn report_illegal_mutation(&self,
                          "cannot assign to `{}` because it is borrowed",
                          self.bccx.loan_path_to_string(loan_path))
             .span_label(loan.span,
-                       &format!("borrow of `{}` occurs here",
+                       format!("borrow of `{}` occurs here",
                                self.bccx.loan_path_to_string(loan_path)))
             .span_label(span,
-                       &format!("assignment to borrowed `{}` occurs here",
+                       format!("assignment to borrowed `{}` occurs here",
                                self.bccx.loan_path_to_string(loan_path)))
             .emit();
     }
index 12854d3c9792251d54f4a3ff040c2a64c827285b..5fc5682a60b456c38ba9f22e5745839b3e3cd6b5 100644 (file)
@@ -24,7 +24,7 @@
 type R = Result<(),()>;
 
 pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
-                                    item_scope: region::CodeExtent<'tcx>,
+                                    item_scope: region::CodeExtent,
                                     span: Span,
                                     cause: euv::LoanCause,
                                     cmt: mc::cmt<'tcx>,
@@ -52,7 +52,7 @@ struct GuaranteeLifetimeContext<'a, 'tcx: 'a> {
     bccx: &'a BorrowckCtxt<'a, 'tcx>,
 
     // the scope of the function body for the enclosing item
-    item_scope: region::CodeExtent<'tcx>,
+    item_scope: region::CodeExtent,
 
     span: Span,
     cause: euv::LoanCause,
index 8c1bcdc1fe2b0f4cdefcfcdcedcf4ae2bc7da21b..4cfee36359cd7576522dc4a871cbf339741b5d24 100644 (file)
@@ -45,7 +45,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         bccx: bccx,
         infcx: &infcx,
         all_loans: Vec::new(),
-        item_ub: bccx.tcx.node_extent(body.node_id),
+        item_ub: region::CodeExtent::Misc(body.node_id),
         move_data: MoveData::new(),
         move_error_collector: move_error::MoveErrorCollector::new(),
     };
@@ -66,7 +66,7 @@ struct GatherLoanCtxt<'a, 'tcx: 'a> {
     all_loans: Vec<Loan<'tcx>>,
     /// `item_ub` is used as an upper-bound on the lifetime whenever we
     /// ask for the scope of an expression categorized as an upvar.
-    item_ub: region::CodeExtent<'tcx>,
+    item_ub: region::CodeExtent,
 }
 
 impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
@@ -353,13 +353,18 @@ fn guarantee_valid(&mut self,
                 let loan_scope = match *loan_region {
                     ty::ReScope(scope) => scope,
 
-                    ty::ReFree(ref fr) => fr.scope.unwrap_or(self.item_ub),
+                    ty::ReEarlyBound(ref br) => {
+                        self.bccx.region_maps.early_free_extent(self.tcx(), br)
+                    }
+
+                    ty::ReFree(ref fr) => {
+                        self.bccx.region_maps.free_extent(self.tcx(), fr)
+                    }
 
                     ty::ReStatic => self.item_ub,
 
                     ty::ReEmpty |
                     ty::ReLateBound(..) |
-                    ty::ReEarlyBound(..) |
                     ty::ReVar(..) |
                     ty::ReSkolemized(..) |
                     ty::ReErased => {
@@ -371,7 +376,7 @@ fn guarantee_valid(&mut self,
                 };
                 debug!("loan_scope = {:?}", loan_scope);
 
-                let borrow_scope = self.tcx().node_extent(borrow_id);
+                let borrow_scope = region::CodeExtent::Misc(borrow_id);
                 let gen_scope = self.compute_gen_scope(borrow_scope, loan_scope);
                 debug!("gen_scope = {:?}", gen_scope);
 
@@ -450,9 +455,9 @@ pub fn mark_loan_path_as_mutated(&self, loan_path: &LoanPath) {
     }
 
     pub fn compute_gen_scope(&self,
-                             borrow_scope: region::CodeExtent<'tcx>,
-                             loan_scope: region::CodeExtent<'tcx>)
-                             -> region::CodeExtent<'tcx> {
+                             borrow_scope: region::CodeExtent,
+                             loan_scope: region::CodeExtent)
+                             -> region::CodeExtent {
         //! Determine when to introduce the loan. Typically the loan
         //! is introduced at the point of the borrow, but in some cases,
         //! notably method arguments, the loan may be introduced only
@@ -465,8 +470,8 @@ pub fn compute_gen_scope(&self,
         }
     }
 
-    pub fn compute_kill_scope(&self, loan_scope: region::CodeExtent<'tcx>, lp: &LoanPath<'tcx>)
-                              -> region::CodeExtent<'tcx> {
+    pub fn compute_kill_scope(&self, loan_scope: region::CodeExtent, lp: &LoanPath<'tcx>)
+                              -> region::CodeExtent {
         //! Determine when the loan restrictions go out of scope.
         //! This is either when the lifetime expires or when the
         //! local variable which roots the loan-path goes out of scope,
index b7ce9d982331c92a80b8e61c1154ece340dcf824..1ee6d565d0d7debd0718f06e5382d62f7b3cc776 100644 (file)
@@ -94,7 +94,7 @@ fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, errors: &Vec<Move
         }
         if let NoteClosureEnv(upvar_id) = error.move_from.note {
             err.span_label(bccx.tcx.hir.span(upvar_id.var_id),
-                           &"captured outer variable");
+                           "captured outer variable");
         }
         err.emit();
 
@@ -147,7 +147,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                              move_from.descriptive_string(bccx.tcx));
             err.span_label(
                 move_from.span,
-                &format!("cannot move out of {}", move_from.descriptive_string(bccx.tcx))
+                format!("cannot move out of {}", move_from.descriptive_string(bccx.tcx))
                 );
             err
         }
@@ -160,7 +160,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                                    "cannot move out of type `{}`, \
                                                     a non-copy array",
                                                    b.ty);
-                    err.span_label(move_from.span, &format!("cannot move out of here"));
+                    err.span_label(move_from.span, "cannot move out of here");
                     err
                 }
                 (_, Kind::Pattern) => {
@@ -177,7 +177,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                                    "cannot move out of type `{}`, \
                                                    which implements the `Drop` trait",
                                                    b.ty);
-                    err.span_label(move_from.span, &format!("cannot move out of here"));
+                    err.span_label(move_from.span, "cannot move out of here");
                     err
                 },
                 _ => {
@@ -198,12 +198,12 @@ fn note_move_destination(mut err: DiagnosticBuilder,
     if is_first_note {
         err.span_label(
             move_to_span,
-            &format!("hint: to prevent move, use `ref {0}` or `ref mut {0}`",
+            format!("hint: to prevent move, use `ref {0}` or `ref mut {0}`",
                      pat_name));
         err
     } else {
         err.span_label(move_to_span,
-                      &format!("...and here (use `ref {0}` or `ref mut {0}`)",
+                      format!("...and here (use `ref {0}` or `ref mut {0}`)",
                                pat_name));
         err
     }
index 4ae8bdc284b226760c17ddcd924f71e715679711..520a90d940b3912d292448891e569244063cefef 100644 (file)
@@ -44,7 +44,7 @@ fn run_pass<'a, 'tcx>(&self,
             _ => return
         }
         let id = src.item_id();
-        let param_env = ty::ParameterEnvironment::for_item(tcx, id);
+        let param_env = tcx.parameter_environment(tcx.hir.local_def_id(id));
         let move_data = MoveData::gather_moves(mir, tcx, &param_env);
         let elaborate_patch = {
             let mir = &*mir;
@@ -517,11 +517,11 @@ fn elaborate_replace(
     }
 
     fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
-        Rvalue::Use(Operand::Constant(Constant {
+        Rvalue::Use(Operand::Constant(Box::new(Constant {
             span: span,
             ty: self.tcx.types.bool,
             literal: Literal::Value { value: ConstVal::Bool(val) }
-        }))
+        })))
     }
 
     fn set_drop_flag(&mut self, loc: Location, path: MovePathIndex, val: DropFlagState) {
index 47f708bf58367215e64ba9b9e25e0a57f1425471..fbaa60f84450b26f4596bb99728af967f47344ba 100644 (file)
@@ -65,7 +65,7 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
     // steals it, but it forces the `borrowck` query.
     let mir = &tcx.mir_validated(def_id).borrow();
 
-    let param_env = ty::ParameterEnvironment::for_item(tcx, id);
+    let param_env = tcx.parameter_environment(def_id);
     let move_data = MoveData::gather_moves(mir, tcx, &param_env);
     let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
     let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
index f8073455bd08ad422077ffd583228274fa7aa002..99df1431265084b80f8307a2c3734f1f28b922dd 100644 (file)
@@ -208,7 +208,7 @@ pub struct BorrowckCtxt<'a, 'tcx: 'a> {
     // Some in `borrowck_fn` and cleared later
     tables: &'a ty::TypeckTables<'tcx>,
 
-    region_maps: Rc<RegionMaps<'tcx>>,
+    region_maps: Rc<RegionMaps>,
 
     owner_def_id: DefId,
 }
@@ -228,13 +228,13 @@ pub struct Loan<'tcx> {
     /// cases, notably method arguments, the loan may be introduced
     /// only later, once it comes into scope.  See also
     /// `GatherLoanCtxt::compute_gen_scope`.
-    gen_scope: region::CodeExtent<'tcx>,
+    gen_scope: region::CodeExtent,
 
     /// kill_scope indicates when the loan goes out of scope.  This is
     /// either when the lifetime expires or when the local variable
     /// which roots the loan-path goes out of scope, whichever happens
     /// faster. See also `GatherLoanCtxt::compute_kill_scope`.
-    kill_scope: region::CodeExtent<'tcx>,
+    kill_scope: region::CodeExtent,
     span: Span,
     cause: euv::LoanCause,
 }
@@ -334,12 +334,12 @@ pub fn closure_to_block(closure_id: ast::NodeId,
 }
 
 impl<'a, 'tcx> LoanPath<'tcx> {
-    pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::CodeExtent<'tcx> {
+    pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::CodeExtent {
         match self.kind {
             LpVar(local_id) => bccx.region_maps.var_scope(local_id),
             LpUpvar(upvar_id) => {
                 let block_id = closure_to_block(upvar_id.closure_expr_id, bccx.tcx);
-                bccx.tcx.node_extent(block_id)
+                region::CodeExtent::Misc(block_id)
             }
             LpDowncast(ref base, _) |
             LpExtend(ref base, ..) => base.kill_scope(bccx),
@@ -513,6 +513,8 @@ pub fn report(&self, err: BckError<'tcx>) {
         match (&err.code, &err.cause) {
             (&err_out_of_scope(&ty::ReScope(_), &ty::ReStatic, _),
              &BorrowViolation(euv::ClosureCapture(span))) |
+            (&err_out_of_scope(&ty::ReScope(_), &ty::ReEarlyBound(..), _),
+             &BorrowViolation(euv::ClosureCapture(span))) |
             (&err_out_of_scope(&ty::ReScope(_), &ty::ReFree(..), _),
              &BorrowViolation(euv::ClosureCapture(span))) => {
                 return self.report_out_of_scope_escaping_closure_capture(&err, span);
@@ -546,7 +548,7 @@ pub fn report_use_of_moved_value(&self,
                     "{} of possibly uninitialized variable: `{}`",
                     verb,
                     self.loan_path_to_string(lp))
-                .span_label(use_span, &format!("use of possibly uninitialized `{}`",
+                .span_label(use_span, format!("use of possibly uninitialized `{}`",
                     self.loan_path_to_string(lp)))
                 .emit();
                 return;
@@ -616,12 +618,12 @@ pub fn report_use_of_moved_value(&self,
         err = if use_span == move_span {
             err.span_label(
                 use_span,
-                &format!("value moved{} here in previous iteration of loop",
+                format!("value moved{} here in previous iteration of loop",
                          move_note));
             err
         } else {
-            err.span_label(use_span, &format!("value {} here after move", verb_participle))
-               .span_label(move_span, &format!("value moved{} here", move_note));
+            err.span_label(use_span, format!("value {} here after move", verb_participle))
+               .span_label(move_span, format!("value moved{} here", move_note));
             err
         };
 
@@ -657,9 +659,9 @@ pub fn report_reassigned_immutable_variable(&self,
             self.tcx.sess, span, E0384,
             "re-assignment of immutable variable `{}`",
             self.loan_path_to_string(lp));
-        err.span_label(span, &format!("re-assignment of immutable variable"));
+        err.span_label(span, "re-assignment of immutable variable");
         if span != assign.span {
-            err.span_label(assign.span, &format!("first assignment to `{}`",
+            err.span_label(assign.span, format!("first assignment to `{}`",
                                               self.loan_path_to_string(lp)));
         }
         err.emit();
@@ -821,7 +823,7 @@ pub fn report_aliasability_violation(&self,
                 let mut err = struct_span_err!(
                     self.tcx.sess, span, E0389,
                     "{} in a `&` reference", prefix);
-                err.span_label(span, &"assignment into an immutable reference");
+                err.span_label(span, "assignment into an immutable reference");
                 err
             }
         };
@@ -914,7 +916,7 @@ fn note_immutability_blame(&self,
                         }
                         db.span_label(
                             let_span,
-                            &format!("consider changing this to `mut {}`", snippet)
+                            format!("consider changing this to `mut {}`", snippet)
                         );
                     }
                 }
@@ -927,7 +929,7 @@ fn note_immutability_blame(&self,
                         if let Ok(snippet) = snippet {
                             db.span_label(
                                 let_span,
-                                &format!("consider changing this to `{}`",
+                                format!("consider changing this to `{}`",
                                          snippet.replace("ref ", "ref mut "))
                             );
                         }
@@ -936,7 +938,7 @@ fn note_immutability_blame(&self,
                         if let (Some(local_ty), is_implicit_self) = self.local_ty(node_id) {
                             if let Some(msg) =
                                  self.suggest_mut_for_immutable(local_ty, is_implicit_self) {
-                                db.span_label(local_ty.span, &msg);
+                                db.span_label(local_ty.span, msg);
                             }
                         }
                     }
@@ -950,7 +952,7 @@ fn note_immutability_blame(&self,
 
                 if let hir_map::Node::NodeField(ref field) = self.tcx.hir.get(node_id) {
                     if let Some(msg) = self.suggest_mut_for_immutable(&field.ty, false) {
-                        db.span_label(field.ty.span, &msg);
+                        db.span_label(field.ty.span, msg);
                     }
                 }
             }
@@ -975,10 +977,10 @@ fn report_out_of_scope_escaping_closure_capture(&self,
                           which is owned by the current function",
                          cmt_path_or_string)
             .span_label(capture_span,
-                       &format!("{} is borrowed here",
+                       format!("{} is borrowed here",
                                 cmt_path_or_string))
             .span_label(err.span,
-                       &format!("may outlive borrowed value {}",
+                       format!("may outlive borrowed value {}",
                                 cmt_path_or_string))
             .span_suggestion(err.span,
                              &format!("to force the closure to take ownership of {} \
@@ -1029,15 +1031,15 @@ fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<'tcx
                         match db.span.primary_span() {
                             Some(primary) => {
                                 db.span = MultiSpan::from_span(s);
-                                db.span_label(primary, &format!("capture occurs here"));
-                                db.span_label(s, &"does not live long enough");
+                                db.span_label(primary, "capture occurs here");
+                                db.span_label(s, "does not live long enough");
                                 true
                             }
                             None => false
                         }
                     }
                     _ => {
-                        db.span_label(error_span, &"does not live long enough");
+                        db.span_label(error_span, "does not live long enough");
                         false
                     }
                 };
@@ -1049,7 +1051,7 @@ fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<'tcx
                     (Some(s1), Some(s2)) if s1 == s2 => {
                         if !is_closure {
                             db.span = MultiSpan::from_span(s1);
-                            db.span_label(error_span, &value_msg);
+                            db.span_label(error_span, value_msg);
                             let msg = match opt_loan_path(&err.cmt) {
                                 None => value_kind.to_string(),
                                 Some(lp) => {
@@ -1057,29 +1059,29 @@ fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<'tcx
                                 }
                             };
                             db.span_label(s1,
-                                          &format!("{} dropped here while still borrowed", msg));
+                                          format!("{} dropped here while still borrowed", msg));
                         } else {
-                            db.span_label(s1, &format!("{} dropped before borrower", value_kind));
+                            db.span_label(s1, format!("{} dropped before borrower", value_kind));
                         }
                         db.note("values in a scope are dropped in the opposite order \
                                 they are created");
                     }
                     (Some(s1), Some(s2)) if !is_closure => {
                         db.span = MultiSpan::from_span(s2);
-                        db.span_label(error_span, &value_msg);
+                        db.span_label(error_span, value_msg);
                         let msg = match opt_loan_path(&err.cmt) {
                             None => value_kind.to_string(),
                             Some(lp) => {
                                 format!("`{}`", self.loan_path_to_string(&lp))
                             }
                         };
-                        db.span_label(s2, &format!("{} dropped here while still borrowed", msg));
-                        db.span_label(s1, &format!("{} needs to live until here", value_kind));
+                        db.span_label(s2, format!("{} dropped here while still borrowed", msg));
+                        db.span_label(s1, format!("{} needs to live until here", value_kind));
                     }
                     _ => {
                         match sub_span {
                             Some(s) => {
-                                db.span_label(s, &format!("{} needs to live until here",
+                                db.span_label(s, format!("{} needs to live until here",
                                                           value_kind));
                             }
                             None => {
@@ -1092,7 +1094,7 @@ fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<'tcx
                         }
                         match super_span {
                             Some(s) => {
-                                db.span_label(s, &format!("{} only lives until here", value_kind));
+                                db.span_label(s, format!("{} only lives until here", value_kind));
                             }
                             None => {
                                 self.tcx.note_and_explain_region(
@@ -1162,23 +1164,23 @@ fn note_and_explain_mutbl_error(&self, db: &mut DiagnosticBuilder, err: &BckErro
             }
             _ => {
                 if let Categorization::Deref(..) = err.cmt.cat {
-                    db.span_label(*error_span, &"cannot borrow as mutable");
+                    db.span_label(*error_span, "cannot borrow as mutable");
                 } else if let Categorization::Local(local_id) = err.cmt.cat {
                     let span = self.tcx.hir.span(local_id);
                     if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
                         if snippet.starts_with("ref mut ") || snippet.starts_with("&mut ") {
-                            db.span_label(*error_span, &format!("cannot reborrow mutably"));
-                            db.span_label(*error_span, &format!("try removing `&mut` here"));
+                            db.span_label(*error_span, "cannot reborrow mutably");
+                            db.span_label(*error_span, "try removing `&mut` here");
                         } else {
-                            db.span_label(*error_span, &format!("cannot borrow mutably"));
+                            db.span_label(*error_span, "cannot borrow mutably");
                         }
                     } else {
-                        db.span_label(*error_span, &format!("cannot borrow mutably"));
+                        db.span_label(*error_span, "cannot borrow mutably");
                     }
                 } else if let Categorization::Interior(ref cmt, _) = err.cmt.cat {
                     if let mc::MutabilityCategory::McImmutable = cmt.mutbl {
                         db.span_label(*error_span,
-                                      &"cannot mutably borrow immutable field");
+                                      "cannot mutably borrow immutable field");
                     }
                 }
             }
index a1d3357faf56684931ee9e2899c59e93bb665555..617326808970ba082a763ee66b15075dd0df4f94 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![crate_name = "rustc_borrowck"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
 #![feature(associated_consts)]
 #![feature(nonzero)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
 extern crate syntax_pos;
index 6ec5f38aa5bb529c94ac7d9edc7ba133e68c3b35..a18f91a9ee391408f069981f119d09ead357e618 100644 (file)
@@ -46,14 +46,13 @@ fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
                 b: hir::BodyId, s: Span, id: ast::NodeId) {
         intravisit::walk_fn(self, fk, fd, b, s, id);
 
-        let region_context = self.tcx.hir.local_def_id(id);
-        let region_maps = self.tcx.region_maps(region_context);
+        let def_id = self.tcx.hir.local_def_id(id);
 
         MatchVisitor {
             tcx: self.tcx,
             tables: self.tcx.body_tables(b),
-            region_maps: &region_maps,
-            param_env: &ty::ParameterEnvironment::for_item(self.tcx, id)
+            region_maps: &self.tcx.region_maps(def_id),
+            param_env: &self.tcx.parameter_environment(def_id)
         }.visit_body(self.tcx.hir.body(b));
     }
 }
@@ -71,7 +70,7 @@ struct MatchVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
     param_env: &'a ty::ParameterEnvironment<'tcx>,
-    region_maps: &'a RegionMaps<'tcx>,
+    region_maps: &'a RegionMaps,
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
@@ -258,7 +257,7 @@ fn check_irrefutable(&self, pat: &Pat, is_fn_arg: bool) {
                 "refutable pattern in {}: `{}` not covered",
                 origin, pattern_string
             );
-            diag.span_label(pat.span, &format!("pattern `{}` not covered", pattern_string));
+            diag.span_label(pat.span, format!("pattern `{}` not covered", pattern_string));
             diag.emit();
         });
     }
@@ -328,7 +327,7 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                                 let span = first_pat.0.span;
                                 struct_span_err!(cx.tcx.sess, span, E0162,
                                                 "irrefutable if-let pattern")
-                                    .span_label(span, &format!("irrefutable pattern"))
+                                    .span_label(span, "irrefutable pattern")
                                     .emit();
                                 printed_if_let_err = true;
                             }
@@ -355,7 +354,7 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                                 1 => {
                                     struct_span_err!(cx.tcx.sess, span, E0165,
                                                      "irrefutable while-let pattern")
-                                        .span_label(span, &format!("irrefutable pattern"))
+                                        .span_label(span, "irrefutable pattern")
                                         .emit();
                                 },
                                 _ => bug!(),
@@ -369,7 +368,7 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                             diagnostic.set_span(pat.span);
                             // if we had a catchall pattern, hint at that
                             if let Some(catchall) = catchall {
-                                diagnostic.span_label(pat.span, &"this is an unreachable pattern");
+                                diagnostic.span_label(pat.span, "this is an unreachable pattern");
                                 diagnostic.span_note(catchall, "this pattern matches any value");
                             }
                             cx.tcx.sess.add_lint_diagnostic(lint::builtin::UNREACHABLE_PATTERNS,
@@ -426,7 +425,7 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                         "refutable pattern in `for` loop binding: \
                                 `{}` not covered",
                                 pattern_string)
-                        .span_label(sp, &format!("pattern `{}` not covered", pattern_string))
+                        .span_label(sp, format!("pattern `{}` not covered", pattern_string))
                         .emit();
                 },
                 _ => {
@@ -453,7 +452,7 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                     create_e0004(cx.tcx.sess, sp,
                                  format!("non-exhaustive patterns: {} not covered",
                                          joined_patterns))
-                        .span_label(sp, &label_text)
+                        .span_label(sp, label_text)
                         .emit();
                 },
             }
@@ -485,18 +484,18 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
         if sub.map_or(false, |p| p.contains_bindings()) {
             struct_span_err!(cx.tcx.sess, p.span, E0007,
                              "cannot bind by-move with sub-bindings")
-                .span_label(p.span, &format!("binds an already bound by-move value by moving it"))
+                .span_label(p.span, "binds an already bound by-move value by moving it")
                 .emit();
         } else if has_guard {
             struct_span_err!(cx.tcx.sess, p.span, E0008,
                       "cannot bind by-move into a pattern guard")
-                .span_label(p.span, &format!("moves value into pattern guard"))
+                .span_label(p.span, "moves value into pattern guard")
                 .emit();
         } else if by_ref_span.is_some() {
             struct_span_err!(cx.tcx.sess, p.span, E0009,
                             "cannot bind by-move and by-ref in the same pattern")
-                    .span_label(p.span, &format!("by-move pattern here"))
-                    .span_label(by_ref_span.unwrap(), &format!("both by-ref and by-move used"))
+                    .span_label(p.span, "by-move pattern here")
+                    .span_label(by_ref_span.unwrap(), "both by-ref and by-move used")
                     .emit();
         }
     };
@@ -546,7 +545,7 @@ fn borrow(&mut self,
             ty::MutBorrow => {
                 struct_span_err!(self.cx.tcx.sess, span, E0301,
                           "cannot mutably borrow in a pattern guard")
-                    .span_label(span, &format!("borrowed mutably in pattern guard"))
+                    .span_label(span, "borrowed mutably in pattern guard")
                     .emit();
             }
             ty::ImmBorrow | ty::UniqueImmBorrow => {}
@@ -557,7 +556,7 @@ fn mutate(&mut self, _: ast::NodeId, span: Span, _: cmt, mode: MutateMode) {
         match mode {
             MutateMode::JustWrite | MutateMode::WriteAndRead => {
                 struct_span_err!(self.cx.tcx.sess, span, E0302, "cannot assign in a pattern guard")
-                    .span_label(span, &format!("assignment in pattern guard"))
+                    .span_label(span, "assignment in pattern guard")
                     .emit();
             }
             MutateMode::Init => {}
@@ -588,7 +587,7 @@ fn visit_pat(&mut self, pat: &Pat) {
                 if !self.bindings_allowed {
                     struct_span_err!(self.cx.tcx.sess, pat.span, E0303,
                                      "pattern bindings are not allowed after an `@`")
-                        .span_label(pat.span,  &format!("not allowed after `@`"))
+                        .span_label(pat.span,  "not allowed after `@`")
                         .emit();
                 }
 
index 8b1aa0708807bc4284b8b7f8bad0c09840e7ec70..e79f23aee11456e2fd3f3ce35f7e72a95f45d1ca 100644 (file)
@@ -74,7 +74,7 @@ pub fn lookup_const_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 // constants, we only try to find the expression for a
                 // trait-associated const if the caller gives us the
                 // substitutions for the reference to it.
-                if tcx.sess.cstore.trait_of_item(def_id).is_some() {
+                if tcx.trait_of_item(def_id).is_some() {
                     resolve_trait_associated_const(tcx, def_id, substs)
                 } else {
                     Some((def_id, substs))
index fa3161a860498c17dd866295a008c25e86e66e63..8142829e81601ebba952ec5d57e7df90cc39a443 100644 (file)
@@ -15,7 +15,6 @@
 //! This API is completely unstable and subject to change.
 
 #![crate_name = "rustc_const_eval"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -23,8 +22,6 @@
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![deny(warnings)]
 
-#![feature(rustc_private)]
-#![feature(staged_api)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
 #![feature(box_patterns)]
 #![feature(const_fn)]
 #![feature(i128_type)]
 
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
 extern crate arena;
 #[macro_use] extern crate syntax;
 #[macro_use] extern crate log;
index b7833a5440321221eb934a00ef08fd675550cfcc..528170781ea7519cb1a3cf75d205bf8e48373e80 100644 (file)
@@ -15,7 +15,6 @@
 //! This API is completely unstable and subject to change.
 
 #![crate_name = "rustc_const_math"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![deny(warnings)]
 
-#![feature(rustc_private)]
-#![feature(staged_api)]
 #![feature(const_fn)]
 #![feature(i128)]
 #![feature(i128_type)]
 
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
 extern crate syntax;
 
 extern crate serialize as rustc_serialize; // used by deriving
index 00c46d992bfd5a05498e6b58b5c84f40b1952a0a..c254dfc48d22549da834a03de2cbb999e479bb53 100644 (file)
@@ -17,7 +17,6 @@
 //! This API is completely unstable and subject to change.
 
 #![crate_name = "rustc_data_structures"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -28,8 +27,6 @@
 #![feature(shared)]
 #![feature(collections_range)]
 #![feature(nonzero)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
 #![feature(unboxed_closures)]
 #![feature(fn_traits)]
 #![feature(untagged_unions)]
 #![feature(manually_drop)]
 #![feature(struct_field_attributes)]
 
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
 #![cfg_attr(unix, feature(libc))]
 #![cfg_attr(test, feature(test))]
 
index 95f063976d491018a44cc55c149d40dec931a1ed..635b95d861dafec9e88a401952c96f31222ce5f2 100644 (file)
@@ -283,6 +283,16 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
+
+impl<CTX> HashStable<CTX> for String {
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        (&self[..]).hash_stable(hcx, hasher);
+    }
+}
+
 impl<CTX> HashStable<CTX> for bool {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
index 5b5113caa8e8c0dd9d68e7e8078b71991efa107e..2e949f48c175ee7e44c9126d771043367b352e30 100644 (file)
@@ -22,7 +22,6 @@ rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_incremental = { path = "../librustc_incremental" }
 rustc_lint = { path = "../librustc_lint" }
-rustc_llvm = { path = "../librustc_llvm" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_mir = { path = "../librustc_mir" }
 rustc_passes = { path = "../librustc_passes" }
index 9f0f567b6cee1b5519db89074683098de89e1d4a..bca82ff9a46dfb803dfa7ec8947763c66ad5a468 100644 (file)
@@ -22,6 +22,7 @@
 use rustc::middle::privacy::AccessLevels;
 use rustc::mir::transform::{MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED, Passes};
 use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
+use rustc::traits;
 use rustc::util::common::time;
 use rustc::util::nodemap::NodeSet;
 use rustc::util::fs::rename_or_copy_remove;
@@ -699,6 +700,8 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
 
         let krate = ecx.monotonic_expander().expand_crate(krate);
 
+        ecx.check_unused_macros();
+
         let mut missing_fragment_specifiers: Vec<_> =
             ecx.parse_sess.missing_fragment_specifiers.borrow().iter().cloned().collect();
         missing_fragment_specifiers.sort();
@@ -882,7 +885,7 @@ macro_rules! try_with_f {
               "static item recursion checking",
               || static_recursion::check_crate(sess, &hir_map))?;
 
-    let index = stability::Index::new(&hir_map);
+    let index = stability::Index::new(&sess);
 
     let mut local_providers = ty::maps::Providers::default();
     borrowck::provide(&mut local_providers);
@@ -892,6 +895,7 @@ macro_rules! try_with_f {
     trans::provide(&mut local_providers);
     typeck::provide(&mut local_providers);
     ty::provide(&mut local_providers);
+    traits::provide(&mut local_providers);
     reachable::provide(&mut local_providers);
     rustc_const_eval::provide(&mut local_providers);
     middle::region::provide(&mut local_providers);
@@ -900,6 +904,7 @@ macro_rules! try_with_f {
     cstore::provide(&mut extern_providers);
     trans::provide(&mut extern_providers);
     ty::provide_extern(&mut extern_providers);
+    traits::provide_extern(&mut extern_providers);
     // FIXME(eddyb) get rid of this once we replace const_eval with miri.
     rustc_const_eval::provide(&mut extern_providers);
 
@@ -1155,8 +1160,7 @@ fn write_out_deps(sess: &Session, outputs: &OutputFilenames, crate_name: &str) {
             // Build a list of files used to compile the output and
             // write Makefile-compatible dependency rules
             let files: Vec<String> = sess.codemap()
-                                         .files
-                                         .borrow()
+                                         .files()
                                          .iter()
                                          .filter(|fmap| fmap.is_real_file())
                                          .filter(|fmap| !fmap.is_imported())
index 889f4dd4b9aac9d3c526ffff8863a0f84e4b0a30..34f636d0b9a12db2225e9c212d5c390b3e9309fc 100644 (file)
@@ -15,7 +15,6 @@
 //! This API is completely unstable and subject to change.
 
 #![crate_name = "rustc_driver"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 #![feature(libc)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
 #![feature(set_stdio)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
 
 extern crate arena;
 extern crate getopts;
@@ -55,7 +56,6 @@
 extern crate rustc_trans;
 extern crate rustc_typeck;
 extern crate serialize;
-extern crate rustc_llvm as llvm;
 #[macro_use]
 extern crate log;
 extern crate syntax;
@@ -69,7 +69,7 @@
 use rustc_save_analysis as save;
 use rustc_save_analysis::DumpHandler;
 use rustc_trans::back::link;
-use rustc_trans::back::write::{create_target_machine, RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS};
+use rustc_trans::back::write::{RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS};
 use rustc::dep_graph::DepGraph;
 use rustc::session::{self, config, Session, build_session, CompileResult};
 use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType};
@@ -181,7 +181,7 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
     let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
 
     if sopts.debugging_opts.debug_llvm {
-        unsafe { llvm::LLVMRustSetDebug(1); }
+        rustc_trans::enable_llvm_debug();
     }
 
     let descriptions = diagnostics_registry();
@@ -203,13 +203,14 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
     };
 
     let dep_graph = DepGraph::new(sopts.build_dep_graph());
-    let cstore = Rc::new(CStore::new(&dep_graph));
+    let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
 
     let loader = file_loader.unwrap_or(box RealFileLoader);
     let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
     let mut sess = session::build_session_with_codemap(
         sopts, &dep_graph, input_file_path, descriptions, cstore.clone(), codemap, emitter_dest,
     );
+    rustc_trans::init(&sess);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
     let mut cfg = config::build_configuration(&sess, cfg);
@@ -408,12 +409,13 @@ fn no_input(&mut self,
                     return None;
                 }
                 let dep_graph = DepGraph::new(sopts.build_dep_graph());
-                let cstore = Rc::new(CStore::new(&dep_graph));
+                let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
                 let mut sess = build_session(sopts.clone(),
                     &dep_graph,
                     None,
                     descriptions.clone(),
                     cstore.clone());
+                rustc_trans::init(&sess);
                 rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
                 let mut cfg = config::build_configuration(&sess, cfg.clone());
                 target_features::add_configuration(&mut cfg, &sess);
@@ -557,7 +559,11 @@ pub fn list_metadata(sess: &Session, matches: &getopts::Matches, input: &Input)
                 &Input::File(ref ifile) => {
                     let path = &(*ifile);
                     let mut v = Vec::new();
-                    locator::list_file_metadata(&sess.target.target, path, &mut v).unwrap();
+                    locator::list_file_metadata(&sess.target.target,
+                                                path,
+                                                sess.cstore.metadata_loader(),
+                                                &mut v)
+                            .unwrap();
                     println!("{}", String::from_utf8(v).unwrap());
                 }
                 &Input::Str { .. } => {
@@ -635,11 +641,24 @@ fn print_crate_info(sess: &Session,
                             node: ast::MetaItemKind::Word,
                             span: DUMMY_SP,
                         });
-                        if !allow_unstable_cfg && gated_cfg.is_some() {
-                            continue;
+
+                        // Note that crt-static is a specially recognized cfg
+                        // directive that's printed out here as part of
+                        // rust-lang/rust#37406, but in general the
+                        // `target_feature` cfg is gated under
+                        // rust-lang/rust#29717. For now this is just
+                        // specifically allowing the crt-static cfg and that's
+                        // it, this is intended to get into Cargo and then go
+                        // through to build scripts.
+                        let value = value.as_ref().map(|s| s.as_str());
+                        let value = value.as_ref().map(|s| s.as_ref());
+                        if name != "target_feature" || value != Some("crt-static") {
+                            if !allow_unstable_cfg && gated_cfg.is_some() {
+                                continue;
+                            }
                         }
 
-                        cfgs.push(if let &Some(ref value) = value {
+                        cfgs.push(if let Some(value) = value {
                             format!("{}=\"{}\"", name, value)
                         } else {
                             format!("{}", name)
@@ -651,14 +670,6 @@ fn print_crate_info(sess: &Session,
                         println!("{}", cfg);
                     }
                 }
-                PrintRequest::TargetCPUs => {
-                    let tm = create_target_machine(sess);
-                    unsafe { llvm::LLVMRustPrintTargetCPUs(tm); }
-                }
-                PrintRequest::TargetFeatures => {
-                    let tm = create_target_machine(sess);
-                    unsafe { llvm::LLVMRustPrintTargetFeatures(tm); }
-                }
                 PrintRequest::RelocationModels => {
                     println!("Available relocation models:");
                     for &(name, _) in RELOC_MODEL_ARGS.iter() {
@@ -673,6 +684,9 @@ fn print_crate_info(sess: &Session,
                     }
                     println!("");
                 }
+                PrintRequest::TargetCPUs | PrintRequest::TargetFeatures => {
+                    rustc_trans::print(*req, sess);
+                }
             }
         }
         return Compilation::Stop;
@@ -710,10 +724,7 @@ fn unw(x: Option<&str>) -> &str {
         println!("commit-date: {}", unw(commit_date_str()));
         println!("host: {}", config::host_triple());
         println!("release: {}", unw(release_str()));
-        unsafe {
-            println!("LLVM version: {}.{}",
-                     llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
-        }
+        rustc_trans::print_version();
     }
 }
 
@@ -1006,9 +1017,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
     }
 
     if cg_flags.contains(&"passes=list".to_string()) {
-        unsafe {
-            ::llvm::LLVMRustPrintPasses();
-        }
+        rustc_trans::print_passes();
         return None;
     }
 
index 4f3abbb362ff90ff1b3a5315cff8408708b093ff..bee61bb398029756511fcc1a2300c1209b9ac618 100644 (file)
@@ -9,23 +9,9 @@
 // except according to those terms.
 
 use syntax::ast;
-use llvm::LLVMRustHasFeature;
 use rustc::session::Session;
-use rustc_trans::back::write::create_target_machine;
-use syntax::feature_gate::UnstableFeatures;
 use syntax::symbol::Symbol;
-use libc::c_char;
-
-// WARNING: the features must be known to LLVM or the feature
-// detection code will walk past the end of the feature array,
-// leading to crashes.
-
-const ARM_WHITELIST: &'static [&'static str] = &["neon\0", "vfp2\0", "vfp3\0", "vfp4\0"];
-
-const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0",
-                                                 "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0",
-                                                 "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0",
-                                                 "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0"];
+use rustc_trans;
 
 /// Add `target_feature = "..."` cfgs for a variety of platform
 /// specific features (SSE, NEON etc.).
 /// This is performed by checking whether a whitelisted set of
 /// features is available on the target machine, by querying LLVM.
 pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) {
-    let target_machine = create_target_machine(sess);
-
-    let whitelist = match &*sess.target.target.arch {
-        "arm" => ARM_WHITELIST,
-        "x86" | "x86_64" => X86_WHITELIST,
-        _ => &[],
-    };
-
     let tf = Symbol::intern("target_feature");
-    for feat in whitelist {
-        assert_eq!(feat.chars().last(), Some('\0'));
-        if unsafe { LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } {
-            cfg.insert((tf, Some(Symbol::intern(&feat[..feat.len() - 1]))));
-        }
+
+    for feat in rustc_trans::target_features(sess) {
+        cfg.insert((tf, Some(feat)));
     }
 
     let requested_features = sess.opts.cg.target_feature.split(',');
-    let unstable_options = sess.opts.debugging_opts.unstable_options;
-    let is_nightly = UnstableFeatures::from_environment().is_nightly_build();
     let found_negative = requested_features.clone().any(|r| r == "-crt-static");
     let found_positive = requested_features.clone().any(|r| r == "+crt-static");
 
@@ -65,14 +39,6 @@ pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) {
         found_positive
     };
 
-    // If we switched from the default then that's only allowed on nightly, so
-    // gate that here.
-    if (found_positive || found_negative) && (!is_nightly || !unstable_options) {
-        sess.fatal("specifying the `crt-static` target feature is only allowed \
-                    on the nightly channel with `-Z unstable-options` passed \
-                    as well");
-    }
-
     if crt_static {
         cfg.insert((tf, Some(Symbol::intern("crt-static"))));
     }
index 8b95be00fa752cb50bf6c90b00641aff783579e4..1d236a96bf62ed97c313cfad34909734a9def2aa 100644 (file)
 use rustc::dep_graph::DepGraph;
 use rustc_lint;
 use rustc_resolve::MakeGlobMap;
+use rustc_trans;
 use rustc::middle::lang_items;
 use rustc::middle::free_region::FreeRegionMap;
 use rustc::middle::region::{CodeExtent, RegionMaps};
-use rustc::middle::region::CodeExtentData;
 use rustc::middle::resolve_lifetime;
 use rustc::middle::stability;
 use rustc::ty::subst::{Kind, Subst};
@@ -45,7 +45,7 @@
 
 struct Env<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     infcx: &'a infer::InferCtxt<'a, 'gcx, 'tcx>,
-    region_maps: &'a mut RegionMaps<'tcx>,
+    region_maps: &'a mut RegionMaps,
 }
 
 struct RH<'a> {
@@ -105,13 +105,14 @@ fn test_env<F>(source_string: &str,
 
     let dep_graph = DepGraph::new(false);
     let _ignore = dep_graph.in_ignore();
-    let cstore = Rc::new(CStore::new(&dep_graph));
+    let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
     let sess = session::build_session_(options,
                                        &dep_graph,
                                        None,
                                        diagnostic_handler,
                                        Rc::new(CodeMap::new(FilePathMapping::empty())),
                                        cstore.clone());
+    rustc_trans::init(&sess);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
     let input = config::Input::Str {
         name: driver::anon_src(),
@@ -138,7 +139,7 @@ fn test_env<F>(source_string: &str,
     // run just enough stuff to build a tcx:
     let lang_items = lang_items::collect_language_items(&sess, &hir_map);
     let named_region_map = resolve_lifetime::krate(&sess, &hir_map);
-    let index = stability::Index::new(&hir_map);
+    let index = stability::Index::new(&sess);
     TyCtxt::create_and_enter(&sess,
                              ty::maps::Providers::default(),
                              ty::maps::Providers::default(),
@@ -168,8 +169,8 @@ pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
         self.infcx.tcx
     }
 
-    pub fn create_region_hierarchy(&mut self, rh: &RH, parent: CodeExtent<'tcx>) {
-        let me = self.tcx().intern_code_extent(CodeExtentData::Misc(rh.id));
+    pub fn create_region_hierarchy(&mut self, rh: &RH, parent: CodeExtent) {
+        let me = CodeExtent::Misc(rh.id);
         self.region_maps.record_code_extent(me, Some(parent));
         for child_rh in rh.sub {
             self.create_region_hierarchy(child_rh, me);
@@ -181,7 +182,7 @@ pub fn create_simple_region_hierarchy(&mut self) {
         // children of 1, etc
 
         let node = ast::NodeId::from_u32;
-        let dscope = self.tcx().intern_code_extent(CodeExtentData::DestructionScope(node(1)));
+        let dscope = CodeExtent::DestructionScope(node(1));
         self.region_maps.record_code_extent(dscope, None);
         self.create_region_hierarchy(&RH {
                                          id: node(1),
@@ -296,8 +297,9 @@ pub fn t_param(&self, index: u32) -> Ty<'tcx> {
     pub fn re_early_bound(&self, index: u32, name: &'static str) -> ty::Region<'tcx> {
         let name = Symbol::intern(name);
         self.infcx.tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
-            index: index,
-            name: name,
+            def_id: self.infcx.tcx.hir.local_def_id(ast::CRATE_NODE_ID),
+            index,
+            name,
         }))
     }
 
@@ -326,19 +328,19 @@ pub fn t_rptr_late_bound_with_debruijn(&self,
     }
 
     pub fn t_rptr_scope(&self, id: u32) -> Ty<'tcx> {
-        let r = ty::ReScope(self.tcx().node_extent(ast::NodeId::from_u32(id)));
+        let r = ty::ReScope(CodeExtent::Misc(ast::NodeId::from_u32(id)));
         self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize)
     }
 
-    pub fn re_free(&self, nid: ast::NodeId, id: u32) -> ty::Region<'tcx> {
+    pub fn re_free(&self, id: u32) -> ty::Region<'tcx> {
         self.infcx.tcx.mk_region(ty::ReFree(ty::FreeRegion {
-            scope: Some(self.tcx().node_extent(nid)),
+            scope: self.infcx.tcx.hir.local_def_id(ast::CRATE_NODE_ID),
             bound_region: ty::BrAnon(id),
         }))
     }
 
-    pub fn t_rptr_free(&self, nid: u32, id: u32) -> Ty<'tcx> {
-        let r = self.re_free(ast::NodeId::from_u32(nid), id);
+    pub fn t_rptr_free(&self, id: u32) -> Ty<'tcx> {
+        let r = self.re_free(id);
         self.infcx.tcx.mk_imm_ref(r, self.tcx().types.isize)
     }
 
@@ -464,7 +466,7 @@ fn sub_free_bound_false() {
 
     test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
         env.create_simple_region_hierarchy();
-        let t_rptr_free1 = env.t_rptr_free(1, 1);
+        let t_rptr_free1 = env.t_rptr_free(1);
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         env.check_not_sub(env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
                           env.t_fn(&[t_rptr_bound1], env.tcx().types.isize));
@@ -482,7 +484,7 @@ fn sub_bound_free_true() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
         env.create_simple_region_hierarchy();
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
-        let t_rptr_free1 = env.t_rptr_free(1, 1);
+        let t_rptr_free1 = env.t_rptr_free(1);
         env.check_sub(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
                       env.t_fn(&[t_rptr_free1], env.tcx().types.isize));
     })
@@ -518,7 +520,7 @@ fn lub_free_bound_infer() {
         env.create_simple_region_hierarchy();
         let t_infer1 = env.infcx.next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP));
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
-        let t_rptr_free1 = env.t_rptr_free(1, 1);
+        let t_rptr_free1 = env.t_rptr_free(1);
         env.check_lub(env.t_fn(&[t_infer1], env.tcx().types.isize),
                       env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
                       env.t_fn(&[t_rptr_free1], env.tcx().types.isize));
@@ -541,7 +543,7 @@ fn lub_bound_free() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
         env.create_simple_region_hierarchy();
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
-        let t_rptr_free1 = env.t_rptr_free(1, 1);
+        let t_rptr_free1 = env.t_rptr_free(1);
         env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
                       env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
                       env.t_fn(&[t_rptr_free1], env.tcx().types.isize));
@@ -574,8 +576,8 @@ fn lub_bound_bound_inverse_order() {
 fn lub_free_free() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
         env.create_simple_region_hierarchy();
-        let t_rptr_free1 = env.t_rptr_free(1, 1);
-        let t_rptr_free2 = env.t_rptr_free(1, 2);
+        let t_rptr_free1 = env.t_rptr_free(1);
+        let t_rptr_free2 = env.t_rptr_free(2);
         let t_rptr_static = env.t_rptr_static();
         env.check_lub(env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
                       env.t_fn(&[t_rptr_free2], env.tcx().types.isize),
@@ -600,8 +602,8 @@ fn lub_returning_scope() {
 fn glb_free_free_with_common_scope() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
         env.create_simple_region_hierarchy();
-        let t_rptr_free1 = env.t_rptr_free(1, 1);
-        let t_rptr_free2 = env.t_rptr_free(1, 2);
+        let t_rptr_free1 = env.t_rptr_free(1);
+        let t_rptr_free2 = env.t_rptr_free(2);
         let t_rptr_scope = env.t_rptr_scope(1);
         env.check_glb(env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
                       env.t_fn(&[t_rptr_free2], env.tcx().types.isize),
@@ -625,7 +627,7 @@ fn glb_bound_free() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
         env.create_simple_region_hierarchy();
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
-        let t_rptr_free1 = env.t_rptr_free(1, 1);
+        let t_rptr_free1 = env.t_rptr_free(1);
         env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
                       env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
                       env.t_fn(&[t_rptr_bound1], env.tcx().types.isize));
@@ -751,7 +753,7 @@ fn escaping() {
 
         assert!(!env.t_nil().has_escaping_regions());
 
-        let t_rptr_free1 = env.t_rptr_free(1, 1);
+        let t_rptr_free1 = env.t_rptr_free(1);
         assert!(!t_rptr_free1.has_escaping_regions());
 
         let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, ty::DebruijnIndex::new(1));
index 38fa35ecb126299a7fec1f01638447bf3c510b07..861880aa265ec140a1072f8b25a12bc211c827e6 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use CodeSuggestion;
+use Substitution;
 use Level;
 use RenderSpan;
 use std::fmt;
@@ -23,7 +24,7 @@ pub struct Diagnostic {
     pub code: Option<String>,
     pub span: MultiSpan,
     pub children: Vec<SubDiagnostic>,
-    pub suggestion: Option<CodeSuggestion>,
+    pub suggestions: Vec<CodeSuggestion>,
 }
 
 /// For example a note attached to an error.
@@ -87,7 +88,7 @@ pub fn new_with_code(level: Level, code: Option<String>, message: &str) -> Self
             code: code,
             span: MultiSpan::new(),
             children: vec![],
-            suggestion: None,
+            suggestions: vec![],
         }
     }
 
@@ -114,9 +115,8 @@ pub fn is_fatal(&self) -> bool {
     /// all, and you just supplied a `Span` to create the diagnostic,
     /// then the snippet will just include that `Span`, which is
     /// called the primary span.
-    pub fn span_label(&mut self, span: Span, label: &fmt::Display)
-                      -> &mut Self {
-        self.span.push_span_label(span, format!("{}", label));
+    pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self {
+        self.span.push_span_label(span, label.into());
         self
     }
 
@@ -205,10 +205,22 @@ pub fn span_help<S: Into<MultiSpan>>(&mut self,
     ///
     /// See `diagnostic::CodeSuggestion` for more information.
     pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
-        assert!(self.suggestion.is_none());
-        self.suggestion = Some(CodeSuggestion {
-            msp: sp.into(),
-            substitutes: vec![suggestion],
+        self.suggestions.push(CodeSuggestion {
+            substitution_parts: vec![Substitution {
+                span: sp,
+                substitutions: vec![suggestion],
+            }],
+            msg: msg.to_owned(),
+        });
+        self
+    }
+
+    pub fn span_suggestions(&mut self, sp: Span, msg: &str, suggestions: Vec<String>) -> &mut Self {
+        self.suggestions.push(CodeSuggestion {
+            substitution_parts: vec![Substitution {
+                span: sp,
+                substitutions: suggestions,
+            }],
             msg: msg.to_owned(),
         });
         self
index 9dfd47b8464d78ed730e51879491f49f4a660133..fc5fd44f091f119d2be004159f2309cb5343150d 100644 (file)
@@ -99,7 +99,10 @@ pub fn emit(&mut self) {
 
         self.handler.emitter.borrow_mut().emit(&self);
         self.cancel();
-        self.handler.panic_if_treat_err_as_bug();
+
+        if self.level == Level::Error {
+            self.handler.panic_if_treat_err_as_bug();
+        }
 
         // if self.is_fatal() {
         //     panic!(FatalError);
@@ -112,8 +115,10 @@ pub fn emit(&mut self) {
     /// all, and you just supplied a `Span` to create the diagnostic,
     /// then the snippet will just include that `Span`, which is
     /// called the primary span.
-    forward!(pub fn span_label(&mut self, span: Span, label: &fmt::Display)
-                               -> &mut Self);
+    pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self {
+        self.diagnostic.span_label(span, label);
+        self
+    }
 
     forward!(pub fn note_expected_found(&mut self,
                                         label: &fmt::Display,
@@ -146,6 +151,11 @@ pub fn emit(&mut self) {
                                     msg: &str,
                                     suggestion: String)
                                     -> &mut Self);
+    forward!(pub fn span_suggestions(&mut self,
+                                     sp: Span,
+                                     msg: &str,
+                                     suggestions: Vec<String>)
+                                     -> &mut Self);
     forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
     forward!(pub fn code(&mut self, s: String) -> &mut Self);
 
index 53999eb9138b6f3b5054f8a0884706fd7e74dad6..03f1b94b169370826395976da0c4fa9cc2f5f787 100644 (file)
@@ -35,23 +35,32 @@ fn emit(&mut self, db: &DiagnosticBuilder) {
         let mut primary_span = db.span.clone();
         let mut children = db.children.clone();
 
-        if let Some(sugg) = db.suggestion.clone() {
-            assert_eq!(sugg.msp.primary_spans().len(), sugg.substitutes.len());
-            // don't display multispans as labels
-            if sugg.substitutes.len() == 1 &&
+        if let Some((sugg, rest)) = db.suggestions.split_first() {
+            if rest.is_empty() &&
+               // don't display multipart suggestions as labels
+               sugg.substitution_parts.len() == 1 &&
+               // don't display multi-suggestions as labels
+               sugg.substitutions() == 1 &&
                // don't display long messages as labels
                sugg.msg.split_whitespace().count() < 10 &&
                // don't display multiline suggestions as labels
-               sugg.substitutes[0].find('\n').is_none() {
-                let msg = format!("help: {} `{}`", sugg.msg, sugg.substitutes[0]);
-                primary_span.push_span_label(sugg.msp.primary_spans()[0], msg);
+               sugg.substitution_parts[0].substitutions[0].find('\n').is_none() {
+                let substitution = &sugg.substitution_parts[0].substitutions[0];
+                let msg = format!("help: {} `{}`", sugg.msg, substitution);
+                primary_span.push_span_label(sugg.substitution_spans().next().unwrap(), msg);
             } else {
-                children.push(SubDiagnostic {
-                    level: Level::Help,
-                    message: Vec::new(),
-                    span: MultiSpan::new(),
-                    render_span: Some(Suggestion(sugg)),
-                });
+                // if there are multiple suggestions, print them all in full
+                // to be consistent. We could try to figure out if we can
+                // make one (or the first one) inline, but that would give
+                // undue importance to a semi-random suggestion
+                for sugg in &db.suggestions {
+                    children.push(SubDiagnostic {
+                        level: Level::Help,
+                        message: Vec::new(),
+                        span: MultiSpan::new(),
+                        render_span: Some(Suggestion(sugg.clone())),
+                    });
+                }
             }
         }
 
@@ -66,6 +75,10 @@ fn emit(&mut self, db: &DiagnosticBuilder) {
 
 /// maximum number of lines we will print for each error; arbitrary.
 pub const MAX_HIGHLIGHT_LINES: usize = 6;
+/// maximum number of suggestions to be shown
+///
+/// Arbitrary, but taken from trait import suggestion limit
+pub const MAX_SUGGESTIONS: usize = 4;
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum ColorConfig {
@@ -95,21 +108,6 @@ struct FileWithAnnotatedLines {
     multiline_depth: usize,
 }
 
-
-/// Do not use this for messages that end in `\n` – use `println_maybe_styled` instead. See
-/// `EmitterWriter::print_maybe_styled` for details.
-macro_rules! print_maybe_styled {
-    ($dst: expr, $style: expr, $($arg: tt)*) => {
-        $dst.print_maybe_styled(format_args!($($arg)*), $style, false)
-    }
-}
-
-macro_rules! println_maybe_styled {
-    ($dst: expr, $style: expr, $($arg: tt)*) => {
-        $dst.print_maybe_styled(format_args!($($arg)*), $style, true)
-    }
-}
-
 impl EmitterWriter {
     pub fn stderr(color_config: ColorConfig, code_map: Option<Rc<CodeMapper>>) -> EmitterWriter {
         if color_config.use_color() {
@@ -1054,38 +1052,44 @@ fn emit_suggestion_default(&mut self,
                                -> io::Result<()> {
         use std::borrow::Borrow;
 
-        let primary_span = suggestion.msp.primary_span().unwrap();
+        let primary_span = suggestion.substitution_spans().next().unwrap();
         if let Some(ref cm) = self.cm {
             let mut buffer = StyledBuffer::new();
 
-            buffer.append(0, &level.to_string(), Style::Level(level.clone()));
-            buffer.append(0, ": ", Style::HeaderMsg);
-            self.msg_to_buffer(&mut buffer,
-                               &[(suggestion.msg.to_owned(), Style::NoStyle)],
-                               max_line_num_len,
-                               "suggestion",
-                               Some(Style::HeaderMsg));
-
             let lines = cm.span_to_lines(primary_span).unwrap();
 
             assert!(!lines.lines.is_empty());
 
-            let complete = suggestion.splice_lines(cm.borrow());
+            buffer.append(0, &level.to_string(), Style::Level(level.clone()));
+            buffer.append(0, ": ", Style::HeaderMsg);
+            self.msg_to_buffer(&mut buffer,
+                            &[(suggestion.msg.to_owned(), Style::NoStyle)],
+                            max_line_num_len,
+                            "suggestion",
+                            Some(Style::HeaderMsg));
 
-            // print the suggestion without any line numbers, but leave
-            // space for them. This helps with lining up with previous
-            // snippets from the actual error being reported.
-            let mut lines = complete.lines();
+            let suggestions = suggestion.splice_lines(cm.borrow());
             let mut row_num = 1;
-            for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
-                draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
-                buffer.append(row_num, line, Style::NoStyle);
-                row_num += 1;
-            }
+            for complete in suggestions.iter().take(MAX_SUGGESTIONS) {
+
+                // print the suggestion without any line numbers, but leave
+                // space for them. This helps with lining up with previous
+                // snippets from the actual error being reported.
+                let mut lines = complete.lines();
+                for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
+                    draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
+                    buffer.append(row_num, line, Style::NoStyle);
+                    row_num += 1;
+                }
 
-            // if we elided some lines, add an ellipsis
-            if let Some(_) = lines.next() {
-                buffer.append(row_num, "...", Style::NoStyle);
+                // if we elided some lines, add an ellipsis
+                if let Some(_) = lines.next() {
+                    buffer.append(row_num, "...", Style::NoStyle);
+                }
+            }
+            if suggestions.len() > MAX_SUGGESTIONS {
+                let msg = format!("and {} other candidates", suggestions.len() - MAX_SUGGESTIONS);
+                buffer.append(row_num, &msg, Style::NoStyle);
             }
             emit_to_destination(&buffer.render(), level, &mut self.dst)?;
         }
index 02d8297dd46140e30f3bef15f5fb7cd4f82a91fe..7a561e3a9703f82623fa80f28de306a8e9a9882b 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![crate_name = "rustc_errors"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
 #![feature(range_contains)]
 #![feature(libc)]
+#![feature(conservative_impl_trait)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
 
 extern crate term;
 extern crate libc;
@@ -65,11 +67,35 @@ pub enum RenderSpan {
 
 #[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
 pub struct CodeSuggestion {
-    pub msp: MultiSpan,
-    pub substitutes: Vec<String>,
+    /// Each substitute can have multiple variants due to multiple
+    /// applicable suggestions
+    ///
+    /// `foo.bar` might be replaced with `a.b` or `x.y` by replacing
+    /// `foo` and `bar` on their own:
+    ///
+    /// ```
+    /// vec![
+    ///     (0..3, vec!["a", "x"]),
+    ///     (4..7, vec!["b", "y"]),
+    /// ]
+    /// ```
+    ///
+    /// or by replacing the entire span:
+    ///
+    /// ```
+    /// vec![(0..7, vec!["a.b", "x.y"])]
+    /// ```
+    pub substitution_parts: Vec<Substitution>,
     pub msg: String,
 }
 
+#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+/// See the docs on `CodeSuggestion::substitutions`
+pub struct Substitution {
+    pub span: Span,
+    pub substitutions: Vec<String>,
+}
+
 pub trait CodeMapper {
     fn lookup_char_pos(&self, pos: BytePos) -> Loc;
     fn span_to_lines(&self, sp: Span) -> FileLinesResult;
@@ -79,8 +105,18 @@ pub trait CodeMapper {
 }
 
 impl CodeSuggestion {
-    /// Returns the assembled code suggestion.
-    pub fn splice_lines(&self, cm: &CodeMapper) -> String {
+    /// Returns the number of substitutions
+    fn substitutions(&self) -> usize {
+        self.substitution_parts[0].substitutions.len()
+    }
+
+    /// Returns the number of substitutions
+    pub fn substitution_spans<'a>(&'a self) -> impl Iterator<Item = Span> + 'a {
+        self.substitution_parts.iter().map(|sub| sub.span)
+    }
+
+    /// Returns the assembled code suggestions.
+    pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<String> {
         use syntax_pos::{CharPos, Loc, Pos};
 
         fn push_trailing(buf: &mut String,
@@ -102,20 +138,22 @@ fn push_trailing(buf: &mut String,
             }
         }
 
-        let mut primary_spans = self.msp.primary_spans().to_owned();
-
-        assert_eq!(primary_spans.len(), self.substitutes.len());
-        if primary_spans.is_empty() {
-            return format!("");
+        if self.substitution_parts.is_empty() {
+            return vec![String::new()];
         }
 
+        let mut primary_spans: Vec<_> = self.substitution_parts
+            .iter()
+            .map(|sub| (sub.span, &sub.substitutions))
+            .collect();
+
         // Assumption: all spans are in the same file, and all spans
         // are disjoint. Sort in ascending order.
-        primary_spans.sort_by_key(|sp| sp.lo);
+        primary_spans.sort_by_key(|sp| sp.0.lo);
 
         // Find the bounding span.
-        let lo = primary_spans.iter().map(|sp| sp.lo).min().unwrap();
-        let hi = primary_spans.iter().map(|sp| sp.hi).min().unwrap();
+        let lo = primary_spans.iter().map(|sp| sp.0.lo).min().unwrap();
+        let hi = primary_spans.iter().map(|sp| sp.0.hi).min().unwrap();
         let bounding_span = Span {
             lo: lo,
             hi: hi,
@@ -138,33 +176,40 @@ fn push_trailing(buf: &mut String,
         prev_hi.col = CharPos::from_usize(0);
 
         let mut prev_line = fm.get_line(lines.lines[0].line_index);
-        let mut buf = String::new();
+        let mut bufs = vec![String::new(); self.substitutions()];
 
-        for (sp, substitute) in primary_spans.iter().zip(self.substitutes.iter()) {
+        for (sp, substitutes) in primary_spans {
             let cur_lo = cm.lookup_char_pos(sp.lo);
-            if prev_hi.line == cur_lo.line {
-                push_trailing(&mut buf, prev_line, &prev_hi, Some(&cur_lo));
-            } else {
-                push_trailing(&mut buf, prev_line, &prev_hi, None);
-                // push lines between the previous and current span (if any)
-                for idx in prev_hi.line..(cur_lo.line - 1) {
-                    if let Some(line) = fm.get_line(idx) {
-                        buf.push_str(line);
-                        buf.push('\n');
+            for (buf, substitute) in bufs.iter_mut().zip(substitutes) {
+                if prev_hi.line == cur_lo.line {
+                    push_trailing(buf, prev_line, &prev_hi, Some(&cur_lo));
+                } else {
+                    push_trailing(buf, prev_line, &prev_hi, None);
+                    // push lines between the previous and current span (if any)
+                    for idx in prev_hi.line..(cur_lo.line - 1) {
+                        if let Some(line) = fm.get_line(idx) {
+                            buf.push_str(line);
+                            buf.push('\n');
+                        }
+                    }
+                    if let Some(cur_line) = fm.get_line(cur_lo.line - 1) {
+                        buf.push_str(&cur_line[..cur_lo.col.to_usize()]);
                     }
                 }
-                if let Some(cur_line) = fm.get_line(cur_lo.line - 1) {
-                    buf.push_str(&cur_line[..cur_lo.col.to_usize()]);
-                }
+                buf.push_str(substitute);
             }
-            buf.push_str(substitute);
             prev_hi = cm.lookup_char_pos(sp.hi);
             prev_line = fm.get_line(prev_hi.line - 1);
         }
-        push_trailing(&mut buf, prev_line, &prev_hi, None);
-        // remove trailing newline
-        buf.pop();
-        buf
+        for buf in &mut bufs {
+            // if the replacement already ends with a newline, don't print the next line
+            if !buf.ends_with('\n') {
+                push_trailing(buf, prev_line, &prev_hi, None);
+            }
+            // remove trailing newline
+            buf.pop();
+        }
+        bufs
     }
 }
 
@@ -388,6 +433,14 @@ pub fn span_bug_no_panic<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
     pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.emit(&sp.into(), msg, Note);
     }
+    pub fn span_note_diag<'a>(&'a self,
+                              sp: Span,
+                              msg: &str)
+                              -> DiagnosticBuilder<'a> {
+        let mut db = DiagnosticBuilder::new(self, Note, msg);
+        db.set_span(sp);
+        db
+    }
     pub fn span_unimpl<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
         self.span_bug(sp, &format!("unimplemented {}", msg));
     }
index 7905128bb6eca4266c734c38a9762e2628edcd3d..39fe2188f68d1f5756015404d19c0b49999e7003 100644 (file)
@@ -154,7 +154,7 @@ fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
                     None => {
                         self.tcx.sess.span_fatal(
                             attr.span,
-                            &format!("missing DepNode variant"));
+                            "missing DepNode variant");
                     }
                 };
                 self.then_this_would_need.push((attr.span,
@@ -201,7 +201,7 @@ fn check_paths<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         for &(target_span, _, _, _) in then_this_would_need {
             tcx.sess.span_err(
                 target_span,
-                &format!("no #[rustc_if_this_changed] annotation detected"));
+                "no #[rustc_if_this_changed] annotation detected");
 
         }
         return;
@@ -219,7 +219,7 @@ fn check_paths<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             } else {
                 tcx.sess.span_err(
                     target_span,
-                    &format!("OK"));
+                    "OK");
             }
         }
     }
index c67866971e1990ac398308ada8ce5fb62f201a95..8cdabc1d894e229af7070f87337312e11c5fda0b 100644 (file)
 
 use std::cell::RefCell;
 use std::hash::Hash;
+use std::sync::Arc;
 use rustc::dep_graph::DepNode;
 use rustc::hir;
-use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
+use rustc::hir::def_id::{LOCAL_CRATE, CRATE_DEF_INDEX, DefId};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ich::{Fingerprint, StableHashingContext};
 use rustc::ty::TyCtxt;
+use rustc::util::common::record_time;
 use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
 use rustc_data_structures::fx::FxHashMap;
-use rustc::util::common::record_time;
+use rustc_data_structures::accumulate_vec::AccumulateVec;
 
 pub type IchHasher = StableHasher<Fingerprint>;
 
@@ -60,6 +62,10 @@ pub fn new() -> IncrementalHashesMap {
         }
     }
 
+    pub fn get(&self, k: &DepNode<DefId>) -> Option<&Fingerprint> {
+        self.hashes.get(k)
+    }
+
     pub fn insert(&mut self, k: DepNode<DefId>, v: Fingerprint) -> Option<Fingerprint> {
         self.hashes.insert(k, v)
     }
@@ -140,14 +146,39 @@ fn compute_crate_hash(&mut self) {
             let hcx = &mut self.hcx;
             let mut item_hashes: Vec<_> =
                 self.hashes.iter()
-                           .map(|(item_dep_node, &item_hash)| {
-                               // convert from a DepNode<DefId> tp a
-                               // DepNode<u64> where the u64 is the
-                               // hash of the def-id's def-path:
-                               let item_dep_node =
-                                   item_dep_node.map_def(|&did| Some(hcx.def_path_hash(did)))
-                                                .unwrap();
-                               (item_dep_node, item_hash)
+                           .filter_map(|(item_dep_node, &item_hash)| {
+                                // This `match` determines what kinds of nodes
+                                // go into the SVH:
+                                match *item_dep_node {
+                                    DepNode::Hir(_) |
+                                    DepNode::HirBody(_) => {
+                                        // We want to incoporate these into the
+                                        // SVH.
+                                    }
+                                    DepNode::FileMap(..) => {
+                                        // These don't make a semantic
+                                        // difference, filter them out.
+                                        return None
+                                    }
+                                    DepNode::AllLocalTraitImpls => {
+                                        // These are already covered by hashing
+                                        // the HIR.
+                                        return None
+                                    }
+                                    ref other => {
+                                        bug!("Found unexpected DepNode during \
+                                              SVH computation: {:?}",
+                                             other)
+                                    }
+                                }
+
+                                // Convert from a DepNode<DefId> to a
+                                // DepNode<u64> where the u64 is the hash of
+                                // the def-id's def-path:
+                                let item_dep_node =
+                                    item_dep_node.map_def(|&did| Some(hcx.def_path_hash(did)))
+                                                 .unwrap();
+                                Some((item_dep_node, item_hash))
                            })
                            .collect();
             item_hashes.sort_unstable(); // avoid artificial dependencies on item ordering
@@ -188,6 +219,49 @@ fn hash_crate_root_module(&mut self, krate: &'tcx hir::Crate) {
                                                  true,
                                                  (module, (span, attrs)));
     }
+
+    fn compute_and_store_ich_for_trait_impls(&mut self, krate: &'tcx hir::Crate)
+    {
+        let tcx = self.hcx.tcx();
+
+        let mut impls: Vec<(u64, Fingerprint)> = krate
+            .trait_impls
+            .iter()
+            .map(|(&trait_id, impls)| {
+                let trait_id = tcx.def_path_hash(trait_id);
+                let mut impls: AccumulateVec<[_; 32]> = impls
+                    .iter()
+                    .map(|&node_id| {
+                        let def_id = tcx.hir.local_def_id(node_id);
+                        tcx.def_path_hash(def_id)
+                    })
+                    .collect();
+
+                impls.sort_unstable();
+                let mut hasher = StableHasher::new();
+                impls.hash_stable(&mut self.hcx, &mut hasher);
+                (trait_id, hasher.finish())
+            })
+            .collect();
+
+        impls.sort_unstable();
+
+        let mut default_impls: AccumulateVec<[_; 32]> = krate
+            .trait_default_impl
+            .iter()
+            .map(|(&trait_def_id, &impl_node_id)| {
+                let impl_def_id = tcx.hir.local_def_id(impl_node_id);
+                (tcx.def_path_hash(trait_def_id), tcx.def_path_hash(impl_def_id))
+            })
+            .collect();
+
+        default_impls.sort_unstable();
+
+        let mut hasher = StableHasher::new();
+        impls.hash_stable(&mut self.hcx, &mut hasher);
+
+        self.hashes.insert(DepNode::AllLocalTraitImpls, hasher.finish());
+    }
 }
 
 impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for ComputeItemHashesVisitor<'a, 'tcx> {
@@ -210,6 +284,8 @@ fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
     }
 }
 
+
+
 pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                                     -> IncrementalHashesMap {
     let _ignore = tcx.dep_graph.in_ignore();
@@ -229,6 +305,26 @@ pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
             visitor.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, macro_def);
             visitor.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, macro_def);
         }
+
+        for filemap in tcx.sess
+                          .codemap()
+                          .files_untracked()
+                          .iter()
+                          .filter(|fm| !fm.is_imported()) {
+            assert_eq!(LOCAL_CRATE.as_u32(), filemap.crate_of_origin);
+            let def_id = DefId {
+                krate: LOCAL_CRATE,
+                index: CRATE_DEF_INDEX,
+            };
+            let name = Arc::new(filemap.name.clone());
+            let dep_node = DepNode::FileMap(def_id, name);
+            let mut hasher = IchHasher::new();
+            filemap.hash_stable(&mut visitor.hcx, &mut hasher);
+            let fingerprint = hasher.finish();
+            visitor.hashes.insert(dep_node, fingerprint);
+        }
+
+        visitor.compute_and_store_ich_for_trait_impls(krate);
     });
 
     tcx.sess.perf_stats.incr_comp_hashes_count.set(visitor.hashes.len() as u64);
index 95f0a96fdf965c4940c2ffeb56e74ab528a74596..70f967d50b0e1db97688ea48d88c18da60a668e3 100644 (file)
@@ -11,7 +11,6 @@
 //! Support for serializing the dep-graph and reloading it.
 
 #![crate_name = "rustc_incremental"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![deny(warnings)]
 
-#![feature(rustc_private)]
-#![feature(staged_api)]
 #![feature(rand)]
 #![feature(conservative_impl_trait)]
 #![feature(sort_unstable)]
 
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
 extern crate graphviz;
 #[macro_use] extern crate rustc;
 extern crate rustc_data_structures;
index 8a1af5dd08d74d7dfb85dac9ff9d94e5acbbcd9b..b016ff34bc5c604be24c0b0d4c1557d34bf2a573 100644 (file)
@@ -99,7 +99,11 @@ pub struct SerializedMetadataHashes {
     /// where `X` refers to some item in this crate. That `X` will be
     /// a `DefPathIndex` that gets retracted to the current `DefId`
     /// (matching the one found in this structure).
-    pub hashes: Vec<EncodedMetadataHash>,
+    pub entry_hashes: Vec<EncodedMetadataHash>,
+
+    /// This map contains fingerprints that are not specific to some DefId but
+    /// describe something global to the whole crate.
+    pub global_hashes: Vec<(DepNode<()>, Fingerprint)>,
 
     /// For each DefIndex (as it occurs in SerializedMetadataHash), this
     /// map stores the DefPathIndex (as it occurs in DefIdDirectory), so
index b73b3e161f9b547fcfb0ef6f0b26090ad794d31d..5facfe36efdb93c8b452b186e50b15526f23e1e3 100644 (file)
@@ -383,7 +383,7 @@ fn check_config(tcx: TyCtxt, attr: &Attribute) -> bool {
 
     tcx.sess.span_fatal(
         attr.span,
-        &format!("no cfg attribute"));
+        "no cfg attribute");
 }
 
 fn expect_associated_value(tcx: TyCtxt, item: &NestedMetaItem) -> ast::Name {
index 9d8ff57e03bcc4b39d9144653e8b77cfc2f0f2bc..2f727a80f016e0589ccb8069554338645c3db31d 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use rustc::dep_graph::DepNode;
-use rustc::hir::def_id::{CrateNum, DefId};
+use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
 use rustc::hir::svh::Svh;
 use rustc::ich::Fingerprint;
 use rustc::ty::TyCtxt;
 use super::fs::*;
 use super::file_format;
 
+use std::hash::Hash;
+use std::fmt::Debug;
+
 pub struct HashContext<'a, 'tcx: 'a> {
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     incremental_hashes_map: &'a IncrementalHashesMap,
     item_metadata_hashes: FxHashMap<DefId, Fingerprint>,
     crate_hashes: FxHashMap<CrateNum, Svh>,
+    global_metadata_hashes: FxHashMap<DepNode<DefId>, Fingerprint>,
 }
 
 impl<'a, 'tcx> HashContext<'a, 'tcx> {
@@ -39,6 +43,7 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             incremental_hashes_map: incremental_hashes_map,
             item_metadata_hashes: FxHashMap(),
             crate_hashes: FxHashMap(),
+            global_metadata_hashes: FxHashMap(),
         }
     }
 
@@ -46,9 +51,11 @@ pub fn is_hashable(dep_node: &DepNode<DefId>) -> bool {
         match *dep_node {
             DepNode::Krate |
             DepNode::Hir(_) |
-            DepNode::HirBody(_) =>
+            DepNode::HirBody(_) |
+            DepNode::FileMap(..) =>
                 true,
-            DepNode::MetaData(def_id) => !def_id.is_local(),
+            DepNode::MetaData(def_id) |
+            DepNode::GlobalMetaData(def_id, _) => !def_id.is_local(),
             _ => false,
         }
     }
@@ -60,7 +67,8 @@ pub fn hash(&mut self, dep_node: &DepNode<DefId>) -> Option<Fingerprint> {
             }
 
             // HIR nodes (which always come from our crate) are an input:
-            DepNode::Hir(def_id) | DepNode::HirBody(def_id) => {
+            DepNode::Hir(def_id) |
+            DepNode::HirBody(def_id) => {
                 assert!(def_id.is_local(),
                         "cannot hash HIR for non-local def-id {:?} => {:?}",
                         def_id,
@@ -69,12 +77,34 @@ pub fn hash(&mut self, dep_node: &DepNode<DefId>) -> Option<Fingerprint> {
                 Some(self.incremental_hashes_map[dep_node])
             }
 
+            DepNode::FileMap(def_id, ref name) => {
+                if def_id.is_local() {
+                    // We will have been able to retrace the DefId (which is
+                    // always the local CRATE_DEF_INDEX), but the file with the
+                    // given name might have been removed, so we use get() in
+                    // order to allow for that case.
+                    self.incremental_hashes_map.get(dep_node).map(|x| *x)
+                } else {
+                    Some(self.metadata_hash(DepNode::FileMap(def_id, name.clone()),
+                                            def_id.krate,
+                                            |this| &mut this.global_metadata_hashes))
+                }
+            }
+
             // MetaData from other crates is an *input* to us.
             // MetaData nodes from *our* crates are an *output*; we
             // don't hash them, but we do compute a hash for them and
             // save it for others to use.
             DepNode::MetaData(def_id) if !def_id.is_local() => {
-                Some(self.metadata_hash(def_id))
+                Some(self.metadata_hash(def_id,
+                                        def_id.krate,
+                                        |this| &mut this.item_metadata_hashes))
+            }
+
+            DepNode::GlobalMetaData(def_id, kind) => {
+                Some(self.metadata_hash(DepNode::GlobalMetaData(def_id, kind),
+                                        def_id.krate,
+                                        |this| &mut this.global_metadata_hashes))
             }
 
             _ => {
@@ -87,33 +117,37 @@ pub fn hash(&mut self, dep_node: &DepNode<DefId>) -> Option<Fingerprint> {
         }
     }
 
-    fn metadata_hash(&mut self, def_id: DefId) -> Fingerprint {
-        debug!("metadata_hash(def_id={:?})", def_id);
+    fn metadata_hash<K, C>(&mut self,
+                           key: K,
+                           cnum: CrateNum,
+                           cache: C)
+                           -> Fingerprint
+        where K: Hash + Eq + Debug,
+              C: Fn(&mut Self) -> &mut FxHashMap<K, Fingerprint>,
+    {
+        debug!("metadata_hash(key={:?})", key);
 
-        assert!(!def_id.is_local());
+        debug_assert!(cnum != LOCAL_CRATE);
         loop {
             // check whether we have a result cached for this def-id
-            if let Some(&hash) = self.item_metadata_hashes.get(&def_id) {
-                debug!("metadata_hash: def_id={:?} hash={:?}", def_id, hash);
+            if let Some(&hash) = cache(self).get(&key) {
                 return hash;
             }
 
             // check whether we did not find detailed metadata for this
             // krate; in that case, we just use the krate's overall hash
-            if let Some(&svh) = self.crate_hashes.get(&def_id.krate) {
-                debug!("metadata_hash: def_id={:?} crate_hash={:?}", def_id, svh);
-
+            if let Some(&svh) = self.crate_hashes.get(&cnum) {
                 // micro-"optimization": avoid a cache miss if we ask
                 // for metadata from this particular def-id again.
                 let fingerprint = svh_to_fingerprint(svh);
-                self.item_metadata_hashes.insert(def_id, fingerprint);
+                cache(self).insert(key, fingerprint);
 
                 return fingerprint;
             }
 
             // otherwise, load the data and repeat.
-            self.load_data(def_id.krate);
-            assert!(self.crate_hashes.contains_key(&def_id.krate));
+            self.load_data(cnum);
+            assert!(self.crate_hashes.contains_key(&cnum));
         }
     }
 
@@ -191,7 +225,7 @@ fn load_from_data(&mut self,
         }
 
         let serialized_hashes = SerializedMetadataHashes::decode(&mut decoder)?;
-        for serialized_hash in serialized_hashes.hashes {
+        for serialized_hash in serialized_hashes.entry_hashes {
             // the hashes are stored with just a def-index, which is
             // always relative to the old crate; convert that to use
             // our internal crate number
@@ -202,6 +236,24 @@ fn load_from_data(&mut self,
             debug!("load_from_data: def_id={:?} hash={}", def_id, serialized_hash.hash);
             assert!(old.is_none(), "already have hash for {:?}", def_id);
         }
+
+        for (dep_node, fingerprint) in serialized_hashes.global_hashes {
+            // Here we need to remap the CrateNum in the DepNode.
+            let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
+            let dep_node = match dep_node {
+                DepNode::GlobalMetaData(_, kind) => DepNode::GlobalMetaData(def_id, kind),
+                DepNode::FileMap(_, name) => DepNode::FileMap(def_id, name),
+                other => {
+                    bug!("unexpected DepNode variant: {:?}", other)
+                }
+            };
+
+            // record the hash for this dep-node
+            debug!("load_from_data: def_node={:?} hash={}", dep_node, fingerprint);
+            let old = self.global_metadata_hashes.insert(dep_node.clone(), fingerprint);
+            assert!(old.is_none(), "already have hash for {:?}", dep_node);
+        }
+
         Ok(())
     }
 }
index ed2e2e72ee79f7381db081082f6d5a608b4ac8d9..7fad600d1054294ff769cec9341d5172fa28bf6f 100644 (file)
@@ -240,35 +240,40 @@ fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut hcx = HashContext::new(tcx, incremental_hashes_map);
     let mut dirty_nodes = FxHashMap();
 
+    let print_removed_message = |dep_node: &DepNode<_>| {
+        if tcx.sess.opts.debugging_opts.incremental_dump_hash {
+            println!("node {:?} is dirty as it was removed", dep_node);
+        }
+
+        debug!("initial_dirty_nodes: {:?} is dirty as it was removed", dep_node);
+    };
+
     for hash in serialized_hashes {
         if let Some(dep_node) = retraced.map(&hash.dep_node) {
-            let current_hash = hcx.hash(&dep_node).unwrap();
-            if current_hash == hash.hash {
-                debug!("initial_dirty_nodes: {:?} is clean (hash={:?})",
-                   dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(),
-                   current_hash);
-                continue;
-            }
+            if let Some(current_hash) = hcx.hash(&dep_node) {
+                if current_hash == hash.hash {
+                    debug!("initial_dirty_nodes: {:?} is clean (hash={:?})",
+                       dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(),
+                       current_hash);
+                    continue;
+                }
 
-            if tcx.sess.opts.debugging_opts.incremental_dump_hash {
-                println!("node {:?} is dirty as hash is {:?} was {:?}",
-                         dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(),
-                         current_hash,
-                         hash.hash);
-            }
+                if tcx.sess.opts.debugging_opts.incremental_dump_hash {
+                    println!("node {:?} is dirty as hash is {:?} was {:?}",
+                             dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(),
+                             current_hash,
+                             hash.hash);
+                }
 
-            debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}",
-                   dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(),
-                   current_hash,
-                   hash.hash);
-        } else {
-            if tcx.sess.opts.debugging_opts.incremental_dump_hash {
-                println!("node {:?} is dirty as it was removed",
-                         hash.dep_node);
+                debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}",
+                       dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(),
+                       current_hash,
+                       hash.hash);
+            } else {
+                print_removed_message(&hash.dep_node);
             }
-
-            debug!("initial_dirty_nodes: {:?} is dirty as it was removed",
-                   hash.dep_node);
+        } else {
+            print_removed_message(&hash.dep_node);
         }
 
         dirty_nodes.insert(hash.dep_node.clone(), hash.dep_node.clone());
@@ -382,8 +387,8 @@ fn load_prev_metadata_hashes(tcx: TyCtxt,
 
     debug!("load_prev_metadata_hashes() - Mapping DefIds");
 
-    assert_eq!(serialized_hashes.index_map.len(), serialized_hashes.hashes.len());
-    for serialized_hash in serialized_hashes.hashes {
+    assert_eq!(serialized_hashes.index_map.len(), serialized_hashes.entry_hashes.len());
+    for serialized_hash in serialized_hashes.entry_hashes {
         let def_path_index = serialized_hashes.index_map[&serialized_hash.def_index];
         if let Some(def_id) = retraced.def_id(def_path_index) {
             let old = output.insert(def_id, serialized_hash.hash);
index 31b30d2b2857cb253e97e8a1a94b581f8ae52ae2..044b143e306250944542e6b7fb12b3c73a090a21 100644 (file)
@@ -37,14 +37,3 @@ macro_rules! graph {
         }
     }
 }
-
-macro_rules! set {
-    ($( $value:expr ),*) => {
-        {
-            use $crate::rustc_data_structures::fx::FxHashSet;
-            let mut set = FxHashSet();
-            $(set.insert($value);)*
-            set
-        }
-    }
-}
index 1864009fbdf21f119b2ff80dec63f02c2118ea19..06e49e9d37c8464c82061bd4fb46198b5b8551ba 100644 (file)
@@ -12,7 +12,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::hir::svh::Svh;
 use rustc::ich::Fingerprint;
-use rustc::middle::cstore::EncodedMetadataHash;
+use rustc::middle::cstore::EncodedMetadataHashes;
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashMap;
@@ -34,7 +34,7 @@
 
 pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 incremental_hashes_map: &IncrementalHashesMap,
-                                metadata_hashes: &[EncodedMetadataHash],
+                                metadata_hashes: &EncodedMetadataHashes,
                                 svh: Svh) {
     debug!("save_dep_graph()");
     let _ignore = tcx.dep_graph.in_ignore();
@@ -240,18 +240,19 @@ pub fn encode_dep_graph(preds: &Predecessors,
 
 pub fn encode_metadata_hashes(tcx: TyCtxt,
                               svh: Svh,
-                              metadata_hashes: &[EncodedMetadataHash],
+                              metadata_hashes: &EncodedMetadataHashes,
                               builder: &mut DefIdDirectoryBuilder,
                               current_metadata_hashes: &mut FxHashMap<DefId, Fingerprint>,
                               encoder: &mut Encoder)
                               -> io::Result<()> {
     let mut serialized_hashes = SerializedMetadataHashes {
-        hashes: metadata_hashes.to_vec(),
+        entry_hashes: metadata_hashes.entry_hashes.to_vec(),
+        global_hashes: metadata_hashes.global_hashes.to_vec(),
         index_map: FxHashMap()
     };
 
     if tcx.sess.opts.debugging_opts.query_dep_graph {
-        for serialized_hash in &serialized_hashes.hashes {
+        for serialized_hash in &serialized_hashes.entry_hashes {
             let def_id = DefId::local(serialized_hash.def_index);
 
             // Store entry in the index_map
index c9ec152841b2025a1e57e8b09344355aba06a405..6423d65a4c23fc7175ee598ef365ae7ed90c3ce1 100644 (file)
@@ -692,6 +692,81 @@ fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
     }
 }
 
+declare_lint! {
+    pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+    Warn,
+    "floating-point literals cannot be used in patterns"
+}
+
+/// Checks for floating point literals in patterns.
+#[derive(Clone)]
+pub struct IllegalFloatLiteralPattern;
+
+impl LintPass for IllegalFloatLiteralPattern {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN)
+    }
+}
+
+fn fl_lit_check_expr(cx: &EarlyContext, expr: &ast::Expr) {
+    use self::ast::{ExprKind, LitKind};
+    match expr.node {
+        ExprKind::Lit(ref l) => {
+            match l.node {
+                LitKind::FloatUnsuffixed(..) |
+                LitKind::Float(..) => {
+                    cx.span_lint(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+                                 l.span,
+                                 "floating-point literals cannot be used in patterns");
+                    },
+                _ => (),
+            }
+        }
+        // These may occur in patterns
+        // and can maybe contain float literals
+        ExprKind::Unary(_, ref f) => fl_lit_check_expr(cx, f),
+        // These may occur in patterns
+        // and can't contain float literals
+        ExprKind::Path(..) => (),
+        // If something unhandled is encountered, we need to expand the
+        // search or ignore more ExprKinds.
+        _ => span_bug!(expr.span, "Unhandled expression {:?} in float lit pattern lint",
+                       expr.node),
+    }
+}
+
+impl EarlyLintPass for IllegalFloatLiteralPattern {
+    fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat) {
+        use self::ast::PatKind;
+        pat.walk(&mut |p| {
+            match p.node {
+                // Wildcard patterns and paths are uninteresting for the lint
+                PatKind::Wild |
+                PatKind::Path(..) => (),
+
+                // The walk logic recurses inside these
+                PatKind::Ident(..) |
+                PatKind::Struct(..) |
+                PatKind::Tuple(..) |
+                PatKind::TupleStruct(..) |
+                PatKind::Ref(..) |
+                PatKind::Box(..) |
+                PatKind::Slice(..) => (),
+
+                // Extract the expressions and check them
+                PatKind::Lit(ref e) => fl_lit_check_expr(cx, e),
+                PatKind::Range(ref st, ref en, _) => {
+                    fl_lit_check_expr(cx, st);
+                    fl_lit_check_expr(cx, en);
+                },
+
+                PatKind::Mac(_) => bug!("lint must run post-expansion"),
+            }
+            true
+        });
+    }
+}
+
 declare_lint! {
     pub UNCONDITIONAL_RECURSION,
     Warn,
@@ -915,12 +990,7 @@ fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         traits::Obligation::new(traits::ObligationCause::misc(span, expr_id),
                                                 trait_ref.to_poly_trait_predicate());
 
-                    // unwrap() is ok here b/c `method` is the method
-                    // defined in this crate whose body we are
-                    // checking, so it's always local
-                    let node_id = tcx.hir.as_local_node_id(method.def_id).unwrap();
-
-                    let param_env = ty::ParameterEnvironment::for_item(tcx, node_id);
+                    let param_env = tcx.parameter_environment(method.def_id);
                     tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
                         let mut selcx = traits::SelectionContext::new(&infcx);
                         match selcx.select(&obligation) {
@@ -1188,7 +1258,7 @@ fn get_lints(&self) -> LintArray {
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
     fn check_item(&mut self, ctx: &LateContext, item: &hir::Item) {
         if let hir::ItemUnion(ref vdata, _) = item.node {
-            let param_env = &ty::ParameterEnvironment::for_item(ctx.tcx, item.id);
+            let param_env = &ctx.tcx.parameter_environment(ctx.tcx.hir.local_def_id(item.id));
             for field in vdata.fields() {
                 let field_ty = ctx.tcx.type_of(ctx.tcx.hir.local_def_id(field.id));
                 if field_ty.needs_drop(ctx.tcx, param_env) {
index c1c14cb1fd29e3d8f3e6d6500a193d0f65fa4367..479c7206cb4cb95b150c5b0adcb0b40daf86c0de 100644 (file)
@@ -20,7 +20,6 @@
 //! This API is completely unstable and subject to change.
 
 #![crate_name = "rustc_lint"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 #![feature(i128_type)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
 #![feature(slice_patterns)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
 
 #[macro_use]
 extern crate syntax;
@@ -113,6 +114,7 @@ macro_rules! add_lint_group {
                        UnusedParens,
                        UnusedImportBraces,
                        AnonymousParameters,
+                       IllegalFloatLiteralPattern,
                        );
 
     add_early_builtin_with_new!(sess,
@@ -169,7 +171,8 @@ macro_rules! add_lint_group {
                     UNUSED_MUST_USE,
                     UNUSED_UNSAFE,
                     PATH_STATEMENTS,
-                    UNUSED_ATTRIBUTES);
+                    UNUSED_ATTRIBUTES,
+                    UNUSED_MACROS);
 
     // Guidelines for creating a future incompatibility lint:
     //
@@ -201,6 +204,10 @@ macro_rules! add_lint_group {
             id: LintId::of(ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN),
             reference: "issue #36890 <https://github.com/rust-lang/rust/issues/36890>",
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN),
+            reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
+        },
         FutureIncompatibleInfo {
             id: LintId::of(ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN),
             reference: "issue #36891 <https://github.com/rust-lang/rust/issues/36891>",
index 86bf209ccf8c8d92c5c841f684f356f869293b20..93ff609a280ae1d4b0d24431dcadef941b32b6a2 100644 (file)
@@ -215,7 +215,7 @@ fn is_enclosed(cx: &LateContext, id: ast::NodeId) -> Option<(String, ast::NodeId
                 let mut db = cx.struct_span_lint(UNUSED_UNSAFE, blk.span,
                                                  "unnecessary `unsafe` block");
 
-                db.span_label(blk.span, &"unnecessary `unsafe` block");
+                db.span_label(blk.span, "unnecessary `unsafe` block");
                 if let Some((kind, id)) = is_enclosed(cx, blk.id) {
                     db.span_note(cx.tcx.hir.span(id),
                                  &format!("because it's nested under this `unsafe` {}", kind));
index c9b3a7ff3f3aac4d1880c8610c66ef2761092d47..790d493f1914c066fa105bb3f1ba774c3ad8524a 100644 (file)
@@ -14,7 +14,6 @@
 #![allow(dead_code)]
 
 #![crate_name = "rustc_llvm"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 #![feature(concat_idents)]
 #![feature(libc)]
 #![feature(link_args)]
-#![feature(staged_api)]
-#![feature(rustc_private)]
 #![feature(static_nobundle)]
 
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
 extern crate libc;
 #[macro_use]
 #[no_link]
index e8b906092730e5cbee6f873daa302fd57eaf46a6..f47788ee036dc5e312d4a05754a3f4b0cd8c7143 100644 (file)
@@ -11,13 +11,13 @@ crate-type = ["dylib"]
 [dependencies]
 flate = { path = "../libflate" }
 log = "0.3"
+owning_ref = "0.3.3"
 proc_macro = { path = "../libproc_macro" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
-rustc_llvm = { path = "../librustc_llvm" }
 serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_ext = { path = "../libsyntax_ext" }
index d9008ce555cc17afa48a0e4924f3dba299450dc9..6c02ac7eafec32e0dba689f5cba942281a897bf1 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
 
-use index_builder::EntryBuilder;
+use isolated_encoder::IsolatedEncoder;
 use schema::*;
 
 use rustc::hir;
@@ -31,7 +31,7 @@ pub struct Ast<'tcx> {
     rvalue_promotable_to_static
 });
 
-impl<'a, 'b, 'tcx> EntryBuilder<'a, 'b, 'tcx> {
+impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> {
     pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
         let body = self.tcx.hir.body(body_id);
         let lazy_body = self.lazy(body);
index 966e814e3379075741b2809585814f95e5a5624b..ec6947b4a486c31ebcaa1444fc827d2115c72f04 100644 (file)
 
 use cstore::{self, CStore, CrateSource, MetadataBlob};
 use locator::{self, CratePaths};
-use schema::CrateRoot;
+use schema::{CrateRoot, Tracked};
 
-use rustc::hir::def_id::{CrateNum, DefIndex};
+use rustc::dep_graph::{DepNode, GlobalMetaDataKind};
+use rustc::hir::def_id::{DefId, CrateNum, DefIndex, CRATE_DEF_INDEX};
 use rustc::hir::svh::Svh;
 use rustc::middle::cstore::DepKind;
 use rustc::session::Session;
@@ -88,7 +89,7 @@ fn register_native_lib(sess: &Session,
             Some(span) => {
                 struct_span_err!(sess, span, E0454,
                                  "#[link(name = \"\")] given with empty name")
-                    .span_label(span, &format!("empty name given"))
+                    .span_label(span, "empty name given")
                     .emit();
             }
             None => {
@@ -311,13 +312,23 @@ fn register_crate(&mut self,
             crate_root.def_path_table.decode(&metadata)
         });
 
-        let exported_symbols = crate_root.exported_symbols.decode(&metadata).collect();
+        let exported_symbols = crate_root.exported_symbols
+                                         .map(|x| x.decode(&metadata).collect());
+
+        let trait_impls = crate_root
+            .impls
+            .map(|impls| {
+                impls.decode(&metadata)
+                     .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
+                     .collect()
+            });
 
         let mut cmeta = cstore::CrateMetadata {
             name: name,
             extern_crate: Cell::new(None),
             def_path_table: def_path_table,
             exported_symbols: exported_symbols,
+            trait_impls: trait_impls,
             proc_macros: crate_root.macro_derive_registrar.map(|_| {
                 self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
             }),
@@ -333,16 +344,27 @@ fn register_crate(&mut self,
                 rlib: rlib,
                 rmeta: rmeta,
             },
-            dllimport_foreign_items: FxHashSet(),
+            // Initialize this with an empty set. The field is populated below
+            // after we were able to deserialize its contents.
+            dllimport_foreign_items: Tracked::new(FxHashSet()),
         };
 
-        let dllimports: Vec<_> = cmeta.get_native_libraries().iter()
-                            .filter(|lib| relevant_lib(self.sess, lib) &&
-                                          lib.kind == cstore::NativeLibraryKind::NativeUnknown)
-                            .flat_map(|lib| &lib.foreign_items)
-                            .map(|id| *id)
-                            .collect();
-        cmeta.dllimport_foreign_items.extend(dllimports);
+        let dllimports: Tracked<FxHashSet<_>> = cmeta
+            .root
+            .native_libraries
+            .map(|native_libraries| {
+                let native_libraries: Vec<_> = native_libraries.decode(&cmeta)
+                                                               .collect();
+                native_libraries
+                    .iter()
+                    .filter(|lib| relevant_lib(self.sess, lib) &&
+                                  lib.kind == cstore::NativeLibraryKind::NativeUnknown)
+                    .flat_map(|lib| lib.foreign_items.iter())
+                    .map(|id| *id)
+                    .collect()
+            });
+
+        cmeta.dllimport_foreign_items = dllimports;
 
         let cmeta = Rc::new(cmeta);
         self.cstore.set_crate_data(cnum, cmeta.clone());
@@ -380,6 +402,7 @@ fn resolve_crate(&mut self,
                 rejected_via_filename: vec![],
                 should_match_name: true,
                 is_proc_macro: Some(false),
+                metadata_loader: &*self.cstore.metadata_loader,
             };
 
             self.load(&mut locate_ctxt).or_else(|| {
@@ -493,10 +516,16 @@ fn resolve_crate_deps(&mut self,
             return cstore::CrateNumMap::new();
         }
 
+        let dep_node = DepNode::GlobalMetaData(DefId { krate, index: CRATE_DEF_INDEX },
+                                               GlobalMetaDataKind::CrateDeps);
+
         // The map from crate numbers in the crate we're resolving to local crate numbers.
         // We map 0 and all other holes in the map to our parent crate. The "additional"
         // self-dependencies should be harmless.
-        ::std::iter::once(krate).chain(crate_root.crate_deps.decode(metadata).map(|dep| {
+        ::std::iter::once(krate).chain(crate_root.crate_deps
+                                                 .get(&self.sess.dep_graph, dep_node)
+                                                 .decode(metadata)
+                                                 .map(|dep| {
             debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
             if dep.kind == DepKind::UnexportedMacrosOnly {
                 return krate;
@@ -535,6 +564,7 @@ fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> Extens
             rejected_via_filename: vec![],
             should_match_name: true,
             is_proc_macro: None,
+            metadata_loader: &*self.cstore.metadata_loader,
         };
         let library = self.load(&mut locate_ctxt).or_else(|| {
             if !is_cross {
@@ -654,7 +684,9 @@ fn register_bang_proc_macro(&mut self,
 
     /// Look for a plugin registrar. Returns library path, crate
     /// SVH and DefIndex of the registrar function.
-    pub fn find_plugin_registrar(&mut self, span: Span, name: &str)
+    pub fn find_plugin_registrar(&mut self,
+                                 span: Span,
+                                 name: &str)
                                  -> Option<(PathBuf, Symbol, DefIndex)> {
         let ekrate = self.read_extension_crate(span, &ExternCrateInfo {
              name: Symbol::intern(name),
@@ -740,13 +772,17 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
         let mut runtime_found = false;
         let mut needs_panic_runtime = attr::contains_name(&krate.attrs,
                                                           "needs_panic_runtime");
+
+        let dep_graph = &self.sess.dep_graph;
+
         self.cstore.iter_crate_data(|cnum, data| {
-            needs_panic_runtime = needs_panic_runtime || data.needs_panic_runtime();
-            if data.is_panic_runtime() {
+            needs_panic_runtime = needs_panic_runtime ||
+                                  data.needs_panic_runtime(dep_graph);
+            if data.is_panic_runtime(dep_graph) {
                 // Inject a dependency from all #![needs_panic_runtime] to this
                 // #![panic_runtime] crate.
                 self.inject_dependency_if(cnum, "a panic runtime",
-                                          &|data| data.needs_panic_runtime());
+                                          &|data| data.needs_panic_runtime(dep_graph));
                 runtime_found = runtime_found || data.dep_kind.get() == DepKind::Explicit;
             }
         });
@@ -782,11 +818,11 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
 
         // Sanity check the loaded crate to ensure it is indeed a panic runtime
         // and the panic strategy is indeed what we thought it was.
-        if !data.is_panic_runtime() {
+        if !data.is_panic_runtime(dep_graph) {
             self.sess.err(&format!("the crate `{}` is not a panic runtime",
                                    name));
         }
-        if data.panic_strategy() != desired_strategy {
+        if data.panic_strategy(dep_graph) != desired_strategy {
             self.sess.err(&format!("the crate `{}` does not have the panic \
                                     strategy `{}`",
                                    name, desired_strategy.desc()));
@@ -794,7 +830,7 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
 
         self.sess.injected_panic_runtime.set(Some(cnum));
         self.inject_dependency_if(cnum, "a panic runtime",
-                                  &|data| data.needs_panic_runtime());
+                                  &|data| data.needs_panic_runtime(dep_graph));
     }
 
     fn inject_sanitizer_runtime(&mut self) {
@@ -862,7 +898,7 @@ fn inject_sanitizer_runtime(&mut self) {
                                        PathKind::Crate, dep_kind);
 
                 // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime
-                if !data.is_sanitizer_runtime() {
+                if !data.is_sanitizer_runtime(&self.sess.dep_graph) {
                     self.sess.err(&format!("the crate `{}` is not a sanitizer runtime",
                                            name));
                 }
@@ -878,12 +914,13 @@ fn inject_allocator_crate(&mut self) {
         // also bail out as we don't need to implicitly inject one.
         let mut needs_allocator = false;
         let mut found_required_allocator = false;
+        let dep_graph = &self.sess.dep_graph;
         self.cstore.iter_crate_data(|cnum, data| {
-            needs_allocator = needs_allocator || data.needs_allocator();
-            if data.is_allocator() {
+            needs_allocator = needs_allocator || data.needs_allocator(dep_graph);
+            if data.is_allocator(dep_graph) {
                 info!("{} required by rlib and is an allocator", data.name());
                 self.inject_dependency_if(cnum, "an allocator",
-                                          &|data| data.needs_allocator());
+                                          &|data| data.needs_allocator(dep_graph));
                 found_required_allocator = found_required_allocator ||
                     data.dep_kind.get() == DepKind::Explicit;
             }
@@ -937,14 +974,14 @@ fn inject_allocator_crate(&mut self) {
 
         // Sanity check the crate we loaded to ensure that it is indeed an
         // allocator.
-        if !data.is_allocator() {
+        if !data.is_allocator(dep_graph) {
             self.sess.err(&format!("the allocator crate `{}` is not tagged \
                                     with #![allocator]", data.name()));
         }
 
         self.sess.injected_allocator.set(Some(cnum));
         self.inject_dependency_if(cnum, "an allocator",
-                                  &|data| data.needs_allocator());
+                                  &|data| data.needs_allocator(dep_graph));
     }
 
     fn inject_dependency_if(&self,
@@ -1029,7 +1066,7 @@ fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod,
                 Some(k) => {
                     struct_span_err!(self.sess, m.span, E0458,
                               "unknown kind: `{}`", k)
-                        .span_label(m.span, &format!("unknown kind")).emit();
+                        .span_label(m.span, "unknown kind").emit();
                     cstore::NativeUnknown
                 }
                 None => cstore::NativeUnknown
@@ -1042,7 +1079,7 @@ fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod,
                 None => {
                     struct_span_err!(self.sess, m.span, E0459,
                                      "#[link(...)] specified without `name = \"foo\"`")
-                        .span_label(m.span, &format!("missing `name` argument")).emit();
+                        .span_label(m.span, "missing `name` argument").emit();
                     Symbol::intern("foo")
                 }
             };
index 72ad1d75a5615761543ffdd61fd26b35a4fd2d38..64fccb0314e97d67743a613a58406568dbcde43f 100644 (file)
 // The crate store - a central repo for information collected about external
 // crates and libraries
 
-use locator;
-use schema;
+use schema::{self, Tracked};
 
-use rustc::dep_graph::DepGraph;
+use rustc::dep_graph::{DepGraph, DepNode, GlobalMetaDataKind};
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefIndex, DefId};
 use rustc::hir::map::definitions::DefPathTable;
 use rustc::hir::svh::Svh;
-use rustc::middle::cstore::{DepKind, ExternCrate};
+use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
 use rustc_back::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap, DefIdMap};
 
 use std::cell::{RefCell, Cell};
 use std::rc::Rc;
-use flate::Bytes;
+use owning_ref::ErasedBoxRef;
 use syntax::{ast, attr};
 use syntax::ext::base::SyntaxExtension;
 use syntax::symbol::Symbol;
 // own crate numbers.
 pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
 
-pub enum MetadataBlob {
-    Inflated(Bytes),
-    Archive(locator::ArchiveMetadata),
-    Raw(Vec<u8>),
-}
+pub struct MetadataBlob(pub ErasedBoxRef<[u8]>);
 
 /// Holds information about a syntax_pos::FileMap imported from another crate.
 /// See `imported_filemaps()` for more information.
@@ -83,14 +78,16 @@ pub struct CrateMetadata {
     /// compilation support.
     pub def_path_table: DefPathTable,
 
-    pub exported_symbols: FxHashSet<DefIndex>,
+    pub exported_symbols: Tracked<FxHashSet<DefIndex>>,
+
+    pub trait_impls: Tracked<FxHashMap<(u32, DefIndex), schema::LazySeq<DefIndex>>>,
 
     pub dep_kind: Cell<DepKind>,
     pub source: CrateSource,
 
     pub proc_macros: Option<Vec<(ast::Name, Rc<SyntaxExtension>)>>,
     // Foreign items imported from a dylib (Windows only)
-    pub dllimport_foreign_items: FxHashSet<DefIndex>,
+    pub dllimport_foreign_items: Tracked<FxHashSet<DefIndex>>,
 }
 
 pub struct CStore {
@@ -103,10 +100,11 @@ pub struct CStore {
     statically_included_foreign_items: RefCell<FxHashSet<DefIndex>>,
     pub dllimport_foreign_items: RefCell<FxHashSet<DefIndex>>,
     pub visible_parent_map: RefCell<DefIdMap<DefId>>,
+    pub metadata_loader: Box<MetadataLoader>,
 }
 
 impl CStore {
-    pub fn new(dep_graph: &DepGraph) -> CStore {
+    pub fn new(dep_graph: &DepGraph, metadata_loader: Box<MetadataLoader>) -> CStore {
         CStore {
             dep_graph: dep_graph.clone(),
             metas: RefCell::new(FxHashMap()),
@@ -116,6 +114,7 @@ pub fn new(dep_graph: &DepGraph) -> CStore {
             statically_included_foreign_items: RefCell::new(FxHashSet()),
             dllimport_foreign_items: RefCell::new(FxHashSet()),
             visible_parent_map: RefCell::new(FxHashMap()),
+            metadata_loader: metadata_loader,
         }
     }
 
@@ -269,51 +268,51 @@ pub fn disambiguator(&self) -> Symbol {
         self.root.disambiguator
     }
 
-    pub fn is_staged_api(&self) -> bool {
-        for attr in self.get_item_attrs(CRATE_DEF_INDEX).iter() {
-            if attr.path == "stable" || attr.path == "unstable" {
-                return true;
-            }
-        }
-        false
-    }
-
-    pub fn is_allocator(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn is_allocator(&self, dep_graph: &DepGraph) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
         attr::contains_name(&attrs, "allocator")
     }
 
-    pub fn needs_allocator(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn needs_allocator(&self, dep_graph: &DepGraph) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
         attr::contains_name(&attrs, "needs_allocator")
     }
 
-    pub fn is_panic_runtime(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn is_panic_runtime(&self, dep_graph: &DepGraph) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
         attr::contains_name(&attrs, "panic_runtime")
     }
 
-    pub fn needs_panic_runtime(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn needs_panic_runtime(&self, dep_graph: &DepGraph) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
         attr::contains_name(&attrs, "needs_panic_runtime")
     }
 
-    pub fn is_compiler_builtins(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn is_compiler_builtins(&self, dep_graph: &DepGraph) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
         attr::contains_name(&attrs, "compiler_builtins")
     }
 
-    pub fn is_sanitizer_runtime(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn is_sanitizer_runtime(&self, dep_graph: &DepGraph) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
         attr::contains_name(&attrs, "sanitizer_runtime")
     }
 
-    pub fn is_no_builtins(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn is_no_builtins(&self, dep_graph: &DepGraph) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
         attr::contains_name(&attrs, "no_builtins")
     }
 
-    pub fn panic_strategy(&self) -> PanicStrategy {
-        self.root.panic_strategy.clone()
+    pub fn panic_strategy(&self, dep_graph: &DepGraph) -> PanicStrategy {
+        let def_id = DefId {
+            krate: self.cnum,
+            index: CRATE_DEF_INDEX,
+        };
+        let dep_node = DepNode::GlobalMetaData(def_id, GlobalMetaDataKind::Krate);
+
+        self.root
+            .panic_strategy
+            .get(dep_graph, dep_node)
+            .clone()
     }
 }
index a1794ec2d82cace665364da1860a24d09c90c9bb..4b7083590d24af70af5fe809b12a06351564f494 100644 (file)
 
 use cstore;
 use encoder;
-use locator;
 use schema;
 
 use rustc::dep_graph::DepTrackingMapConfig;
 use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind,
-                            ExternCrate, NativeLibrary, LinkMeta,
+                            ExternCrate, NativeLibrary, MetadataLoader, LinkMeta,
                             LinkagePreference, LoadedMacro, EncodedMetadata};
 use rustc::hir::def;
 use rustc::middle::lang_items;
@@ -24,7 +23,7 @@
 use rustc::ty::maps::Providers;
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
 
-use rustc::dep_graph::DepNode;
+use rustc::dep_graph::{DepNode, GlobalMetaDataKind};
 use rustc::hir::map::{DefKey, DefPath, DisambiguatedDefPathData};
 use rustc::util::nodemap::{NodeSet, DefIdMap};
 use rustc_back::PanicStrategy;
 use syntax::symbol::Symbol;
 use syntax_pos::{Span, NO_EXPANSION};
 use rustc::hir::svh::Svh;
-use rustc_back::target::Target;
 use rustc::hir;
 
-use std::collections::BTreeMap;
-
 macro_rules! provide {
     (<$lt:tt> $tcx:ident, $def_id:ident, $cdata:ident $($name:ident => $compute:block)*) => {
         pub fn provide<$lt>(providers: &mut Providers<$lt>) {
@@ -113,21 +109,23 @@ pub fn provide<$lt>(providers: &mut Providers<$lt>) {
     def_span => { cdata.get_span(def_id.index, &tcx.sess) }
     stability => { cdata.get_stability(def_id.index) }
     deprecation => { cdata.get_deprecation(def_id.index) }
-    item_body_nested_bodies => {
-        let map: BTreeMap<_, _> = cdata.entry(def_id.index).ast.into_iter().flat_map(|ast| {
-            ast.decode(cdata).nested_bodies.decode(cdata).map(|body| (body.id(), body))
-        }).collect();
-
-        Rc::new(map)
-    }
+    item_attrs => { cdata.get_item_attrs(def_id.index, &tcx.dep_graph) }
+    // FIXME(#38501) We've skipped a `read` on the `HirBody` of
+    // a `fn` when encoding, so the dep-tracking wouldn't work.
+    // This is only used by rustdoc anyway, which shouldn't have
+    // incremental recompilation ever enabled.
+    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) }
+    is_exported_symbol => {
+        let dep_node = cdata.metadata_dep_node(GlobalMetaDataKind::ExportedSymbols);
+        cdata.exported_symbols.get(&tcx.dep_graph, dep_node).contains(&def_id.index)
+    }
+    item_body_nested_bodies => { Rc::new(cdata.item_body_nested_bodies(def_id.index)) }
     const_is_rvalue_promotable_to_static => {
-        cdata.entry(def_id.index).ast.expect("const item missing `ast`")
-            .decode(cdata).rvalue_promotable_to_static
-    }
-    is_mir_available => {
-        !cdata.is_proc_macro(def_id.index) &&
-        cdata.maybe_entry(def_id.index).and_then(|item| item.decode(cdata).mir).is_some()
+        cdata.const_is_rvalue_promotable_to_static(def_id.index)
     }
+    is_mir_available => { cdata.is_item_mir_available(def_id.index) }
 }
 
 impl CrateStore for cstore::CStore {
@@ -135,6 +133,10 @@ fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any> {
         self.get_crate_data(krate)
     }
 
+    fn metadata_loader(&self) -> &MetadataLoader {
+        &*self.metadata_loader
+    }
+
     fn visibility(&self, def: DefId) -> ty::Visibility {
         self.dep_graph.read(DepNode::MetaData(def));
         self.get_crate_data(def.krate).get_visibility(def.index)
@@ -145,30 +147,12 @@ fn item_generics_cloned(&self, def: DefId) -> ty::Generics {
         self.get_crate_data(def.krate).get_generics(def.index)
     }
 
-    fn item_attrs(&self, def_id: DefId) -> Rc<[ast::Attribute]>
-    {
-        self.dep_graph.read(DepNode::MetaData(def_id));
-        self.get_crate_data(def_id.krate).get_item_attrs(def_id.index)
-    }
-
-    fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name>
-    {
-        // FIXME(#38501) We've skipped a `read` on the `HirBody` of
-        // a `fn` when encoding, so the dep-tracking wouldn't work.
-        // This is only used by rustdoc anyway, which shouldn't have
-        // incremental recompilation ever enabled.
-        assert!(!self.dep_graph.is_fully_enabled());
-        self.get_crate_data(did.krate).get_fn_arg_names(did.index)
-    }
-
     fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>
     {
-        if let Some(def_id) = filter {
-            self.dep_graph.read(DepNode::MetaData(def_id));
-        }
         let mut result = vec![];
+
         self.iter_crate_data(|_, cdata| {
-            cdata.get_implementations_for_trait(filter, &mut result)
+            cdata.get_implementations_for_trait(filter, &self.dep_graph, &mut result)
         });
         result
     }
@@ -179,16 +163,6 @@ fn impl_defaultness(&self, def: DefId) -> hir::Defaultness
         self.get_crate_data(def.krate).get_impl_defaultness(def.index)
     }
 
-    fn impl_parent(&self, impl_def: DefId) -> Option<DefId> {
-        self.dep_graph.read(DepNode::MetaData(impl_def));
-        self.get_crate_data(impl_def.krate).get_parent_impl(impl_def.index)
-    }
-
-    fn trait_of_item(&self, def_id: DefId) -> Option<DefId> {
-        self.dep_graph.read(DepNode::MetaData(def_id));
-        self.get_crate_data(def_id.krate).get_trait_of_item(def_id.index)
-    }
-
     fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem
     {
         self.dep_graph.read(DepNode::MetaData(def));
@@ -206,80 +180,75 @@ fn is_default_impl(&self, impl_did: DefId) -> bool {
         self.get_crate_data(impl_did.krate).is_default_impl(impl_did.index)
     }
 
-    fn is_foreign_item(&self, did: DefId) -> bool {
-        self.get_crate_data(did.krate).is_foreign_item(did.index)
-    }
-
     fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool
     {
         self.do_is_statically_included_foreign_item(def_id)
     }
 
-    fn is_exported_symbol(&self, def_id: DefId) -> bool {
-        self.get_crate_data(def_id.krate).exported_symbols.contains(&def_id.index)
-    }
-
     fn is_dllimport_foreign_item(&self, def_id: DefId) -> bool {
         if def_id.krate == LOCAL_CRATE {
             self.dllimport_foreign_items.borrow().contains(&def_id.index)
         } else {
-            self.get_crate_data(def_id.krate).is_dllimport_foreign_item(def_id.index)
+            self.get_crate_data(def_id.krate)
+                .is_dllimport_foreign_item(def_id.index, &self.dep_graph)
         }
     }
 
     fn dylib_dependency_formats(&self, cnum: CrateNum)
                                 -> Vec<(CrateNum, LinkagePreference)>
     {
-        self.get_crate_data(cnum).get_dylib_dependency_formats()
+        self.get_crate_data(cnum).get_dylib_dependency_formats(&self.dep_graph)
     }
 
     fn dep_kind(&self, cnum: CrateNum) -> DepKind
     {
-        self.get_crate_data(cnum).dep_kind.get()
+        let data = self.get_crate_data(cnum);
+        let dep_node = data.metadata_dep_node(GlobalMetaDataKind::CrateDeps);
+        self.dep_graph.read(dep_node);
+        data.dep_kind.get()
     }
 
     fn export_macros(&self, cnum: CrateNum) {
-        if self.get_crate_data(cnum).dep_kind.get() == DepKind::UnexportedMacrosOnly {
-            self.get_crate_data(cnum).dep_kind.set(DepKind::MacrosOnly)
+        let data = self.get_crate_data(cnum);
+        let dep_node = data.metadata_dep_node(GlobalMetaDataKind::CrateDeps);
+
+        self.dep_graph.read(dep_node);
+        if data.dep_kind.get() == DepKind::UnexportedMacrosOnly {
+            data.dep_kind.set(DepKind::MacrosOnly)
         }
     }
 
     fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>
     {
-        self.get_crate_data(cnum).get_lang_items()
+        self.get_crate_data(cnum).get_lang_items(&self.dep_graph)
     }
 
     fn missing_lang_items(&self, cnum: CrateNum)
                           -> Vec<lang_items::LangItem>
     {
-        self.get_crate_data(cnum).get_missing_lang_items()
-    }
-
-    fn is_staged_api(&self, cnum: CrateNum) -> bool
-    {
-        self.get_crate_data(cnum).is_staged_api()
+        self.get_crate_data(cnum).get_missing_lang_items(&self.dep_graph)
     }
 
     fn is_allocator(&self, cnum: CrateNum) -> bool
     {
-        self.get_crate_data(cnum).is_allocator()
+        self.get_crate_data(cnum).is_allocator(&self.dep_graph)
     }
 
     fn is_panic_runtime(&self, cnum: CrateNum) -> bool
     {
-        self.get_crate_data(cnum).is_panic_runtime()
+        self.get_crate_data(cnum).is_panic_runtime(&self.dep_graph)
     }
 
     fn is_compiler_builtins(&self, cnum: CrateNum) -> bool {
-        self.get_crate_data(cnum).is_compiler_builtins()
+        self.get_crate_data(cnum).is_compiler_builtins(&self.dep_graph)
     }
 
     fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool {
-        self.get_crate_data(cnum).is_sanitizer_runtime()
+        self.get_crate_data(cnum).is_sanitizer_runtime(&self.dep_graph)
     }
 
     fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
-        self.get_crate_data(cnum).panic_strategy()
+        self.get_crate_data(cnum).panic_strategy(&self.dep_graph)
     }
 
     fn crate_name(&self, cnum: CrateNum) -> Symbol
@@ -325,16 +294,16 @@ fn derive_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>
 
     fn native_libraries(&self, cnum: CrateNum) -> Vec<NativeLibrary>
     {
-        self.get_crate_data(cnum).get_native_libraries()
+        self.get_crate_data(cnum).get_native_libraries(&self.dep_graph)
     }
 
     fn exported_symbols(&self, cnum: CrateNum) -> Vec<DefId>
     {
-        self.get_crate_data(cnum).get_exported_symbols()
+        self.get_crate_data(cnum).get_exported_symbols(&self.dep_graph)
     }
 
     fn is_no_builtins(&self, cnum: CrateNum) -> bool {
-        self.get_crate_data(cnum).is_no_builtins()
+        self.get_crate_data(cnum).is_no_builtins(&self.dep_graph)
     }
 
     fn retrace_path(&self,
@@ -401,7 +370,7 @@ fn load_macro(&self, id: DefId, sess: &Session) -> LoadedMacro {
         let body = filemap_to_stream(&sess.parse_sess, filemap);
 
         // Mark the attrs as used
-        let attrs = data.get_item_attrs(id.index);
+        let attrs = data.get_item_attrs(id.index, &self.dep_graph);
         for attr in attrs.iter() {
             attr::mark_used(attr);
         }
@@ -451,17 +420,6 @@ fn used_link_args(&self) -> Vec<String>
     {
         self.get_used_link_args().borrow().clone()
     }
-
-    fn metadata_filename(&self) -> &str
-    {
-        locator::METADATA_FILENAME
-    }
-
-    fn metadata_section_name(&self, target: &Target) -> &str
-    {
-        locator::meta_section_name(target)
-    }
-
     fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
     {
         self.do_get_used_crates(prefer)
@@ -483,7 +441,7 @@ fn encode_metadata<'a, 'tcx>(&self,
                                  reachable: &NodeSet)
                                  -> EncodedMetadata
     {
-        encoder::encode_metadata(tcx, self, link_meta, reachable)
+        encoder::encode_metadata(tcx, link_meta, reachable)
     }
 
     fn metadata_encoding_version(&self) -> &[u8]
@@ -553,4 +511,4 @@ fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>> {
         drop(visible_parent_map);
         self.visible_parent_map.borrow()
     }
-}
+}
\ No newline at end of file
index ae755adcf5fbbe8bb92b76fc9fa7ad9144371b2d..754f27810c453962e405463e3a83317896382c38 100644 (file)
@@ -13,6 +13,7 @@
 use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary};
 use schema::*;
 
+use rustc::dep_graph::{DepGraph, DepNode, GlobalMetaDataKind};
 use rustc::hir::map::{DefKey, DefPath, DefPathData};
 use rustc::hir;
 
@@ -20,7 +21,6 @@
 use rustc::hir::def::{self, Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::middle::lang_items;
-use rustc::middle::region;
 use rustc::session::Session;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::Substs;
@@ -29,6 +29,7 @@
 
 use std::borrow::Cow;
 use std::cell::Ref;
+use std::collections::BTreeMap;
 use std::io;
 use std::mem;
 use std::rc::Rc;
@@ -76,11 +77,7 @@ fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
 
 impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob {
     fn raw_bytes(self) -> &'a [u8] {
-        match *self {
-            MetadataBlob::Inflated(ref vec) => vec,
-            MetadataBlob::Archive(ref ar) => ar.as_slice(),
-            MetadataBlob::Raw(ref vec) => vec,
-        }
+        &self.0
     }
 }
 
@@ -358,12 +355,6 @@ fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
     }
 }
 
-impl<'a, 'tcx> SpecializedDecoder<region::CodeExtent<'tcx>> for DecodeContext<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<region::CodeExtent<'tcx>, Self::Error> {
-        Ok(self.tcx().intern_code_extent(Decodable::decode(self)?))
-    }
-}
-
 impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<Ty<'tcx>>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice<Ty<'tcx>>, Self::Error> {
         Ok(self.tcx().mk_type_list((0..self.read_usize()?).map(|_| Decodable::decode(self)))?)
@@ -404,10 +395,14 @@ pub fn get_root(&self) -> CrateRoot {
         Lazy::with_position(pos).decode(self)
     }
 
-    pub fn list_crate_metadata(&self, out: &mut io::Write) -> io::Result<()> {
+    pub fn list_crate_metadata(&self,
+                               out: &mut io::Write) -> io::Result<()> {
         write!(out, "=External Dependencies=\n")?;
         let root = self.get_root();
-        for (i, dep) in root.crate_deps.decode(self).enumerate() {
+        for (i, dep) in root.crate_deps
+                            .get_untracked()
+                            .decode(self)
+                            .enumerate() {
             write!(out, "{} {}-{}\n", i + 1, dep.name, dep.hash)?;
         }
         write!(out, "\n")?;
@@ -448,16 +443,16 @@ fn to_def(&self, did: DefId) -> Option<Def> {
 }
 
 impl<'a, 'tcx> CrateMetadata {
-    pub fn is_proc_macro(&self, id: DefIndex) -> bool {
+    fn is_proc_macro(&self, id: DefIndex) -> bool {
         self.proc_macros.is_some() && id != CRATE_DEF_INDEX
     }
 
-    pub fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
+    fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
         assert!(!self.is_proc_macro(item_id));
         self.root.index.lookup(self.blob.raw_bytes(), item_id)
     }
 
-    pub fn entry(&self, item_id: DefIndex) -> Entry<'tcx> {
+    fn entry(&self, item_id: DefIndex) -> Entry<'tcx> {
         match self.maybe_entry(item_id) {
             None => {
                 bug!("entry: id not found: {:?} in crate {:?} with number {}",
@@ -506,16 +501,11 @@ pub fn get_trait_def(&self, item_id: DefIndex) -> ty::TraitDef {
             _ => bug!(),
         };
 
-        let def = ty::TraitDef::new(self.local_def_id(item_id),
-                                    data.unsafety,
-                                    data.paren_sugar,
-                                    self.def_path_table.def_path_hash(item_id));
-
-        if data.has_default_impl {
-            def.record_has_default_impl();
-        }
-
-        def
+        ty::TraitDef::new(self.local_def_id(item_id),
+                          data.unsafety,
+                          data.paren_sugar,
+                          data.has_default_impl,
+                          self.def_path_table.def_path_hash(item_id))
     }
 
     fn get_variant(&self, item: &Entry, index: DefIndex) -> ty::VariantDef {
@@ -653,8 +643,13 @@ pub fn get_impl_trait(&self,
     }
 
     /// Iterates over the language items in the given crate.
-    pub fn get_lang_items(&self) -> Vec<(DefIndex, usize)> {
-        self.root.lang_items.decode(self).collect()
+    pub fn get_lang_items(&self, dep_graph: &DepGraph) -> Vec<(DefIndex, usize)> {
+        let dep_node = self.metadata_dep_node(GlobalMetaDataKind::LangItems);
+        self.root
+            .lang_items
+            .get(dep_graph, dep_node)
+            .decode(self)
+            .collect()
     }
 
     /// Iterates over each child of the given item.
@@ -779,6 +774,22 @@ pub fn item_body_tables(&self,
         tcx.alloc_tables(ast.tables.decode((self, tcx)))
     }
 
+    pub fn item_body_nested_bodies(&self, id: DefIndex) -> BTreeMap<hir::BodyId, hir::Body> {
+        self.entry(id).ast.into_iter().flat_map(|ast| {
+            ast.decode(self).nested_bodies.decode(self).map(|body| (body.id(), body))
+        }).collect()
+    }
+
+    pub fn const_is_rvalue_promotable_to_static(&self, id: DefIndex) -> bool {
+        self.entry(id).ast.expect("const item missing `ast`")
+            .decode(self).rvalue_promotable_to_static
+    }
+
+    pub fn is_item_mir_available(&self, id: DefIndex) -> bool {
+        !self.is_proc_macro(id) &&
+        self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some()
+    }
+
     pub fn maybe_get_optimized_mir(&self,
                                    tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    id: DefIndex)
@@ -853,13 +864,17 @@ pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
         }
     }
 
-    pub fn get_item_attrs(&self, node_id: DefIndex) -> Rc<[ast::Attribute]> {
+    pub fn get_item_attrs(&self,
+                          node_id: DefIndex,
+                          dep_graph: &DepGraph) -> Rc<[ast::Attribute]> {
         let (node_as, node_index) =
             (node_id.address_space().index(), node_id.as_array_index());
         if self.is_proc_macro(node_id) {
             return Rc::new([]);
         }
 
+        dep_graph.read(DepNode::MetaData(self.local_def_id(node_id)));
+
         if let Some(&Some(ref val)) =
             self.attribute_cache.borrow()[node_as].get(node_index) {
             return val.clone();
@@ -924,7 +939,10 @@ pub fn get_inherent_implementations_for_type(&self, id: DefIndex) -> Vec<DefId>
             .collect()
     }
 
-    pub fn get_implementations_for_trait(&self, filter: Option<DefId>, result: &mut Vec<DefId>) {
+    pub fn get_implementations_for_trait(&self,
+                                         filter: Option<DefId>,
+                                         dep_graph: &DepGraph,
+                                         result: &mut Vec<DefId>) {
         // Do a reverse lookup beforehand to avoid touching the crate_num
         // hash map in the loop below.
         let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) {
@@ -934,16 +952,17 @@ pub fn get_implementations_for_trait(&self, filter: Option<DefId>, result: &mut
             None => None,
         };
 
-        // FIXME(eddyb) Make this O(1) instead of O(n).
-        for trait_impls in self.root.impls.decode(self) {
-            if filter.is_some() && filter != Some(trait_impls.trait_id) {
-                continue;
-            }
-
-            result.extend(trait_impls.impls.decode(self).map(|index| self.local_def_id(index)));
+        let dep_node = self.metadata_dep_node(GlobalMetaDataKind::Impls);
 
-            if filter.is_some() {
-                break;
+        if let Some(filter) = filter {
+            if let Some(impls) = self.trait_impls
+                                     .get(dep_graph, dep_node)
+                                     .get(&filter) {
+                result.extend(impls.decode(self).map(|idx| self.local_def_id(idx)));
+            }
+        } else {
+            for impls in self.trait_impls.get(dep_graph, dep_node).values() {
+                result.extend(impls.decode(self).map(|idx| self.local_def_id(idx)));
             }
         }
     }
@@ -958,13 +977,29 @@ pub fn get_trait_of_item(&self, id: DefIndex) -> Option<DefId> {
     }
 
 
-    pub fn get_native_libraries(&self) -> Vec<NativeLibrary> {
-        self.root.native_libraries.decode(self).collect()
+    pub fn get_native_libraries(&self,
+                                dep_graph: &DepGraph)
+                                -> Vec<NativeLibrary> {
+        let dep_node = self.metadata_dep_node(GlobalMetaDataKind::NativeLibraries);
+        self.root
+            .native_libraries
+            .get(dep_graph, dep_node)
+            .decode(self)
+            .collect()
     }
 
-    pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> {
+    pub fn get_dylib_dependency_formats(&self,
+                                        dep_graph: &DepGraph)
+                                        -> Vec<(CrateNum, LinkagePreference)> {
+        let def_id = DefId {
+            krate: self.cnum,
+            index: CRATE_DEF_INDEX,
+        };
+        let dep_node = DepNode::GlobalMetaData(def_id,
+                                               GlobalMetaDataKind::DylibDependencyFormats);
         self.root
             .dylib_dependency_formats
+            .get(dep_graph, dep_node)
             .decode(self)
             .enumerate()
             .flat_map(|(i, link)| {
@@ -974,8 +1009,13 @@ pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)>
             .collect()
     }
 
-    pub fn get_missing_lang_items(&self) -> Vec<lang_items::LangItem> {
-        self.root.lang_items_missing.decode(self).collect()
+    pub fn get_missing_lang_items(&self, dep_graph: &DepGraph) -> Vec<lang_items::LangItem> {
+        let dep_node = self.metadata_dep_node(GlobalMetaDataKind::LangItemsMissing);
+        self.root
+            .lang_items_missing
+            .get(dep_graph, dep_node)
+            .decode(self)
+            .collect()
     }
 
     pub fn get_fn_arg_names(&self, id: DefIndex) -> Vec<ast::Name> {
@@ -988,8 +1028,13 @@ pub fn get_fn_arg_names(&self, id: DefIndex) -> Vec<ast::Name> {
         arg_names.decode(self).collect()
     }
 
-    pub fn get_exported_symbols(&self) -> Vec<DefId> {
-        self.exported_symbols.iter().map(|&index| self.local_def_id(index)).collect()
+    pub fn get_exported_symbols(&self, dep_graph: &DepGraph) -> Vec<DefId> {
+        let dep_node = self.metadata_dep_node(GlobalMetaDataKind::ExportedSymbols);
+        self.exported_symbols
+            .get(dep_graph, dep_node)
+            .iter()
+            .map(|&index| self.local_def_id(index))
+            .collect()
     }
 
     pub fn get_macro(&self, id: DefIndex) -> (ast::Name, MacroDef) {
@@ -1018,8 +1063,11 @@ pub fn is_foreign_item(&self, id: DefIndex) -> bool {
         }
     }
 
-    pub fn is_dllimport_foreign_item(&self, id: DefIndex) -> bool {
-        self.dllimport_foreign_items.contains(&id)
+    pub fn is_dllimport_foreign_item(&self, id: DefIndex, dep_graph: &DepGraph) -> bool {
+        let dep_node = self.metadata_dep_node(GlobalMetaDataKind::NativeLibraries);
+        self.dllimport_foreign_items
+            .get(dep_graph, dep_node)
+            .contains(&id)
     }
 
     pub fn is_default_impl(&self, impl_id: DefIndex) -> bool {
@@ -1097,121 +1145,62 @@ pub fn imported_filemaps(&'a self,
         let external_codemap = self.root.codemap.decode(self);
 
         let imported_filemaps = external_codemap.map(|filemap_to_import| {
-                // Try to find an existing FileMap that can be reused for the filemap to
-                // be imported. A FileMap is reusable if it is exactly the same, just
-                // positioned at a different offset within the codemap.
-                let reusable_filemap = {
-                    local_codemap.files
-                        .borrow()
-                        .iter()
-                        .find(|fm| are_equal_modulo_startpos(&fm, &filemap_to_import))
-                        .map(|rc| rc.clone())
-                };
-
-                match reusable_filemap {
-                    Some(fm) => {
-
-                        debug!("CrateMetaData::imported_filemaps reuse \
-                                filemap {:?} original (start_pos {:?} end_pos {:?}) \
-                                translated (start_pos {:?} end_pos {:?})",
-                               filemap_to_import.name,
-                               filemap_to_import.start_pos, filemap_to_import.end_pos,
-                               fm.start_pos, fm.end_pos);
-
-                        cstore::ImportedFileMap {
-                            original_start_pos: filemap_to_import.start_pos,
-                            original_end_pos: filemap_to_import.end_pos,
-                            translated_filemap: fm,
-                        }
-                    }
-                    None => {
-                        // We can't reuse an existing FileMap, so allocate a new one
-                        // containing the information we need.
-                        let syntax_pos::FileMap { name,
-                                                  name_was_remapped,
-                                                  start_pos,
-                                                  end_pos,
-                                                  lines,
-                                                  multibyte_chars,
-                                                  .. } = filemap_to_import;
-
-                        let source_length = (end_pos - start_pos).to_usize();
-
-                        // Translate line-start positions and multibyte character
-                        // position into frame of reference local to file.
-                        // `CodeMap::new_imported_filemap()` will then translate those
-                        // coordinates to their new global frame of reference when the
-                        // offset of the FileMap is known.
-                        let mut lines = lines.into_inner();
-                        for pos in &mut lines {
-                            *pos = *pos - start_pos;
-                        }
-                        let mut multibyte_chars = multibyte_chars.into_inner();
-                        for mbc in &mut multibyte_chars {
-                            mbc.pos = mbc.pos - start_pos;
-                        }
+            // We can't reuse an existing FileMap, so allocate a new one
+            // containing the information we need.
+            let syntax_pos::FileMap { name,
+                                      name_was_remapped,
+                                      start_pos,
+                                      end_pos,
+                                      lines,
+                                      multibyte_chars,
+                                      .. } = filemap_to_import;
+
+            let source_length = (end_pos - start_pos).to_usize();
+
+            // Translate line-start positions and multibyte character
+            // position into frame of reference local to file.
+            // `CodeMap::new_imported_filemap()` will then translate those
+            // coordinates to their new global frame of reference when the
+            // offset of the FileMap is known.
+            let mut lines = lines.into_inner();
+            for pos in &mut lines {
+                *pos = *pos - start_pos;
+            }
+            let mut multibyte_chars = multibyte_chars.into_inner();
+            for mbc in &mut multibyte_chars {
+                mbc.pos = mbc.pos - start_pos;
+            }
 
-                        let local_version = local_codemap.new_imported_filemap(name,
-                                                                               name_was_remapped,
-                                                                               source_length,
-                                                                               lines,
-                                                                               multibyte_chars);
-                        debug!("CrateMetaData::imported_filemaps alloc \
-                                filemap {:?} original (start_pos {:?} end_pos {:?}) \
-                                translated (start_pos {:?} end_pos {:?})",
-                               local_version.name, start_pos, end_pos,
-                               local_version.start_pos, local_version.end_pos);
-
-                        cstore::ImportedFileMap {
-                            original_start_pos: start_pos,
-                            original_end_pos: end_pos,
-                            translated_filemap: local_version,
-                        }
-                    }
-                }
-            })
-            .collect();
+            let local_version = local_codemap.new_imported_filemap(name,
+                                                                   name_was_remapped,
+                                                                   self.cnum.as_u32(),
+                                                                   source_length,
+                                                                   lines,
+                                                                   multibyte_chars);
+            debug!("CrateMetaData::imported_filemaps alloc \
+                    filemap {:?} original (start_pos {:?} end_pos {:?}) \
+                    translated (start_pos {:?} end_pos {:?})",
+                   local_version.name, start_pos, end_pos,
+                   local_version.start_pos, local_version.end_pos);
+
+            cstore::ImportedFileMap {
+                original_start_pos: start_pos,
+                original_end_pos: end_pos,
+                translated_filemap: local_version,
+            }
+        }).collect();
 
         // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref.
         *self.codemap_import_info.borrow_mut() = imported_filemaps;
         self.codemap_import_info.borrow()
     }
-}
-
-fn are_equal_modulo_startpos(fm1: &syntax_pos::FileMap, fm2: &syntax_pos::FileMap) -> bool {
-    if fm1.byte_length() != fm2.byte_length() {
-        return false;
-    }
 
-    if fm1.name != fm2.name {
-        return false;
-    }
-
-    let lines1 = fm1.lines.borrow();
-    let lines2 = fm2.lines.borrow();
-
-    if lines1.len() != lines2.len() {
-        return false;
-    }
-
-    for (&line1, &line2) in lines1.iter().zip(lines2.iter()) {
-        if (line1 - fm1.start_pos) != (line2 - fm2.start_pos) {
-            return false;
-        }
-    }
-
-    let multibytes1 = fm1.multibyte_chars.borrow();
-    let multibytes2 = fm2.multibyte_chars.borrow();
-
-    if multibytes1.len() != multibytes2.len() {
-        return false;
-    }
+    pub fn metadata_dep_node(&self, kind: GlobalMetaDataKind) -> DepNode<DefId> {
+        let def_id = DefId {
+            krate: self.cnum,
+            index: CRATE_DEF_INDEX,
+        };
 
-    for (mb1, mb2) in multibytes1.iter().zip(multibytes2.iter()) {
-        if (mb1.bytes != mb2.bytes) || ((mb1.pos - fm1.start_pos) != (mb2.pos - fm2.start_pos)) {
-            return false;
-        }
+        DepNode::GlobalMetaData(def_id, kind)
     }
-
-    true
 }
index 796cb8c4d651d08f02a107965013af44899af221..93fcdc455e5dd3762dc7dfe7d6f78e13c4e66ea0 100644 (file)
@@ -8,14 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use cstore;
 use index::Index;
+use index_builder::{FromId, IndexBuilder, Untracked};
+use isolated_encoder::IsolatedEncoder;
 use schema::*;
 
 use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary,
-                            EncodedMetadata, EncodedMetadataHash};
+                            EncodedMetadata, EncodedMetadataHashes};
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE};
 use rustc::hir::map::definitions::DefPathTable;
+use rustc::dep_graph::{DepNode, GlobalMetaDataKind};
+use rustc::ich::{StableHashingContext, Fingerprint};
 use rustc::middle::dependency_format::Linkage;
 use rustc::middle::lang_items;
 use rustc::mir;
 use rustc::util::nodemap::{FxHashMap, NodeSet};
 
 use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
+use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
+
 use std::hash::Hash;
 use std::intrinsics;
 use std::io::prelude::*;
 use std::io::Cursor;
 use std::path::Path;
 use std::rc::Rc;
+use std::sync::Arc;
 use std::u32;
 use syntax::ast::{self, CRATE_NODE_ID};
 use syntax::codemap::Spanned;
 use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
 use rustc::hir::intravisit;
 
-use super::index_builder::{FromId, IndexBuilder, Untracked, EntryBuilder};
-
 pub struct EncodeContext<'a, 'tcx: 'a> {
     opaque: opaque::Encoder<'a>,
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     link_meta: &'a LinkMeta,
-    cstore: &'a cstore::CStore,
     exported_symbols: &'a NodeSet,
 
     lazy_state: LazyState,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
     predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
 
-    pub metadata_hashes: Vec<EncodedMetadataHash>,
+    pub metadata_hashes: EncodedMetadataHashes,
+    pub compute_ich: bool,
 }
 
 macro_rules! encoder_methods {
@@ -134,6 +138,7 @@ fn specialized_encode(&mut self,
 }
 
 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
+
     pub fn position(&self) -> usize {
         self.opaque.position()
     }
@@ -237,11 +242,240 @@ fn encode_with_shorthand<T, U, M>(&mut self,
 
         Ok(())
     }
+
+    // Encodes something that corresponds to a single DepNode::GlobalMetaData
+    // and registers the Fingerprint in the `metadata_hashes` map.
+    pub fn tracked<'x, DATA, R>(&'x mut self,
+                                dep_node: DepNode<()>,
+                                op: fn(&mut IsolatedEncoder<'x, 'a, 'tcx>, DATA) -> R,
+                                data: DATA)
+                                -> Tracked<R> {
+        let mut entry_builder = IsolatedEncoder::new(self);
+        let ret = op(&mut entry_builder, data);
+        let (fingerprint, this) = entry_builder.finish();
+
+        if let Some(fingerprint) = fingerprint {
+            this.metadata_hashes.global_hashes.push((dep_node, fingerprint));
+        }
+
+        Tracked::new(ret)
+    }
+
+    fn encode_info_for_items(&mut self) -> Index {
+        let krate = self.tcx.hir.krate();
+        let mut index = IndexBuilder::new(self);
+        index.record(DefId::local(CRATE_DEF_INDEX),
+                     IsolatedEncoder::encode_info_for_mod,
+                     FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public)));
+        let mut visitor = EncodeVisitor { index: index };
+        krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
+        for macro_def in &krate.exported_macros {
+            visitor.visit_macro_def(macro_def);
+        }
+        visitor.index.into_items()
+    }
+
+    fn encode_def_path_table(&mut self) -> Lazy<DefPathTable> {
+        let definitions = self.tcx.hir.definitions();
+        self.lazy(definitions.def_path_table())
+    }
+
+    fn encode_codemap(&mut self) -> LazySeq<syntax_pos::FileMap> {
+        let codemap = self.tcx.sess.codemap();
+        let all_filemaps = codemap.files();
+
+        let hcx = &mut StableHashingContext::new(self.tcx);
+        let (working_dir, working_dir_was_remapped) = self.tcx.sess.working_dir.clone();
+
+        let adapted = all_filemaps.iter()
+            .filter(|filemap| {
+                // No need to re-export imported filemaps, as any downstream
+                // crate will import them from their original source.
+                !filemap.is_imported()
+            })
+            .map(|filemap| {
+                // When exporting FileMaps, we expand all paths to absolute
+                // paths because any relative paths are potentially relative to
+                // a wrong directory.
+                // However, if a path has been modified via
+                // `-Zremap-path-prefix` we assume the user has already set
+                // things up the way they want and don't touch the path values
+                // anymore.
+                let name = Path::new(&filemap.name);
+                if filemap.name_was_remapped ||
+                   (name.is_relative() && working_dir_was_remapped) {
+                    // This path of this FileMap has been modified by
+                    // path-remapping, so we use it verbatim (and avoid cloning
+                    // the whole map in the process).
+                    filemap.clone()
+                } else {
+                    let mut adapted = (**filemap).clone();
+                    let abs_path = Path::new(&working_dir).join(name)
+                                                         .to_string_lossy()
+                                                         .into_owned();
+                    adapted.name = abs_path;
+                    Rc::new(adapted)
+                }
+            });
+
+        let filemaps: Vec<_> = if self.compute_ich {
+            adapted.inspect(|filemap| {
+                let mut hasher = StableHasher::new();
+                filemap.hash_stable(hcx, &mut hasher);
+                let fingerprint = hasher.finish();
+                let dep_node = DepNode::FileMap((), Arc::new(filemap.name.clone()));
+                self.metadata_hashes.global_hashes.push((dep_node, fingerprint));
+            }).collect()
+        } else {
+            adapted.collect()
+        };
+
+        self.lazy_seq_ref(filemaps.iter().map(|fm| &**fm))
+    }
+
+    fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
+        let mut i = self.position();
+
+        let crate_deps = self.tracked(
+            DepNode::GlobalMetaData((), GlobalMetaDataKind::CrateDeps),
+            IsolatedEncoder::encode_crate_deps,
+            ());
+        let dylib_dependency_formats = self.tracked(
+            DepNode::GlobalMetaData((), GlobalMetaDataKind::DylibDependencyFormats),
+            IsolatedEncoder::encode_dylib_dependency_formats,
+            ());
+        let dep_bytes = self.position() - i;
+
+        // Encode the language items.
+        i = self.position();
+        let lang_items = self.tracked(
+            DepNode::GlobalMetaData((), GlobalMetaDataKind::LangItems),
+            IsolatedEncoder::encode_lang_items,
+            ());
+
+        let lang_items_missing = self.tracked(
+            DepNode::GlobalMetaData((), GlobalMetaDataKind::LangItemsMissing),
+            IsolatedEncoder::encode_lang_items_missing,
+            ());
+        let lang_item_bytes = self.position() - i;
+
+        // Encode the native libraries used
+        i = self.position();
+        let native_libraries = self.tracked(
+            DepNode::GlobalMetaData((), GlobalMetaDataKind::NativeLibraries),
+            IsolatedEncoder::encode_native_libraries,
+            ());
+        let native_lib_bytes = self.position() - i;
+
+        // Encode codemap
+        i = self.position();
+        let codemap = self.encode_codemap();
+        let codemap_bytes = self.position() - i;
+
+        // Encode DefPathTable
+        i = self.position();
+        let def_path_table = self.encode_def_path_table();
+        let def_path_table_bytes = self.position() - i;
+
+        // Encode the def IDs of impls, for coherence checking.
+        i = self.position();
+        let impls = self.tracked(
+            DepNode::GlobalMetaData((), GlobalMetaDataKind::Impls),
+            IsolatedEncoder::encode_impls,
+            ());
+        let impl_bytes = self.position() - i;
+
+        // Encode exported symbols info.
+        i = self.position();
+        let exported_symbols = self.tracked(
+            DepNode::GlobalMetaData((), GlobalMetaDataKind::ExportedSymbols),
+            IsolatedEncoder::encode_exported_symbols,
+            self.exported_symbols);
+        let exported_symbols_bytes = self.position() - i;
+
+        // Encode and index the items.
+        i = self.position();
+        let items = self.encode_info_for_items();
+        let item_bytes = self.position() - i;
+
+        i = self.position();
+        let index = items.write_index(&mut self.opaque.cursor);
+        let index_bytes = self.position() - i;
+
+        let tcx = self.tcx;
+        let link_meta = self.link_meta;
+        let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro);
+        let root = self.lazy(&CrateRoot {
+            name: tcx.crate_name(LOCAL_CRATE),
+            triple: tcx.sess.opts.target_triple.clone(),
+            hash: link_meta.crate_hash,
+            disambiguator: tcx.sess.local_crate_disambiguator(),
+            panic_strategy: Tracked::new(tcx.sess.panic_strategy()),
+            plugin_registrar_fn: tcx.sess
+                .plugin_registrar_fn
+                .get()
+                .map(|id| tcx.hir.local_def_id(id).index),
+            macro_derive_registrar: if is_proc_macro {
+                let id = tcx.sess.derive_registrar_fn.get().unwrap();
+                Some(tcx.hir.local_def_id(id).index)
+            } else {
+                None
+            },
+
+            crate_deps: crate_deps,
+            dylib_dependency_formats: dylib_dependency_formats,
+            lang_items: lang_items,
+            lang_items_missing: lang_items_missing,
+            native_libraries: native_libraries,
+            codemap: codemap,
+            def_path_table: def_path_table,
+            impls: impls,
+            exported_symbols: exported_symbols,
+            index: index,
+        });
+
+        let total_bytes = self.position();
+
+        self.metadata_hashes.global_hashes.push((
+            DepNode::GlobalMetaData((), GlobalMetaDataKind::Krate),
+            Fingerprint::from_smaller_hash(link_meta.crate_hash.as_u64())
+        ));
+
+        if self.tcx.sess.meta_stats() {
+            let mut zero_bytes = 0;
+            for e in self.opaque.cursor.get_ref() {
+                if *e == 0 {
+                    zero_bytes += 1;
+                }
+            }
+
+            println!("metadata stats:");
+            println!("             dep bytes: {}", dep_bytes);
+            println!("       lang item bytes: {}", lang_item_bytes);
+            println!("          native bytes: {}", native_lib_bytes);
+            println!("         codemap bytes: {}", codemap_bytes);
+            println!("            impl bytes: {}", impl_bytes);
+            println!("    exp. symbols bytes: {}", exported_symbols_bytes);
+            println!("  def-path table bytes: {}", def_path_table_bytes);
+            println!("            item bytes: {}", item_bytes);
+            println!("           index bytes: {}", index_bytes);
+            println!("            zero bytes: {}", zero_bytes);
+            println!("           total bytes: {}", total_bytes);
+        }
+
+        root
+    }
 }
 
-impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
+// These are methods for encoding various things. They are meant to be used with
+// IndexBuilder::record() and EncodeContext::tracked(). They actually
+// would not have to be methods of IsolatedEncoder (free standing functions
+// taking IsolatedEncoder as first argument would be just fine) but by making
+// them methods we don't have to repeat the lengthy `<'a, 'b: 'a, 'tcx: 'b>`
+// clause again and again.
+impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
     fn encode_variances_of(&mut self, def_id: DefId) -> LazySeq<ty::Variance> {
-        debug!("EntryBuilder::encode_variances_of({:?})", def_id);
+        debug!("IsolatedEncoder::encode_variances_of({:?})", def_id);
         let tcx = self.tcx;
         self.lazy_seq_from_slice(&tcx.variances_of(def_id))
     }
@@ -249,7 +483,7 @@ fn encode_variances_of(&mut self, def_id: DefId) -> LazySeq<ty::Variance> {
     fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> {
         let tcx = self.tcx;
         let ty = tcx.type_of(def_id);
-        debug!("EntryBuilder::encode_item_type({:?}) => {:?}", def_id, ty);
+        debug!("IsolatedEncoder::encode_item_type({:?}) => {:?}", def_id, ty);
         self.lazy(&ty)
     }
 
@@ -265,7 +499,7 @@ fn encode_enum_variant_info(&mut self,
         let def = tcx.adt_def(enum_did);
         let variant = &def.variants[index];
         let def_id = variant.did;
-        debug!("EntryBuilder::encode_enum_variant_info({:?})", def_id);
+        debug!("IsolatedEncoder::encode_enum_variant_info({:?})", def_id);
 
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
@@ -306,7 +540,7 @@ fn encode_info_for_mod(&mut self,
                            -> Entry<'tcx> {
         let tcx = self.tcx;
         let def_id = tcx.hir.local_def_id(id);
-        debug!("EntryBuilder::encode_info_for_mod({:?})", def_id);
+        debug!("IsolatedEncoder::encode_info_for_mod({:?})", def_id);
 
         let data = ModData {
             reexports: match tcx.export_map.get(&id) {
@@ -338,22 +572,7 @@ fn encode_info_for_mod(&mut self,
             mir: None
         }
     }
-}
-
-impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
-    fn encode_fields(&mut self, adt_def_id: DefId) {
-        let def = self.tcx.adt_def(adt_def_id);
-        for (variant_index, variant) in def.variants.iter().enumerate() {
-            for (field_index, field) in variant.fields.iter().enumerate() {
-                self.record(field.did,
-                            EntryBuilder::encode_field,
-                            (adt_def_id, Untracked((variant_index, field_index))));
-            }
-        }
-    }
-}
 
-impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
     /// Encode data for the given field of the given variant of the
     /// given ADT. The indices of the variant/field are untracked:
     /// this is ok because we will have to lookup the adt-def by its
@@ -370,7 +589,7 @@ fn encode_field(&mut self,
         let field = &variant.fields[field_index];
 
         let def_id = field.did;
-        debug!("EntryBuilder::encode_field({:?})", def_id);
+        debug!("IsolatedEncoder::encode_field({:?})", def_id);
 
         let variant_id = tcx.hir.as_local_node_id(variant.did).unwrap();
         let variant_data = tcx.hir.expect_variant_data(variant_id);
@@ -396,7 +615,7 @@ fn encode_field(&mut self,
     }
 
     fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> {
-        debug!("EntryBuilder::encode_struct_ctor({:?})", def_id);
+        debug!("IsolatedEncoder::encode_struct_ctor({:?})", def_id);
         let tcx = self.tcx;
         let variant = tcx.adt_def(adt_def_id).struct_variant();
 
@@ -438,19 +657,19 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
     }
 
     fn encode_generics(&mut self, def_id: DefId) -> Lazy<ty::Generics> {
-        debug!("EntryBuilder::encode_generics({:?})", def_id);
+        debug!("IsolatedEncoder::encode_generics({:?})", def_id);
         let tcx = self.tcx;
         self.lazy(tcx.generics_of(def_id))
     }
 
     fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
-        debug!("EntryBuilder::encode_predicates({:?})", def_id);
+        debug!("IsolatedEncoder::encode_predicates({:?})", def_id);
         let tcx = self.tcx;
         self.lazy(&tcx.predicates_of(def_id))
     }
 
     fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
-        debug!("EntryBuilder::encode_info_for_trait_item({:?})", def_id);
+        debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id);
         let tcx = self.tcx;
 
         let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
@@ -533,7 +752,7 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
     }
 
     fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
-        debug!("EntryBuilder::encode_info_for_impl_item({:?})", def_id);
+        debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id);
         let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
         let ast_item = self.tcx.hir.expect_impl_item(node_id);
         let impl_item = self.tcx.associated_item(def_id);
@@ -631,7 +850,7 @@ fn encode_optimized_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>
 
     // Encodes the inherent implementations of a structure, enumeration, or trait.
     fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex> {
-        debug!("EntryBuilder::encode_inherent_implementations({:?})", def_id);
+        debug!("IsolatedEncoder::encode_inherent_implementations({:?})", def_id);
         let implementations = self.tcx.inherent_impls(def_id);
         if implementations.is_empty() {
             LazySeq::empty()
@@ -644,19 +863,19 @@ fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex
     }
 
     fn encode_stability(&mut self, def_id: DefId) -> Option<Lazy<attr::Stability>> {
-        debug!("EntryBuilder::encode_stability({:?})", def_id);
+        debug!("IsolatedEncoder::encode_stability({:?})", def_id);
         self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab))
     }
 
     fn encode_deprecation(&mut self, def_id: DefId) -> Option<Lazy<attr::Deprecation>> {
-        debug!("EntryBuilder::encode_deprecation({:?})", def_id);
+        debug!("IsolatedEncoder::encode_deprecation({:?})", def_id);
         self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr))
     }
 
     fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> {
         let tcx = self.tcx;
 
-        debug!("EntryBuilder::encode_info_for_item({:?})", def_id);
+        debug!("IsolatedEncoder::encode_info_for_item({:?})", def_id);
 
         let kind = match item.node {
             hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic,
@@ -724,7 +943,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 let trait_ref = tcx.impl_trait_ref(def_id);
                 let parent = if let Some(trait_ref) = trait_ref {
                     let trait_def = tcx.trait_def(trait_ref.def_id);
-                    trait_def.ancestors(def_id).skip(1).next().and_then(|node| {
+                    trait_def.ancestors(tcx, def_id).skip(1).next().and_then(|node| {
                         match node {
                             specialization_graph::Node::Impl(parent) => Some(parent),
                             _ => None,
@@ -902,224 +1121,38 @@ fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx
             mir: None,
         }
     }
-}
 
-impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
-    /// In some cases, along with the item itself, we also
-    /// encode some sub-items. Usually we want some info from the item
-    /// so it's easier to do that here then to wait until we would encounter
-    /// normally in the visitor walk.
-    fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
-        let def_id = self.tcx.hir.local_def_id(item.id);
-        match item.node {
-            hir::ItemStatic(..) |
-            hir::ItemConst(..) |
-            hir::ItemFn(..) |
-            hir::ItemMod(..) |
-            hir::ItemForeignMod(..) |
-            hir::ItemGlobalAsm(..) |
-            hir::ItemExternCrate(..) |
-            hir::ItemUse(..) |
-            hir::ItemDefaultImpl(..) |
-            hir::ItemTy(..) => {
-                // no sub-item recording needed in these cases
-            }
-            hir::ItemEnum(..) => {
-                self.encode_fields(def_id);
+    fn encode_info_for_ty_param(&mut self,
+                                (def_id, Untracked(has_default)): (DefId, Untracked<bool>))
+                                -> Entry<'tcx> {
+        debug!("IsolatedEncoder::encode_info_for_ty_param({:?})", def_id);
+        let tcx = self.tcx;
+        Entry {
+            kind: EntryKind::Type,
+            visibility: self.lazy(&ty::Visibility::Public),
+            span: self.lazy(&tcx.def_span(def_id)),
+            attributes: LazySeq::empty(),
+            children: LazySeq::empty(),
+            stability: None,
+            deprecation: None,
 
-                let def = self.tcx.adt_def(def_id);
-                for (i, variant) in def.variants.iter().enumerate() {
-                    self.record(variant.did,
-                                EntryBuilder::encode_enum_variant_info,
-                                (def_id, Untracked(i)));
-                }
-            }
-            hir::ItemStruct(ref struct_def, _) => {
-                self.encode_fields(def_id);
+            ty: if has_default {
+                Some(self.encode_item_type(def_id))
+            } else {
+                None
+            },
+            inherent_impls: LazySeq::empty(),
+            variances: LazySeq::empty(),
+            generics: None,
+            predicates: None,
 
-                // If the struct has a constructor, encode it.
-                if !struct_def.is_struct() {
-                    let ctor_def_id = self.tcx.hir.local_def_id(struct_def.id());
-                    self.record(ctor_def_id,
-                                EntryBuilder::encode_struct_ctor,
-                                (def_id, ctor_def_id));
-                }
-            }
-            hir::ItemUnion(..) => {
-                self.encode_fields(def_id);
-            }
-            hir::ItemImpl(..) => {
-                for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
-                    self.record(trait_item_def_id,
-                                EntryBuilder::encode_info_for_impl_item,
-                                trait_item_def_id);
-                }
-            }
-            hir::ItemTrait(..) => {
-                for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
-                    self.record(item_def_id,
-                                EntryBuilder::encode_info_for_trait_item,
-                                item_def_id);
-                }
-            }
-        }
-    }
-}
-
-impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
-    fn encode_info_for_foreign_item(&mut self,
-                                    (def_id, nitem): (DefId, &hir::ForeignItem))
-                                    -> Entry<'tcx> {
-        let tcx = self.tcx;
-
-        debug!("EntryBuilder::encode_info_for_foreign_item({:?})", def_id);
-
-        let kind = match nitem.node {
-            hir::ForeignItemFn(_, ref names, _) => {
-                let data = FnData {
-                    constness: hir::Constness::NotConst,
-                    arg_names: self.encode_fn_arg_names(names),
-                };
-                EntryKind::ForeignFn(self.lazy(&data))
-            }
-            hir::ForeignItemStatic(_, true) => EntryKind::ForeignMutStatic,
-            hir::ForeignItemStatic(_, false) => EntryKind::ForeignImmStatic,
-        };
-
-        Entry {
-            kind: kind,
-            visibility: self.lazy(&ty::Visibility::from_hir(&nitem.vis, nitem.id, tcx)),
-            span: self.lazy(&nitem.span),
-            attributes: self.encode_attributes(&nitem.attrs),
-            children: LazySeq::empty(),
-            stability: self.encode_stability(def_id),
-            deprecation: self.encode_deprecation(def_id),
-
-            ty: Some(self.encode_item_type(def_id)),
-            inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
-            generics: Some(self.encode_generics(def_id)),
-            predicates: Some(self.encode_predicates(def_id)),
-
-            ast: None,
-            mir: None,
-        }
-    }
-}
-
-struct EncodeVisitor<'a, 'b: 'a, 'tcx: 'b> {
-    index: IndexBuilder<'a, 'b, 'tcx>,
-}
-
-impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::OnlyBodies(&self.index.tcx.hir)
-    }
-    fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
-        intravisit::walk_expr(self, ex);
-        self.index.encode_info_for_expr(ex);
-    }
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
-        intravisit::walk_item(self, item);
-        let def_id = self.index.tcx.hir.local_def_id(item.id);
-        match item.node {
-            hir::ItemExternCrate(_) |
-            hir::ItemUse(..) => (), // ignore these
-            _ => self.index.record(def_id, EntryBuilder::encode_info_for_item, (def_id, item)),
-        }
-        self.index.encode_addl_info_for_item(item);
-    }
-    fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
-        intravisit::walk_foreign_item(self, ni);
-        let def_id = self.index.tcx.hir.local_def_id(ni.id);
-        self.index.record(def_id,
-                          EntryBuilder::encode_info_for_foreign_item,
-                          (def_id, ni));
-    }
-    fn visit_variant(&mut self,
-                     v: &'tcx hir::Variant,
-                     g: &'tcx hir::Generics,
-                     id: ast::NodeId) {
-        intravisit::walk_variant(self, v, g, id);
-
-        if let Some(discr) = v.node.disr_expr {
-            let def_id = self.index.tcx.hir.body_owner_def_id(discr);
-            self.index.record(def_id, EntryBuilder::encode_info_for_embedded_const, def_id);
-        }
-    }
-    fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
-        intravisit::walk_generics(self, generics);
-        self.index.encode_info_for_generics(generics);
-    }
-    fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
-        intravisit::walk_ty(self, ty);
-        self.index.encode_info_for_ty(ty);
-    }
-    fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
-        let def_id = self.index.tcx.hir.local_def_id(macro_def.id);
-        self.index.record(def_id, EntryBuilder::encode_info_for_macro_def, macro_def);
-    }
-}
-
-impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
-    fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
-        for ty_param in &generics.ty_params {
-            let def_id = self.tcx.hir.local_def_id(ty_param.id);
-            let has_default = Untracked(ty_param.default.is_some());
-            self.record(def_id, EntryBuilder::encode_info_for_ty_param, (def_id, has_default));
-        }
-    }
-
-    fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
-        if let hir::TyImplTrait(_) = ty.node {
-            let def_id = self.tcx.hir.local_def_id(ty.id);
-            self.record(def_id, EntryBuilder::encode_info_for_anon_ty, def_id);
-        }
-    }
-
-    fn encode_info_for_expr(&mut self, expr: &hir::Expr) {
-        match expr.node {
-            hir::ExprClosure(..) => {
-                let def_id = self.tcx.hir.local_def_id(expr.id);
-                self.record(def_id, EntryBuilder::encode_info_for_closure, def_id);
-            }
-            _ => {}
-        }
-    }
-}
-
-impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
-    fn encode_info_for_ty_param(&mut self,
-                                (def_id, Untracked(has_default)): (DefId, Untracked<bool>))
-                                -> Entry<'tcx> {
-        debug!("EntryBuilder::encode_info_for_ty_param({:?})", def_id);
-        let tcx = self.tcx;
-        Entry {
-            kind: EntryKind::Type,
-            visibility: self.lazy(&ty::Visibility::Public),
-            span: self.lazy(&tcx.def_span(def_id)),
-            attributes: LazySeq::empty(),
-            children: LazySeq::empty(),
-            stability: None,
-            deprecation: None,
-
-            ty: if has_default {
-                Some(self.encode_item_type(def_id))
-            } else {
-                None
-            },
-            inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
-            generics: None,
-            predicates: None,
-
-            ast: None,
-            mir: None,
+            ast: None,
+            mir: None,
         }
     }
 
     fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
-        debug!("EntryBuilder::encode_info_for_anon_ty({:?})", def_id);
+        debug!("IsolatedEncoder::encode_info_for_anon_ty({:?})", def_id);
         let tcx = self.tcx;
         Entry {
             kind: EntryKind::Type,
@@ -1142,7 +1175,7 @@ fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
     }
 
     fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
-        debug!("EntryBuilder::encode_info_for_closure({:?})", def_id);
+        debug!("IsolatedEncoder::encode_info_for_closure({:?})", def_id);
         let tcx = self.tcx;
 
         let data = ClosureData {
@@ -1171,7 +1204,7 @@ fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
     }
 
     fn encode_info_for_embedded_const(&mut self, def_id: DefId) -> Entry<'tcx> {
-        debug!("EntryBuilder::encode_info_for_embedded_const({:?})", def_id);
+        debug!("IsolatedEncoder::encode_info_for_embedded_const({:?})", def_id);
         let tcx = self.tcx;
         let id = tcx.hir.as_local_node_id(def_id).unwrap();
         let body = tcx.hir.body_owned_by(id);
@@ -1198,171 +1231,101 @@ fn encode_info_for_embedded_const(&mut self, def_id: DefId) -> Entry<'tcx> {
 
     fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
         // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because
-        //       we really on the HashStable specialization for [Attribute]
+        //       we rely on the HashStable specialization for [Attribute]
         //       to properly filter things out.
         self.lazy_seq_from_slice(attrs)
     }
-}
 
-impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
-    fn encode_info_for_items(&mut self) -> Index {
-        let krate = self.tcx.hir.krate();
-        let mut index = IndexBuilder::new(self);
-        index.record(DefId::local(CRATE_DEF_INDEX),
-                     EntryBuilder::encode_info_for_mod,
-                     FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public)));
-        let mut visitor = EncodeVisitor { index: index };
-        krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
-        for macro_def in &krate.exported_macros {
-            visitor.visit_macro_def(macro_def);
-        }
-        visitor.index.into_items()
+    fn encode_native_libraries(&mut self, _: ()) -> LazySeq<NativeLibrary> {
+        let used_libraries = self.tcx.sess.cstore.used_libraries();
+        self.lazy_seq(used_libraries)
     }
 
-    fn encode_crate_deps(&mut self) -> LazySeq<CrateDep> {
-        fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<(CrateNum, Rc<cstore::CrateMetadata>)> {
-            // Pull the cnums and name,vers,hash out of cstore
-            let mut deps = Vec::new();
-            cstore.iter_crate_data(|cnum, val| {
-                deps.push((cnum, val.clone()));
-            });
+    fn encode_crate_deps(&mut self, _: ()) -> LazySeq<CrateDep> {
+        let cstore = &*self.tcx.sess.cstore;
+        let crates = cstore.crates();
 
-            // Sort by cnum
-            deps.sort_by(|kv1, kv2| kv1.0.cmp(&kv2.0));
+        let mut deps = crates
+            .iter()
+            .map(|&cnum| {
+                let dep = CrateDep {
+                    name: cstore.original_crate_name(cnum),
+                    hash: cstore.crate_hash(cnum),
+                    kind: cstore.dep_kind(cnum),
+                };
+                (cnum, dep)
+            })
+            .collect::<Vec<_>>();
 
+        deps.sort_by_key(|&(cnum, _)| cnum);
+
+        {
             // Sanity-check the crate numbers
             let mut expected_cnum = 1;
             for &(n, _) in &deps {
                 assert_eq!(n, CrateNum::new(expected_cnum));
                 expected_cnum += 1;
             }
-
-            deps
         }
 
         // We're just going to write a list of crate 'name-hash-version's, with
         // the assumption that they are numbered 1 to n.
         // FIXME (#2166): This is not nearly enough to support correct versioning
         // but is enough to get transitive crate dependencies working.
-        let deps = get_ordered_deps(self.cstore);
-        self.lazy_seq(deps.iter().map(|&(_, ref dep)| {
-            CrateDep {
-                name: dep.name(),
-                hash: dep.hash(),
-                kind: dep.dep_kind.get(),
-            }
-        }))
+        self.lazy_seq_ref(deps.iter().map(|&(_, ref dep)| dep))
     }
 
-    fn encode_lang_items(&mut self) -> (LazySeq<(DefIndex, usize)>, LazySeq<lang_items::LangItem>) {
+    fn encode_lang_items(&mut self, _: ()) -> LazySeq<(DefIndex, usize)> {
         let tcx = self.tcx;
         let lang_items = tcx.lang_items.items().iter();
-        (self.lazy_seq(lang_items.enumerate().filter_map(|(i, &opt_def_id)| {
+        self.lazy_seq(lang_items.enumerate().filter_map(|(i, &opt_def_id)| {
             if let Some(def_id) = opt_def_id {
                 if def_id.is_local() {
                     return Some((def_id.index, i));
                 }
             }
             None
-        })),
-         self.lazy_seq_ref(&tcx.lang_items.missing))
-    }
-
-    fn encode_native_libraries(&mut self) -> LazySeq<NativeLibrary> {
-        let used_libraries = self.tcx.sess.cstore.used_libraries();
-        self.lazy_seq(used_libraries)
-    }
-
-    fn encode_codemap(&mut self) -> LazySeq<syntax_pos::FileMap> {
-        let codemap = self.tcx.sess.codemap();
-        let all_filemaps = codemap.files.borrow();
-        let adapted = all_filemaps.iter()
-            .filter(|filemap| {
-                // No need to re-export imported filemaps, as any downstream
-                // crate will import them from their original source.
-                !filemap.is_imported()
-            })
-            .map(|filemap| {
-                // When exporting FileMaps, we expand all paths to absolute
-                // paths because any relative paths are potentially relative to
-                // a wrong directory.
-                // However, if a path has been modified via
-                // `-Zremap-path-prefix` we assume the user has already set
-                // things up the way they want and don't touch the path values
-                // anymore.
-                let name = Path::new(&filemap.name);
-                let (ref working_dir, working_dir_was_remapped) = self.tcx.sess.working_dir;
-                if filemap.name_was_remapped ||
-                   (name.is_relative() && working_dir_was_remapped) {
-                    // This path of this FileMap has been modified by
-                    // path-remapping, so we use it verbatim (and avoid cloning
-                    // the whole map in the process).
-                    filemap.clone()
-                } else {
-                    let mut adapted = (**filemap).clone();
-                    let abs_path = Path::new(working_dir).join(name)
-                                                         .to_string_lossy()
-                                                         .into_owned();
-                    adapted.name = abs_path;
-                    Rc::new(adapted)
-                }
-            })
-            .collect::<Vec<_>>();
-
-        self.lazy_seq_ref(adapted.iter().map(|fm| &**fm))
-    }
-
-    fn encode_def_path_table(&mut self) -> Lazy<DefPathTable> {
-        let definitions = self.tcx.hir.definitions();
-        self.lazy(definitions.def_path_table())
-    }
-}
-
-struct ImplVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    impls: FxHashMap<DefId, Vec<DefIndex>>,
-}
-
-impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
-        if let hir::ItemImpl(..) = item.node {
-            let impl_id = self.tcx.hir.local_def_id(item.id);
-            if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) {
-                self.impls
-                    .entry(trait_ref.def_id)
-                    .or_insert(vec![])
-                    .push(impl_id.index);
-            }
-        }
+        }))
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem) {}
-
-    fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) {
-        // handled in `visit_item` above
+    fn encode_lang_items_missing(&mut self, _: ()) -> LazySeq<lang_items::LangItem> {
+        let tcx = self.tcx;
+        self.lazy_seq_ref(&tcx.lang_items.missing)
     }
-}
 
-impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     /// Encodes an index, mapping each trait to its (local) implementations.
-    fn encode_impls(&mut self) -> LazySeq<TraitImpls> {
+    fn encode_impls(&mut self, _: ()) -> LazySeq<TraitImpls> {
+        debug!("IsolatedEncoder::encode_impls()");
+        let tcx = self.tcx;
         let mut visitor = ImplVisitor {
-            tcx: self.tcx,
+            tcx: tcx,
             impls: FxHashMap(),
         };
-        self.tcx.hir.krate().visit_all_item_likes(&mut visitor);
+        tcx.hir.krate().visit_all_item_likes(&mut visitor);
 
-        let all_impls: Vec<_> = visitor.impls
+        let mut all_impls: Vec<_> = visitor.impls.into_iter().collect();
+
+        // Bring everything into deterministic order for hashing
+        all_impls.sort_unstable_by_key(|&(trait_def_id, _)| {
+            tcx.def_path_hash(trait_def_id)
+        });
+
+        let all_impls: Vec<_> = all_impls
             .into_iter()
-            .map(|(trait_def_id, impls)| {
+            .map(|(trait_def_id, mut impls)| {
+                // Bring everything into deterministic order for hashing
+                impls.sort_unstable_by_key(|&def_index| {
+                    tcx.hir.definitions().def_path_hash(def_index)
+                });
+
                 TraitImpls {
                     trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
-                    impls: self.lazy_seq(impls),
+                    impls: self.lazy_seq_from_slice(&impls[..]),
                 }
             })
             .collect();
 
-        self.lazy_seq(all_impls)
+        self.lazy_seq_from_slice(&all_impls[..])
     }
 
     // Encodes all symbols exported from this crate into the metadata.
@@ -1371,13 +1334,12 @@ fn encode_impls(&mut self) -> LazySeq<TraitImpls> {
     // middle::reachable module but filters out items that either don't have a
     // symbol associated with them (they weren't translated) or if they're an FFI
     // definition (as that's not defined in this crate).
-    fn encode_exported_symbols(&mut self) -> LazySeq<DefIndex> {
-        let exported_symbols = self.exported_symbols;
+    fn encode_exported_symbols(&mut self, exported_symbols: &NodeSet) -> LazySeq<DefIndex> {
         let tcx = self.tcx;
         self.lazy_seq(exported_symbols.iter().map(|&id| tcx.hir.local_def_id(id).index))
     }
 
-    fn encode_dylib_dependency_formats(&mut self) -> LazySeq<Option<LinkagePreference>> {
+    fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq<Option<LinkagePreference>> {
         match self.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) {
             Some(arr) => {
                 self.lazy_seq(arr.iter().map(|slot| {
@@ -1393,111 +1355,221 @@ fn encode_dylib_dependency_formats(&mut self) -> LazySeq<Option<LinkagePreferenc
             None => LazySeq::empty(),
         }
     }
-}
 
-impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
-    fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
-        let mut i = self.position();
-        let crate_deps = self.encode_crate_deps();
-        let dylib_dependency_formats = self.encode_dylib_dependency_formats();
-        let dep_bytes = self.position() - i;
+    fn encode_info_for_foreign_item(&mut self,
+                                    (def_id, nitem): (DefId, &hir::ForeignItem))
+                                    -> Entry<'tcx> {
+        let tcx = self.tcx;
 
-        // Encode the language items.
-        i = self.position();
-        let (lang_items, lang_items_missing) = self.encode_lang_items();
-        let lang_item_bytes = self.position() - i;
+        debug!("IsolatedEncoder::encode_info_for_foreign_item({:?})", def_id);
 
-        // Encode the native libraries used
-        i = self.position();
-        let native_libraries = self.encode_native_libraries();
-        let native_lib_bytes = self.position() - i;
+        let kind = match nitem.node {
+            hir::ForeignItemFn(_, ref names, _) => {
+                let data = FnData {
+                    constness: hir::Constness::NotConst,
+                    arg_names: self.encode_fn_arg_names(names),
+                };
+                EntryKind::ForeignFn(self.lazy(&data))
+            }
+            hir::ForeignItemStatic(_, true) => EntryKind::ForeignMutStatic,
+            hir::ForeignItemStatic(_, false) => EntryKind::ForeignImmStatic,
+        };
 
-        // Encode codemap
-        i = self.position();
-        let codemap = self.encode_codemap();
-        let codemap_bytes = self.position() - i;
+        Entry {
+            kind: kind,
+            visibility: self.lazy(&ty::Visibility::from_hir(&nitem.vis, nitem.id, tcx)),
+            span: self.lazy(&nitem.span),
+            attributes: self.encode_attributes(&nitem.attrs),
+            children: LazySeq::empty(),
+            stability: self.encode_stability(def_id),
+            deprecation: self.encode_deprecation(def_id),
 
-        // Encode DefPathTable
-        i = self.position();
-        let def_path_table = self.encode_def_path_table();
-        let def_path_table_bytes = self.position() - i;
+            ty: Some(self.encode_item_type(def_id)),
+            inherent_impls: LazySeq::empty(),
+            variances: LazySeq::empty(),
+            generics: Some(self.encode_generics(def_id)),
+            predicates: Some(self.encode_predicates(def_id)),
 
-        // Encode the def IDs of impls, for coherence checking.
-        i = self.position();
-        let impls = self.encode_impls();
-        let impl_bytes = self.position() - i;
+            ast: None,
+            mir: None,
+        }
+    }
+}
 
-        // Encode exported symbols info.
-        i = self.position();
-        let exported_symbols = self.encode_exported_symbols();
-        let exported_symbols_bytes = self.position() - i;
+struct EncodeVisitor<'a, 'b: 'a, 'tcx: 'b> {
+    index: IndexBuilder<'a, 'b, 'tcx>,
+}
 
-        // Encode and index the items.
-        i = self.position();
-        let items = self.encode_info_for_items();
-        let item_bytes = self.position() - i;
+impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        NestedVisitorMap::OnlyBodies(&self.index.tcx.hir)
+    }
+    fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
+        intravisit::walk_expr(self, ex);
+        self.index.encode_info_for_expr(ex);
+    }
+    fn visit_item(&mut self, item: &'tcx hir::Item) {
+        intravisit::walk_item(self, item);
+        let def_id = self.index.tcx.hir.local_def_id(item.id);
+        match item.node {
+            hir::ItemExternCrate(_) |
+            hir::ItemUse(..) => (), // ignore these
+            _ => self.index.record(def_id, IsolatedEncoder::encode_info_for_item, (def_id, item)),
+        }
+        self.index.encode_addl_info_for_item(item);
+    }
+    fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
+        intravisit::walk_foreign_item(self, ni);
+        let def_id = self.index.tcx.hir.local_def_id(ni.id);
+        self.index.record(def_id,
+                          IsolatedEncoder::encode_info_for_foreign_item,
+                          (def_id, ni));
+    }
+    fn visit_variant(&mut self,
+                     v: &'tcx hir::Variant,
+                     g: &'tcx hir::Generics,
+                     id: ast::NodeId) {
+        intravisit::walk_variant(self, v, g, id);
 
-        i = self.position();
-        let index = items.write_index(&mut self.opaque.cursor);
-        let index_bytes = self.position() - i;
+        if let Some(discr) = v.node.disr_expr {
+            let def_id = self.index.tcx.hir.body_owner_def_id(discr);
+            self.index.record(def_id, IsolatedEncoder::encode_info_for_embedded_const, def_id);
+        }
+    }
+    fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
+        intravisit::walk_generics(self, generics);
+        self.index.encode_info_for_generics(generics);
+    }
+    fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
+        intravisit::walk_ty(self, ty);
+        self.index.encode_info_for_ty(ty);
+    }
+    fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
+        let def_id = self.index.tcx.hir.local_def_id(macro_def.id);
+        self.index.record(def_id, IsolatedEncoder::encode_info_for_macro_def, macro_def);
+    }
+}
 
-        let tcx = self.tcx;
-        let link_meta = self.link_meta;
-        let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro);
-        let root = self.lazy(&CrateRoot {
-            name: tcx.crate_name(LOCAL_CRATE),
-            triple: tcx.sess.opts.target_triple.clone(),
-            hash: link_meta.crate_hash,
-            disambiguator: tcx.sess.local_crate_disambiguator(),
-            panic_strategy: tcx.sess.panic_strategy(),
-            plugin_registrar_fn: tcx.sess
-                .plugin_registrar_fn
-                .get()
-                .map(|id| tcx.hir.local_def_id(id).index),
-            macro_derive_registrar: if is_proc_macro {
-                let id = tcx.sess.derive_registrar_fn.get().unwrap();
-                Some(tcx.hir.local_def_id(id).index)
-            } else {
-                None
-            },
+impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
+    fn encode_fields(&mut self, adt_def_id: DefId) {
+        let def = self.tcx.adt_def(adt_def_id);
+        for (variant_index, variant) in def.variants.iter().enumerate() {
+            for (field_index, field) in variant.fields.iter().enumerate() {
+                self.record(field.did,
+                            IsolatedEncoder::encode_field,
+                            (adt_def_id, Untracked((variant_index, field_index))));
+            }
+        }
+    }
 
-            crate_deps: crate_deps,
-            dylib_dependency_formats: dylib_dependency_formats,
-            lang_items: lang_items,
-            lang_items_missing: lang_items_missing,
-            native_libraries: native_libraries,
-            codemap: codemap,
-            def_path_table: def_path_table,
-            impls: impls,
-            exported_symbols: exported_symbols,
-            index: index,
-        });
+    fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
+        for ty_param in &generics.ty_params {
+            let def_id = self.tcx.hir.local_def_id(ty_param.id);
+            let has_default = Untracked(ty_param.default.is_some());
+            self.record(def_id, IsolatedEncoder::encode_info_for_ty_param, (def_id, has_default));
+        }
+    }
 
-        let total_bytes = self.position();
+    fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
+        if let hir::TyImplTrait(_) = ty.node {
+            let def_id = self.tcx.hir.local_def_id(ty.id);
+            self.record(def_id, IsolatedEncoder::encode_info_for_anon_ty, def_id);
+        }
+    }
 
-        if self.tcx.sess.meta_stats() {
-            let mut zero_bytes = 0;
-            for e in self.opaque.cursor.get_ref() {
-                if *e == 0 {
-                    zero_bytes += 1;
+    fn encode_info_for_expr(&mut self, expr: &hir::Expr) {
+        match expr.node {
+            hir::ExprClosure(..) => {
+                let def_id = self.tcx.hir.local_def_id(expr.id);
+                self.record(def_id, IsolatedEncoder::encode_info_for_closure, def_id);
+            }
+            _ => {}
+        }
+    }
+
+    /// In some cases, along with the item itself, we also
+    /// encode some sub-items. Usually we want some info from the item
+    /// so it's easier to do that here then to wait until we would encounter
+    /// normally in the visitor walk.
+    fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
+        let def_id = self.tcx.hir.local_def_id(item.id);
+        match item.node {
+            hir::ItemStatic(..) |
+            hir::ItemConst(..) |
+            hir::ItemFn(..) |
+            hir::ItemMod(..) |
+            hir::ItemForeignMod(..) |
+            hir::ItemGlobalAsm(..) |
+            hir::ItemExternCrate(..) |
+            hir::ItemUse(..) |
+            hir::ItemDefaultImpl(..) |
+            hir::ItemTy(..) => {
+                // no sub-item recording needed in these cases
+            }
+            hir::ItemEnum(..) => {
+                self.encode_fields(def_id);
+
+                let def = self.tcx.adt_def(def_id);
+                for (i, variant) in def.variants.iter().enumerate() {
+                    self.record(variant.did,
+                                IsolatedEncoder::encode_enum_variant_info,
+                                (def_id, Untracked(i)));
                 }
             }
+            hir::ItemStruct(ref struct_def, _) => {
+                self.encode_fields(def_id);
 
-            println!("metadata stats:");
-            println!("             dep bytes: {}", dep_bytes);
-            println!("       lang item bytes: {}", lang_item_bytes);
-            println!("          native bytes: {}", native_lib_bytes);
-            println!("         codemap bytes: {}", codemap_bytes);
-            println!("            impl bytes: {}", impl_bytes);
-            println!("    exp. symbols bytes: {}", exported_symbols_bytes);
-            println!("  def-path table bytes: {}", def_path_table_bytes);
-            println!("            item bytes: {}", item_bytes);
-            println!("           index bytes: {}", index_bytes);
-            println!("            zero bytes: {}", zero_bytes);
-            println!("           total bytes: {}", total_bytes);
+                // If the struct has a constructor, encode it.
+                if !struct_def.is_struct() {
+                    let ctor_def_id = self.tcx.hir.local_def_id(struct_def.id());
+                    self.record(ctor_def_id,
+                                IsolatedEncoder::encode_struct_ctor,
+                                (def_id, ctor_def_id));
+                }
+            }
+            hir::ItemUnion(..) => {
+                self.encode_fields(def_id);
+            }
+            hir::ItemImpl(..) => {
+                for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
+                    self.record(trait_item_def_id,
+                                IsolatedEncoder::encode_info_for_impl_item,
+                                trait_item_def_id);
+                }
+            }
+            hir::ItemTrait(..) => {
+                for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
+                    self.record(item_def_id,
+                                IsolatedEncoder::encode_info_for_trait_item,
+                                item_def_id);
+                }
+            }
         }
+    }
+}
 
-        root
+struct ImplVisitor<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    impls: FxHashMap<DefId, Vec<DefIndex>>,
+}
+
+impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> {
+    fn visit_item(&mut self, item: &hir::Item) {
+        if let hir::ItemImpl(..) = item.node {
+            let impl_id = self.tcx.hir.local_def_id(item.id);
+            if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) {
+                self.impls
+                    .entry(trait_ref.def_id)
+                    .or_insert(vec![])
+                    .push(impl_id.index);
+            }
+        }
+    }
+
+    fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem) {}
+
+    fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) {
+        // handled in `visit_item` above
     }
 }
 
@@ -1525,7 +1597,6 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
 // generated regardless of trailing bytes that end up in it.
 
 pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                 cstore: &cstore::CStore,
                                  link_meta: &LinkMeta,
                                  exported_symbols: &NodeSet)
                                  -> EncodedMetadata
@@ -1533,20 +1604,24 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut cursor = Cursor::new(vec![]);
     cursor.write_all(METADATA_HEADER).unwrap();
 
-    // Will be filed with the root position after encoding everything.
+    // Will be filled with the root position after encoding everything.
     cursor.write_all(&[0, 0, 0, 0]).unwrap();
 
+     let compute_ich = (tcx.sess.opts.debugging_opts.query_dep_graph ||
+                        tcx.sess.opts.debugging_opts.incremental_cc) &&
+                        tcx.sess.opts.build_dep_graph();
+
     let (root, metadata_hashes) = {
         let mut ecx = EncodeContext {
             opaque: opaque::Encoder::new(&mut cursor),
             tcx: tcx,
             link_meta: link_meta,
-            cstore: cstore,
             exported_symbols: exported_symbols,
             lazy_state: LazyState::NoNode,
             type_shorthands: Default::default(),
             predicate_shorthands: Default::default(),
-            metadata_hashes: Vec::new(),
+            metadata_hashes: EncodedMetadataHashes::new(),
+            compute_ich: compute_ich,
         };
 
         // Encode the rustc version string in a predictable location.
index 01f948866b85081b8ba42889f7bcdf3598d5c270..478202aeba4449db284369d45fa876f3c9d835f8 100644 (file)
 use encoder::EncodeContext;
 use index::Index;
 use schema::*;
+use isolated_encoder::IsolatedEncoder;
 
 use rustc::hir;
 use rustc::hir::def_id::DefId;
-use rustc::ich::{StableHashingContext, Fingerprint};
 use rustc::middle::cstore::EncodedMetadataHash;
 use rustc::ty::TyCtxt;
 use syntax::ast;
 
 use std::ops::{Deref, DerefMut};
 
-use rustc_data_structures::accumulate_vec::AccumulateVec;
-use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
-use rustc_serialize::Encodable;
-
 /// Builder that can encode new items, adding them into the index.
 /// Item encoding cannot be nested.
 pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> {
@@ -119,7 +115,7 @@ pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self {
     /// content system.
     pub fn record<'x, DATA>(&'x mut self,
                             id: DefId,
-                            op: fn(&mut EntryBuilder<'x, 'b, 'tcx>, DATA) -> Entry<'tcx>,
+                            op: fn(&mut IsolatedEncoder<'x, 'b, 'tcx>, DATA) -> Entry<'tcx>,
                             data: DATA)
         where DATA: DepGraphRead
     {
@@ -132,29 +128,19 @@ pub fn record<'x, DATA>(&'x mut self,
         // unclear whether that would be a win since hashing is cheap enough.
         let _task = tcx.dep_graph.in_ignore();
 
-        let compute_ich = (tcx.sess.opts.debugging_opts.query_dep_graph ||
-                           tcx.sess.opts.debugging_opts.incremental_cc) &&
-                           tcx.sess.opts.build_dep_graph();
-
         let ecx: &'x mut EncodeContext<'b, 'tcx> = &mut *self.ecx;
-        let mut entry_builder = EntryBuilder {
-            tcx: tcx,
-            ecx: ecx,
-            hcx: if compute_ich {
-                Some((StableHashingContext::new(tcx), StableHasher::new()))
-            } else {
-                None
-            }
-        };
-
+        let mut entry_builder = IsolatedEncoder::new(ecx);
         let entry = op(&mut entry_builder, data);
+        let entry = entry_builder.lazy(&entry);
 
-        if let Some((ref mut hcx, ref mut hasher)) = entry_builder.hcx {
-            entry.hash_stable(hcx, hasher);
+        let (fingerprint, ecx) = entry_builder.finish();
+        if let Some(hash) = fingerprint {
+            ecx.metadata_hashes.entry_hashes.push(EncodedMetadataHash {
+                def_index: id.index,
+                hash: hash,
+            });
         }
 
-        let entry = entry_builder.ecx.lazy(&entry);
-        entry_builder.finish(id);
         self.items.record(id, entry);
     }
 
@@ -257,91 +243,3 @@ fn read(&self, tcx: TyCtxt) {
         tcx.hir.read(self.0);
     }
 }
-
-pub struct EntryBuilder<'a, 'b: 'a, 'tcx: 'b> {
-    pub tcx: TyCtxt<'b, 'tcx, 'tcx>,
-    ecx: &'a mut EncodeContext<'b, 'tcx>,
-    hcx: Option<(StableHashingContext<'b, 'tcx>, StableHasher<Fingerprint>)>,
-}
-
-impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
-
-    pub fn finish(self, def_id: DefId) {
-        if let Some((_, hasher)) = self.hcx {
-            let hash = hasher.finish();
-            self.ecx.metadata_hashes.push(EncodedMetadataHash {
-                def_index: def_id.index,
-                hash: hash,
-            });
-        }
-    }
-
-    pub fn lazy<T>(&mut self, value: &T) -> Lazy<T>
-        where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
-    {
-        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
-            value.hash_stable(hcx, hasher);
-            debug!("metadata-hash: {:?}", hasher);
-        }
-        self.ecx.lazy(value)
-    }
-
-    pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
-        where I: IntoIterator<Item = T>,
-              T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
-    {
-        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
-            let iter = iter.into_iter();
-            let (lower_bound, upper_bound) = iter.size_hint();
-
-            if upper_bound == Some(lower_bound) {
-                lower_bound.hash_stable(hcx, hasher);
-                let mut num_items_hashed = 0;
-                let ret = self.ecx.lazy_seq(iter.inspect(|item| {
-                    item.hash_stable(hcx, hasher);
-                    num_items_hashed += 1;
-                }));
-
-                // Sometimes items in a sequence are filtered out without being
-                // hashed (e.g. for &[ast::Attribute]) and this code path cannot
-                // handle that correctly, so we want to make sure we didn't hit
-                // it by accident.
-                if lower_bound != num_items_hashed {
-                    bug!("Hashed a different number of items ({}) than expected ({})",
-                         num_items_hashed,
-                         lower_bound);
-                }
-                debug!("metadata-hash: {:?}", hasher);
-                ret
-            } else {
-                // Collect into a vec so we know the length of the sequence
-                let items: AccumulateVec<[T; 32]> = iter.collect();
-                items.hash_stable(hcx, hasher);
-                debug!("metadata-hash: {:?}", hasher);
-                self.ecx.lazy_seq(items)
-            }
-        } else {
-            self.ecx.lazy_seq(iter)
-        }
-    }
-
-    pub fn lazy_seq_from_slice<T>(&mut self, slice: &[T]) -> LazySeq<T>
-        where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
-    {
-        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
-            slice.hash_stable(hcx, hasher);
-            debug!("metadata-hash: {:?}", hasher);
-        }
-        self.ecx.lazy_seq_ref(slice.iter())
-    }
-
-    pub fn lazy_seq_ref_from_slice<T>(&mut self, slice: &[&T]) -> LazySeq<T>
-        where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
-    {
-        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
-            slice.hash_stable(hcx, hasher);
-            debug!("metadata-hash: {:?}", hasher);
-        }
-        self.ecx.lazy_seq_ref(slice.iter().map(|x| *x))
-    }
-}
diff --git a/src/librustc_metadata/isolated_encoder.rs b/src/librustc_metadata/isolated_encoder.rs
new file mode 100644 (file)
index 0000000..7722a7b
--- /dev/null
@@ -0,0 +1,160 @@
+// 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 encoder::EncodeContext;
+use schema::{Lazy, LazySeq};
+
+use rustc::ich::{StableHashingContext, Fingerprint};
+use rustc::ty::TyCtxt;
+
+use rustc_data_structures::accumulate_vec::AccumulateVec;
+use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
+use rustc_serialize::Encodable;
+
+/// The IsolatedEncoder provides facilities to write to crate metadata while
+/// making sure that anything going through it is also feed into an ICH hasher.
+pub struct IsolatedEncoder<'a, 'b: 'a, 'tcx: 'b> {
+    pub tcx: TyCtxt<'b, 'tcx, 'tcx>,
+    ecx: &'a mut EncodeContext<'b, 'tcx>,
+    hcx: Option<(StableHashingContext<'b, 'tcx>, StableHasher<Fingerprint>)>,
+}
+
+impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
+
+    pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self {
+        let tcx = ecx.tcx;
+        let compute_ich = ecx.compute_ich;
+        IsolatedEncoder {
+            tcx: tcx,
+            ecx: ecx,
+            hcx: if compute_ich {
+                Some((StableHashingContext::new(tcx), StableHasher::new()))
+            } else {
+                None
+            }
+        }
+    }
+
+    pub fn finish(self) -> (Option<Fingerprint>, &'a mut EncodeContext<'b, 'tcx>) {
+        if let Some((_, hasher)) = self.hcx {
+            (Some(hasher.finish()), self.ecx)
+        } else {
+            (None, self.ecx)
+        }
+    }
+
+    pub fn lazy<T>(&mut self, value: &T) -> Lazy<T>
+        where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
+    {
+        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
+            value.hash_stable(hcx, hasher);
+            debug!("metadata-hash: {:?}", hasher);
+        }
+        self.ecx.lazy(value)
+    }
+
+    pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
+        where I: IntoIterator<Item = T>,
+              T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
+    {
+        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
+            let iter = iter.into_iter();
+            let (lower_bound, upper_bound) = iter.size_hint();
+
+            if upper_bound == Some(lower_bound) {
+                lower_bound.hash_stable(hcx, hasher);
+                let mut num_items_hashed = 0;
+                let ret = self.ecx.lazy_seq(iter.inspect(|item| {
+                    item.hash_stable(hcx, hasher);
+                    num_items_hashed += 1;
+                }));
+
+                // Sometimes items in a sequence are filtered out without being
+                // hashed (e.g. for &[ast::Attribute]) and this code path cannot
+                // handle that correctly, so we want to make sure we didn't hit
+                // it by accident.
+                if lower_bound != num_items_hashed {
+                    bug!("Hashed a different number of items ({}) than expected ({})",
+                         num_items_hashed,
+                         lower_bound);
+                }
+                debug!("metadata-hash: {:?}", hasher);
+                ret
+            } else {
+                // Collect into a vec so we know the length of the sequence
+                let items: AccumulateVec<[T; 32]> = iter.collect();
+                items.hash_stable(hcx, hasher);
+                debug!("metadata-hash: {:?}", hasher);
+                self.ecx.lazy_seq(items)
+            }
+        } else {
+            self.ecx.lazy_seq(iter)
+        }
+    }
+
+    pub fn lazy_seq_ref<'x, I, T>(&mut self, iter: I) -> LazySeq<T>
+        where I: IntoIterator<Item = &'x T>,
+              T: 'x + Encodable + HashStable<StableHashingContext<'b, 'tcx>>
+    {
+        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
+            let iter = iter.into_iter();
+            let (lower_bound, upper_bound) = iter.size_hint();
+
+            if upper_bound == Some(lower_bound) {
+                lower_bound.hash_stable(hcx, hasher);
+                let mut num_items_hashed = 0;
+                let ret = self.ecx.lazy_seq_ref(iter.inspect(|item| {
+                    item.hash_stable(hcx, hasher);
+                    num_items_hashed += 1;
+                }));
+
+                // Sometimes items in a sequence are filtered out without being
+                // hashed (e.g. for &[ast::Attribute]) and this code path cannot
+                // handle that correctly, so we want to make sure we didn't hit
+                // it by accident.
+                if lower_bound != num_items_hashed {
+                    bug!("Hashed a different number of items ({}) than expected ({})",
+                         num_items_hashed,
+                         lower_bound);
+                }
+                debug!("metadata-hash: {:?}", hasher);
+                ret
+            } else {
+                // Collect into a vec so we know the length of the sequence
+                let items: AccumulateVec<[&'x T; 32]> = iter.collect();
+                items.hash_stable(hcx, hasher);
+                debug!("metadata-hash: {:?}", hasher);
+                self.ecx.lazy_seq_ref(items.iter().map(|x| *x))
+            }
+        } else {
+            self.ecx.lazy_seq_ref(iter)
+        }
+    }
+
+    pub fn lazy_seq_from_slice<T>(&mut self, slice: &[T]) -> LazySeq<T>
+        where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
+    {
+        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
+            slice.hash_stable(hcx, hasher);
+            debug!("metadata-hash: {:?}", hasher);
+        }
+        self.ecx.lazy_seq_ref(slice.iter())
+    }
+
+    pub fn lazy_seq_ref_from_slice<T>(&mut self, slice: &[&T]) -> LazySeq<T>
+        where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
+    {
+        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
+            slice.hash_stable(hcx, hasher);
+            debug!("metadata-hash: {:?}", hasher);
+        }
+        self.ecx.lazy_seq_ref(slice.iter().map(|x| *x))
+    }
+}
index b9e142ac65072e18dd2c256a4a418067700d0553..56c150fd4c82f27608f2c6bc57da9df72c08762a 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![crate_name = "rustc_metadata"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 #![feature(proc_macro_internals)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
 #![feature(specialization)]
-#![feature(staged_api)]
 #![feature(discriminant_value)]
+#![feature(rustc_private)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(staged_api))]
+#![feature(sort_unstable)]
 
 #[macro_use]
 extern crate log;
@@ -36,6 +38,7 @@
 extern crate syntax_pos;
 extern crate flate;
 extern crate serialize as rustc_serialize; // used by deriving
+extern crate owning_ref;
 extern crate rustc_errors as errors;
 extern crate syntax_ext;
 extern crate proc_macro;
@@ -45,7 +48,6 @@
 extern crate rustc_back;
 extern crate rustc_const_math;
 extern crate rustc_data_structures;
-extern crate rustc_llvm;
 
 mod diagnostics;
 
@@ -57,6 +59,7 @@
 mod encoder;
 mod decoder;
 mod cstore_impl;
+mod isolated_encoder;
 mod schema;
 
 pub mod creader;
index e8bc8b01652a62a5c71161b6b8e489a21ea21a6f..34b07af9f01f439cf84e551c5ff5cd629b6bcf98 100644 (file)
 use schema::{METADATA_HEADER, rustc_version};
 
 use rustc::hir::svh::Svh;
+use rustc::middle::cstore::MetadataLoader;
 use rustc::session::{config, Session};
 use rustc::session::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
 use rustc::session::search_paths::PathKind;
-use rustc::util::common;
 use rustc::util::nodemap::FxHashMap;
 
-use rustc_llvm as llvm;
-use rustc_llvm::{False, ObjectFile, mk_section_iter};
-use rustc_llvm::archive_ro::ArchiveRO;
 use errors::DiagnosticBuilder;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
 use std::fs::{self, File};
 use std::io::{self, Read};
 use std::path::{Path, PathBuf};
-use std::ptr;
-use std::slice;
 use std::time::Instant;
 
 use flate;
+use owning_ref::{ErasedBoxRef, OwningRef};
 
 pub struct CrateMismatch {
     path: PathBuf,
@@ -272,12 +268,7 @@ pub struct Context<'a> {
     pub rejected_via_filename: Vec<CrateMismatch>,
     pub should_match_name: bool,
     pub is_proc_macro: Option<bool>,
-}
-
-pub struct ArchiveMetadata {
-    _archive: ArchiveRO,
-    // points into self._archive
-    data: *const [u8],
+    pub metadata_loader: &'a MetadataLoader,
 }
 
 pub struct CratePaths {
@@ -287,8 +278,6 @@ pub struct CratePaths {
     pub rmeta: Option<PathBuf>,
 }
 
-pub const METADATA_FILENAME: &'static str = "rust.metadata.bin";
-
 #[derive(Copy, Clone, PartialEq)]
 enum CrateFlavor {
     Rlib,
@@ -367,7 +356,7 @@ pub fn report_errs(&mut self) -> ! {
                 && self.triple != config::host_triple() {
                 err.note(&format!("the `{}` target may not be installed", self.triple));
             }
-            err.span_label(self.span, &format!("can't find crate"));
+            err.span_label(self.span, "can't find crate");
             err
         };
 
@@ -596,20 +585,21 @@ fn extract_one(&mut self,
         let mut err: Option<DiagnosticBuilder> = None;
         for (lib, kind) in m {
             info!("{} reading metadata from: {}", flavor, lib.display());
-            let (hash, metadata) = match get_metadata_section(self.target, flavor, &lib) {
-                Ok(blob) => {
-                    if let Some(h) = self.crate_matches(&blob, &lib) {
-                        (h, blob)
-                    } else {
-                        info!("metadata mismatch");
+            let (hash, metadata) =
+                match get_metadata_section(self.target, flavor, &lib, self.metadata_loader) {
+                    Ok(blob) => {
+                        if let Some(h) = self.crate_matches(&blob, &lib) {
+                            (h, blob)
+                        } else {
+                            info!("metadata mismatch");
+                            continue;
+                        }
+                    }
+                    Err(err) => {
+                        info!("no metadata found: {}", err);
                         continue;
                     }
-                }
-                Err(err) => {
-                    info!("no metadata found: {}", err);
-                    continue;
-                }
-            };
+                };
             // If we see multiple hashes, emit an error about duplicate candidates.
             if slot.as_ref().map_or(false, |s| s.0 != hash) {
                 let mut e = struct_span_err!(self.sess,
@@ -833,50 +823,14 @@ pub fn note_crate_name(err: &mut DiagnosticBuilder, name: &str) {
     err.note(&format!("crate name: {}", name));
 }
 
-impl ArchiveMetadata {
-    fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
-        let data = {
-            let section = ar.iter()
-                .filter_map(|s| s.ok())
-                .find(|sect| sect.name() == Some(METADATA_FILENAME));
-            match section {
-                Some(s) => s.data() as *const [u8],
-                None => {
-                    debug!("didn't find '{}' in the archive", METADATA_FILENAME);
-                    return None;
-                }
-            }
-        };
-
-        Some(ArchiveMetadata {
-            _archive: ar,
-            data: data,
-        })
-    }
-
-    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
-        unsafe { &*self.data }
-    }
-}
-
-fn verify_decompressed_encoding_version(blob: &MetadataBlob,
-                                        filename: &Path)
-                                        -> Result<(), String> {
-    if !blob.is_compatible() {
-        Err((format!("incompatible metadata version found: '{}'",
-                     filename.display())))
-    } else {
-        Ok(())
-    }
-}
-
 // Just a small wrapper to time how long reading metadata takes.
 fn get_metadata_section(target: &Target,
                         flavor: CrateFlavor,
-                        filename: &Path)
+                        filename: &Path,
+                        loader: &MetadataLoader)
                         -> Result<MetadataBlob, String> {
     let start = Instant::now();
-    let ret = get_metadata_section_imp(target, flavor, filename);
+    let ret = get_metadata_section_imp(target, flavor, filename, loader);
     info!("reading {:?} => {:?}",
           filename.file_name().unwrap(),
           start.elapsed());
@@ -885,118 +839,61 @@ fn get_metadata_section(target: &Target,
 
 fn get_metadata_section_imp(target: &Target,
                             flavor: CrateFlavor,
-                            filename: &Path)
+                            filename: &Path,
+                            loader: &MetadataLoader)
                             -> Result<MetadataBlob, String> {
     if !filename.exists() {
         return Err(format!("no such file: '{}'", filename.display()));
     }
-    if flavor == CrateFlavor::Rlib {
-        // Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
-        // internally to read the file. We also avoid even using a memcpy by
-        // just keeping the archive along while the metadata is in use.
-        let archive = match ArchiveRO::open(filename) {
-            Some(ar) => ar,
-            None => {
-                debug!("llvm didn't like `{}`", filename.display());
-                return Err(format!("failed to read rlib metadata: '{}'", filename.display()));
+    let raw_bytes: ErasedBoxRef<[u8]> = match flavor {
+        CrateFlavor::Rlib => loader.get_rlib_metadata(target, filename)?,
+        CrateFlavor::Dylib => {
+            let buf = loader.get_dylib_metadata(target, filename)?;
+            // The header is uncompressed
+            let header_len = METADATA_HEADER.len();
+            debug!("checking {} bytes of metadata-version stamp", header_len);
+            let header = &buf[..cmp::min(header_len, buf.len())];
+            if header != METADATA_HEADER {
+                return Err(format!("incompatible metadata version found: '{}'",
+                                   filename.display()));
             }
-        };
-        return match ArchiveMetadata::new(archive).map(|ar| MetadataBlob::Archive(ar)) {
-            None => Err(format!("failed to read rlib metadata: '{}'", filename.display())),
-            Some(blob) => {
-                verify_decompressed_encoding_version(&blob, filename)?;
-                Ok(blob)
-            }
-        };
-    } else if flavor == CrateFlavor::Rmeta {
-        let mut file = File::open(filename).map_err(|_|
-            format!("could not open file: '{}'", filename.display()))?;
-        let mut buf = vec![];
-        file.read_to_end(&mut buf).map_err(|_|
-            format!("failed to read rlib metadata: '{}'", filename.display()))?;
-        let blob = MetadataBlob::Raw(buf);
-        verify_decompressed_encoding_version(&blob, filename)?;
-        return Ok(blob);
-    }
-    unsafe {
-        let buf = common::path2cstr(filename);
-        let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
-        if mb as isize == 0 {
-            return Err(format!("error reading library: '{}'", filename.display()));
-        }
-        let of = match ObjectFile::new(mb) {
-            Some(of) => of,
-            _ => {
-                return Err((format!("provided path not an object file: '{}'", filename.display())))
-            }
-        };
-        let si = mk_section_iter(of.llof);
-        while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
-            let mut name_buf = ptr::null();
-            let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
-            let name = slice::from_raw_parts(name_buf as *const u8, name_len as usize).to_vec();
-            let name = String::from_utf8(name).unwrap();
-            debug!("get_metadata_section: name {}", name);
-            if read_meta_section_name(target) == name {
-                let cbuf = llvm::LLVMGetSectionContents(si.llsi);
-                let csz = llvm::LLVMGetSectionSize(si.llsi) as usize;
-                let cvbuf: *const u8 = cbuf as *const u8;
-                let vlen = METADATA_HEADER.len();
-                debug!("checking {} bytes of metadata-version stamp", vlen);
-                let minsz = cmp::min(vlen, csz);
-                let buf0 = slice::from_raw_parts(cvbuf, minsz);
-                let version_ok = buf0 == METADATA_HEADER;
-                if !version_ok {
-                    return Err((format!("incompatible metadata version found: '{}'",
-                                        filename.display())));
-                }
 
-                let cvbuf1 = cvbuf.offset(vlen as isize);
-                debug!("inflating {} bytes of compressed metadata", csz - vlen);
-                let bytes = slice::from_raw_parts(cvbuf1, csz - vlen);
-                match flate::inflate_bytes(bytes) {
-                    Ok(inflated) => {
-                        let blob = MetadataBlob::Inflated(inflated);
-                        verify_decompressed_encoding_version(&blob, filename)?;
-                        return Ok(blob);
-                    }
-                    Err(_) => {}
+            // Header is okay -> inflate the actual metadata
+            let compressed_bytes = &buf[header_len..];
+            debug!("inflating {} bytes of compressed metadata", compressed_bytes.len());
+            match flate::inflate_bytes(compressed_bytes) {
+                Ok(inflated) => {
+                    let buf = unsafe { OwningRef::new_assert_stable_address(inflated) };
+                    buf.map_owner_box().erase_owner()
+                }
+                Err(_) => {
+                    return Err(format!("failed to decompress metadata: {}", filename.display()));
                 }
             }
-            llvm::LLVMMoveToNextSection(si.llsi);
         }
-        Err(format!("metadata not found: '{}'", filename.display()))
-    }
-}
-
-pub fn meta_section_name(target: &Target) -> &'static str {
-    // Historical note:
-    //
-    // When using link.exe it was seen that the section name `.note.rustc`
-    // was getting shortened to `.note.ru`, and according to the PE and COFF
-    // specification:
-    //
-    // > Executable images do not use a string table and do not support
-    // > section names longer than 8 characters
-    //
-    // https://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx
-    //
-    // As a result, we choose a slightly shorter name! As to why
-    // `.note.rustc` works on MinGW, that's another good question...
-
-    if target.options.is_like_osx {
-        "__DATA,.rustc"
+        CrateFlavor::Rmeta => {
+            let mut file = File::open(filename).map_err(|_|
+                format!("could not open file: '{}'", filename.display()))?;
+            let mut buf = vec![];
+            file.read_to_end(&mut buf).map_err(|_|
+                format!("failed to read rmeta metadata: '{}'", filename.display()))?;
+            OwningRef::new(buf).map_owner_box().erase_owner()
+        }
+    };
+    let blob = MetadataBlob(raw_bytes);
+    if blob.is_compatible() {
+        Ok(blob)
     } else {
-        ".rustc"
+        Err(format!("incompatible metadata version found: '{}'", filename.display()))
     }
 }
 
-pub fn read_meta_section_name(_target: &Target) -> &'static str {
-    ".rustc"
-}
-
 // A diagnostic function for dumping crate metadata to an output stream
-pub fn list_file_metadata(target: &Target, path: &Path, out: &mut io::Write) -> io::Result<()> {
+pub fn list_file_metadata(target: &Target,
+                          path: &Path,
+                          loader: &MetadataLoader,
+                          out: &mut io::Write)
+                          -> io::Result<()> {
     let filename = path.file_name().unwrap().to_str().unwrap();
     let flavor = if filename.ends_with(".rlib") {
         CrateFlavor::Rlib
@@ -1005,7 +902,7 @@ pub fn list_file_metadata(target: &Target, path: &Path, out: &mut io::Write) ->
     } else {
         CrateFlavor::Dylib
     };
-    match get_metadata_section(target, flavor, path) {
+    match get_metadata_section(target, flavor, path, loader) {
         Ok(metadata) => metadata.list_crate_metadata(out),
         Err(msg) => write!(out, "{}\n", msg),
     }
index 5870903e7718fd0820cb1341d78d9ab321abb2d4..91a22d922199da6d2e6f3e35192ec9957a9491e1 100644 (file)
@@ -13,7 +13,7 @@
 
 use rustc::hir;
 use rustc::hir::def::{self, CtorKind};
-use rustc::hir::def_id::{DefIndex, DefId};
+use rustc::hir::def_id::{DefIndex, DefId, CrateNum};
 use rustc::ich::StableHashingContext;
 use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
 use rustc::middle::lang_items;
@@ -32,6 +32,8 @@
 use rustc_data_structures::stable_hasher::{StableHasher, HashStable,
                                            StableHasherResult};
 
+use rustc::dep_graph::{DepGraph, DepNode};
+
 pub fn rustc_version() -> String {
     format!("rustc {}",
             option_env!("CFG_VERSION").unwrap_or("unknown version"))
@@ -186,25 +188,73 @@ pub enum LazyState {
     Previous(usize),
 }
 
+/// A `Tracked<T>` wraps a value so that one can only access it when specifying
+/// the `DepNode` for that value. This makes it harder to forget registering
+/// reads.
+#[derive(RustcEncodable, RustcDecodable)]
+pub struct Tracked<T> {
+    state: T,
+}
+
+impl<T> Tracked<T> {
+    pub fn new(state: T) -> Tracked<T> {
+        Tracked {
+            state: state,
+        }
+    }
+
+    pub fn get(&self, dep_graph: &DepGraph, dep_node: DepNode<DefId>) -> &T {
+        dep_graph.read(dep_node);
+        &self.state
+    }
+
+    pub fn get_untracked(&self) -> &T {
+        &self.state
+    }
+
+    pub fn map<F, R>(&self, f: F) -> Tracked<R>
+        where F: FnOnce(&T) -> R
+    {
+        Tracked {
+            state: f(&self.state),
+        }
+    }
+}
+
+impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for Tracked<T>
+    where T: HashStable<StableHashingContext<'a, 'tcx>>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let Tracked {
+            ref state
+        } = *self;
+
+        state.hash_stable(hcx, hasher);
+    }
+}
+
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct CrateRoot {
     pub name: Symbol,
     pub triple: String,
     pub hash: hir::svh::Svh,
     pub disambiguator: Symbol,
-    pub panic_strategy: PanicStrategy,
+    pub panic_strategy: Tracked<PanicStrategy>,
     pub plugin_registrar_fn: Option<DefIndex>,
     pub macro_derive_registrar: Option<DefIndex>,
 
-    pub crate_deps: LazySeq<CrateDep>,
-    pub dylib_dependency_formats: LazySeq<Option<LinkagePreference>>,
-    pub lang_items: LazySeq<(DefIndex, usize)>,
-    pub lang_items_missing: LazySeq<lang_items::LangItem>,
-    pub native_libraries: LazySeq<NativeLibrary>,
+    pub crate_deps: Tracked<LazySeq<CrateDep>>,
+    pub dylib_dependency_formats: Tracked<LazySeq<Option<LinkagePreference>>>,
+    pub lang_items: Tracked<LazySeq<(DefIndex, usize)>>,
+    pub lang_items_missing: Tracked<LazySeq<lang_items::LangItem>>,
+    pub native_libraries: Tracked<LazySeq<NativeLibrary>>,
     pub codemap: LazySeq<syntax_pos::FileMap>,
     pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
-    pub impls: LazySeq<TraitImpls>,
-    pub exported_symbols: LazySeq<DefIndex>,
+    pub impls: Tracked<LazySeq<TraitImpls>>,
+    pub exported_symbols: Tracked<LazySeq<DefIndex>>,
     pub index: LazySeq<index::Index>,
 }
 
@@ -215,12 +265,35 @@ pub struct CrateDep {
     pub kind: DepKind,
 }
 
+impl_stable_hash_for!(struct CrateDep {
+    name,
+    hash,
+    kind
+});
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct TraitImpls {
     pub trait_id: (u32, DefIndex),
     pub impls: LazySeq<DefIndex>,
 }
 
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for TraitImpls {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let TraitImpls {
+            trait_id: (krate, def_index),
+            ref impls,
+        } = *self;
+
+        DefId {
+            krate: CrateNum::from_u32(krate),
+            index: def_index
+        }.hash_stable(hcx, hasher);
+        impls.hash_stable(hcx, hasher);
+    }
+}
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct Entry<'tcx> {
     pub kind: EntryKind<'tcx>,
index c503b8c7fe06f7bb9c58ed0fce452203e35551e0..40a78933aad2d8e5718f28a25f0fd63f5f2def6e 100644 (file)
@@ -60,7 +60,7 @@ pub fn push_assign_constant(&mut self,
                                 temp: &Lvalue<'tcx>,
                                 constant: Constant<'tcx>) {
         self.push_assign(block, source_info, temp,
-                         Rvalue::Use(Operand::Constant(constant)));
+                         Rvalue::Use(Operand::Constant(box constant)));
     }
 
     pub fn push_assign_unit(&mut self,
@@ -68,7 +68,7 @@ pub fn push_assign_unit(&mut self,
                             source_info: SourceInfo,
                             lvalue: &Lvalue<'tcx>) {
         self.push_assign(block, source_info, lvalue, Rvalue::Aggregate(
-            AggregateKind::Tuple, vec![]
+            box AggregateKind::Tuple, vec![]
         ));
     }
 
index 22a36bb21d8753f6cafc5b285007cdf6e9a69a87..a368021443292b36a844039ab75b37333721c6c5 100644 (file)
@@ -39,7 +39,7 @@ pub fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M)
     /// The operand is known to be live until the end of `scope`.
     pub fn as_operand<M>(&mut self,
                          block: BasicBlock,
-                         scope: Option<CodeExtent<'tcx>>,
+                         scope: Option<CodeExtent>,
                          expr: M) -> BlockAnd<Operand<'tcx>>
         where M: Mirror<'tcx, Output = Expr<'tcx>>
     {
@@ -49,7 +49,7 @@ pub fn as_operand<M>(&mut self,
 
     fn expr_as_operand(&mut self,
                        mut block: BasicBlock,
-                       scope: Option<CodeExtent<'tcx>>,
+                       scope: Option<CodeExtent>,
                        expr: Expr<'tcx>)
                        -> BlockAnd<Operand<'tcx>> {
         debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
@@ -66,7 +66,7 @@ fn expr_as_operand(&mut self,
         match category {
             Category::Constant => {
                 let constant = this.as_constant(expr);
-                block.and(Operand::Constant(constant))
+                block.and(Operand::Constant(box constant))
             }
             Category::Lvalue |
             Category::Rvalue(..) => {
index 8dc7745cd9eb998772201cfd2d519b56fdf861ec..7b29cd970d7d4447c852d0feaa39542afc77d0a6 100644 (file)
@@ -38,7 +38,7 @@ pub fn as_local_rvalue<M>(&mut self, block: BasicBlock, expr: M)
     }
 
     /// Compile `expr`, yielding an rvalue.
-    pub fn as_rvalue<M>(&mut self, block: BasicBlock, scope: Option<CodeExtent<'tcx>>, expr: M)
+    pub fn as_rvalue<M>(&mut self, block: BasicBlock, scope: Option<CodeExtent>, expr: M)
                         -> BlockAnd<Rvalue<'tcx>>
         where M: Mirror<'tcx, Output = Expr<'tcx>>
     {
@@ -48,7 +48,7 @@ pub fn as_rvalue<M>(&mut self, block: BasicBlock, scope: Option<CodeExtent<'tcx>
 
     fn expr_as_rvalue(&mut self,
                       mut block: BasicBlock,
-                      scope: Option<CodeExtent<'tcx>>,
+                      scope: Option<CodeExtent>,
                       expr: Expr<'tcx>)
                       -> BlockAnd<Rvalue<'tcx>> {
         debug!("expr_as_rvalue(block={:?}, expr={:?})", block, expr);
@@ -166,7 +166,7 @@ fn expr_as_rvalue(&mut self,
                           .map(|f| unpack!(block = this.as_operand(block, scope, f)))
                           .collect();
 
-                block.and(Rvalue::Aggregate(AggregateKind::Array(el_ty), fields))
+                block.and(Rvalue::Aggregate(box AggregateKind::Array(el_ty), fields))
             }
             ExprKind::Tuple { fields } => { // see (*) above
                 // first process the set of fields
@@ -175,14 +175,14 @@ fn expr_as_rvalue(&mut self,
                           .map(|f| unpack!(block = this.as_operand(block, scope, f)))
                           .collect();
 
-                block.and(Rvalue::Aggregate(AggregateKind::Tuple, fields))
+                block.and(Rvalue::Aggregate(box AggregateKind::Tuple, fields))
             }
             ExprKind::Closure { closure_id, substs, upvars } => { // see (*) above
                 let upvars =
                     upvars.into_iter()
                           .map(|upvar| unpack!(block = this.as_operand(block, scope, upvar)))
                           .collect();
-                block.and(Rvalue::Aggregate(AggregateKind::Closure(closure_id, substs), upvars))
+                block.and(Rvalue::Aggregate(box AggregateKind::Closure(closure_id, substs), upvars))
             }
             ExprKind::Adt {
                 adt_def, variant_index, substs, fields, base
@@ -215,7 +215,8 @@ fn expr_as_rvalue(&mut self,
                     field_names.iter().filter_map(|n| fields_map.get(n).cloned()).collect()
                 };
 
-                let adt = AggregateKind::Adt(adt_def, variant_index, substs, active_field_index);
+                let adt =
+                    box AggregateKind::Adt(adt_def, variant_index, substs, active_field_index);
                 block.and(Rvalue::Aggregate(adt, fields))
             }
             ExprKind::Assign { .. } |
index db4561af734d5627d5faae1b4497f34df825486e..a334923546fb2df76a8c4ccb73cd242bf11ae6ab 100644 (file)
@@ -21,7 +21,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     /// up rvalues so as to freeze the value that will be consumed.
     pub fn as_temp<M>(&mut self,
                       block: BasicBlock,
-                      temp_lifetime: Option<CodeExtent<'tcx>>,
+                      temp_lifetime: Option<CodeExtent>,
                       expr: M)
                       -> BlockAnd<Lvalue<'tcx>>
         where M: Mirror<'tcx, Output = Expr<'tcx>>
@@ -32,7 +32,7 @@ pub fn as_temp<M>(&mut self,
 
     fn expr_as_temp(&mut self,
                     mut block: BasicBlock,
-                    temp_lifetime: Option<CodeExtent<'tcx>>,
+                    temp_lifetime: Option<CodeExtent>,
                     expr: Expr<'tcx>)
                     -> BlockAnd<Lvalue<'tcx>> {
         debug!("expr_as_temp(block={:?}, expr={:?})", block, expr);
index c03432312b0ab6c4adc235e2a3036603c6f3854b..3c7ab373651d2c7983eda3d1c06116d137fbc147 100644 (file)
@@ -129,7 +129,7 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
                 this.cfg.push(block, Statement {
                     source_info: source_info,
                     kind: StatementKind::InlineAsm {
-                        asm: asm.clone(),
+                        asm: box asm.clone(),
                         outputs: outputs,
                         inputs: inputs
                     },
index 0833342927fec9dbbb31bab1164aa70a44080b58..28386fa598ce6c7890ddd6762a44d3e4bb65d369 100644 (file)
@@ -308,7 +308,7 @@ pub fn perform_test(&mut self,
                     let eq_block = self.cfg.start_new_block();
                     let cleanup = self.diverge_cleanup();
                     self.cfg.terminate(block, source_info, TerminatorKind::Call {
-                        func: Operand::Constant(Constant {
+                        func: Operand::Constant(box Constant {
                             span: test.span,
                             ty: mty,
                             literal: method
index 35a8b245f2bb64203a7e19e14d8c891015e02821..6c93e073de6b1953bd56b60de2d9069409b9d390 100644 (file)
@@ -40,7 +40,7 @@ pub fn literal_operand(&mut self,
                            ty: Ty<'tcx>,
                            literal: Literal<'tcx>)
                            -> Operand<'tcx> {
-        let constant = Constant {
+        let constant = box Constant {
             span: span,
             ty: ty,
             literal: literal,
@@ -49,7 +49,7 @@ pub fn literal_operand(&mut self,
     }
 
     pub fn unit_rvalue(&mut self) -> Rvalue<'tcx> {
-        Rvalue::Aggregate(AggregateKind::Tuple, vec![])
+        Rvalue::Aggregate(box AggregateKind::Tuple, vec![])
     }
 
     // Returns a zero literal operand for the appropriate type, works for
index 8c057b02df2bf35c07c81dd550669a2ecbd82227..fb173e2487bff0c5091fb68566f4a5975f16b9f3 100644 (file)
@@ -14,7 +14,7 @@
 use hair::Pattern;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
-use rustc::middle::region::{CodeExtent, CodeExtentData};
+use rustc::middle::region::CodeExtent;
 use rustc::mir::*;
 use rustc::mir::transform::MirSource;
 use rustc::mir::visit::MutVisitor;
@@ -172,7 +172,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 {
     let span = tcx.hir.span(ctor_id);
     if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
-        let pe = ty::ParameterEnvironment::for_item(tcx, ctor_id);
+        let pe = tcx.parameter_environment(tcx.hir.local_def_id(ctor_id));
         tcx.infer_ctxt(pe, Reveal::UserFacing).enter(|infcx| {
             let (mut mir, src) =
                 shim::build_adt_ctor(&infcx, ctor_id, fields, span);
@@ -206,13 +206,14 @@ fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              -> Ty<'tcx> {
     let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_id);
 
+    let closure_def_id = tcx.hir.local_def_id(closure_expr_id);
     let region = ty::ReFree(ty::FreeRegion {
-        scope: Some(tcx.item_extent(body_id.node_id)),
+        scope: closure_def_id,
         bound_region: ty::BoundRegion::BrEnv,
     });
     let region = tcx.mk_region(region);
 
-    match tcx.closure_kind(tcx.hir.local_def_id(closure_expr_id)) {
+    match tcx.closure_kind(closure_def_id) {
         ty::ClosureKind::Fn =>
             tcx.mk_ref(region,
                        ty::TypeAndMut { ty: closure_ty,
@@ -337,12 +338,8 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
     let span = tcx.hir.span(fn_id);
     let mut builder = Builder::new(hir.clone(), span, arguments.len(), return_ty);
 
-    let call_site_extent =
-        tcx.intern_code_extent(
-            CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body.value.id });
-    let arg_extent =
-        tcx.intern_code_extent(
-            CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.value.id });
+    let call_site_extent = CodeExtent::CallSiteScope(body.id());
+    let arg_extent = CodeExtent::ParameterScope(body.id());
     let mut block = START_BLOCK;
     unpack!(block = builder.in_scope(call_site_extent, block, |builder| {
         unpack!(block = builder.in_scope(arg_extent, block, |builder| {
@@ -405,22 +402,15 @@ pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
     let span = tcx.hir.span(owner_id);
     let mut builder = Builder::new(hir.clone(), span, 0, ty);
 
-    let extent = hir.region_maps.temporary_scope(tcx, ast_expr.id)
-                                .unwrap_or(tcx.item_extent(owner_id));
     let mut block = START_BLOCK;
-    let _ = builder.in_scope(extent, block, |builder| {
-        let expr = builder.hir.mirror(ast_expr);
-        unpack!(block = builder.into(&Lvalue::Local(RETURN_POINTER), block, expr));
+    let expr = builder.hir.mirror(ast_expr);
+    unpack!(block = builder.into_expr(&Lvalue::Local(RETURN_POINTER), block, expr));
 
-        let source_info = builder.source_info(span);
-        let return_block = builder.return_block();
-        builder.cfg.terminate(block, source_info,
-                              TerminatorKind::Goto { target: return_block });
-        builder.cfg.terminate(return_block, source_info,
-                              TerminatorKind::Return);
+    let source_info = builder.source_info(span);
+    builder.cfg.terminate(block, source_info, TerminatorKind::Return);
 
-        return_block.unit()
-    });
+    // Constants can't `return` so a return block should not be created.
+    assert_eq!(builder.cached_return_block, None);
 
     builder.finish(vec![], ty)
 }
@@ -490,7 +480,7 @@ fn finish(self,
     fn args_and_body(&mut self,
                      mut block: BasicBlock,
                      arguments: &[(Ty<'gcx>, Option<&'gcx hir::Pat>)],
-                     argument_extent: CodeExtent<'tcx>,
+                     argument_extent: CodeExtent,
                      ast_body: &'gcx hir::Expr)
                      -> BlockAnd<()>
     {
index f9c08f34eaf3f4fde47daac87c75282d3391760b..ae47f4c42442041fe47241444d4c796fb5a91c39 100644 (file)
@@ -87,7 +87,7 @@
 */
 
 use build::{BlockAnd, BlockAndExtension, Builder, CFG};
-use rustc::middle::region::{CodeExtent, CodeExtentData};
+use rustc::middle::region::CodeExtent;
 use rustc::middle::lang_items;
 use rustc::middle::const_val::ConstVal;
 use rustc::ty::subst::{Kind, Subst};
@@ -102,7 +102,7 @@ pub struct Scope<'tcx> {
     visibility_scope: VisibilityScope,
 
     /// the extent of this scope within source code.
-    extent: CodeExtent<'tcx>,
+    extent: CodeExtent,
 
     /// Whether there's anything to do for the cleanup path, that is,
     /// when unwinding through this scope. This includes destructors,
@@ -137,7 +137,7 @@ pub struct Scope<'tcx> {
     free: Option<FreeData<'tcx>>,
 
     /// The cache for drop chain on “normal” exit into a particular BasicBlock.
-    cached_exits: FxHashMap<(BasicBlock, CodeExtent<'tcx>), BasicBlock>,
+    cached_exits: FxHashMap<(BasicBlock, CodeExtent), BasicBlock>,
 }
 
 struct DropData<'tcx> {
@@ -180,7 +180,7 @@ struct FreeData<'tcx> {
 #[derive(Clone, Debug)]
 pub struct BreakableScope<'tcx> {
     /// Extent of the loop
-    pub extent: CodeExtent<'tcx>,
+    pub extent: CodeExtent,
     /// Where the body of the loop begins. `None` if block
     pub continue_block: Option<BasicBlock>,
     /// Block to branch into when the loop or block terminates (either by being `break`-en out
@@ -271,7 +271,7 @@ pub fn in_breakable_scope<F, R>(&mut self,
     /// Convenience wrapper that pushes a scope and then executes `f`
     /// to build its contents, popping the scope afterwards.
     pub fn in_scope<F, R>(&mut self,
-                          extent: CodeExtent<'tcx>,
+                          extent: CodeExtent,
                           mut block: BasicBlock,
                           f: F)
                           -> BlockAnd<R>
@@ -289,7 +289,7 @@ pub fn in_scope<F, R>(&mut self,
     /// scope and call `pop_scope` afterwards. Note that these two
     /// calls must be paired; using `in_scope` as a convenience
     /// wrapper maybe preferable.
-    pub fn push_scope(&mut self, extent: CodeExtent<'tcx>) {
+    pub fn push_scope(&mut self, extent: CodeExtent) {
         debug!("push_scope({:?})", extent);
         let vis_scope = self.visibility_scope;
         self.scopes.push(Scope {
@@ -306,7 +306,7 @@ pub fn push_scope(&mut self, extent: CodeExtent<'tcx>) {
     /// drops onto the end of `block` that are needed.  This must
     /// match 1-to-1 with `push_scope`.
     pub fn pop_scope(&mut self,
-                     extent: CodeExtent<'tcx>,
+                     extent: CodeExtent,
                      mut block: BasicBlock)
                      -> BlockAnd<()> {
         debug!("pop_scope({:?}, {:?})", extent, block);
@@ -330,7 +330,7 @@ pub fn pop_scope(&mut self,
     /// module comment for details.
     pub fn exit_scope(&mut self,
                       span: Span,
-                      extent: CodeExtent<'tcx>,
+                      extent: CodeExtent,
                       mut block: BasicBlock,
                       target: BasicBlock) {
         debug!("exit_scope(extent={:?}, block={:?}, target={:?})", extent, block, target);
@@ -391,7 +391,7 @@ pub fn new_visibility_scope(&mut self, span: Span) -> VisibilityScope {
     /// resolving `break` and `continue`.
     pub fn find_breakable_scope(&mut self,
                            span: Span,
-                           label: CodeExtent<'tcx>)
+                           label: CodeExtent)
                            -> &mut BreakableScope<'tcx> {
         // find the loop-scope with the correct id
         self.breakable_scopes.iter_mut()
@@ -411,12 +411,12 @@ pub fn source_info(&self, span: Span) -> SourceInfo {
 
     /// Returns the extent of the scope which should be exited by a
     /// return.
-    pub fn extent_of_return_scope(&self) -> CodeExtent<'tcx> {
+    pub fn extent_of_return_scope(&self) -> CodeExtent {
         // The outermost scope (`scopes[0]`) will be the `CallSiteScope`.
         // We want `scopes[1]`, which is the `ParameterScope`.
         assert!(self.scopes.len() >= 2);
-        assert!(match *self.scopes[1].extent {
-            CodeExtentData::ParameterScope { .. } => true,
+        assert!(match self.scopes[1].extent {
+            CodeExtent::ParameterScope(_) => true,
             _ => false,
         });
         self.scopes[1].extent
@@ -424,7 +424,7 @@ pub fn extent_of_return_scope(&self) -> CodeExtent<'tcx> {
 
     /// Returns the topmost active scope, which is known to be alive until
     /// the next scope expression.
-    pub fn topmost_scope(&self) -> CodeExtent<'tcx> {
+    pub fn topmost_scope(&self) -> CodeExtent {
         self.scopes.last().expect("topmost_scope: no scopes present").extent
     }
 
@@ -434,7 +434,7 @@ pub fn topmost_scope(&self) -> CodeExtent<'tcx> {
     /// `extent`.
     pub fn schedule_drop(&mut self,
                          span: Span,
-                         extent: CodeExtent<'tcx>,
+                         extent: CodeExtent,
                          lvalue: &Lvalue<'tcx>,
                          lvalue_ty: Ty<'tcx>) {
         let needs_drop = self.hir.needs_drop(lvalue_ty);
@@ -524,7 +524,7 @@ pub fn schedule_drop(&mut self,
     /// There may only be one “free” scheduled in any given scope.
     pub fn schedule_box_free(&mut self,
                              span: Span,
-                             extent: CodeExtent<'tcx>,
+                             extent: CodeExtent,
                              value: &Lvalue<'tcx>,
                              item_ty: Ty<'tcx>) {
         for scope in self.scopes.iter_mut().rev() {
@@ -786,7 +786,7 @@ fn build_free<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
     let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
     let substs = tcx.intern_substs(&[Kind::from(data.item_ty)]);
     TerminatorKind::Call {
-        func: Operand::Constant(Constant {
+        func: Operand::Constant(box Constant {
             span: data.span,
             ty: tcx.type_of(free_func).subst(tcx, substs),
             literal: Literal::Value {
index 2ec4a8a07df71640d0538d5effdd867a66bb2e92..920da30611633d64d66bd5ef18f3003f18d04adf 100644 (file)
@@ -11,7 +11,7 @@
 use hair::*;
 use hair::cx::Cx;
 use hair::cx::to_ref::ToRef;
-use rustc::middle::region::{BlockRemainder, CodeExtentData};
+use rustc::middle::region::{BlockRemainder, CodeExtent};
 use rustc::hir;
 use syntax::ast;
 
@@ -24,7 +24,7 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> {
         let stmts = mirror_stmts(cx, self.id, &*self.stmts);
         Block {
             targeted_by_break: self.targeted_by_break,
-            extent: cx.tcx.node_extent(self.id),
+            extent: CodeExtent::Misc(self.id),
             span: self.span,
             stmts: stmts,
             expr: self.expr.to_ref(),
@@ -44,7 +44,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 result.push(StmtRef::Mirror(Box::new(Stmt {
                     span: stmt.span,
                     kind: StmtKind::Expr {
-                        scope: cx.tcx.node_extent(id),
+                        scope: CodeExtent::Misc(id),
                         expr: expr.to_ref(),
                     },
                 })))
@@ -55,19 +55,17 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         // ignore for purposes of the MIR
                     }
                     hir::DeclLocal(ref local) => {
-                        let remainder_extent = CodeExtentData::Remainder(BlockRemainder {
+                        let remainder_extent = CodeExtent::Remainder(BlockRemainder {
                             block: block_id,
                             first_statement_index: index as u32,
                         });
-                        let remainder_extent =
-                            cx.tcx.intern_code_extent(remainder_extent);
 
                         let pattern = Pattern::from_hir(cx.tcx, cx.tables(), &local.pat);
                         result.push(StmtRef::Mirror(Box::new(Stmt {
                             span: stmt.span,
                             kind: StmtKind::Let {
                                 remainder_scope: remainder_extent,
-                                init_scope: cx.tcx.node_extent(id),
+                                init_scope: CodeExtent::Misc(id),
                                 pattern: pattern,
                                 initializer: local.init.to_ref(),
                             },
@@ -84,7 +82,7 @@ pub fn to_expr_ref<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                    block: &'tcx hir::Block)
                                    -> ExprRef<'tcx> {
     let block_ty = cx.tables().node_id_to_type(block.id);
-    let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, block.id);
+    let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(block.id);
     let expr = Expr {
         ty: block_ty,
         temp_lifetime: temp_lifetime,
index 6a1817aba09835348459479f38e11b15ff15fc44..b180d982e86b669c9be4c517efa98d2a7503e454 100644 (file)
@@ -14,7 +14,6 @@
 use hair::cx::Cx;
 use hair::cx::block;
 use hair::cx::to_ref::ToRef;
-use rustc::hir::map;
 use rustc::hir::def::{Def, CtorKind};
 use rustc::middle::const_val::ConstVal;
 use rustc::ty::{self, AdtKind, VariantDef, Ty};
@@ -26,8 +25,8 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
     type Output = Expr<'tcx>;
 
     fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
-        let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, self.id);
-        let expr_extent = cx.tcx.node_extent(self.id);
+        let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(self.id);
+        let expr_extent = CodeExtent::Misc(self.id);
 
         debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span);
 
@@ -238,7 +237,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                           expr: &'tcx hir::Expr)
                                           -> Expr<'tcx> {
     let expr_ty = cx.tables().expr_ty(expr);
-    let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+    let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
 
     let kind = match expr.node {
         // Here comes the interesting stuff:
@@ -610,7 +609,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             match dest.target_id {
                 hir::ScopeTarget::Block(target_id) |
                 hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(target_id)) => ExprKind::Break {
-                    label: cx.tcx.node_extent(target_id),
+                    label: CodeExtent::Misc(target_id),
                     value: value.to_ref(),
                 },
                 hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
@@ -621,7 +620,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             match dest.target_id {
                 hir::ScopeTarget::Block(_) => bug!("cannot continue to blocks"),
                 hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(loop_id)) => ExprKind::Continue {
-                    label: cx.tcx.node_extent(loop_id),
+                    label: CodeExtent::Misc(loop_id),
                 },
                 hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
                     bug!("invalid loop id for continue: {}", err)
@@ -686,7 +685,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         hir::ExprBox(ref value) => {
             ExprKind::Box {
                 value: value.to_ref(),
-                value_extents: cx.tcx.node_extent(value.id),
+                value_extents: CodeExtent::Misc(value.id),
             }
         }
         hir::ExprArray(ref fields) => ExprKind::Array { fields: fields.to_ref() },
@@ -707,7 +706,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                  method_call: ty::MethodCall)
                                  -> Expr<'tcx> {
     let callee = cx.tables().method_map[&method_call];
-    let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+    let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
     Expr {
         temp_lifetime: temp_lifetime,
         temp_lifetime_was_shrunk: was_shrunk,
@@ -791,7 +790,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                expr: &'tcx hir::Expr,
                                def: Def)
                                -> ExprKind<'tcx> {
-    let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+    let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
 
     match def {
         Def::Local(def_id) => {
@@ -807,33 +806,20 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                    closure_expr_id);
             let var_ty = cx.tables().node_id_to_type(id_var);
 
-            let body_id = match cx.tcx.hir.find(closure_expr_id) {
-                Some(map::NodeExpr(expr)) => {
-                    match expr.node {
-                        hir::ExprClosure(.., body, _) => body.node_id,
-                        _ => {
-                            span_bug!(expr.span, "closure expr is not a closure expr");
-                        }
-                    }
-                }
-                _ => {
-                    span_bug!(expr.span, "ast-map has garbage for closure expr");
-                }
-            };
-
             // FIXME free regions in closures are not right
             let closure_ty = cx.tables().node_id_to_type(closure_expr_id);
 
             // FIXME we're just hard-coding the idea that the
             // signature will be &self or &mut self and hence will
             // have a bound region with number 0
+            let closure_def_id = cx.tcx.hir.local_def_id(closure_expr_id);
             let region = ty::ReFree(ty::FreeRegion {
-                scope: Some(cx.tcx.node_extent(body_id)),
+                scope: closure_def_id,
                 bound_region: ty::BoundRegion::BrAnon(0),
             });
             let region = cx.tcx.mk_region(region);
 
-            let self_expr = match cx.tcx.closure_kind(cx.tcx.hir.local_def_id(closure_expr_id)) {
+            let self_expr = match cx.tcx.closure_kind(closure_def_id) {
                 ty::ClosureKind::Fn => {
                     let ref_closure_ty = cx.tcx.mk_ref(region,
                                                        ty::TypeAndMut {
@@ -979,7 +965,7 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         PassArgs::ByRef => {
             let region = cx.tcx.node_scope_region(expr.id);
             let (temp_lifetime, was_shrunk) =
-                cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+                cx.region_maps.temporary_scope2(expr.id);
             argrefs.extend(args.iter()
                 .map(|arg| {
                     let arg_ty = cx.tables().expr_ty_adjusted(arg);
@@ -1031,7 +1017,7 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
     // construct the complete expression `foo()` for the overloaded call,
     // which will yield the &T type
-    let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+    let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
     let ref_kind = overloaded_operator(cx, expr, method_call, pass_args, receiver, args);
     let ref_expr = Expr {
         temp_lifetime: temp_lifetime,
@@ -1056,7 +1042,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         closure_expr_id: closure_expr.id,
     };
     let upvar_capture = cx.tables().upvar_capture(upvar_id).unwrap();
-    let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, closure_expr.id);
+    let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(closure_expr.id);
     let var_ty = cx.tables().node_id_to_type(id_var);
     let captured_var = Expr {
         temp_lifetime: temp_lifetime,
index ee8547e5dd679f9f4694d8e75e6c8d6cdf37a50c..9ffce18fe150e0c8b52ac54df9164910d5631345 100644 (file)
@@ -35,7 +35,7 @@
 pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-    pub region_maps: Rc<RegionMaps<'tcx>>,
+    pub region_maps: Rc<RegionMaps>,
     constness: hir::Constness,
 
     /// True if this constant/function needs overflow checks.
index 0e8992e62ea6c8968eff6420194c7e7be817736f..1af9d722599e6e7663e035aa47659a31969d8415 100644 (file)
@@ -32,7 +32,7 @@
 #[derive(Clone, Debug)]
 pub struct Block<'tcx> {
     pub targeted_by_break: bool,
-    pub extent: CodeExtent<'tcx>,
+    pub extent: CodeExtent,
     pub span: Span,
     pub stmts: Vec<StmtRef<'tcx>>,
     pub expr: Option<ExprRef<'tcx>>,
@@ -53,7 +53,7 @@ pub struct Stmt<'tcx> {
 pub enum StmtKind<'tcx> {
     Expr {
         /// scope for this statement; may be used as lifetime of temporaries
-        scope: CodeExtent<'tcx>,
+        scope: CodeExtent,
 
         /// expression being evaluated in this statement
         expr: ExprRef<'tcx>,
@@ -62,11 +62,11 @@ pub enum StmtKind<'tcx> {
     Let {
         /// scope for variables bound in this let; covers this and
         /// remaining statements in block
-        remainder_scope: CodeExtent<'tcx>,
+        remainder_scope: CodeExtent,
 
         /// scope for the initialization itself; might be used as
         /// lifetime of temporaries
-        init_scope: CodeExtent<'tcx>,
+        init_scope: CodeExtent,
 
         /// let <PAT> = ...
         pattern: Pattern<'tcx>,
@@ -97,7 +97,7 @@ pub struct Expr<'tcx> {
 
     /// lifetime of this expression if it should be spilled into a
     /// temporary; should be None only if in a constant context
-    pub temp_lifetime: Option<CodeExtent<'tcx>>,
+    pub temp_lifetime: Option<CodeExtent>,
 
     /// whether this temp lifetime was shrunk by #36082.
     pub temp_lifetime_was_shrunk: bool,
@@ -112,12 +112,12 @@ pub struct Expr<'tcx> {
 #[derive(Clone, Debug)]
 pub enum ExprKind<'tcx> {
     Scope {
-        extent: CodeExtent<'tcx>,
+        extent: CodeExtent,
         value: ExprRef<'tcx>,
     },
     Box {
         value: ExprRef<'tcx>,
-        value_extents: CodeExtent<'tcx>,
+        value_extents: CodeExtent,
     },
     Call {
         ty: ty::Ty<'tcx>,
@@ -210,11 +210,11 @@ pub enum ExprKind<'tcx> {
         arg: ExprRef<'tcx>,
     },
     Break {
-        label: CodeExtent<'tcx>,
+        label: CodeExtent,
         value: Option<ExprRef<'tcx>>,
     },
     Continue {
-        label: CodeExtent<'tcx>,
+        label: CodeExtent,
     },
     Return {
         value: Option<ExprRef<'tcx>>,
index 5fa56bac1379be8b120ab0e044d77bd4bee40877..014705bf32fa8b454391fc68b83ff2af95b44cf0 100644 (file)
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![deny(warnings)]
-#![unstable(feature = "rustc_private", issue = "27812")]
 
 #![feature(associated_consts)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(i128_type)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
 #![feature(placement_in_syntax)]
 #![feature(collection_placement)]
 
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
 #[macro_use] extern crate log;
 extern crate graphviz as dot;
 #[macro_use]
index 1458ea7fdd6a29fcd9fb5e9b75c5ddf88bf95337..6f4480bf6dd16d525bdb54dc8ba02a9f66b2ffa7 100644 (file)
@@ -15,7 +15,7 @@
 use rustc::mir::*;
 use rustc::mir::transform::MirSource;
 use rustc::ty::{self, Ty};
-use rustc::ty::subst::{Kind, Subst};
+use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::ty::maps::Providers;
 
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
@@ -41,8 +41,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
 {
     debug!("make_shim({:?})", instance);
     let did = instance.def_id();
-    let span = tcx.def_span(did);
-    let param_env = tcx.construct_parameter_environment(span, did, None);
+    let param_env = tcx.parameter_environment(did);
 
     let mut result = match instance {
         ty::InstanceDef::Item(..) =>
@@ -66,7 +65,6 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
 
             build_call_shim(
                 tcx,
-                &param_env,
                 def_id,
                 adjustment,
                 CallKind::Indirect,
@@ -78,7 +76,6 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
             // trans::mir knows to turn to an actual virtual call.
             build_call_shim(
                 tcx,
-                &param_env,
                 def_id,
                 Adjustment::Identity,
                 CallKind::Direct(def_id),
@@ -94,7 +91,6 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
 
             build_call_shim(
                 tcx,
-                &param_env,
                 call_once,
                 Adjustment::RefMut,
                 CallKind::Direct(call_mut),
@@ -158,7 +154,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
     let substs = if let Some(ty) = ty {
         tcx.mk_substs(iter::once(Kind::from(ty)))
     } else {
-        param_env.free_substs
+        Substs::identity_for_item(tcx, def_id)
     };
     let fn_ty = tcx.type_of(def_id).subst(tcx, substs);
     let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
@@ -272,7 +268,6 @@ fn downcast_subpath(&self, _path: Self::Path, _variant: usize) -> Option<Self::P
 /// If `untuple_args` is a vec of types, the second argument of the
 /// function will be untupled as these types.
 fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
-                             param_env: &ty::ParameterEnvironment<'tcx>,
                              def_id: DefId,
                              rcvr_adjustment: Adjustment,
                              call_kind: CallKind,
@@ -283,7 +278,7 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
             call_kind={:?}, untuple_args={:?})",
            def_id, rcvr_adjustment, call_kind, untuple_args);
 
-    let fn_ty = tcx.type_of(def_id).subst(tcx, param_env.free_substs);
+    let fn_ty = tcx.type_of(def_id);
     let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
     let span = tcx.def_span(def_id);
 
@@ -323,11 +318,12 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
     let (callee, mut args) = match call_kind {
         CallKind::Indirect => (rcvr, vec![]),
         CallKind::Direct(def_id) => (
-            Operand::Constant(Constant {
+            Operand::Constant(box Constant {
                 span: span,
-                ty: tcx.type_of(def_id).subst(tcx, param_env.free_substs),
+                ty: tcx.type_of(def_id),
                 literal: Literal::Value {
-                    value: ConstVal::Function(def_id, param_env.free_substs),
+                    value: ConstVal::Function(def_id,
+                        Substs::identity_for_item(tcx, def_id)),
                 },
             }),
             vec![rcvr]
@@ -449,7 +445,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
             kind: StatementKind::Assign(
                 Lvalue::Local(RETURN_POINTER),
                 Rvalue::Aggregate(
-                    AggregateKind::Adt(adt_def, variant_no, substs, None),
+                    box AggregateKind::Adt(adt_def, variant_no, substs, None),
                     (1..sig.inputs().len()+1).map(|i| {
                         Operand::Consume(Lvalue::Local(Local::new(i)))
                     }).collect()
index fbb67161bac9d82fb7d5034ccab663d481d9819c..08a4961c6cd1ba40317605a73c95e0110a10d303 100644 (file)
@@ -316,7 +316,7 @@ fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
             _ => return,
         }
 
-        *operand = Operand::Constant(self.constant.clone());
+        *operand = Operand::Constant(box self.constant.clone());
         self.uses_replaced += 1
     }
 }
index 4309f91c635bb15bc6f733123354c0d24b733625..d21dbeafb5d0a0b269184aec28b2fcd8942ddfeb 100644 (file)
@@ -49,8 +49,8 @@ fn run_pass<'a, 'tcx>(&self,
                     &Rvalue::Aggregate(ref agg_kind, ref operands) => (agg_kind, operands),
                     _ => span_bug!(src_info.span, "expected aggregate, not {:?}", rhs),
                 };
-                let (adt_def, variant, substs) = match agg_kind {
-                    &AggregateKind::Adt(adt_def, variant, substs, None)
+                let (adt_def, variant, substs) = match **agg_kind {
+                    AggregateKind::Adt(adt_def, variant, substs, None)
                         => (adt_def, variant, substs),
                     _ => span_bug!(src_info.span, "expected struct, not {:?}", rhs),
                 };
@@ -114,8 +114,8 @@ fn get_aggregate_statement_index<'a, 'tcx, 'b>(start: usize,
             &Rvalue::Aggregate(ref kind, ref operands) => (kind, operands),
             _ => continue,
         };
-        let (adt_def, variant) = match kind {
-            &AggregateKind::Adt(adt_def, variant, _, None) => (adt_def, variant),
+        let (adt_def, variant) = match **kind {
+            AggregateKind::Adt(adt_def, variant, _, None) => (adt_def, variant),
             _ => continue,
         };
         if operands.len() == 0 {
index f60dcbed6ba474bee54f34fd07d9042b35f97e39..e6d62dc6460726365dc560edb3492f74964f5f44 100644 (file)
@@ -219,7 +219,8 @@ fn should_inline(&self,
 
         // FIXME: Give a bonus to functions with only a single caller
 
-        let param_env = ty::ParameterEnvironment::for_item(tcx, self.source.item_id());
+        let def_id = tcx.hir.local_def_id(self.source.item_id());
+        let param_env = tcx.parameter_environment(def_id);
 
         let mut first_block = true;
         let mut cost = 0;
index ed9a0d3809f245886e0aa6e41bee1c7f76ba3d7f..e1c4602b045ebab53404a86b715176f6c4a7c84e 100644 (file)
@@ -230,7 +230,7 @@ fn promote_temp(&mut self, temp: Local) -> Local {
                 (if self.keep_original {
                     rhs.clone()
                 } else {
-                    let unit = Rvalue::Aggregate(AggregateKind::Tuple, vec![]);
+                    let unit = Rvalue::Aggregate(box AggregateKind::Tuple, vec![]);
                     mem::replace(rhs, unit)
                 }, statement.source_info)
             };
@@ -288,7 +288,7 @@ fn promote_temp(&mut self, temp: Local) -> Local {
 
     fn promote_candidate(mut self, candidate: Candidate) {
         let span = self.promoted.span;
-        let new_operand = Operand::Constant(Constant {
+        let new_operand = Operand::Constant(box Constant {
             span: span,
             ty: self.promoted.return_ty,
             literal: Literal::Promoted {
index 4b1c82f383f85ce1a638dc2e048b0980f1af43a3..72edf68f4034c47121332cf54b57d7647115ed56 100644 (file)
@@ -242,9 +242,9 @@ fn deny_drop(&self) {
                    to the crate attributes to enable");
         } else {
             self.find_drop_implementation_method_span()
-                .map(|span| err.span_label(span, &format!("destructor defined here")));
+                .map(|span| err.span_label(span, "destructor defined here"));
 
-            err.span_label(self.span, &format!("constants cannot have destructors"));
+            err.span_label(self.span, "constants cannot have destructors");
         }
 
         err.emit();
@@ -291,8 +291,8 @@ fn try_consume(&mut self) -> bool {
                 "cannot refer to statics by value, use a constant instead"
             };
             struct_span_err!(self.tcx.sess, self.span, E0394, "{}", msg)
-                .span_label(self.span, &format!("referring to another static by value"))
-                .note(&format!("use the address-of operator or a constant instead"))
+                .span_label(self.span, "referring to another static by value")
+                .note("use the address-of operator or a constant instead")
                 .emit();
 
             // Replace STATIC with NOT_CONST to avoid further errors.
@@ -529,7 +529,7 @@ fn visit_lvalue(&mut self,
                                         "raw pointers cannot be dereferenced in {}s",
                                         this.mode)
                                     .span_label(this.span,
-                                        &format!("dereference of raw pointer in constant"))
+                                        "dereference of raw pointer in constant")
                                     .emit();
                                 }
                             }
@@ -645,7 +645,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                             struct_span_err!(self.tcx.sess,  self.span, E0017,
                                              "references in {}s may only refer \
                                               to immutable values", self.mode)
-                                .span_label(self.span, &format!("{}s require immutable values",
+                                .span_label(self.span, format!("{}s require immutable values",
                                                                 self.mode))
                                 .emit();
                         }
@@ -713,7 +713,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                             self.mode)
                         .span_label(
                             self.span,
-                            &format!("comparing raw pointers in static"))
+                            "comparing raw pointers in static")
                         .emit();
                     }
                 }
@@ -724,13 +724,13 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                 if self.mode != Mode::Fn {
                     struct_span_err!(self.tcx.sess, self.span, E0010,
                                      "allocations are not allowed in {}s", self.mode)
-                        .span_label(self.span, &format!("allocation not allowed in {}s", self.mode))
+                        .span_label(self.span, format!("allocation not allowed in {}s", self.mode))
                         .emit();
                 }
             }
 
             Rvalue::Aggregate(ref kind, _) => {
-                if let AggregateKind::Adt(def, ..) = *kind {
+                if let AggregateKind::Adt(def, ..) = **kind {
                     if def.has_dtor(self.tcx) {
                         self.add(Qualif::NEEDS_DROP);
                         self.deny_drop();
@@ -937,8 +937,7 @@ fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return Qualif::NOT_CONST.bits();
     }
 
-    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
-    let param_env = ty::ParameterEnvironment::for_item(tcx, node_id);
+    let param_env = tcx.parameter_environment(def_id);
 
     let mut qualifier = Qualifier::new(tcx, param_env, def_id, mir, Mode::Const);
     qualifier.qualify_const().bits()
@@ -966,7 +965,7 @@ fn run_pass<'a, 'tcx>(&self,
             MirSource::Const(_) |
             MirSource::Promoted(..) => return
         };
-        let param_env = ty::ParameterEnvironment::for_item(tcx, id);
+        let param_env = tcx.parameter_environment(def_id);
 
         if mode == Mode::Fn || mode == Mode::ConstFn {
             // This is ugly because Qualifier holds onto mir,
index d21a6ddfdfb970c85b57276238399370133ddeff..1dcacb29c3ecc406807630affdfd7e7209b14910 100644 (file)
@@ -37,7 +37,7 @@ fn run_pass<'a, 'tcx>(&self,
         for block in mir.basic_blocks_mut() {
             let terminator = block.terminator_mut();
             terminator.kind = match terminator.kind {
-                TerminatorKind::SwitchInt { discr: Operand::Constant(Constant {
+                TerminatorKind::SwitchInt { discr: Operand::Constant(box Constant {
                     literal: Literal::Value { ref value }, ..
                 }), ref values, ref targets, .. } => {
                     if let Some(ref constint) = value.to_const_int() {
@@ -54,7 +54,7 @@ fn run_pass<'a, 'tcx>(&self,
                         continue
                     }
                 },
-                TerminatorKind::Assert { target, cond: Operand::Constant(Constant {
+                TerminatorKind::Assert { target, cond: Operand::Constant(box Constant {
                     literal: Literal::Value {
                         value: ConstVal::Bool(cond)
                     }, ..
@@ -66,4 +66,3 @@ fn run_pass<'a, 'tcx>(&self,
         }
     }
 }
-
index b325470ec818cadcd33f6dd3309ec408400a5351..82c0d2c1b01c6ab3f52f688538c4e87b9d7476f1 100644 (file)
@@ -534,7 +534,7 @@ fn check_call_inputs(&mut self,
 
     fn is_box_free(&self, operand: &Operand<'tcx>) -> bool {
         match operand {
-            &Operand::Constant(Constant {
+            &Operand::Constant(box Constant {
                 literal: Literal::Value {
                     value: ConstVal::Function(def_id, _), ..
                 }, ..
@@ -751,7 +751,7 @@ fn run_pass<'a, 'tcx>(&self,
             // broken MIR, so try not to report duplicate errors.
             return;
         }
-        let param_env = ty::ParameterEnvironment::for_item(tcx, item_id);
+        let param_env = tcx.parameter_environment(def_id);
         tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
             let mut checker = TypeChecker::new(&infcx, item_id);
             {
index 5f51888019b9d2cd2f34b1d4ba2e4a55d8b08077..eaba573dcd2e582d21dfdc056e87ba601d820e94 100644 (file)
@@ -13,6 +13,7 @@
 use rustc::mir::*;
 use rustc::mir::transform::{MirSuite, MirPassIndex, MirSource};
 use rustc::ty::TyCtxt;
+use rustc::ty::item_path;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::{Idx};
 use std::fmt::Display;
@@ -48,7 +49,9 @@ pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return;
     }
 
-    let node_path = tcx.item_path_str(tcx.hir.local_def_id(source.item_id()));
+    let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below
+        tcx.item_path_str(tcx.hir.local_def_id(source.item_id()))
+    });
     dump_matched_mir_node(tcx, pass_num, pass_name, &node_path,
                           disambiguator, source, mir);
     for (index, promoted_mir) in mir.promoted.iter_enumerated() {
@@ -67,7 +70,9 @@ pub fn dump_enabled<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         Some(ref filters) => filters,
     };
     let node_id = source.item_id();
-    let node_path = tcx.item_path_str(tcx.hir.local_def_id(node_id));
+    let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below
+        tcx.item_path_str(tcx.hir.local_def_id(node_id))
+    });
     filters.split("&")
            .any(|filter| {
                filter == "all" ||
@@ -76,6 +81,10 @@ pub fn dump_enabled<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            })
 }
 
+// #41697 -- we use `with_forced_impl_filename_line()` because
+// `item_path_str()` would otherwise trigger `type_of`, and this can
+// run while we are already attempting to evaluate `type_of`.
+
 fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    pass_num: Option<(MirSuite, MirPassIndex)>,
                                    pass_name: &str,
@@ -315,7 +324,9 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write)
         MirSource::Promoted(_, i) => write!(w, "{:?} in", i)?
     }
 
-    write!(w, " {}", tcx.node_path_str(src.item_id()))?;
+    item_path::with_forced_impl_filename_line(|| { // see notes on #41697 elsewhere
+        write!(w, " {}", tcx.node_path_str(src.item_id()))
+    })?;
 
     if let MirSource::Fn(_) = src {
         write!(w, "(")?;
index 8c45a6669453354fdfcbe5b9202502f2f9a7d545..d7fee7f3110f4cdb90e197f16dcfcab5fc0f0b63 100644 (file)
@@ -55,7 +55,7 @@ fn invalid_visibility(&self, vis: &Visibility, span: Span, note: Option<&str>) {
                                            E0449,
                                            "unnecessary visibility qualifier");
             if vis == &Visibility::Public {
-                err.span_label(span, &format!("`pub` not needed here"));
+                err.span_label(span, "`pub` not needed here");
             }
             if let Some(note) = note {
                 err.note(note);
@@ -80,7 +80,7 @@ fn check_trait_fn_not_const(&self, constness: Spanned<Constness>) {
             Constness::Const => {
                 struct_span_err!(self.session, constness.span, E0379,
                                  "trait fns cannot be declared const")
-                    .span_label(constness.span, &format!("trait fns cannot be const"))
+                    .span_label(constness.span, "trait fns cannot be const")
                     .emit();
             }
             _ => {}
@@ -272,7 +272,7 @@ fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
                                                    E0130,
                                                    "patterns aren't allowed in foreign function \
                                                     declarations");
-                    err.span_label(span, &format!("pattern not allowed in foreign function"));
+                    err.span_label(span, "pattern not allowed in foreign function");
                     if is_recent {
                         err.span_note(span,
                                       "this is a recent error, see issue #35203 for more details");
index 608238dfe3735d6f46ea5b71648f0a1d7424e308..a0998b1bd1bfb3fd7cd3a54da70b140d3987da0a 100644 (file)
@@ -180,7 +180,7 @@ fn visit_pat(&mut self, p: &'tcx hir::Pat) {
                     Ok(Ordering::Greater) => {
                         struct_span_err!(self.tcx.sess, start.span, E0030,
                             "lower range bound must be less than or equal to upper")
-                            .span_label(start.span, &format!("lower bound larger than upper bound"))
+                            .span_label(start.span, "lower bound larger than upper bound")
                             .emit();
                     }
                     Err(ErrorReported) => {}
index 749146fe49672a766c755e2fd02b180fbadf57cc..29fac5463e557907073c8ea9c165f3b75af6f6c5 100644 (file)
@@ -252,7 +252,7 @@ fn visit_macro_def(&mut self, macro_def: &'v hir::MacroDef) {
 
 impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
 
-    fn visit_mod(&mut self, m: &'v ast::Mod, _s: Span, _n: NodeId) {
+    fn visit_mod(&mut self, m: &'v ast::Mod, _s: Span, _a: &[ast::Attribute], _n: NodeId) {
         self.record("Mod", Id::None, m);
         ast_visit::walk_mod(self, m)
     }
index 22566c813d86ae4da36bd7ed0994e989a566277a..97f0022b8db8ddfc5cd184561af959bd4af1b827 100644 (file)
@@ -15,7 +15,6 @@
 //! This API is completely unstable and subject to change.
 
 #![crate_name = "rustc_passes"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 #![deny(warnings)]
 
 #![feature(rustc_diagnostic_macros)]
-#![feature(staged_api)]
-#![feature(rustc_private)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
 
 #[macro_use]
 extern crate rustc;
index 2ea235af103788b0f9de6e09b5f3a36b139ffbdd..21a4c007fb1926b35144ee74db78919dd8ebf430 100644 (file)
@@ -118,7 +118,7 @@ fn visit_expr(&mut self, e: &'hir hir::Expr) {
                                              "`break` with value from a `{}` loop",
                                              kind.name())
                                 .span_label(e.span,
-                                            &format!("can only break with a value inside `loop`"))
+                                            "can only break with a value inside `loop`")
                                 .emit();
                         }
                     }
@@ -154,12 +154,12 @@ fn require_loop(&self, name: &str, span: Span) {
             Loop(_) => {}
             Closure => {
                 struct_span_err!(self.sess, span, E0267, "`{}` inside of a closure", name)
-                .span_label(span, &format!("cannot break inside of a closure"))
+                .span_label(span, "cannot break inside of a closure")
                 .emit();
             }
             Normal => {
                 struct_span_err!(self.sess, span, E0268, "`{}` outside of loop", name)
-                .span_label(span, &format!("cannot break outside of a loop"))
+                .span_label(span, "cannot break outside of a loop")
                 .emit();
             }
         }
@@ -169,7 +169,7 @@ fn emit_unlabled_cf_in_while_condition(&mut self, span: Span, cf_type: &str) {
         struct_span_err!(self.sess, span, E0590,
                          "`break` or `continue` with no label in the condition of a `while` loop")
             .span_label(span,
-                        &format!("unlabeled `{}` in the condition of a `while` loop", cf_type))
+                        format!("unlabeled `{}` in the condition of a `while` loop", cf_type))
             .emit();
     }
 }
index d9921e62330b95e1fa098a7f39b60540641af3c5..24218725186624525e735628bd03a9fac3b6b07a 100644 (file)
@@ -190,7 +190,7 @@ fn visit_rvalue(&mut self,
             Rvalue::Aggregate(ref kind, ref _operands) => {
                 // AggregateKind is not distinguished by visit API, so
                 // record it. (`super_rvalue` handles `_operands`.)
-                self.record(match *kind {
+                self.record(match **kind {
                     AggregateKind::Array(_) => "AggregateKind::Array",
                     AggregateKind::Tuple => "AggregateKind::Tuple",
                     AggregateKind::Adt(..) => "AggregateKind::Adt",
index d0bf49b7b337d17fff8910c0f17a82602fdc2962..8d455adc23c99d95b500988fec69e1874f192d79 100644 (file)
@@ -138,7 +138,7 @@ fn with_item_id_pushed<F>(&mut self, id: ast::NodeId, f: F, span: Span)
             });
             if !any_static {
                 struct_span_err!(self.sess, span, E0265, "recursive constant")
-                    .span_label(span, &format!("recursion not allowed in constant"))
+                    .span_label(span, "recursion not allowed in constant")
                     .emit();
             }
             return;
diff --git a/src/librustc_platform_intrinsics/hexagon.rs b/src/librustc_platform_intrinsics/hexagon.rs
new file mode 100644 (file)
index 0000000..56d6398
--- /dev/null
@@ -0,0 +1,2937 @@
+// 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.
+
+// DO NOT EDIT: autogenerated by etc/platform-intrinsics/generator.py
+// ignore-tidy-linelength
+
+#![allow(unused_imports)]
+
+use {Intrinsic, Type};
+use IntrinsicDef::Named;
+
+// The default inlining settings trigger a pathological behaviour in
+// LLVM, which causes makes compilation very slow. See #28273.
+#[inline(never)]
+pub fn find(name: &str) -> Option<Intrinsic> {
+    if !name.starts_with("Q6_") { return None }
+    Some(match &name["Q6_".len()..] {
+        "R_vextract64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x16, &::U32]; &INPUTS },
+            output: &::U32,
+            definition: Named("llvm.hexagon.V6.extractw")
+        },
+        "R_vextract128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x32, &::U32]; &INPUTS },
+            output: &::U32,
+            definition: Named("llvm.hexagon.V6.extractw.128B")
+        },
+        "V_lo64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U32x32]; &INPUTS },
+            output: &::U32x16,
+            definition: Named("llvm.hexagon.V6.lo")
+        },
+        "V_lo128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U32x64]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.lo.128B")
+        },
+        "V_hi64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U32x32]; &INPUTS },
+            output: &::U32x16,
+            definition: Named("llvm.hexagon.V6.hi")
+        },
+        "V_hi128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U32x64]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.hi.128B")
+        },
+        "V_vsplat_R64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U32]; &INPUTS },
+            output: &::U32x16,
+            definition: Named("llvm.hexagon.V6.lvsplatuw")
+        },
+        "V_vsplat_R128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.lvsplatuw.128B")
+        },
+        "Q_and_QQ64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.pred.and")
+        },
+        "Q_and_QQ128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.pred.and.128B")
+        },
+        "Q_not_Q64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U32x2]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.pred.not")
+        },
+        "Q_not_Q128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U32x4]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.pred.not.128B")
+        },
+        "Q_or_QQ64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.pred.or")
+        },
+        "Q_or_QQ128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.pred.or.128B")
+        },
+        "Q_xor_QQ64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.pred.xor")
+        },
+        "Q_xor_QQ128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.pred.xor.128B")
+        },
+        "Vub_vabsdiff_VubVub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U8x64]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vabsdiffub")
+        },
+        "Vuh_vabsdiff_VuhVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x32, &::U16x32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vabsdiffuh")
+        },
+        "Vub_vabsdiff_VubVub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vabsdiffub.128B")
+        },
+        "Vuh_vabsdiff_VuhVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vabsdiffuh.128B")
+        },
+        "Vuh_vabsdiff_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vabsdiffh")
+        },
+        "Vuw_vabsdiff_VwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::U32x16,
+            definition: Named("llvm.hexagon.V6.vabsdiffw")
+        },
+        "Vuh_vabsdiff_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vabsdiffh.128B")
+        },
+        "Vuw_vabsdiff_VwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vabsdiffw.128B")
+        },
+        "Vh_vabs_Vh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vabsh")
+        },
+        "Vw_vabs_Vw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vabsw")
+        },
+        "Vh_vabs_Vh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vabsh.128B")
+        },
+        "Vw_vabs_Vw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vabsw.128B")
+        },
+        "Vh_vabs_Vh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vabsh.sat")
+        },
+        "Vw_vabs_Vw_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vabsw.sat")
+        },
+        "Vh_vabs_Vh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vabsh.sat.128B")
+        },
+        "Vw_vabs_Vw_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vabsw.sat.128B")
+        },
+        "Vb_vadd_VbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x64, &::I8x64]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vaddb")
+        },
+        "Vh_vadd_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vaddh")
+        },
+        "Vw_vadd_VwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vaddw")
+        },
+        "Vb_vadd_VbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x128, &::I8x128]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vaddb.128B")
+        },
+        "Vh_vadd_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vaddh.128B")
+        },
+        "Vw_vadd_VwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vaddw.128B")
+        },
+        "Vh_vadd_VhVh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vaddhsat")
+        },
+        "Vw_vadd_VwVw_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vaddwsat")
+        },
+        "Vh_vadd_VhVh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vaddhsat.128B")
+        },
+        "Vw_vadd_VwVw_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vaddwsat.128B")
+        },
+        "Vub_vadd_VubVub_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U8x64]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vaddubsat")
+        },
+        "Vuh_vadd_VuhVuh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x32, &::U16x32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vadduhsat")
+        },
+        "Vub_vadd_VubVub_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vaddubsat.128B")
+        },
+        "Vuh_vadd_VuhVuh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vadduhsat.128B")
+        },
+        "Wb_vadd_WbWb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x128, &::I8x128]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vaddb.dv")
+        },
+        "Wh_vadd_WhWh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vaddh.dv")
+        },
+        "Ww_vadd_WwWw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vaddw.dv")
+        },
+        "Wb_vadd_WbWb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x256, &::I8x256]; &INPUTS },
+            output: &::I8x256,
+            definition: Named("llvm.hexagon.V6.vaddb.dv.128B")
+        },
+        "Wh_vadd_WhWh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x128, &::I16x128]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vaddh.dv.128B")
+        },
+        "Ww_vadd_WwWw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x64, &::I32x64]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vaddw.dv.128B")
+        },
+        "Wh_vadd_WhWh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vaddhsat.dv")
+        },
+        "Ww_vadd_WwWw_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vaddwsat.dv")
+        },
+        "Wh_vadd_WhWh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x128, &::I16x128]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vaddhsat.dv.128B")
+        },
+        "Ww_vadd_WwWw_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x64, &::I32x64]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vaddwsat.dv.128B")
+        },
+        "Wub_vadd_WubWub_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vaddubsat.dv")
+        },
+        "Wuh_vadd_WuhWuh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vadduhsat.dv")
+        },
+        "Wub_vadd_WubWub_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x256, &::U8x256]; &INPUTS },
+            output: &::U8x256,
+            definition: Named("llvm.hexagon.V6.vaddubsat.dv.128B")
+        },
+        "Wuh_vadd_WuhWuh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x128, &::U16x128]; &INPUTS },
+            output: &::U16x128,
+            definition: Named("llvm.hexagon.V6.vadduhsat.dv.128B")
+        },
+        "V_valign_VVR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U8x64, &::U8x64, &::U32]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.valignb")
+        },
+        "V_valign_VVR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U8x128, &::U8x128, &::U32]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.valignb.128B")
+        },
+        "V_valign_VVI64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U8x64, &::U8x64, &::U32]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.valignbi")
+        },
+        "V_valign_VVI128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U8x128, &::U8x128, &::U32]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.valignbi.128B")
+        },
+        "V_vlalign_VVR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U8x64, &::U8x64, &::U32]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vlalignb")
+        },
+        "V_vlalign_VVR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U8x128, &::U8x128, &::U32]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vlalignb.128B")
+        },
+        "V_vlalign_VVI64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U8x64, &::U8x64, &::U32]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vlalignbi")
+        },
+        "V_vlalign_VVI128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U8x128, &::U8x128, &::U32]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vlalignbi.128B")
+        },
+        "V_vand_VV64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x32, &::U16x32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vand")
+        },
+        "V_vand_VV128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vand.128B")
+        },
+        "V_vand_QR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vandqrt")
+        },
+        "V_vand_QR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vandqrt.128B")
+        },
+        "V_vandor_VQR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U8x64, &::U32x2, &::U32]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vandqrt.acc")
+        },
+        "V_vandor_VQR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U8x128, &::U32x4, &::U32]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vandqrt.acc.128B")
+        },
+        "Q_vand_VR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U32]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vandvrt")
+        },
+        "Q_vand_VR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U32]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vandvrt.128B")
+        },
+        "Q_vandor_QVR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::U8x64, &::U32]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vandvrt")
+        },
+        "Q_vandor_QVR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::U8x128, &::U32]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vandvrt.128B")
+        },
+        "Vh_vasl_VhR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::U32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vaslh")
+        },
+        "Vw_vasl_VwR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vaslw")
+        },
+        "Vh_vasl_VhR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vaslh.128B")
+        },
+        "Vw_vasl_VwR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vaslw.128B")
+        },
+        "Vh_vasl_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vaslhv")
+        },
+        "Vw_vasl_VwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vaslwv")
+        },
+        "Vh_vasl_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vaslhv.128B")
+        },
+        "Vw_vasl_VwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vaslwv.128B")
+        },
+        "Vw_vaslacc_VwVwR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I32x16, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vaslw.acc")
+        },
+        "Vw_vaslacc_VwVwR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I32x32, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vaslw.acc.128B")
+        },
+        "Vh_vasr_VhR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::U32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vasrh")
+        },
+        "Vw_vasr_VwR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vasrw")
+        },
+        "Vh_vasr_VhR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vasrh.128B")
+        },
+        "Vw_vasr_VwR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vasrw.128B")
+        },
+        "Vh_vasr_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vasrhv")
+        },
+        "Vw_vasr_VwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vasrwv")
+        },
+        "Vh_vasr_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vasrhv.128B")
+        },
+        "Vw_vasr_VwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vasrwv.128B")
+        },
+        "Vw_vasracc_VwVwR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I32x16, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vasrw.acc")
+        },
+        "Vw_vasracc_VwVwR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I32x32, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vasrw.acc.128B")
+        },
+        "Vh_vasr_VwVwR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I32x16, &::U32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vasrhw")
+        },
+        "Vh_vasr_VwVwR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I32x32, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vasrhw.128B")
+        },
+        "Vb_vasr_VhVhR_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x32, &::I16x32, &::U32]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vasrhbsat")
+        },
+        "Vub_vasr_VhVhR_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x32, &::I16x32, &::U32]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vasrhbsat")
+        },
+        "Vh_vasr_VwVwR_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I32x16, &::U32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vasrwhsat")
+        },
+        "Vuh_vasr_VwVwR_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I32x16, &::U32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vasrwhsat")
+        },
+        "Vb_vasr_VhVhR_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x64, &::I16x64, &::U32]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vasrhbsat.128B")
+        },
+        "Vub_vasr_VhVhR_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x64, &::I16x64, &::U32]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vasrhbsat.128B")
+        },
+        "Vh_vasr_VwVwR_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I32x32, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vasrwhsat.128B")
+        },
+        "Vuh_vasr_VwVwR_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I32x32, &::U32]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vasrwhsat.128B")
+        },
+        "Vb_vasr_VhVhR_rnd_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x32, &::I16x32, &::U32]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vasrhbrndsat")
+        },
+        "Vub_vasr_VhVhR_rnd_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x32, &::I16x32, &::U32]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vasrhbrndsat")
+        },
+        "Vh_vasr_VwVwR_rnd_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I32x16, &::U32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vasrwhrndsat")
+        },
+        "Vuh_vasr_VwVwR_rnd_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I32x16, &::U32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vasrwhrndsat")
+        },
+        "Vb_vasr_VhVhR_rnd_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x64, &::I16x64, &::U32]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vasrhbrndsat.128B")
+        },
+        "Vub_vasr_VhVhR_rnd_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x64, &::I16x64, &::U32]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vasrhbrndsat.128B")
+        },
+        "Vh_vasr_VwVwR_rnd_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I32x32, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vasrwhrndsat.128B")
+        },
+        "Vuh_vasr_VwVwR_rnd_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I32x32, &::U32]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vasrwhrndsat.128B")
+        },
+        "V_equals_V64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U32x16]; &INPUTS },
+            output: &::U32x16,
+            definition: Named("llvm.hexagon.V6.vassign")
+        },
+        "V_equals_V128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U32x32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vassign.128B")
+        },
+        "W_equals_W64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U32x32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vassignp")
+        },
+        "W_equals_W128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U32x64]; &INPUTS },
+            output: &::U32x64,
+            definition: Named("llvm.hexagon.V6.vassignp.128B")
+        },
+        "Vh_vavg_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vavgh")
+        },
+        "Vw_vavg_VwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vavgw")
+        },
+        "Vh_vavg_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vavgh.128B")
+        },
+        "Vw_vavg_VwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vavgw.128B")
+        },
+        "Vub_vavg_VubVub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U8x64]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vavgub")
+        },
+        "Vuh_vavg_VuhVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x32, &::U16x32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vavguh")
+        },
+        "Vub_vavg_VubVub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vavgub.128B")
+        },
+        "Vuh_vavg_VuhVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vavguh.128B")
+        },
+        "Vh_vavg_VhVh_rnd64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vavgrndh")
+        },
+        "Vw_vavg_VwVw_rnd64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vavgrndw")
+        },
+        "Vh_vavg_VhVh_rnd128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vavgrndh.128B")
+        },
+        "Vw_vavg_VwVw_rnd128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vavgrndw.128B")
+        },
+        "Vub_vavg_VubVub_rnd64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U8x64]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vavgrndub")
+        },
+        "Vuh_vavg_VuhVuh_rnd64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x32, &::U16x32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vavgrnduh")
+        },
+        "Vub_vavg_VubVub_rnd128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vavgrndub.128B")
+        },
+        "Vuh_vavg_VuhVuh_rnd128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vavgrnduh.128B")
+        },
+        "Vuh_vcl0_Vuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U16x32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vcl0h")
+        },
+        "Vuw_vcl0_Vuw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U32x16]; &INPUTS },
+            output: &::U32x16,
+            definition: Named("llvm.hexagon.V6.vcl0w")
+        },
+        "Vuh_vcl0_Vuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vcl0h.128B")
+        },
+        "Vuw_vcl0_Vuw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U32x32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vcl0w.128B")
+        },
+        "W_vcombine_VV64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U8x64]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vcombine")
+        },
+        "W_vcombine_VV128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U8x256,
+            definition: Named("llvm.hexagon.V6.vcombine.128B")
+        },
+        "V_vzero64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::U32x16,
+            definition: Named("llvm.hexagon.V6.vd0")
+        },
+        "V_vzero128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vd0.128B")
+        },
+        "Vb_vdeal_Vb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I8x64]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vdealb")
+        },
+        "Vh_vdeal_Vh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vdealh")
+        },
+        "Vb_vdeal_Vb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I8x128]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vdealb.128B")
+        },
+        "Vh_vdeal_Vh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vdealh.128B")
+        },
+        "Vb_vdeale_VbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x64, &::I8x64]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vdealb4w")
+        },
+        "Vb_vdeale_VbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x128, &::I8x128]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vdealb4w.128B")
+        },
+        "W_vdeal_VVR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U8x64, &::U8x64, &::U32]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vdealvdd")
+        },
+        "W_vdeal_VVR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U8x128, &::U8x128, &::U32]; &INPUTS },
+            output: &::U8x256,
+            definition: Named("llvm.hexagon.V6.vdealvdd.128B")
+        },
+        "V_vdelta_VV64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U8x64]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vdelta")
+        },
+        "V_vdelta_VV128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vdelta.128B")
+        },
+        "Vh_vdmpy_VubRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vdmpybus")
+        },
+        "Vh_vdmpy_VubRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vdmpybus.128B")
+        },
+        "Vh_vdmpyacc_VhVubRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x32, &::U8x64, &::U32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vdmpybus.acc")
+        },
+        "Vh_vdmpyacc_VhVubRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x64, &::U8x128, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vdmpybus.acc.128B")
+        },
+        "Wh_vdmpy_WubRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vdmpybus.dv")
+        },
+        "Wh_vdmpy_WubRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x256, &::U32]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vdmpybus.dv.128B")
+        },
+        "Wh_vdmpyacc_WhWubRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x64, &::U8x128, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vdmpybus.dv.acc")
+        },
+        "Wh_vdmpyacc_WhWubRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x128, &::U8x256, &::U32]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vdmpybus.dv.acc.128B")
+        },
+        "Vw_vdmpy_VhRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vdmpyhb")
+        },
+        "Vw_vdmpy_VhRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vdmpyhb.128B")
+        },
+        "Vw_vdmpyacc_VwVhRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I16x32, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vdmpyhb.acc")
+        },
+        "Vw_vdmpyacc_VwVhRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I16x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vdmpyhb.acc.128B")
+        },
+        "Ww_vdmpy_WhRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vdmpyhb.dv")
+        },
+        "Ww_vdmpy_WhRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x128, &::U32]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vdmpyhb.dv.128B")
+        },
+        "Ww_vdmpyacc_WwWhRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I16x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vdmpyhb.dv.acc")
+        },
+        "Ww_vdmpyacc_WwWhRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x64, &::I16x128, &::U32]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vdmpyhb.dv.acc.128B")
+        },
+        "Vw_vdmpy_WwRh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vdmpyhisat")
+        },
+        "Vw_vdmpy_WwRh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vdmpyhisat.128B")
+        },
+        "Vw_vdmpy_VhRh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vdmpyhsat")
+        },
+        "Vw_vdmpy_VhRh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vdmpyhsat.128B")
+        },
+        "Vw_vdmpy_WhRuh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vdmpyhsuisat")
+        },
+        "Vw_vdmpy_WhRuh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x128, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vdmpyhsuisat.128B")
+        },
+        "Vw_vdmpy_VhRuh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vdmpyhsusat")
+        },
+        "Vw_vdmpy_VhRuh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vdmpyhsusat.128B")
+        },
+        "Vw_vdmpy_VhVh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vdmpyhvsat")
+        },
+        "Vw_vdmpy_VhVh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vdmpyhvsat.128B")
+        },
+        "Vw_vdmpyacc_VwWwRh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I32x32, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vdmpyhisat_acc")
+        },
+        "Vw_vdmpyacc_VwWwRh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I32x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vdmpyhisat_acc.128B")
+        },
+        "Wuw_vdsad_WuhRuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vdsaduh")
+        },
+        "Wuw_vdsad_WuhRuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x128, &::U32]; &INPUTS },
+            output: &::U32x64,
+            definition: Named("llvm.hexagon.V6.vdsaduh.128B")
+        },
+        "Wuw_vdsadacc_WuwWuhRuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x32, &::U16x64, &::U32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vdsaduh.acc")
+        },
+        "Wuw_vdsadacc_WuwWuhRuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x64, &::U16x128, &::U32]; &INPUTS },
+            output: &::U32x64,
+            definition: Named("llvm.hexagon.V6.vdsaduh.acc.128B")
+        },
+        "Vw_vdmpyacc_VwVhRh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I16x32, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vdmpyhsat_acc")
+        },
+        "Vw_vdmpyacc_VwVhRh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I16x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vdmpyhsat_acc.128B")
+        },
+        "Vw_vdmpyacc_VwWhRuh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I16x64, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vdmpyhsuisat_acc")
+        },
+        "Vw_vdmpyacc_VwWhRuh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I16x128, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vdmpyhsuisat_acc.128B")
+        },
+        "Vw_vdmpyacc_VwVhRuh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I16x32, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vdmpyhsusat_acc")
+        },
+        "Vw_vdmpyacc_VwVhRuh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I16x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vdmpyhsusat_acc.128B")
+        },
+        "Vw_vdmpyacc_VwVhVh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I16x32, &::I16x32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vdmpyhvsat_acc")
+        },
+        "Vw_vdmpyacc_VwVhVh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I16x64, &::I16x64]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vdmpyhvsat_acc.128B")
+        },
+        "Q_vcmp_eq_VbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x64, &::I8x64]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.veqb")
+        },
+        "Q_vcmp_eq_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.veqh")
+        },
+        "Q_vcmp_eq_VwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.veqw")
+        },
+        "Q_vcmp_eq_VbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x128, &::I8x128]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.veqb.128B")
+        },
+        "Q_vcmp_eq_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.veqh.128B")
+        },
+        "Q_vcmp_eq_VwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.veqw.128B")
+        },
+        "Q_vcmp_eqand_QVbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I8x64, &::I8x64]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.veqb.and")
+        },
+        "Q_vcmp_eqand_QVhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I16x32, &::I16x32]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.veqh.and")
+        },
+        "Q_vcmp_eqand_QVwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I32x16, &::I32x16]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.veqw.and")
+        },
+        "Q_vcmp_eqand_QVbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I8x128, &::I8x128]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.veqb.and.128B")
+        },
+        "Q_vcmp_eqand_QVhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I16x64, &::I16x64]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.veqh.and.128B")
+        },
+        "Q_vcmp_eqand_QVwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I32x32, &::I32x32]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.veqw.and.128B")
+        },
+        "Q_vcmp_eqor_QVbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I8x64, &::I8x64]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.veqb.or")
+        },
+        "Q_vcmp_eqor_QVhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I16x32, &::I16x32]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.veqh.or")
+        },
+        "Q_vcmp_eqor_QVwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I32x16, &::I32x16]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.veqw.or")
+        },
+        "Q_vcmp_eqor_QVbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I8x128, &::I8x128]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.veqb.or.128B")
+        },
+        "Q_vcmp_eqor_QVhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I16x64, &::I16x64]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.veqh.or.128B")
+        },
+        "Q_vcmp_eqor_QVwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I32x32, &::I32x32]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.veqw.or.128B")
+        },
+        "Q_vcmp_eqxacc_QVbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I8x64, &::I8x64]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.veqb.xor")
+        },
+        "Q_vcmp_eqxacc_QVhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I16x32, &::I16x32]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.veqh.xor")
+        },
+        "Q_vcmp_eqxacc_QVwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I32x16, &::I32x16]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.veqw.xor")
+        },
+        "Q_vcmp_eqxacc_QVbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I8x128, &::I8x128]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.veqb.xor.128B")
+        },
+        "Q_vcmp_eqxacc_QVhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I16x64, &::I16x64]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.veqh.xor.128B")
+        },
+        "Q_vcmp_eqxacc_QVwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I32x32, &::I32x32]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.veqw.xor.128B")
+        },
+        "Q_vcmp_gt_VbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x64, &::I8x64]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtb")
+        },
+        "Q_vcmp_gt_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgth")
+        },
+        "Q_vcmp_gt_VwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtw")
+        },
+        "Q_vcmp_gt_VbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x128, &::I8x128]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtb.128B")
+        },
+        "Q_vcmp_gt_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgth.128B")
+        },
+        "Q_vcmp_gt_VwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtw.128B")
+        },
+        "Q_vcmp_gt_VubVub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U8x64]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtub")
+        },
+        "Q_vcmp_gt_VuhVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x32, &::U16x32]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtuh")
+        },
+        "Q_vcmp_gt_VubVub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtub.128B")
+        },
+        "Q_vcmp_gt_VuhVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U16x64]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtuh.128B")
+        },
+        "Q_vcmp_gtand_QVbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I8x64, &::I8x64]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtb.and")
+        },
+        "Q_vcmp_gtand_QVhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I16x32, &::I16x32]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgth.and")
+        },
+        "Q_vcmp_gtand_QVwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I32x16, &::I32x16]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtw.and")
+        },
+        "Q_vcmp_gtand_QVbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I8x128, &::I8x128]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtb.and.128B")
+        },
+        "Q_vcmp_gtand_QVhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I16x64, &::I16x64]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgth.and.128B")
+        },
+        "Q_vcmp_gtand_QVwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I32x32, &::I32x32]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtw.and.128B")
+        },
+        "Q_vcmp_gtand_QVubVub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::U8x64, &::U8x64]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtub.and")
+        },
+        "Q_vcmp_gtand_QVuhVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::U16x32, &::U16x32]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtuh.and")
+        },
+        "Q_vcmp_gtand_QVubVub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::U8x128, &::U8x128]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtub.and.128B")
+        },
+        "Q_vcmp_gtand_QVuhVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::U16x64, &::U16x64]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtuh.and.128B")
+        },
+        "Q_vcmp_gtor_QVbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I8x64, &::I8x64]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtb.or")
+        },
+        "Q_vcmp_gtor_QVhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I16x32, &::I16x32]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgth.or")
+        },
+        "Q_vcmp_gtor_QVwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I32x16, &::I32x16]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtw.or")
+        },
+        "Q_vcmp_gtor_QVbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I8x128, &::I8x128]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtb.or.128B")
+        },
+        "Q_vcmp_gtor_QVhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I16x64, &::I16x64]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgth.or.128B")
+        },
+        "Q_vcmp_gtor_QVwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I32x32, &::I32x32]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtw.or.128B")
+        },
+        "Q_vcmp_gtor_QVubVub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::U8x64, &::U8x64]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtub.or")
+        },
+        "Q_vcmp_gtor_QVuhVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::U16x32, &::U16x32]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtuh.or")
+        },
+        "Q_vcmp_gtor_QVubVub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::U8x128, &::U8x128]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtub.or.128B")
+        },
+        "Q_vcmp_gtor_QVuhVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::U16x64, &::U16x64]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtuh.or.128B")
+        },
+        "Q_vcmp_gtxacc_QVbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I8x64, &::I8x64]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtb.xor")
+        },
+        "Q_vcmp_gtxacc_QVhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I16x32, &::I16x32]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgth.xor")
+        },
+        "Q_vcmp_gtxacc_QVwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I32x16, &::I32x16]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtw.xor")
+        },
+        "Q_vcmp_gtxacc_QVbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I8x128, &::I8x128]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtb.xor.128B")
+        },
+        "Q_vcmp_gtxacc_QVhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I16x64, &::I16x64]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgth.xor.128B")
+        },
+        "Q_vcmp_gtxacc_QVwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I32x32, &::I32x32]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtw.xor.128B")
+        },
+        "Q_vcmp_gtxacc_QVubVub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::U8x64, &::U8x64]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtub.xor")
+        },
+        "Q_vcmp_gtxacc_QVuhVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::U16x32, &::U16x32]; &INPUTS },
+            output: &::U32x2,
+            definition: Named("llvm.hexagon.V6.vgtuh.xor")
+        },
+        "Q_vcmp_gtxacc_QVubVub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::U8x128, &::U8x128]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtub.xor.128B")
+        },
+        "Q_vcmp_gtxacc_QVuhVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::U16x64, &::U16x64]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.hexagon.V6.vgtuh.xor.128B")
+        },
+        "Vw_vinsert_VwR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vinsertwr")
+        },
+        "Vw_vinsert_VwR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vinsertwr.128B")
+        },
+        "Vuh_vlsr_VuhR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x32, &::U32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vlsrh")
+        },
+        "Vuw_vlsr_VuwR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x16, &::U32]; &INPUTS },
+            output: &::U32x16,
+            definition: Named("llvm.hexagon.V6.vlsrw")
+        },
+        "Vuh_vlsr_VuhR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U32]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vlsrh.128B")
+        },
+        "Vuw_vlsr_VuwR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x32, &::U32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vlsrw.128B")
+        },
+        "Vh_vlsr_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vlsrhv")
+        },
+        "Vw_vlsr_VwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vlsrwv")
+        },
+        "Vh_vlsr_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vlsrhv.128B")
+        },
+        "Vw_vlsr_VwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vlsrwv.128B")
+        },
+        "Vb_vlut32_VbVbR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I8x64, &::I8x64, &::U32]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vlutvvb")
+        },
+        "Vb_vlut32_VbVbR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I8x128, &::I8x128, &::U32]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vlutvvb.128B")
+        },
+        "Wh_vlut16_VbVhR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I8x64, &::I16x32, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vlutvwh")
+        },
+        "Wh_vlut16_VbVhR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I8x128, &::I16x64, &::U32]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vlutvwh.128B")
+        },
+        "Vb_vlut32or_VbVbVbR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 4] = [&::I8x64, &::I8x64, &::I8x64, &::U32]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vlutvvb.oracc")
+        },
+        "Vb_vlut32or_VbVbVbR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 4] = [&::I8x128, &::I8x128, &::I8x128, &::U32]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vlutvvb.oracc.128B")
+        },
+        "Wh_vlut16or_WhVbVhR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 4] = [&::I16x64, &::I8x64, &::I16x32, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vlutvwh.oracc")
+        },
+        "Wh_vlut16or_WhVbVhR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 4] = [&::I16x128, &::I8x128, &::I16x64, &::U32]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vlutvwh.oracc.128B")
+        },
+        "Vh_vmax_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vmaxh")
+        },
+        "Vw_vmax_VwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmaxw")
+        },
+        "Vh_vmax_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmaxh.128B")
+        },
+        "Vw_vmax_VwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmaxw.128B")
+        },
+        "Vub_vmax_VubVub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U8x64]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vmaxub")
+        },
+        "Vuh_vmax_VuhVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x32, &::U16x32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vmaxuh")
+        },
+        "Vub_vmax_VubVub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vmaxub.128B")
+        },
+        "Vuh_vmax_VuhVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vmaxuh.128B")
+        },
+        "Vh_vmin_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vminh")
+        },
+        "Vw_vmin_VwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vminw")
+        },
+        "Vh_vmin_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vminh.128B")
+        },
+        "Vw_vmin_VwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vminw.128B")
+        },
+        "Vub_vmin_VubVub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U8x64]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vminub")
+        },
+        "Vuh_vmin_VuhVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x32, &::U16x32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vminuh")
+        },
+        "Vub_vmin_VubVub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vminub.128B")
+        },
+        "Vuh_vmin_VuhVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vminuh.128B")
+        },
+        "Wh_vmpa_WubRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmpabus")
+        },
+        "Wh_vmpa_WubRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x256, &::U32]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vmpabus.128B")
+        },
+        "Wh_vmpaacc_WhWubRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x64, &::U8x128, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmpabus.acc")
+        },
+        "Wh_vmpaacc_WhWubRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x128, &::U8x256, &::U32]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vmpabus.acc.128B")
+        },
+        "Wh_vmpa_WubWb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::I8x128]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmpabusv")
+        },
+        "Wh_vmpa_WubWub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmpabuuv")
+        },
+        "Wh_vmpa_WubWb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x256, &::I8x256]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vmpabusv.128B")
+        },
+        "Wh_vmpa_WubWub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x256, &::U8x256]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vmpabuuv.128B")
+        },
+        "Ww_vmpa_WhRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpahb")
+        },
+        "Ww_vmpa_WhRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x128, &::U32]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vmpahb.128B")
+        },
+        "Ww_vmpaacc_WwWhRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I16x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpahb.acc")
+        },
+        "Ww_vmpaacc_WwWhRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x64, &::I16x128, &::U32]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vmpahb.acc.128B")
+        },
+        "Wh_vmpy_VbVub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x64, &::U8x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmpybus")
+        },
+        "Ww_vmpy_VhVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::U16x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyhus")
+        },
+        "Wh_vmpy_VbVub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x128, &::U8x128]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vmpybus.128B")
+        },
+        "Ww_vmpy_VhVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::U16x64]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vmpyhus.128B")
+        },
+        "Wh_vmpyacc_WhVbVub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x64, &::I8x64, &::U8x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmpybus.acc")
+        },
+        "Ww_vmpyacc_WwVhVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I16x32, &::U16x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyhus.acc")
+        },
+        "Wh_vmpyacc_WhVbVub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x128, &::I8x128, &::U8x128]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vmpybus.acc.128B")
+        },
+        "Ww_vmpyacc_WwVhVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x64, &::I16x64, &::U16x64]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vmpyhus.acc.128B")
+        },
+        "Wh_vmpy_VubVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::I8x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmpybusv")
+        },
+        "Wh_vmpy_VubVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::I8x128]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vmpybusv.128B")
+        },
+        "Wh_vmpyacc_WhVubVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x64, &::U8x64, &::I8x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmpybusv.acc")
+        },
+        "Wh_vmpyacc_WhVubVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x128, &::U8x128, &::I8x128]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vmpybusv.acc.128B")
+        },
+        "Wh_vmpy_VbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x64, &::I8x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmpybv")
+        },
+        "Wuh_vmpy_VubVub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U8x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vmpyubv")
+        },
+        "Ww_vmpy_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyhv")
+        },
+        "Wuw_vmpy_VuhVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x32, &::U16x32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vmpyuhv")
+        },
+        "Wh_vmpy_VbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x128, &::I8x128]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vmpybv.128B")
+        },
+        "Wuh_vmpy_VubVub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U16x128,
+            definition: Named("llvm.hexagon.V6.vmpyubv.128B")
+        },
+        "Ww_vmpy_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vmpyhv.128B")
+        },
+        "Wuw_vmpy_VuhVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U16x64]; &INPUTS },
+            output: &::U32x64,
+            definition: Named("llvm.hexagon.V6.vmpyuhv.128B")
+        },
+        "Wh_vmpyacc_WhVbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x64, &::I8x64, &::I8x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmpybv.acc")
+        },
+        "Wuh_vmpyacc_WuhVubVub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U16x64, &::U8x64, &::U8x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vmpyubv.acc")
+        },
+        "Ww_vmpyacc_WwVhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I16x32, &::I16x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyhv.acc")
+        },
+        "Wuw_vmpyacc_WuwVuhVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x32, &::U16x32, &::U16x32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vmpyuhv.acc")
+        },
+        "Wh_vmpyacc_WhVbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x128, &::I8x128, &::I8x128]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vmpybv.acc.128B")
+        },
+        "Wuh_vmpyacc_WuhVubVub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U16x128, &::U8x128, &::U8x128]; &INPUTS },
+            output: &::U16x128,
+            definition: Named("llvm.hexagon.V6.vmpyubv.acc.128B")
+        },
+        "Ww_vmpyacc_WwVhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x64, &::I16x64, &::I16x64]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vmpyhv.acc.128B")
+        },
+        "Wuw_vmpyacc_WuwVuhVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x64, &::U16x64, &::U16x64]; &INPUTS },
+            output: &::U32x64,
+            definition: Named("llvm.hexagon.V6.vmpyuhv.acc.128B")
+        },
+        "Vw_vmpye_VwVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::U16x32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyewuh")
+        },
+        "Vw_vmpye_VwVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::U16x64]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyewuh.128B")
+        },
+        "Ww_vmpy_VhRh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyh")
+        },
+        "Wuw_vmpy_VuhRuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x32, &::U32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vmpyuh")
+        },
+        "Ww_vmpy_VhRh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::U32]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vmpyh.128B")
+        },
+        "Wuw_vmpy_VuhRuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U32]; &INPUTS },
+            output: &::U32x64,
+            definition: Named("llvm.hexagon.V6.vmpyuh.128B")
+        },
+        "Ww_vmpyacc_WwVhRh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I16x32, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyhsat.acc")
+        },
+        "Ww_vmpyacc_WwVhRh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x64, &::I16x64, &::U32]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vmpyhsat.acc.128B")
+        },
+        "Vw_vmpy_VhRh_s1_rnd_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyhsrs")
+        },
+        "Vw_vmpy_VhRh_s1_rnd_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyhsrs.128B")
+        },
+        "Vw_vmpy_VhRh_s1_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyhss")
+        },
+        "Vw_vmpy_VhRh_s1_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyhss.128B")
+        },
+        "Vh_vmpy_VhVh_s1_rnd_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vmpyhvsrs")
+        },
+        "Vh_vmpy_VhVh_s1_rnd_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmpyhvsrs.128B")
+        },
+        "Vw_vmpyieo_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyieoh")
+        },
+        "Vw_vmpyieo_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyieoh.128B")
+        },
+        "Vw_vmpyieacc_VwVwVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I32x16, &::I16x32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyiewh.acc")
+        },
+        "Vw_vmpyieacc_VwVwVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I32x16, &::U16x32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyiewuh.acc")
+        },
+        "Vw_vmpyieacc_VwVwVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I32x32, &::I16x64]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyiewh.acc.128B")
+        },
+        "Vw_vmpyieacc_VwVwVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I32x32, &::U16x64]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyiewuh.acc.128B")
+        },
+        "Vw_vmpyie_VwVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::U16x32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyiewuh")
+        },
+        "Vw_vmpyie_VwVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::U16x64]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyiewuh.128B")
+        },
+        "Vh_vmpyi_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vmpyih")
+        },
+        "Vh_vmpyi_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmpyih.128B")
+        },
+        "Vh_vmpyiacc_VhVhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x32, &::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vmpyih.acc")
+        },
+        "Vh_vmpyiacc_VhVhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x64, &::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmpyih.acc.128B")
+        },
+        "Vh_vmpyi_VhRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::U32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vmpyihb")
+        },
+        "Vw_vmpyi_VwRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyiwb")
+        },
+        "Vh_vmpyi_VhRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmpyihb.128B")
+        },
+        "Vw_vmpyi_VwRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyiwb.128B")
+        },
+        "Vh_vmpyiacc_VhVhRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x32, &::I16x32, &::U32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vmpyihb.acc")
+        },
+        "Vw_vmpyiacc_VwVwRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I32x16, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyiwb.acc")
+        },
+        "Vh_vmpyiacc_VhVhRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x64, &::I16x64, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vmpyihb.acc.128B")
+        },
+        "Vw_vmpyiacc_VwVwRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I32x32, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyiwb.acc.128B")
+        },
+        "Vw_vmpyi_VwRh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyiwh")
+        },
+        "Vw_vmpyi_VwRh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyiwh.128B")
+        },
+        "Vw_vmpyiacc_VwVwRh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I32x16, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyiwh.acc")
+        },
+        "Vw_vmpyiacc_VwVwRh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I32x32, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyiwh.acc.128B")
+        },
+        "Vw_vmpyi_VwRub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyiwub")
+        },
+        "Vw_vmpyi_VwRub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyiwub.128B")
+        },
+        "Vw_vmpyiacc_VwVwRub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I32x16, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyiwub.acc")
+        },
+        "Vw_vmpyiacc_VwVwRub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I32x32, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyiwub.acc.128B")
+        },
+        "Vw_vmpyo_VwVh_s1_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I16x32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyowh")
+        },
+        "Vw_vmpyo_VwVh_s1_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I16x64]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyowh.128B")
+        },
+        "Vw_vmpyo_VwVh_s1_rnd_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I16x32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyowh.rnd")
+        },
+        "Vw_vmpyo_VwVh_s1_rnd_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I16x64]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyowh.rnd.128B")
+        },
+        "Vw_vmpyo_VwVh_s1_rnd_sat_shift64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I16x32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyowh.rnd.sacc")
+        },
+        "Vw_vmpyo_VwVh_s1_rnd_sat_shift128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I16x64]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyowh.rnd.sacc.128B")
+        },
+        "Vw_vmpyo_VwVh_s1_sat_shift64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I16x32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyowh.sacc")
+        },
+        "Vw_vmpyo_VwVh_s1_sat_shift128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I16x64]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyowh.sacc.128B")
+        },
+        "Vw_vmpyio_VwVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I16x32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vmpyiowh")
+        },
+        "Vw_vmpyio_VwVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I16x64]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vmpyiowh.128B")
+        },
+        "Wuh_vmpy_VubRub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U32]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vmpyub")
+        },
+        "Wuh_vmpy_VubRub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U32]; &INPUTS },
+            output: &::U16x128,
+            definition: Named("llvm.hexagon.V6.vmpyub.128B")
+        },
+        "Wuh_vmpyacc_WuhVubRub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U16x64, &::U8x64, &::U32]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vmpyub.acc")
+        },
+        "Wuw_vmpyacc_WuwVuhRuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x32, &::U16x32, &::U32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vmpyuh.acc")
+        },
+        "Wuh_vmpyacc_WuhVubRub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U16x128, &::U8x128, &::U32]; &INPUTS },
+            output: &::U16x128,
+            definition: Named("llvm.hexagon.V6.vmpyub.acc.128B")
+        },
+        "Wuw_vmpyacc_WuwVuhRuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x64, &::U16x64, &::U32]; &INPUTS },
+            output: &::U32x64,
+            definition: Named("llvm.hexagon.V6.vmpyuh.acc.128B")
+        },
+        "Vuw_vmux_QVV64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::U32x16, &::U32x16]; &INPUTS },
+            output: &::U32x16,
+            definition: Named("llvm.hexagon.V6.vmux")
+        },
+        "Vuw_vmux_QVV128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::U32x32, &::U32x32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vmux.128B")
+        },
+        "Vh_vnavg_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vnavgh")
+        },
+        "Vuh_vnavg_VuhVuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x32, &::U16x32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vnavguh")
+        },
+        "Vw_vnavg_VwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vnavgw")
+        },
+        "Vuw_vnavg_VuwVuw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x16, &::U32x16]; &INPUTS },
+            output: &::U32x16,
+            definition: Named("llvm.hexagon.V6.vnavguw")
+        },
+        "Vh_vnavg_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vnavgh.128B")
+        },
+        "Vuh_vnavg_VuhVuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vnavguh.128B")
+        },
+        "Vw_vnavg_VwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vnavgw.128B")
+        },
+        "Vuw_vnavg_VuwVuw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x32, &::U32x32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vnavguw.128B")
+        },
+        "Vub_vnavg_VubVub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U8x64]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vnavgub")
+        },
+        "Vub_vnavg_VubVub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vnavgub.128B")
+        },
+        "Vh_vnormamt_Vh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vnormamth")
+        },
+        "Vw_vnormamt_Vw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vnormamtw")
+        },
+        "Vh_vnormamt_Vh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vnormamth.128B")
+        },
+        "Vw_vnormamt_Vw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vnormamtw.128B")
+        },
+        "V_vnot_VV64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U16x32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vnot")
+        },
+        "V_vnot_VV128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vnot.128B")
+        },
+        "V_vor_VV64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x32, &::U16x32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vor")
+        },
+        "V_vor_VV128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vor.128B")
+        },
+        "Vb_vpacke_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vpackhe")
+        },
+        "Vh_vpacke_VwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vpackwe")
+        },
+        "Vb_vpacke_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vpackhe.128B")
+        },
+        "Vh_vpacke_VwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vpackwe.128B")
+        },
+        "Vb_vpacko_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vpackho")
+        },
+        "Vh_vpacko_VwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vpackwo")
+        },
+        "Vb_vpacko_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vpackho.128B")
+        },
+        "Vh_vpacko_VwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vpackwo.128B")
+        },
+        "Vb_vpack_VhVh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vpackhb.sat")
+        },
+        "Vub_vpack_VhVh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vpackhub.sat")
+        },
+        "Vh_vpack_VwVw_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vpackwh.sat")
+        },
+        "Vuh_vpack_VwVw_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vpackwuh.sat")
+        },
+        "Vb_vpack_VhVh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vpackhb.sat.128B")
+        },
+        "Vub_vpack_VhVh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vpackhub.sat.128B")
+        },
+        "Vh_vpack_VwVw_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vpackwh.sat.128B")
+        },
+        "Vuh_vpack_VwVw_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vpackwuh.sat.128B")
+        },
+        "Vh_vpopcount_Vh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vpopcounth")
+        },
+        "Vh_vpopcount_Vh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vpopcounth.128B")
+        },
+        "V_vrdelta_VV64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U8x64]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vrdelta")
+        },
+        "V_vrdelta_VV128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vrdelta.128B")
+        },
+        "Vw_vrmpy_VubRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vrmpybus")
+        },
+        "Vw_vrmpy_VubRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vrmpybus.128B")
+        },
+        "Vw_vrmpyacc_VwVubRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::U8x64, &::U32]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vrmpybus.acc")
+        },
+        "Vw_vrmpyacc_VwVubRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::U8x128, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vrmpybus.acc.128B")
+        },
+        "Ww_vrmpy_WubRbI64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vrmpybusi")
+        },
+        "Ww_vrmpy_WubRbI128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x256, &::U32]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vrmpybusi.128B")
+        },
+        "Ww_vrmpyacc_WwWubRbI64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::U8x128, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vrmpybusi.acc")
+        },
+        "Ww_vrmpyacc_WwWubRbI128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x64, &::U8x256, &::U32]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vrmpybusi.acc.128B")
+        },
+        "Vw_vrmpy_VubVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::I8x64]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vrmpybusv")
+        },
+        "Vw_vrmpy_VubVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::I8x128]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vrmpybusv.128B")
+        },
+        "Vw_vrmpyacc_VwVubVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::U8x64, &::I8x64]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vrmpybusv.acc")
+        },
+        "Vw_vrmpyacc_VwVubVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::U8x128, &::I8x128]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vrmpybusv.acc.128B")
+        },
+        "Vw_vrmpy_VbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x64, &::I8x64]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vrmpybv")
+        },
+        "Vuw_vrmpy_VubVub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U8x64]; &INPUTS },
+            output: &::U32x16,
+            definition: Named("llvm.hexagon.V6.vrmpyubv")
+        },
+        "Vw_vrmpy_VbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x128, &::I8x128]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vrmpybv.128B")
+        },
+        "Vuw_vrmpy_VubVub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vrmpyubv.128B")
+        },
+        "Vw_vrmpyacc_VwVbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x16, &::I8x64, &::I8x64]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vrmpywv.acc")
+        },
+        "Vuw_vrmpyacc_VuwVubVub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x16, &::U8x64, &::U8x64]; &INPUTS },
+            output: &::U32x16,
+            definition: Named("llvm.hexagon.V6.vrmpyuwv.acc")
+        },
+        "Vw_vrmpyacc_VwVbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I8x128, &::I8x128]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vrmpywv.acc.128B")
+        },
+        "Vuw_vrmpyacc_VuwVubVub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x32, &::U8x128, &::U8x128]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vrmpyuwv.acc.128B")
+        },
+        "Vuw_vrmpy_VubRub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U32]; &INPUTS },
+            output: &::U32x16,
+            definition: Named("llvm.hexagon.V6.vrmpyub")
+        },
+        "Vuw_vrmpy_VubRub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vrmpyub.128B")
+        },
+        "Vuw_vrmpyacc_VuwVubRub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x16, &::U8x64, &::U32]; &INPUTS },
+            output: &::U32x16,
+            definition: Named("llvm.hexagon.V6.vrmpyub.acc")
+        },
+        "Vuw_vrmpyacc_VuwVubRub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x32, &::U8x128, &::U32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vrmpyub.acc.128B")
+        },
+        "Wuw_vrmpy_WubRubI64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vrmpyubi")
+        },
+        "Wuw_vrmpy_WubRubI128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x256, &::U32]; &INPUTS },
+            output: &::U32x64,
+            definition: Named("llvm.hexagon.V6.vrmpyubi.128B")
+        },
+        "Wuw_vrmpyacc_WuwWubRubI64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x32, &::U8x128, &::U32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vrmpyubi.acc")
+        },
+        "Wuw_vrmpyacc_WuwWubRubI128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x64, &::U8x256, &::U32]; &INPUTS },
+            output: &::U32x64,
+            definition: Named("llvm.hexagon.V6.vrmpyubi.acc.128B")
+        },
+        "V_vror_VR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U32]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vror")
+        },
+        "V_vror_VR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U32]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vror.128B")
+        },
+        "Vb_vround_VhVh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vroundhb")
+        },
+        "Vub_vround_VhVh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vroundhub")
+        },
+        "Vh_vround_VwVw_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vroundwh")
+        },
+        "Vuh_vround_VwVw_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vroundwuh")
+        },
+        "Vb_vround_VhVh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vroundhb.128B")
+        },
+        "Vub_vround_VhVh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vroundhub.128B")
+        },
+        "Vh_vround_VwVw_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vroundwh.128B")
+        },
+        "Vuh_vround_VwVw_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vroundwuh.128B")
+        },
+        "Wuw_vrsad_WubRubI64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vrsadubi")
+        },
+        "Wuw_vrsad_WubRubI128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x256, &::U32]; &INPUTS },
+            output: &::U32x64,
+            definition: Named("llvm.hexagon.V6.vrsadubi.128B")
+        },
+        "Wuw_vrsadacc_WuwWubRubI64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x32, &::U8x128, &::U32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vrsadubi.acc")
+        },
+        "Wuw_vrsadacc_WuwWubRubI128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x64, &::U8x256, &::U32]; &INPUTS },
+            output: &::U32x64,
+            definition: Named("llvm.hexagon.V6.vrsadubi.acc.128B")
+        },
+        "Vub_vsat_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vsathub")
+        },
+        "Vub_vsat_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vsathub.128B")
+        },
+        "Vh_vsat_VwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vsatwh")
+        },
+        "Vh_vsat_VwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vsatwh.128B")
+        },
+        "Wh_vsxt_Vb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I8x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vsb")
+        },
+        "Ww_vsxt_Vh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vsh")
+        },
+        "Wh_vsxt_Vb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I8x128]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vsb.128B")
+        },
+        "Ww_vsxt_Vh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x64]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vsh.128B")
+        },
+        "Wuh_vzxt_Vub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U8x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vzb")
+        },
+        "Wuw_vzxt_Vuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U16x32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vzh")
+        },
+        "Wuh_vzxt_Vub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U8x128]; &INPUTS },
+            output: &::U16x128,
+            definition: Named("llvm.hexagon.V6.vzb.128B")
+        },
+        "Wuw_vzxt_Vuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U16x64]; &INPUTS },
+            output: &::U32x64,
+            definition: Named("llvm.hexagon.V6.vzh.128B")
+        },
+        "Vb_condacc_QVbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I8x64, &::I8x64]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vaddbq")
+        },
+        "Vh_condacc_QVhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vaddhq")
+        },
+        "Vw_condacc_QVwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vaddwq")
+        },
+        "Vb_condacc_QVbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I8x128, &::I8x128]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vaddbq.128B")
+        },
+        "Vh_condacc_QVhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vaddhq.128B")
+        },
+        "Vw_condacc_QVwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vaddwq.128B")
+        },
+        "Vb_condacc_QnVbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I8x64, &::I8x64]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vaddbnq")
+        },
+        "Vh_condacc_QnVhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vaddhnq")
+        },
+        "Vw_condacc_QnVwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vaddwnq")
+        },
+        "Vb_condacc_QnVbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I8x128, &::I8x128]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vaddbnq.128B")
+        },
+        "Vh_condacc_QnVhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vaddhnq.128B")
+        },
+        "Vw_condacc_QnVwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vaddwnq.128B")
+        },
+        "Vb_condnac_QVbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I8x64, &::I8x64]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vsubbq")
+        },
+        "Vh_condnac_QVhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vsubhq")
+        },
+        "Vw_condnac_QVwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vsubwq")
+        },
+        "Vb_condnac_QVbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I8x128, &::I8x128]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vsubbq.128B")
+        },
+        "Vh_condnac_QVhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vsubhq.128B")
+        },
+        "Vw_condnac_QVwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vsubwq.128B")
+        },
+        "Vb_condnac_QnVbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I8x64, &::I8x64]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vsubbnq")
+        },
+        "Vh_condnac_QnVhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vsubhnq")
+        },
+        "Vw_condnac_QnVwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vsubwnq")
+        },
+        "Vb_condnac_QnVbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I8x128, &::I8x128]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vsubbnq.128B")
+        },
+        "Vh_condnac_QnVhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vsubhnq.128B")
+        },
+        "Vw_condnac_QnVwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vsubwnq.128B")
+        },
+        "Vh_vshuffe_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vshufeh")
+        },
+        "Vh_vshuffe_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vshufeh.128B")
+        },
+        "Vh_vshuffo_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vshufoh")
+        },
+        "Vh_vshuffo_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vshufoh.128B")
+        },
+        "Vb_vshuff_Vb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I8x64]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vshuffb")
+        },
+        "Vh_vshuff_Vh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vshuffh")
+        },
+        "Vb_vshuff_Vb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I8x128]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vshuffb.128B")
+        },
+        "Vh_vshuff_Vh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vshuffh.128B")
+        },
+        "Vb_vshuffe_VbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x64, &::I8x64]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vshuffeb")
+        },
+        "Vb_vshuffe_VbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x128, &::I8x128]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vshuffeb.128B")
+        },
+        "Vb_vshuffo_VbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x64, &::I8x64]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vshuffob")
+        },
+        "Vb_vshuffo_VbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x128, &::I8x128]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vshuffob.128B")
+        },
+        "Vb_vshuffoe_VbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x64, &::I8x64]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vshuffoeb")
+        },
+        "Vh_vshuffoe_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vshuffoeh")
+        },
+        "Vb_vshuffoe_VbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x128, &::I8x128]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vshuffoeb.128B")
+        },
+        "Vh_vshuffoe_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vshuffoeh.128B")
+        },
+        "W_vshuff_VVR64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U8x64, &::U8x64, &::U32]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vshufvvd")
+        },
+        "W_vshuff_VVR128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U8x128, &::U8x128, &::U32]; &INPUTS },
+            output: &::U8x256,
+            definition: Named("llvm.hexagon.V6.vshufvvd.128B")
+        },
+        "Vb_vsub_VbVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x64, &::I8x64]; &INPUTS },
+            output: &::I8x64,
+            definition: Named("llvm.hexagon.V6.vsubb")
+        },
+        "Vh_vsub_VhVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vsubh")
+        },
+        "Vw_vsub_VwVw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vsubw")
+        },
+        "Vb_vsub_VbVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x128, &::I8x128]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vsubb.128B")
+        },
+        "Vh_vsub_VhVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vsubh.128B")
+        },
+        "Vw_vsub_VwVw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vsubw.128B")
+        },
+        "Vh_vsub_VhVh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x32, &::I16x32]; &INPUTS },
+            output: &::I16x32,
+            definition: Named("llvm.hexagon.V6.vsubhsat")
+        },
+        "Vw_vsub_VwVw_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x16, &::I32x16]; &INPUTS },
+            output: &::I32x16,
+            definition: Named("llvm.hexagon.V6.vsubwsat")
+        },
+        "Vh_vsub_VhVh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vsubhsat.128B")
+        },
+        "Vw_vsub_VwVw_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vsubwsat.128B")
+        },
+        "Vub_vsub_VubVub_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x64, &::U8x64]; &INPUTS },
+            output: &::U8x64,
+            definition: Named("llvm.hexagon.V6.vsububsat")
+        },
+        "Vuh_vsub_VuhVuh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x32, &::U16x32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vsubuhsat")
+        },
+        "Vub_vsub_VubVub_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vsububsat.128B")
+        },
+        "Vuh_vsub_VuhVuh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vsubuhsat.128B")
+        },
+        "Wb_vsub_WbWb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x128, &::I8x128]; &INPUTS },
+            output: &::I8x128,
+            definition: Named("llvm.hexagon.V6.vsubb.dv")
+        },
+        "Wh_vsub_WhWh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vsubh.dv")
+        },
+        "Ww_vsub_WwWw64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vsubw.dv")
+        },
+        "Wb_vsub_WbWb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x256, &::I8x256]; &INPUTS },
+            output: &::I8x256,
+            definition: Named("llvm.hexagon.V6.vsubb.dv.128B")
+        },
+        "Wh_vsub_WhWh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x128, &::I16x128]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vsubh.dv.128B")
+        },
+        "Ww_vsub_WwWw128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x64, &::I32x64]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vsubw.dv.128B")
+        },
+        "Wh_vsub_WhWh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I16x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vsubhsat.dv")
+        },
+        "Ww_vsub_WwWw_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I32x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vsubwsat.dv")
+        },
+        "Wh_vsub_WhWh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x128, &::I16x128]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vsubhsat.dv.128B")
+        },
+        "Ww_vsub_WwWw_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x64, &::I32x64]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vsubwsat.dv.128B")
+        },
+        "Wub_vsub_WubWub_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U8x128]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vsububsat.dv")
+        },
+        "Wuh_vsub_WuhWuh_sat64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vsubuhsat.dv")
+        },
+        "Wub_vsub_WubWub_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x256, &::U8x256]; &INPUTS },
+            output: &::U8x256,
+            definition: Named("llvm.hexagon.V6.vsububsat.dv.128B")
+        },
+        "Wuh_vsub_WuhWuh_sat128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x128, &::U16x128]; &INPUTS },
+            output: &::U16x128,
+            definition: Named("llvm.hexagon.V6.vsubuhsat.dv.128B")
+        },
+        "W_vswap_QVV64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x2, &::U8x64, &::U8x64]; &INPUTS },
+            output: &::U8x128,
+            definition: Named("llvm.hexagon.V6.vswap")
+        },
+        "W_vswap_QVV128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::U32x4, &::U8x128, &::U8x128]; &INPUTS },
+            output: &::U8x256,
+            definition: Named("llvm.hexagon.V6.vswap.128B")
+        },
+        "Wh_vtmpy_WbRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x128, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vtmpyb")
+        },
+        "Wh_vtmpy_WbRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x256, &::U32]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vtmpyb.128B")
+        },
+        "Wh_vtmpyacc_WhWbRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x64, &::I8x128, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vtmpyb.acc")
+        },
+        "Wh_vtmpyacc_WhWbRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x128, &::I8x256, &::U32]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vtmpyb.acc.128B")
+        },
+        "Wh_vtmpy_WubRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x128, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vtmpybus")
+        },
+        "Wh_vtmpy_WubRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x256, &::U32]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vtmpybus.128B")
+        },
+        "Wh_vtmpyacc_WhWubRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x64, &::U8x128, &::U32]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vtmpybus.acc")
+        },
+        "Wh_vtmpyacc_WhWubRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I16x128, &::U8x256, &::U32]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vtmpybus.acc.128B")
+        },
+        "Ww_vtmpy_WhRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vtmpyhb")
+        },
+        "Ww_vtmpy_WhRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x128, &::U32]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vtmpyhb.128B")
+        },
+        "Wh_vunpack_Vb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I8x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vunpackb")
+        },
+        "Wuh_vunpack_Vub64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U8x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vunpackub")
+        },
+        "Ww_vunpack_Vh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vunpackh")
+        },
+        "Wuw_vunpack_Vuh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U16x32]; &INPUTS },
+            output: &::U32x32,
+            definition: Named("llvm.hexagon.V6.vunpackuh")
+        },
+        "Wh_vunpack_Vb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I8x128]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vunpackb.128B")
+        },
+        "Wuh_vunpack_Vub128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U8x128]; &INPUTS },
+            output: &::U16x128,
+            definition: Named("llvm.hexagon.V6.vunpackub.128B")
+        },
+        "Ww_vunpack_Vh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x64]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vunpackh.128B")
+        },
+        "Wuw_vunpack_Vuh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::U16x64]; &INPUTS },
+            output: &::U32x64,
+            definition: Named("llvm.hexagon.V6.vunpackuh.128B")
+        },
+        "Wh_vunpackoor_WhVb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x64, &::I8x64]; &INPUTS },
+            output: &::I16x64,
+            definition: Named("llvm.hexagon.V6.vunpackob")
+        },
+        "Ww_vunpackoor_WwVh64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x32, &::I16x32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vunpackoh")
+        },
+        "Wh_vunpackoor_WhVb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x128, &::I8x128]; &INPUTS },
+            output: &::I16x128,
+            definition: Named("llvm.hexagon.V6.vunpackob.128B")
+        },
+        "Ww_vunpackoor_WwVh128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x64, &::I16x64]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vunpackoh.128B")
+        },
+        "Ww_vtmpyacc_WwWhRb64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x32, &::I16x64, &::U32]; &INPUTS },
+            output: &::I32x32,
+            definition: Named("llvm.hexagon.V6.vtmpyhb.acc")
+        },
+        "Ww_vtmpyacc_WwWhRb128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 3] = [&::I32x64, &::I16x128, &::U32]; &INPUTS },
+            output: &::I32x64,
+            definition: Named("llvm.hexagon.V6.vtmpyhb.acc.128B")
+        },
+        "V_vxor_VV64" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x32, &::U16x32]; &INPUTS },
+            output: &::U16x32,
+            definition: Named("llvm.hexagon.V6.vxor")
+        },
+        "V_vxor_VV128" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x64, &::U16x64]; &INPUTS },
+            output: &::U16x64,
+            definition: Named("llvm.hexagon.V6.vxor.128B")
+        },
+        _ => return None,
+    })
+}
index 296c133115f4eadd0e7e1cc1eda194ec47b1461a..21dd360c9bb7456770cfc86088c7952bb711aa2d 100644 (file)
@@ -9,10 +9,10 @@
 // except according to those terms.
 
 #![crate_name = "rustc_platform_intrinsics"]
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
 #![deny(warnings)]
 #![allow(bad_style)]
 
@@ -29,7 +29,7 @@ pub enum Type {
     Integer(/* signed */ bool, u8, /* llvm width */ u8),
     Float(u8),
     Pointer(&'static Type, Option<&'static Type>, /* const */ bool),
-    Vector(&'static Type, Option<&'static Type>, u8),
+    Vector(&'static Type, Option<&'static Type>, u16),
     Aggregate(bool, &'static [&'static Type]),
 }
 
@@ -56,6 +56,12 @@ pub enum IntrinsicDef {
 static U8x16: Type = Type::Vector(&U8, None, 16);
 static I8x32: Type = Type::Vector(&I8, None, 32);
 static U8x32: Type = Type::Vector(&U8, None, 32);
+static I8x64: Type = Type::Vector(&I8, None, 64);
+static U8x64: Type = Type::Vector(&U8, None, 64);
+static I8x128: Type = Type::Vector(&I8, None, 128);
+static U8x128: Type = Type::Vector(&U8, None, 128);
+static I8x256: Type = Type::Vector(&I8, None, 256);
+static U8x256: Type = Type::Vector(&U8, None, 256);
 
 static I16x4: Type = Type::Vector(&I16, None, 4);
 static U16x4: Type = Type::Vector(&U16, None, 4);
@@ -63,6 +69,12 @@ pub enum IntrinsicDef {
 static U16x8: Type = Type::Vector(&U16, None, 8);
 static I16x16: Type = Type::Vector(&I16, None, 16);
 static U16x16: Type = Type::Vector(&U16, None, 16);
+static I16x32: Type = Type::Vector(&I16, None, 32);
+static U16x32: Type = Type::Vector(&U16, None, 32);
+static I16x64: Type = Type::Vector(&I16, None, 64);
+static U16x64: Type = Type::Vector(&U16, None, 64);
+static I16x128: Type = Type::Vector(&I16, None, 128);
+static U16x128: Type = Type::Vector(&U16, None, 128);
 
 static I32x2: Type = Type::Vector(&I32, None, 2);
 static U32x2: Type = Type::Vector(&U32, None, 2);
@@ -70,6 +82,12 @@ pub enum IntrinsicDef {
 static U32x4: Type = Type::Vector(&U32, None, 4);
 static I32x8: Type = Type::Vector(&I32, None, 8);
 static U32x8: Type = Type::Vector(&U32, None, 8);
+static I32x16: Type = Type::Vector(&I32, None, 16);
+static U32x16: Type = Type::Vector(&U32, None, 16);
+static I32x32: Type = Type::Vector(&I32, None, 32);
+static U32x32: Type = Type::Vector(&U32, None, 32);
+static I32x64: Type = Type::Vector(&I32, None, 64);
+static U32x64: Type = Type::Vector(&U32, None, 64);
 
 static I64x1: Type = Type::Vector(&I64, None, 1);
 static U64x1: Type = Type::Vector(&U64, None, 1);
@@ -96,6 +114,7 @@ pub enum IntrinsicDef {
 mod arm;
 mod aarch64;
 mod nvptx;
+mod hexagon;
 
 impl Intrinsic {
     pub fn find(name: &str) -> Option<Intrinsic> {
@@ -107,6 +126,8 @@ pub fn find(name: &str) -> Option<Intrinsic> {
             aarch64::find(name)
         } else if name.starts_with("nvptx_") {
             nvptx::find(name)
+        } else if name.starts_with("Q6_") {
+            hexagon::find(name)
         } else {
             None
         }
index 8aa680ca12d10f49845a29f9e55785a695add257..16ab593e47a724b5372b5449b66ccfee1e8348c3 100644 (file)
@@ -51,7 +51,6 @@
 //! for more examples.
 
 #![crate_name = "rustc_plugin"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![deny(warnings)]
 
-#![feature(staged_api)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
 
 #[macro_use] extern crate syntax;
 
index cdde56f5f634be75a2d0917a5a1885bf59606e2d..3027489d65be2ea1f955e5e3c5e1c8e611b66280 100644 (file)
@@ -103,7 +103,8 @@ pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxEx
         }
         self.syntax_exts.push((name, match extension {
             NormalTT(ext, _, allow_internal_unstable) => {
-                NormalTT(ext, Some(self.krate_span), allow_internal_unstable)
+                let nid = ast::CRATE_NODE_ID;
+                NormalTT(ext, Some((nid, self.krate_span)), allow_internal_unstable)
             }
             IdentTT(ext, _, allow_internal_unstable) => {
                 IdentTT(ext, Some(self.krate_span), allow_internal_unstable)
index 82c91727293eddec09cc30f3b8ba3605f69b46ec..2ced61f5753a90c4aaf9c6312ecfd29add334272 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![crate_name = "rustc_privacy"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 #![deny(warnings)]
 
 #![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
 
 extern crate rustc;
 #[macro_use] extern crate syntax;
@@ -433,7 +434,7 @@ fn check_field(&mut self, span: Span, def: &'tcx ty::AdtDef, field: &'tcx ty::Fi
         if !def.is_enum() && !field.vis.is_accessible_from(self.current_item, self.tcx) {
             struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
                              field.name, def.variant_descr(), self.tcx.item_path_str(def.did))
-                .span_label(span, &format!("field `{}` is private", field.name))
+                .span_label(span, format!("field `{}` is private", field.name))
                 .emit();
         }
     }
@@ -926,7 +927,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                     if self.has_pub_restricted || self.has_old_errors {
                         let mut err = struct_span_err!(self.tcx.sess, self.span, E0446,
                             "private type `{}` in public interface", ty);
-                        err.span_label(self.span, &format!("can't leak private type"));
+                        err.span_label(self.span, "can't leak private type");
                         err.emit();
                     } else {
                         self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
@@ -961,7 +962,7 @@ fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
                 if self.has_pub_restricted || self.has_old_errors {
                     struct_span_err!(self.tcx.sess, self.span, E0445,
                                      "private trait `{}` in public interface", trait_ref)
-                        .span_label(self.span, &format!(
+                        .span_label(self.span, format!(
                                     "private trait can't be public"))
                         .emit();
                 } else {
index c797c151de67c602f2a71a1cd302a8e3d5da6933..57639a1ecef7b17b359436a928f5a815602e22c7 100644 (file)
@@ -150,7 +150,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                                           view_path.span,
                                           ResolutionError::SelfImportsOnlyAllowedWithin);
                         } else if source_name == "$crate" && full_path.segments.len() == 1 {
-                            let crate_root = self.resolve_crate_var(source.ctxt);
+                            let crate_root = self.resolve_crate_var(source.ctxt, item.span);
                             let crate_name = match crate_root.kind {
                                 ModuleKind::Def(_, name) => name,
                                 ModuleKind::Block(..) => unreachable!(),
@@ -247,7 +247,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
 
                 // n.b. we don't need to look at the path option here, because cstore already did
                 let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id).unwrap();
-                let module = self.get_extern_crate_root(crate_id);
+                let module = self.get_extern_crate_root(crate_id, item.span);
                 self.populate_module_if_necessary(module);
                 let used = self.process_legacy_macro_imports(item, module, expansion);
                 let binding =
@@ -279,7 +279,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                     no_implicit_prelude: parent.no_implicit_prelude || {
                         attr::contains_name(&item.attrs, "no_implicit_prelude")
                     },
-                    ..ModuleData::new(Some(parent), module_kind, def_id)
+                    ..ModuleData::new(Some(parent), module_kind, def_id, item.span)
                 });
                 self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
                 self.module_map.insert(def_id, module);
@@ -314,7 +314,10 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
             ItemKind::Enum(ref enum_definition, _) => {
                 let def = Def::Enum(self.definitions.local_def_id(item.id));
                 let module_kind = ModuleKind::Def(def, ident.name);
-                let module = self.new_module(parent, module_kind, parent.normal_ancestor_id);
+                let module = self.new_module(parent,
+                                             module_kind,
+                                             parent.normal_ancestor_id,
+                                             item.span);
                 self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
 
                 for variant in &(*enum_definition).variants {
@@ -370,7 +373,10 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
 
                 // Add all the items within to a new module.
                 let module_kind = ModuleKind::Def(Def::Trait(def_id), ident.name);
-                let module = self.new_module(parent, module_kind, parent.normal_ancestor_id);
+                let module = self.new_module(parent,
+                                             module_kind,
+                                             parent.normal_ancestor_id,
+                                             item.span);
                 self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
                 self.current_module = module;
             }
@@ -418,8 +424,10 @@ fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, expansion
     fn build_reduced_graph_for_block(&mut self, block: &Block) {
         let parent = self.current_module;
         if self.block_needs_anonymous_module(block) {
-            let module =
-                self.new_module(parent, ModuleKind::Block(block.id), parent.normal_ancestor_id);
+            let module = self.new_module(parent,
+                                         ModuleKind::Block(block.id),
+                                         parent.normal_ancestor_id,
+                                         block.span);
             self.block_map.insert(block.id, module);
             self.current_module = module; // Descend into the block.
         }
@@ -431,10 +439,14 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, chi
         let def = child.def;
         let def_id = def.def_id();
         let vis = self.session.cstore.visibility(def_id);
+        let span = child.span;
 
         match def {
             Def::Mod(..) | Def::Enum(..) => {
-                let module = self.new_module(parent, ModuleKind::Def(def, ident.name), def_id);
+                let module = self.new_module(parent,
+                                             ModuleKind::Def(def, ident.name),
+                                             def_id,
+                                             span);
                 self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
             }
             Def::Variant(..) | Def::TyAlias(..) => {
@@ -454,7 +466,10 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, chi
             }
             Def::Trait(..) => {
                 let module_kind = ModuleKind::Def(def, ident.name);
-                let module = self.new_module(parent, module_kind, parent.normal_ancestor_id);
+                let module = self.new_module(parent,
+                                             module_kind,
+                                             parent.normal_ancestor_id,
+                                             span);
                 self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
 
                 for child in self.session.cstore.item_children(def_id) {
@@ -483,18 +498,18 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, chi
         }
     }
 
-    fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'a> {
+    fn get_extern_crate_root(&mut self, cnum: CrateNum, span: Span) -> Module<'a> {
         let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
         let name = self.session.cstore.crate_name(cnum);
         let macros_only = self.session.cstore.dep_kind(cnum).macros_only();
         let module_kind = ModuleKind::Def(Def::Mod(def_id), name);
         let arenas = self.arenas;
         *self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| {
-            arenas.alloc_module(ModuleData::new(None, module_kind, def_id))
+            arenas.alloc_module(ModuleData::new(None, module_kind, def_id, span))
         })
     }
 
-    pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
+    pub fn macro_def_scope(&mut self, expansion: Mark, span: Span) -> Module<'a> {
         let def_id = self.macro_defs[&expansion];
         if let Some(id) = self.definitions.as_local_node_id(def_id) {
             self.local_macro_def_scopes[&id]
@@ -503,7 +518,7 @@ pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
             self.graph_root
         } else {
             let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
-            self.get_extern_crate_root(module_def_id.krate)
+            self.get_extern_crate_root(module_def_id.krate, span)
         }
     }
 
@@ -593,7 +608,8 @@ fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expa
         } else {
             for (name, span) in legacy_imports.imports {
                 let ident = Ident::with_empty_ctxt(name);
-                let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None);
+                let result = self.resolve_ident_in_module(module, ident, MacroNS,
+                                                          false, false, span);
                 if let Ok(binding) = result {
                     let directive = macro_use_directive(span);
                     self.potentially_unused_imports.push(directive);
@@ -607,7 +623,7 @@ fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expa
         for (name, span) in legacy_imports.reexports {
             self.session.cstore.export_macros(module.def_id().unwrap().krate);
             let ident = Ident::with_empty_ctxt(name);
-            let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None);
+            let result = self.resolve_ident_in_module(module, ident, MacroNS, false, false, span);
             if let Ok(binding) = result {
                 self.macro_exports.push(Export { name: name, def: binding.def(), span: span });
             } else {
index 2c2babf0a66535724b080ec1d8913c210f98eacd..368fb7a88685b00d461a33a87ba51485920c9e81 100644 (file)
@@ -1222,27 +1222,26 @@ fn bar() -> u32 {
 "##,
 
 E0435: r##"
-A non-constant value was used to initialise a constant.
+A non-constant value was used in a constant expression.
 
 Erroneous code example:
 
 ```compile_fail,E0435
-let foo = 42u32;
-const FOO : u32 = foo; // error: attempt to use a non-constant value in a
-                       //        constant
+let foo = 42;
+let a: [u8; foo]; // error: attempt to use a non-constant value in a constant
 ```
 
 To fix this error, please replace the value with a constant. Example:
 
 ```
-const FOO : u32 = 42u32; // ok!
+let a: [u8; 42]; // ok!
 ```
 
 Or:
 
 ```
-const OTHER_FOO : u32 = 42u32;
-const FOO : u32 = OTHER_FOO; // ok!
+const FOO: usize = 42;
+let a: [u8; FOO]; // ok!
 ```
 "##,
 
@@ -1560,7 +1559,7 @@ fn print_on_failure(state: &State) {
 //  E0157, unused error code
 //  E0257,
 //  E0258,
-    E0402, // cannot use an outer type parameter in this context
+//  E0402, // cannot use an outer type parameter in this context
 //  E0406, merged into 420
 //  E0410, merged into 408
 //  E0413, merged into 530
index a4e9a8be49f4516670466e344e1898d62834a5da..6ea666e21dcdd28fd24ab0bcd4af1e893269d753 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![crate_name = "rustc_resolve"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 
 #![feature(associated_consts)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
 
 #[macro_use]
 extern crate log;
@@ -126,8 +127,6 @@ fn cmp(&self, other: &BindingError) -> cmp::Ordering {
 enum ResolutionError<'a> {
     /// error E0401: can't use type parameters from outer function
     TypeParametersFromOuterFunction,
-    /// error E0402: cannot use an outer type parameter in this context
-    OuterTypeParameterContext,
     /// error E0403: the name is already used for a type parameter in this type parameter list
     NameAlreadyUsedInTypeParameterList(Name, &'a Span),
     /// error E0407: method is not a member of trait
@@ -183,15 +182,9 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                                            E0401,
                                            "can't use type parameters from outer function; \
                                            try using a local type parameter instead");
-            err.span_label(span, &format!("use of type variable from outer function"));
+            err.span_label(span, "use of type variable from outer function");
             err
         }
-        ResolutionError::OuterTypeParameterContext => {
-            struct_span_err!(resolver.session,
-                             span,
-                             E0402,
-                             "cannot use an outer type parameter in this context")
-        }
         ResolutionError::NameAlreadyUsedInTypeParameterList(name, first_use_span) => {
              let mut err = struct_span_err!(resolver.session,
                                             span,
@@ -199,8 +192,8 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                                             "the name `{}` is already used for a type parameter \
                                             in this type parameter list",
                                             name);
-             err.span_label(span, &format!("already used"));
-             err.span_label(first_use_span.clone(), &format!("first use of `{}`", name));
+             err.span_label(span, "already used");
+             err.span_label(first_use_span.clone(), format!("first use of `{}`", name));
              err
         }
         ResolutionError::MethodNotMemberOfTrait(method, trait_) => {
@@ -210,7 +203,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                                            "method `{}` is not a member of trait `{}`",
                                            method,
                                            trait_);
-            err.span_label(span, &format!("not a member of trait `{}`", trait_));
+            err.span_label(span, format!("not a member of trait `{}`", trait_));
             err
         }
         ResolutionError::TypeNotMemberOfTrait(type_, trait_) => {
@@ -220,7 +213,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                              "type `{}` is not a member of trait `{}`",
                              type_,
                              trait_);
-            err.span_label(span, &format!("not a member of trait `{}`", trait_));
+            err.span_label(span, format!("not a member of trait `{}`", trait_));
             err
         }
         ResolutionError::ConstNotMemberOfTrait(const_, trait_) => {
@@ -230,7 +223,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                              "const `{}` is not a member of trait `{}`",
                              const_,
                              trait_);
-            err.span_label(span, &format!("not a member of trait `{}`", trait_));
+            err.span_label(span, format!("not a member of trait `{}`", trait_));
             err
         }
         ResolutionError::VariableNotBoundInPattern(binding_error) => {
@@ -239,11 +232,11 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
             let msg = format!("variable `{}` is not bound in all patterns", binding_error.name);
             let mut err = resolver.session.struct_span_err_with_code(msp, &msg, "E0408");
             for sp in target_sp {
-                err.span_label(sp, &format!("pattern doesn't bind `{}`", binding_error.name));
+                err.span_label(sp, format!("pattern doesn't bind `{}`", binding_error.name));
             }
             let origin_sp = binding_error.origin.iter().map(|x| *x).collect::<Vec<_>>();
             for sp in origin_sp {
-                err.span_label(sp, &"variable not in all patterns");
+                err.span_label(sp, "variable not in all patterns");
             }
             err
         }
@@ -255,8 +248,8 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                              "variable `{}` is bound in inconsistent \
                              ways within the same match arm",
                              variable_name);
-            err.span_label(span, &format!("bound in different ways"));
-            err.span_label(first_binding_span, &format!("first binding"));
+            err.span_label(span, "bound in different ways");
+            err.span_label(first_binding_span, "first binding");
             err
         }
         ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
@@ -265,7 +258,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                              E0415,
                              "identifier `{}` is bound more than once in this parameter list",
                              identifier);
-            err.span_label(span, &format!("used as parameter more than once"));
+            err.span_label(span, "used as parameter more than once");
             err
         }
         ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
@@ -274,7 +267,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                              E0416,
                              "identifier `{}` is bound more than once in the same pattern",
                              identifier);
-            err.span_label(span, &format!("used in a pattern more than once"));
+            err.span_label(span, "used in a pattern more than once");
             err
         }
         ResolutionError::UndeclaredLabel(name) => {
@@ -283,7 +276,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                                            E0426,
                                            "use of undeclared label `{}`",
                                            name);
-            err.span_label(span, &format!("undeclared label `{}`",&name));
+            err.span_label(span, format!("undeclared label `{}`", name));
             err
         }
         ResolutionError::SelfImportsOnlyAllowedWithin => {
@@ -313,14 +306,14 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
             };
             let mut err = struct_span_err!(resolver.session, span, E0432, "{}", msg);
             if let Some((_, p)) = name {
-                err.span_label(span, &p);
+                err.span_label(span, p);
             }
             err
         }
         ResolutionError::FailedToResolve(msg) => {
             let mut err = struct_span_err!(resolver.session, span, E0433,
                                            "failed to resolve. {}", msg);
-            err.span_label(span, &msg);
+            err.span_label(span, msg);
             err
         }
         ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
@@ -336,7 +329,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                              span,
                              E0435,
                              "attempt to use a non-constant value in a constant");
-            err.span_label(span, &format!("non-constant used with constant"));
+            err.span_label(span, "non-constant used with constant");
             err
         }
         ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => {
@@ -345,9 +338,9 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                                            span,
                                            E0530,
                                            "{}s cannot shadow {}s", what_binding, shadows_what);
-            err.span_label(span, &format!("cannot be named the same as a {}", shadows_what));
+            err.span_label(span, format!("cannot be named the same as a {}", shadows_what));
             let participle = if binding.is_import() { "imported" } else { "defined" };
-            let msg = &format!("a {} `{}` is {} here", shadows_what, name, participle);
+            let msg = format!("a {} `{}` is {} here", shadows_what, name, participle);
             err.span_label(binding.span, msg);
             err
         }
@@ -355,7 +348,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
             let mut err = struct_span_err!(resolver.session, span, E0128,
                                            "type parameters with a default cannot use \
                                             forward declared identifiers");
-            err.span_label(span, &format!("defaulted type parameters \
+            err.span_label(span, format!("defaulted type parameters \
                                            cannot be forward declared"));
             err
         }
@@ -613,7 +606,7 @@ fn visit_ty(&mut self, ty: &'tcx Ty) {
             self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
         } else if let TyKind::ImplicitSelf = ty.node {
             let self_ty = keywords::SelfType.ident();
-            let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.span))
+            let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, true, ty.span)
                           .map_or(Def::Err, |d| d.def());
             self.record_def(ty.id, PathResolution::new(def));
         } else if let TyKind::Array(ref element, ref length) = ty.node {
@@ -865,12 +858,18 @@ pub struct ModuleData<'a> {
     // access the children must be preceded with a
     // `populate_module_if_necessary` call.
     populated: Cell<bool>,
+
+    /// Span of the module itself. Used for error reporting.
+    span: Span,
 }
 
 pub type Module<'a> = &'a ModuleData<'a>;
 
 impl<'a> ModuleData<'a> {
-    fn new(parent: Option<Module<'a>>, kind: ModuleKind, normal_ancestor_id: DefId) -> Self {
+    fn new(parent: Option<Module<'a>>,
+           kind: ModuleKind,
+           normal_ancestor_id: DefId,
+           span: Span) -> Self {
         ModuleData {
             parent: parent,
             kind: kind,
@@ -884,6 +883,7 @@ fn new(parent: Option<Module<'a>>, kind: ModuleKind, normal_ancestor_id: DefId)
             globs: RefCell::new((Vec::new())),
             traits: RefCell::new(None),
             populated: Cell::new(normal_ancestor_id.is_local()),
+            span: span,
         }
     }
 
@@ -1187,6 +1187,10 @@ pub struct Resolver<'a> {
     pub whitelisted_legacy_custom_derives: Vec<Name>,
     pub found_unresolved_macro: bool,
 
+    // List of crate local macros that we need to warn about as being unused.
+    // Right now this only includes macro_rules! macros.
+    unused_macros: FxHashSet<DefId>,
+
     // Maps the `Mark` of an expansion to its containing module or block.
     invocations: FxHashMap<Mark, &'a InvocationData<'a>>,
 
@@ -1260,11 +1264,11 @@ fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) {
         let namespace = if is_value { ValueNS } else { TypeNS };
         let hir::Path { ref segments, span, ref mut def } = *path;
         let path: Vec<_> = segments.iter().map(|seg| Ident::with_empty_ctxt(seg.name)).collect();
-        match self.resolve_path(&path, Some(namespace), Some(span)) {
+        match self.resolve_path(&path, Some(namespace), true, span) {
             PathResult::Module(module) => *def = module.def().unwrap(),
             PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
                 *def = path_res.base_def(),
-            PathResult::NonModule(..) => match self.resolve_path(&path, None, Some(span)) {
+            PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span) {
                 PathResult::Failed(msg, _) => {
                     resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
                 }
@@ -1298,7 +1302,7 @@ pub fn new(session: &'a Session,
         let root_module_kind = ModuleKind::Def(Def::Mod(root_def_id), keywords::Invalid.name());
         let graph_root = arenas.alloc_module(ModuleData {
             no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"),
-            ..ModuleData::new(None, root_module_kind, root_def_id)
+            ..ModuleData::new(None, root_module_kind, root_def_id, krate.span)
         });
         let mut module_map = FxHashMap();
         module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root);
@@ -1392,6 +1396,7 @@ pub fn new(session: &'a Session,
             potentially_unused_imports: Vec::new(),
             struct_constructors: DefIdMap(),
             found_unresolved_macro: false,
+            unused_macros: FxHashSet(),
         }
     }
 
@@ -1430,9 +1435,14 @@ pub fn resolve_crate(&mut self, krate: &Crate) {
         self.crate_loader.postprocess(krate);
     }
 
-    fn new_module(&self, parent: Module<'a>, kind: ModuleKind, normal_ancestor_id: DefId)
-                  -> Module<'a> {
-        self.arenas.alloc_module(ModuleData::new(Some(parent), kind, normal_ancestor_id))
+    fn new_module(
+        &self,
+        parent: Module<'a>,
+        kind: ModuleKind,
+        normal_ancestor_id: DefId,
+        span: Span,
+    ) -> Module<'a> {
+        self.arenas.alloc_module(ModuleData::new(Some(parent), kind, normal_ancestor_id, span))
     }
 
     fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span)
@@ -1490,7 +1500,8 @@ fn add_to_glob_map(&mut self, id: NodeId, ident: Ident) {
     fn resolve_ident_in_lexical_scope(&mut self,
                                       mut ident: Ident,
                                       ns: Namespace,
-                                      record_used: Option<Span>)
+                                      record_used: bool,
+                                      path_span: Span)
                                       -> Option<LexicalScopeBinding<'a>> {
         if ns == TypeNS {
             ident = ident.unhygienize();
@@ -1501,12 +1512,13 @@ fn resolve_ident_in_lexical_scope(&mut self,
             if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() {
                 // The ident resolves to a type parameter or local variable.
                 return Some(LexicalScopeBinding::Def(
-                    self.adjust_local_def(ns, i, def, record_used)
+                    self.adjust_local_def(ns, i, def, record_used, path_span)
                 ));
             }
 
             if let ModuleRibKind(module) = self.ribs[ns][i].kind {
-                let item = self.resolve_ident_in_module(module, ident, ns, false, record_used);
+                let item = self.resolve_ident_in_module(module, ident, ns, false,
+                                                        record_used, path_span);
                 if let Ok(binding) = item {
                     // The ident resolves to an item.
                     return Some(LexicalScopeBinding::Item(binding));
@@ -1515,7 +1527,8 @@ fn resolve_ident_in_lexical_scope(&mut self,
                 if let ModuleKind::Block(..) = module.kind { // We can see through blocks
                 } else if !module.no_implicit_prelude {
                     return self.prelude.and_then(|prelude| {
-                        self.resolve_ident_in_module(prelude, ident, ns, false, None).ok()
+                        self.resolve_ident_in_module(prelude, ident, ns, false,
+                                                     false, path_span).ok()
                     }).map(LexicalScopeBinding::Item)
                 } else {
                     return None;
@@ -1535,12 +1548,12 @@ fn resolve_ident_in_lexical_scope(&mut self,
         None
     }
 
-    fn resolve_crate_var(&mut self, crate_var_ctxt: SyntaxContext) -> Module<'a> {
+    fn resolve_crate_var(&mut self, crate_var_ctxt: SyntaxContext, span: Span) -> Module<'a> {
         let mut ctxt_data = crate_var_ctxt.data();
         while ctxt_data.prev_ctxt != SyntaxContext::empty() {
             ctxt_data = ctxt_data.prev_ctxt.data();
         }
-        let module = self.macro_def_scope(ctxt_data.outer_mark);
+        let module = self.macro_def_scope(ctxt_data.outer_mark, span);
         if module.is_local() { self.graph_root } else { module }
     }
 
@@ -1655,16 +1668,16 @@ fn resolve_item(&mut self, item: &Item) {
                             this.check_proc_macro_attrs(&trait_item.attrs);
 
                             match trait_item.node {
-                                TraitItemKind::Const(_, ref default) => {
+                                TraitItemKind::Const(ref ty, ref default) => {
+                                    this.visit_ty(ty);
+
                                     // Only impose the restrictions of
-                                    // ConstRibKind if there's an actual constant
+                                    // ConstRibKind for an actual constant
                                     // expression in a provided default.
-                                    if default.is_some() {
+                                    if let Some(ref expr) = *default{
                                         this.with_constant_rib(|this| {
-                                            visit::walk_trait_item(this, trait_item)
+                                            this.visit_expr(expr);
                                         });
-                                    } else {
-                                        visit::walk_trait_item(this, trait_item)
                                     }
                                 }
                                 TraitItemKind::Method(ref sig, _) => {
@@ -1693,9 +1706,13 @@ fn resolve_item(&mut self, item: &Item) {
                 });
             }
 
-            ItemKind::Const(..) | ItemKind::Static(..) => {
-                self.with_constant_rib(|this| {
-                    visit::walk_item(this, item);
+            ItemKind::Static(ref ty, _, ref expr) |
+            ItemKind::Const(ref ty, ref expr) => {
+                self.with_item_rib(|this| {
+                    this.visit_ty(ty);
+                    this.with_constant_rib(|this| {
+                        this.visit_expr(expr);
+                    });
                 });
             }
 
@@ -1766,13 +1783,21 @@ fn with_label_rib<F>(&mut self, f: F)
         self.label_ribs.pop();
     }
 
+    fn with_item_rib<F>(&mut self, f: F)
+        where F: FnOnce(&mut Resolver)
+    {
+        self.ribs[ValueNS].push(Rib::new(ItemRibKind));
+        self.ribs[TypeNS].push(Rib::new(ItemRibKind));
+        f(self);
+        self.ribs[TypeNS].pop();
+        self.ribs[ValueNS].pop();
+    }
+
     fn with_constant_rib<F>(&mut self, f: F)
         where F: FnOnce(&mut Resolver)
     {
         self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind));
-        self.ribs[TypeNS].push(Rib::new(ConstantItemRibKind));
         f(self);
-        self.ribs[TypeNS].pop();
         self.ribs[ValueNS].pop();
     }
 
@@ -2135,7 +2160,8 @@ fn resolve_pattern(&mut self,
                 PatKind::Ident(bmode, ref 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, None)
+                    let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS,
+                                                                      false, pat.span)
                                       .and_then(LexicalScopeBinding::item);
                     let resolution = binding.map(NameBinding::def).and_then(|def| {
                         let always_binding = !pat_src.is_refutable() || opt_pat.is_some() ||
@@ -2241,7 +2267,7 @@ fn smart_resolve_path_fragment(&mut self,
                     (format!(""), format!("the crate root"))
                 } else {
                     let mod_path = &path[..path.len() - 1];
-                    let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), None) {
+                    let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), false, span) {
                         PathResult::Module(module) => module.def(),
                         _ => None,
                     }.map_or(format!(""), |def| format!("{} ", def.kind_name()));
@@ -2256,13 +2282,13 @@ fn smart_resolve_path_fragment(&mut self,
             if is_self_type(path, ns) {
                 __diagnostic_used!(E0411);
                 err.code("E0411".into());
-                err.span_label(span, &format!("`Self` is only available in traits and impls"));
+                err.span_label(span, "`Self` is only available in traits and impls");
                 return err;
             }
             if is_self_value(path, ns) {
                 __diagnostic_used!(E0424);
                 err.code("E0424".into());
-                err.span_label(span, &format!("`self` value is only available in \
+                err.span_label(span, format!("`self` value is only available in \
                                                methods with `self` parameter"));
                 return err;
             }
@@ -2271,8 +2297,10 @@ fn smart_resolve_path_fragment(&mut self,
             let name = path.last().unwrap().name;
             let candidates = this.lookup_import_candidates(name, ns, is_expected);
             if !candidates.is_empty() {
+                let mut module_span = this.current_module.span;
+                module_span.hi = module_span.lo;
                 // Report import candidates as help and proceed searching for labels.
-                show_candidates(&mut err, &candidates, def.is_some());
+                show_candidates(&mut err, module_span, &candidates, def.is_some());
             } else if is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) {
                 let enum_candidates = this.lookup_import_candidates(name, ns, is_enum_variant);
                 let mut enum_candidates = enum_candidates.iter()
@@ -2289,23 +2317,23 @@ fn smart_resolve_path_fragment(&mut self,
                     }
                 }
             }
-            if path.len() == 1 && this.self_type_is_available() {
+            if path.len() == 1 && this.self_type_is_available(span) {
                 if let Some(candidate) = this.lookup_assoc_candidate(name, ns, is_expected) {
-                    let self_is_available = this.self_value_is_available(path[0].ctxt);
+                    let self_is_available = this.self_value_is_available(path[0].ctxt, span);
                     match candidate {
                         AssocSuggestion::Field => {
-                            err.span_label(span, &format!("did you mean `self.{}`?", path_str));
+                            err.span_label(span, format!("did you mean `self.{}`?", path_str));
                             if !self_is_available {
-                                err.span_label(span, &format!("`self` value is only available in \
+                                err.span_label(span, format!("`self` value is only available in \
                                                                methods with `self` parameter"));
                             }
                         }
                         AssocSuggestion::MethodWithSelf if self_is_available => {
-                            err.span_label(span, &format!("did you mean `self.{}(...)`?",
+                            err.span_label(span, format!("did you mean `self.{}(...)`?",
                                                            path_str));
                         }
                         AssocSuggestion::MethodWithSelf | AssocSuggestion::AssocItem => {
-                            err.span_label(span, &format!("did you mean `Self::{}`?", path_str));
+                            err.span_label(span, format!("did you mean `Self::{}`?", path_str));
                         }
                     }
                     return err;
@@ -2315,8 +2343,8 @@ fn smart_resolve_path_fragment(&mut self,
             let mut levenshtein_worked = false;
 
             // Try Levenshtein.
-            if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected) {
-                err.span_label(ident_span, &format!("did you mean `{}`?", candidate));
+            if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected, span) {
+                err.span_label(ident_span, format!("did you mean `{}`?", candidate));
                 levenshtein_worked = true;
             }
 
@@ -2324,21 +2352,21 @@ fn smart_resolve_path_fragment(&mut self,
             if let Some(def) = def {
                 match (def, source) {
                     (Def::Macro(..), _) => {
-                        err.span_label(span, &format!("did you mean `{}!(...)`?", path_str));
+                        err.span_label(span, format!("did you mean `{}!(...)`?", path_str));
                         return err;
                     }
                     (Def::TyAlias(..), PathSource::Trait) => {
-                        err.span_label(span, &format!("type aliases cannot be used for traits"));
+                        err.span_label(span, "type aliases cannot be used for traits");
                         return err;
                     }
                     (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
                         ExprKind::Field(_, ident) => {
-                            err.span_label(parent.span, &format!("did you mean `{}::{}`?",
+                            err.span_label(parent.span, format!("did you mean `{}::{}`?",
                                                                  path_str, ident.node));
                             return err;
                         }
                         ExprKind::MethodCall(ident, ..) => {
-                            err.span_label(parent.span, &format!("did you mean `{}::{}(...)`?",
+                            err.span_label(parent.span, format!("did you mean `{}::{}(...)`?",
                                                                  path_str, ident.node));
                             return err;
                         }
@@ -2349,12 +2377,12 @@ fn smart_resolve_path_fragment(&mut self,
                             if let Some((ctor_def, ctor_vis))
                                     = this.struct_constructors.get(&def_id).cloned() {
                                 if is_expected(ctor_def) && !this.is_accessible(ctor_vis) {
-                                    err.span_label(span, &format!("constructor is not visible \
+                                    err.span_label(span, format!("constructor is not visible \
                                                                    here due to private fields"));
                                 }
                             }
                         }
-                        err.span_label(span, &format!("did you mean `{} {{ /* fields */ }}`?",
+                        err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
                                                        path_str));
                         return err;
                     }
@@ -2364,7 +2392,7 @@ fn smart_resolve_path_fragment(&mut self,
 
             // Fallback label.
             if !levenshtein_worked {
-                err.span_label(base_span, &fallback_label);
+                err.span_label(base_span, fallback_label);
             }
             err
         };
@@ -2420,14 +2448,15 @@ fn smart_resolve_path_fragment(&mut self,
         resolution
     }
 
-    fn self_type_is_available(&mut self) -> bool {
-        let binding = self.resolve_ident_in_lexical_scope(keywords::SelfType.ident(), TypeNS, None);
+    fn self_type_is_available(&mut self, span: Span) -> bool {
+        let binding = self.resolve_ident_in_lexical_scope(keywords::SelfType.ident(),
+                                                          TypeNS, false, span);
         if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false }
     }
 
-    fn self_value_is_available(&mut self, ctxt: SyntaxContext) -> bool {
+    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, None);
+        let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, false, span);
         if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false }
     }
 
@@ -2491,7 +2520,7 @@ fn resolve_qpath(&mut self,
             ));
         }
 
-        let result = match self.resolve_path(&path, Some(ns), Some(span)) {
+        let result = match self.resolve_path(&path, Some(ns), true, span) {
             PathResult::NonModule(path_res) => path_res,
             PathResult::Module(module) if !module.is_normal() => {
                 PathResolution::new(module.def().unwrap())
@@ -2537,7 +2566,7 @@ fn resolve_qpath(&mut self,
         if path.len() > 1 && !global_by_default && result.base_def() != Def::Err &&
            path[0].name != keywords::CrateRoot.name() && path[0].name != "$crate" {
             let unqualified_result = {
-                match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) {
+                match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span) {
                     PathResult::NonModule(path_res) => path_res.base_def(),
                     PathResult::Module(module) => module.def().unwrap(),
                     _ => return Some(result),
@@ -2555,7 +2584,8 @@ fn resolve_qpath(&mut self,
     fn resolve_path(&mut self,
                     path: &[Ident],
                     opt_ns: Option<Namespace>, // `None` indicates a module path
-                    record_used: Option<Span>)
+                    record_used: bool,
+                    path_span: Span)
                     -> PathResult<'a> {
         let mut module = None;
         let mut allow_super = true;
@@ -2584,17 +2614,17 @@ fn resolve_path(&mut self,
                 module = Some(self.graph_root);
                 continue
             } else if i == 0 && ns == TypeNS && ident.name == "$crate" {
-                module = Some(self.resolve_crate_var(ident.ctxt));
+                module = Some(self.resolve_crate_var(ident.ctxt, path_span));
                 continue
             }
 
             let binding = if let Some(module) = module {
-                self.resolve_ident_in_module(module, ident, ns, false, record_used)
+                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, ns, record_used)
+                self.resolve_lexical_macro_path_segment(ident, ns, record_used, path_span)
                     .map(MacroBinding::binding)
             } else {
-                match self.resolve_ident_in_lexical_scope(ident, ns, record_used) {
+                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) => {
@@ -2602,7 +2632,7 @@ fn resolve_path(&mut self,
                             def, path.len() - 1
                         ));
                     }
-                    _ => Err(if record_used.is_some() { Determined } else { Undetermined }),
+                    _ => Err(if record_used { Determined } else { Undetermined }),
                 }
             };
 
@@ -2659,12 +2689,13 @@ fn adjust_local_def(&mut self,
                         ns: Namespace,
                         rib_index: usize,
                         mut def: Def,
-                        record_used: Option<Span>) -> Def {
+                        record_used: bool,
+                        span: Span) -> Def {
         let ribs = &self.ribs[ns][rib_index + 1..];
 
         // An invalid forward use of a type parameter from a previous default.
         if let ForwardTyParamBanRibKind = self.ribs[ns][rib_index].kind {
-            if let Some(span) = record_used {
+            if record_used {
                 resolve_error(self, span,
                         ResolutionError::ForwardDeclaredTyParam);
             }
@@ -2674,7 +2705,7 @@ fn adjust_local_def(&mut self,
 
         match def {
             Def::Upvar(..) => {
-                span_bug!(record_used.unwrap_or(DUMMY_SP), "unexpected {:?} in bindings", def)
+                span_bug!(span, "unexpected {:?} in bindings", def)
             }
             Def::Local(def_id) => {
                 for rib in ribs {
@@ -2700,7 +2731,7 @@ fn adjust_local_def(&mut self,
                             let depth = vec.len();
                             def = Def::Upvar(def_id, depth, function_id);
 
-                            if let Some(span) = record_used {
+                            if record_used {
                                 vec.push(Freevar {
                                     def: prev_def,
                                     span: span,
@@ -2712,7 +2743,7 @@ fn adjust_local_def(&mut self,
                             // This was an attempt to access an upvar inside a
                             // named function item. This is not allowed, so we
                             // report an error.
-                            if let Some(span) = record_used {
+                            if record_used {
                                 resolve_error(self, span,
                                         ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
                             }
@@ -2720,7 +2751,7 @@ fn adjust_local_def(&mut self,
                         }
                         ConstantItemRibKind => {
                             // Still doesn't deal with upvars
-                            if let Some(span) = record_used {
+                            if record_used {
                                 resolve_error(self, span,
                                         ResolutionError::AttemptToUseNonConstantValueInConstant);
                             }
@@ -2733,26 +2764,19 @@ fn adjust_local_def(&mut self,
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind | MethodRibKind(_) | ClosureRibKind(..) |
-                        ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind => {
+                        ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
+                        ConstantItemRibKind => {
                             // Nothing to do. Continue.
                         }
                         ItemRibKind => {
                             // This was an attempt to use a type parameter outside
                             // its scope.
-                            if let Some(span) = record_used {
+                            if record_used {
                                 resolve_error(self, span,
                                               ResolutionError::TypeParametersFromOuterFunction);
                             }
                             return Def::Err;
                         }
-                        ConstantItemRibKind => {
-                            // see #9186
-                            if let Some(span) = record_used {
-                                resolve_error(self, span,
-                                              ResolutionError::OuterTypeParameterContext);
-                            }
-                            return Def::Err;
-                        }
                     }
                 }
             }
@@ -2843,7 +2867,8 @@ fn extract_node_id(t: &Ty) -> Option<NodeId> {
     fn lookup_typo_candidate<FilterFn>(&mut self,
                                        path: &[Ident],
                                        ns: Namespace,
-                                       filter_fn: FilterFn)
+                                       filter_fn: FilterFn,
+                                       span: Span)
                                        -> Option<Symbol>
         where FilterFn: Fn(Def) -> bool
     {
@@ -2895,7 +2920,8 @@ fn lookup_typo_candidate<FilterFn>(&mut self,
         } else {
             // Search in module.
             let mod_path = &path[..path.len() - 1];
-            if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), None) {
+            if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS),
+                                                                  false, span) {
                 add_module_candidates(module, &mut names);
             }
         }
@@ -3374,9 +3400,9 @@ fn report_conflict(&mut self,
             },
         };
 
-        err.span_label(span, &format!("`{}` already {}", name, participle));
+        err.span_label(span, format!("`{}` already {}", name, participle));
         if old_binding.span != syntax_pos::DUMMY_SP {
-            err.span_label(old_binding.span, &format!("previous {} of `{}` here", noun, name));
+            err.span_label(old_binding.span, format!("previous {} of `{}` here", noun, name));
         }
         err.emit();
         self.name_already_seen.insert(name, span);
@@ -3396,7 +3422,10 @@ fn check_proc_macro_attrs(&mut self, attrs: &[ast::Attribute]) {
                 continue
             }
             let ident = attr.path.segments[0].identifier;
-            let result = self.resolve_lexical_macro_path_segment(ident, MacroNS, None);
+            let result = self.resolve_lexical_macro_path_segment(ident,
+                                                                 MacroNS,
+                                                                 false,
+                                                                 attr.path.span);
             if let Ok(binding) = result {
                 if let SyntaxExtension::AttrProcMacro(..) = *binding.binding().get_macro(self) {
                     attr::mark_known(attr);
@@ -3463,12 +3492,10 @@ fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, St
 /// When an entity with a given name is not available in scope, we search for
 /// entities with that name in all crates. This method allows outputting the
 /// results of this search in a programmer-friendly way
-fn show_candidates(session: &mut DiagnosticBuilder,
+fn show_candidates(err: &mut DiagnosticBuilder,
+                   span: Span,
                    candidates: &[ImportSuggestion],
                    better: bool) {
-    // don't show more than MAX_CANDIDATES results, so
-    // we're consistent with the trait suggestions
-    const MAX_CANDIDATES: usize = 4;
 
     // we want consistent results across executions, but candidates are produced
     // by iterating through a hash map, so make sure they are ordered:
@@ -3481,21 +3508,13 @@ fn show_candidates(session: &mut DiagnosticBuilder,
         1 => " is found in another module, you can import it",
         _ => "s are found in other modules, you can import them",
     };
+    let msg = format!("possible {}candidate{} into scope", better, msg_diff);
+
+    for candidate in &mut path_strings {
+        *candidate = format!("use {};\n", candidate);
+    }
 
-    let end = cmp::min(MAX_CANDIDATES, path_strings.len());
-    session.help(&format!("possible {}candidate{} into scope:{}{}",
-                          better,
-                          msg_diff,
-                          &path_strings[0..end].iter().map(|candidate| {
-                              format!("\n  `use {};`", candidate)
-                          }).collect::<String>(),
-                          if path_strings.len() > MAX_CANDIDATES {
-                              format!("\nand {} other candidates",
-                                      path_strings.len() - MAX_CANDIDATES)
-                          } else {
-                              "".to_owned()
-                          }
-                          ));
+    err.span_suggestions(span, &msg, path_strings);
 }
 
 /// A somewhat inefficient routine to obtain the name of a module.
index 030e3936de994fb24c436b5bb389e209855afd75..231d30cd2a22decfdd8729f4f68f46dfa16fe305 100644 (file)
@@ -16,7 +16,7 @@
 use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex};
 use rustc::hir::def::{Def, Export};
 use rustc::hir::map::{self, DefCollector};
-use rustc::ty;
+use rustc::{ty, lint};
 use syntax::ast::{self, Name, Ident};
 use syntax::attr::{self, HasAttrs};
 use syntax::errors::DiagnosticBuilder;
@@ -123,14 +123,14 @@ fn get_module_scope(&mut self, id: ast::NodeId) -> Mark {
     }
 
     fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> {
-        struct EliminateCrateVar<'b, 'a: 'b>(&'b mut Resolver<'a>);
+        struct EliminateCrateVar<'b, 'a: 'b>(&'b mut Resolver<'a>, Span);
 
         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;
                 if ident.name == "$crate" {
                     path.segments[0].identifier.name = keywords::CrateRoot.name();
-                    let module = self.0.resolve_crate_var(ident.ctxt);
+                    let module = self.0.resolve_crate_var(ident.ctxt, self.1);
                     if !module.is_local() {
                         let span = path.segments[0].span;
                         path.segments.insert(1, match module.kind {
@@ -149,7 +149,7 @@ fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
             }
         }
 
-        EliminateCrateVar(self).fold_item(item).expect_one("")
+        EliminateCrateVar(self, item.span).fold_item(item).expect_one("")
     }
 
     fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool {
@@ -291,12 +291,32 @@ fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
             },
         };
         self.macro_defs.insert(invoc.expansion_data.mark, def.def_id());
+        self.unused_macros.remove(&def.def_id());
         Ok(Some(self.get_macro(def)))
     }
 
     fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
                      -> Result<Rc<SyntaxExtension>, Determinacy> {
-        self.resolve_macro_to_def(scope, path, kind, force).map(|def| self.get_macro(def))
+        self.resolve_macro_to_def(scope, path, kind, force).map(|def| {
+            self.unused_macros.remove(&def.def_id());
+            self.get_macro(def)
+        })
+    }
+
+    fn check_unused_macros(&self) {
+        for did in self.unused_macros.iter() {
+            let id_span = match *self.macro_map[did] {
+                SyntaxExtension::NormalTT(_, isp, _) => isp,
+                _ => None,
+            };
+            if let Some((id, span)) = id_span {
+                let lint = lint::builtin::UNUSED_MACROS;
+                let msg = "unused macro definition".to_string();
+                self.session.add_lint(lint, id, span, msg);
+            } else {
+                bug!("attempted to create unused macro error, but span not available");
+            }
+        }
     }
 }
 
@@ -379,7 +399,7 @@ fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKin
                 return Err(Determinacy::Determined);
             }
 
-            let def = match self.resolve_path(&path, Some(MacroNS), None) {
+            let def = match self.resolve_path(&path, Some(MacroNS), false, span) {
                 PathResult::NonModule(path_res) => match path_res.base_def() {
                     Def::Err => Err(Determinacy::Determined),
                     def @ _ => Ok(def),
@@ -401,7 +421,7 @@ fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKin
         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], MacroNS, None) {
+            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(_) => {
@@ -421,18 +441,19 @@ fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKin
     pub fn resolve_lexical_macro_path_segment(&mut self,
                                               ident: Ident,
                                               ns: Namespace,
-                                              record_used: Option<Span>)
+                                              record_used: bool,
+                                              path_span: Span)
                                               -> Result<MacroBinding<'a>, Determinacy> {
         let mut module = Some(self.current_module);
         let mut potential_illegal_shadower = Err(Determinacy::Determined);
         let determinacy =
-            if record_used.is_some() { Determinacy::Determined } else { Determinacy::Undetermined };
+            if record_used { Determinacy::Determined } else { Determinacy::Undetermined };
         loop {
             let result = if let Some(module) = module {
                 // Since expanded macros may not shadow the lexical scope and
                 // globs may not shadow global macros (both enforced below),
                 // we resolve with restricted shadowing (indicated by the penultimate argument).
-                self.resolve_ident_in_module(module, ident, ns, true, record_used)
+                self.resolve_ident_in_module(module, ident, ns, true, record_used, path_span)
                     .map(MacroBinding::Modern)
             } else {
                 self.global_macros.get(&ident.name).cloned().ok_or(determinacy)
@@ -441,15 +462,18 @@ pub fn resolve_lexical_macro_path_segment(&mut self,
 
             match result.map(MacroBinding::binding) {
                 Ok(binding) => {
-                    let span = match record_used {
-                        Some(span) => span,
-                        None => return result,
-                    };
+                    if !record_used {
+                        return result;
+                    }
                     if let Ok(MacroBinding::Modern(shadower)) = potential_illegal_shadower {
                         if shadower.def() != binding.def() {
                             let name = ident.name;
                             self.ambiguity_errors.push(AmbiguityError {
-                                span: span, name: name, b1: shadower, b2: binding, lexical: true,
+                                span: path_span,
+                                name: name,
+                                b1: shadower,
+                                b2: binding,
+                                lexical: true,
                                 legacy: false,
                             });
                             return potential_illegal_shadower;
@@ -543,7 +567,7 @@ 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() {
-            match self.resolve_path(path, Some(MacroNS), Some(span)) {
+            match self.resolve_path(path, Some(MacroNS), true, span) {
                 PathResult::NonModule(_) => {},
                 PathResult::Failed(msg, _) => {
                     resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
@@ -555,7 +579,7 @@ pub fn finalize_current_module_macro_resolutions(&mut self) {
         for &(mark, ident, span, kind) in module.legacy_macro_resolutions.borrow().iter() {
             let legacy_scope = &self.invocations[&mark].legacy_scope;
             let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident.name, true);
-            let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, Some(span));
+            let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, true, span);
             match (legacy_resolution, resolution) {
                 (Some(MacroBinding::Legacy(legacy_binding)), Ok(MacroBinding::Modern(binding))) => {
                     let msg1 = format!("`{}` could refer to the macro defined here", ident);
@@ -579,7 +603,7 @@ pub fn finalize_current_module_macro_resolutions(&mut self) {
                             format!("cannot find derive macro `{}` in this scope", ident),
                     };
                     let mut err = self.session.struct_span_err(span, &msg);
-                    self.suggest_macro_name(&ident.name.as_str(), kind, &mut err);
+                    self.suggest_macro_name(&ident.name.as_str(), kind, &mut err, span);
                     err.emit();
                 },
                 _ => {},
@@ -588,7 +612,7 @@ pub fn finalize_current_module_macro_resolutions(&mut self) {
     }
 
     fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
-                          err: &mut DiagnosticBuilder<'a>) {
+                          err: &mut DiagnosticBuilder<'a>, span: Span) {
         // First check if this is a locally-defined bang macro.
         let suggestion = if let MacroKind::Bang = kind {
             find_best_match_for_name(self.macro_names.iter(), name, None)
@@ -619,7 +643,7 @@ fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
                 }
             };
             let ident = Ident::from_str(name);
-            self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro)
+            self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro, span)
         });
 
         if let Some(suggestion) = suggestion {
@@ -630,7 +654,7 @@ fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
                     err.help(&format!("did you mean `{}`?", suggestion));
                 }
             } else {
-                err.help(&format!("have you added the `#[macro_use]` on the module/import?"));
+                err.help("have you added the `#[macro_use]` on the module/import?");
             }
         }
     }
@@ -683,6 +707,8 @@ pub fn define_macro(&mut self, item: &ast::Item, legacy_scope: &mut LegacyScope<
         if attr::contains_name(&item.attrs, "macro_export") {
             let def = Def::Macro(def_id, MacroKind::Bang);
             self.macro_exports.push(Export { name: ident.name, def: def, span: item.span });
+        } else {
+            self.unused_macros.insert(def_id);
         }
     }
 
index 43654c8ce6f6875b13aa5009fabec257024ae784..1d4ba4ed100b72e3139fbcf29b42e70e1e9eed13 100644 (file)
@@ -146,7 +146,8 @@ pub fn resolve_ident_in_module(&mut self,
                                    ident: Ident,
                                    ns: Namespace,
                                    restricted_shadowing: bool,
-                                   record_used: Option<Span>)
+                                   record_used: bool,
+                                   path_span: Span)
                                    -> Result<&'a NameBinding<'a>, Determinacy> {
         self.populate_module_if_necessary(module);
 
@@ -154,7 +155,7 @@ pub fn resolve_ident_in_module(&mut self,
             .try_borrow_mut()
             .map_err(|_| Determined)?; // This happens when there is a cycle of imports
 
-        if let Some(span) = record_used {
+        if record_used {
             if let Some(binding) = resolution.binding {
                 if let Some(shadowed_glob) = resolution.shadows_glob {
                     let name = ident.name;
@@ -164,16 +165,20 @@ pub fn resolve_ident_in_module(&mut self,
                        ns != MacroNS && // In MacroNS, `try_define` always forbids this shadowing
                        binding.def() != shadowed_glob.def() {
                         self.ambiguity_errors.push(AmbiguityError {
-                            span: span, name: name, lexical: false, b1: binding, b2: shadowed_glob,
+                            span: path_span,
+                            name: name,
+                            lexical: false,
+                            b1: binding,
+                            b2: shadowed_glob,
                             legacy: false,
                         });
                     }
                 }
-                if self.record_use(ident, ns, binding, span) {
+                if self.record_use(ident, ns, binding, path_span) {
                     return Ok(self.dummy_binding);
                 }
                 if !self.is_accessible(binding.vis) {
-                    self.privacy_errors.push(PrivacyError(span, ident.name, binding));
+                    self.privacy_errors.push(PrivacyError(path_span, ident.name, binding));
                 }
             }
 
@@ -205,7 +210,7 @@ pub fn resolve_ident_in_module(&mut self,
                     SingleImport { source, .. } => source,
                     _ => unreachable!(),
                 };
-                match self.resolve_ident_in_module(module, ident, ns, false, None) {
+                match self.resolve_ident_in_module(module, ident, ns, false, false, path_span) {
                     Err(Determined) => {}
                     _ => return Err(Undetermined),
                 }
@@ -230,7 +235,12 @@ pub fn resolve_ident_in_module(&mut self,
         for directive in module.globs.borrow().iter() {
             if self.is_accessible(directive.vis.get()) {
                 if let Some(module) = directive.imported_module.get() {
-                    let result = self.resolve_ident_in_module(module, ident, ns, false, None);
+                    let result = self.resolve_ident_in_module(module,
+                                                              ident,
+                                                              ns,
+                                                              false,
+                                                              false,
+                                                              path_span);
                     if let Err(Undetermined) = result {
                         return Err(Undetermined);
                     }
@@ -499,7 +509,7 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
             // For better failure detection, pretend that the import will not define any names
             // while resolving its module path.
             directive.vis.set(ty::Visibility::Invisible);
-            let result = self.resolve_path(&directive.module_path, None, None);
+            let result = self.resolve_path(&directive.module_path, None, false, directive.span);
             directive.vis.set(vis);
 
             match result {
@@ -523,7 +533,12 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
         let mut indeterminate = false;
         self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
             if let Err(Undetermined) = result[ns].get() {
-                result[ns].set(this.resolve_ident_in_module(module, source, ns, false, None));
+                result[ns].set(this.resolve_ident_in_module(module,
+                                                            source,
+                                                            ns,
+                                                            false,
+                                                            false,
+                                                            directive.span));
             } else {
                 return
             };
@@ -539,7 +554,7 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
                 Ok(binding) if !binding.is_importable() => {
                     let msg = format!("`{}` is not directly importable", target);
                     struct_span_err!(this.session, directive.span, E0253, "{}", &msg)
-                        .span_label(directive.span, &format!("cannot be imported directly"))
+                        .span_label(directive.span, "cannot be imported directly")
                         .emit();
                     // Do not import this illegal binding. Import a dummy binding and pretend
                     // everything is fine
@@ -563,14 +578,14 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<Stri
         self.current_module = directive.parent;
 
         let ImportDirective { ref module_path, span, .. } = *directive;
-        let module_result = self.resolve_path(&module_path, None, Some(span));
+        let module_result = self.resolve_path(&module_path, None, true, span);
         let module = match module_result {
             PathResult::Module(module) => module,
             PathResult::Failed(msg, _) => {
                 let (mut self_path, mut self_result) = (module_path.clone(), None);
                 if !self_path.is_empty() && !token::Ident(self_path[0]).is_path_segment_keyword() {
                     self_path[0].name = keywords::SelfValue.name();
-                    self_result = Some(self.resolve_path(&self_path, None, None));
+                    self_result = Some(self.resolve_path(&self_path, None, false, span));
                 }
                 return if let Some(PathResult::Module(..)) = self_result {
                     Some(format!("Did you mean `{}`?", names_to_string(&self_path)))
@@ -609,7 +624,12 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<Stri
                         Some(this.dummy_binding);
                 }
             }
-        } else if let Ok(binding) = this.resolve_ident_in_module(module, ident, ns, false, None) {
+        } else if let Ok(binding) = this.resolve_ident_in_module(module,
+                                                                 ident,
+                                                                 ns,
+                                                                 false,
+                                                                 false,
+                                                                 directive.span) {
             legacy_self_import = Some(directive);
             let binding = this.arenas.alloc_name_binding(NameBinding {
                 kind: NameBindingKind::Import {
@@ -630,7 +650,7 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<Stri
             }
             let mut all_ns_failed = true;
             self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
-                match this.resolve_ident_in_module(module, ident, ns, false, Some(span)) {
+                match this.resolve_ident_in_module(module, ident, ns, false, true, span) {
                     Ok(_) => all_ns_failed = false,
                     _ => {}
                 }
@@ -701,7 +721,7 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<Stri
             } else if ns == TypeNS {
                 struct_span_err!(self.session, directive.span, E0365,
                                  "`{}` is private, and cannot be reexported", ident)
-                    .span_label(directive.span, &format!("reexport of private `{}`", ident))
+                    .span_label(directive.span, format!("reexport of private `{}`", ident))
                     .note(&format!("consider declaring type or module `{}` with `pub`", ident))
                     .emit();
             } else {
@@ -794,7 +814,7 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
                             let msg =
                                 format!("a macro named `{}` has already been exported", ident);
                             self.session.struct_span_err(span, &msg)
-                                .span_label(span, &format!("`{}` already exported", ident))
+                                .span_label(span, format!("`{}` already exported", ident))
                                 .span_note(binding.span, "previous macro export here")
                                 .emit();
                         }
index 702c4b691c9860568c61cb20b145b81250fea92d..6d04bff82829ae7c763822c1cc6219ccef2c43ac 100644 (file)
@@ -14,7 +14,7 @@ rustc = { path = "../librustc" }
 rustc_typeck = { path = "../librustc_typeck" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
-rls-data = "0.1"
-rls-span = "0.1"
+rls-data = "0.3"
+rls-span = "0.4"
 # FIXME(#40527) should move rustc serialize out of tree
 rustc-serialize = "0.3"
index d4ded71a3339091fa2b53af1e650b0f3770ef25e..cac1a2e3c5af15a00160791226899cbf9f85a37d 100644 (file)
@@ -267,7 +267,7 @@ pub struct ModData {
     pub items: Vec<NodeId>,
     pub visibility: Visibility,
     pub docs: String,
-    pub sig: Signature,
+    pub sig: Option<Signature>,
     pub attributes: Vec<Attribute>,
 }
 
index 763414c1a555fb2250b958da9899e51b333e79fd..a95236e2a5072936710d1dcb4ac14adca87ec876 100644 (file)
@@ -1211,6 +1211,31 @@ fn process_impl_item(&mut self, impl_item: &'l ast::ImplItem, impl_id: DefId) {
 }
 
 impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, D> {
+    fn visit_mod(&mut self, m: &'l ast::Mod, span: Span, attrs: &[ast::Attribute], id: NodeId) {
+        // Since we handle explicit modules ourselves in visit_item, this should
+        // only get called for the root module of a crate.
+        assert_eq!(id, ast::CRATE_NODE_ID);
+
+        let qualname = format!("::{}", self.tcx.node_path_str(id));
+
+        let cm = self.tcx.sess.codemap();
+        let filename = cm.span_to_filename(span);
+        self.dumper.mod_data(ModData {
+            id: id,
+            name: String::new(),
+            qualname: qualname,
+            span: span,
+            scope: id,
+            filename: filename,
+            items: m.items.iter().map(|i| i.id).collect(),
+            visibility: Visibility::Public,
+            docs: docs_for_attrs(attrs),
+            sig: None,
+            attributes: attrs.to_owned(),
+        }.lower(self.tcx));
+        self.nest_scope(id, |v| visit::walk_mod(v, m));
+    }
+
     fn visit_item(&mut self, item: &'l ast::Item) {
         use syntax::ast::ItemKind::*;
         self.process_macro_use(item.span, item.id);
index 6fd2de97767e18d318a44257424ee7b379a48843..02441a0587eb6a9ad2596ec72a411d7732ad829c 100644 (file)
@@ -392,7 +392,7 @@ pub struct ModData {
     pub items: Vec<DefId>,
     pub visibility: Visibility,
     pub docs: String,
-    pub sig: Signature,
+    pub sig: Option<Signature>,
     pub attributes: Vec<Attribute>,
 }
 
@@ -410,7 +410,7 @@ fn lower(self, tcx: TyCtxt) -> ModData {
             items: self.items.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(),
             visibility: self.visibility,
             docs: self.docs,
-            sig: self.sig.lower(tcx),
+            sig: self.sig.map(|s| s.lower(tcx)),
             attributes: self.attributes.lower(tcx),
         }
     }
index 41221ad986379b7f720875fa5ce997d95675dd8a..49b14f5eca07261471085dc780b89824cbd2de50 100644 (file)
@@ -293,7 +293,7 @@ fn into(self) -> Option<Def> {
                 parent: None,
                 decl_id: None,
                 docs: self.docs,
-                sig: Some(self.sig.into()),
+                sig: self.sig.map(|s| s.into()),
                 attributes: vec![],
             }),
             _ => None,
index 2d1e12bf0a10dfd379e4d90488a6f915a9059d9e..eaa0c0825f0e9314282a95e13bee6f4b7218644a 100644 (file)
@@ -121,7 +121,7 @@ fn mod_data(&mut self, data: ModData) {
             children: data.items.into_iter().map(|id| id_from_def_id(id)).collect(),
             decl_id: None,
             docs: data.docs,
-            sig: Some(data.sig.into()),
+            sig: data.sig.map(|s| s.into()),
             attributes: data.attributes.into_iter().map(|a| a.into()).collect(),
         };
         if def.span.file_name.to_str().unwrap() != def.value {
index fd6898d19d84fce59cea36b0ffbaff53e5f56aaa..5a8acf9abe1d015115a178758e5d479edca497c6 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![crate_name = "rustc_save_analysis"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
 
 #[macro_use] extern crate rustc;
 
@@ -257,7 +258,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     items: m.items.iter().map(|i| i.id).collect(),
                     visibility: From::from(&item.vis),
                     docs: docs_for_attrs(&item.attrs),
-                    sig: self.sig_base(item),
+                    sig: Some(self.sig_base(item)),
                     attributes: item.attrs.clone(),
                 }))
             }
index af477f5a15217bf7ca4c132a5dba9f77a9cb17d1..4ccc85257f3c990ba313df23fa87a9de43476721 100644 (file)
@@ -12,6 +12,7 @@ test = false
 [dependencies]
 flate = { path = "../libflate" }
 log = "0.3"
+owning_ref = "0.3.3"
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_bitflags = { path = "../librustc_bitflags" }
index 0f908b7d0698bc48e7bd1fd529d46212c5433a0f..902065c8688d0d808fb6c2c29d25c82d8bbd219a 100644 (file)
@@ -20,6 +20,7 @@
 use libc;
 use llvm::archive_ro::{ArchiveRO, Child};
 use llvm::{self, ArchiveKind};
+use metadata::METADATA_FILENAME;
 use rustc::session::Session;
 
 pub struct ArchiveConfig<'a> {
@@ -158,11 +159,9 @@ pub fn add_rlib(&mut self,
         // Ignoring all bytecode files, no matter of
         // name
         let bc_ext = ".bytecode.deflate";
-        let metadata_filename =
-            self.config.sess.cstore.metadata_filename().to_owned();
 
         self.add_archive(rlib, move |fname: &str| {
-            if fname.ends_with(bc_ext) || fname == metadata_filename {
+            if fname.ends_with(bc_ext) || fname == METADATA_FILENAME {
                 return true
             }
 
index e42e69d2a76e27979718317626a86ee2a51df1de..f85d3f9f54dfd7cd8b63ad152089bfa10e10eca0 100644 (file)
@@ -13,6 +13,7 @@
 use super::rpath::RPathConfig;
 use super::rpath;
 use super::msvc;
+use metadata::METADATA_FILENAME;
 use session::config;
 use session::config::NoDebugInfo;
 use session::config::{OutputFilenames, Input, OutputType};
@@ -521,7 +522,7 @@ fn link_rlib<'a>(sess: &'a Session,
             // contain the metadata in a separate file. We use a temp directory
             // here so concurrent builds in the same directory don't try to use
             // the same filename for metadata (stomping over one another)
-            let metadata = tmpdir.join(sess.cstore.metadata_filename());
+            let metadata = tmpdir.join(METADATA_FILENAME);
             emit_metadata(sess, trans, &metadata);
             ab.add_file(&metadata);
 
@@ -714,6 +715,10 @@ fn link_natively(sess: &Session,
     if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) {
         cmd.args(args);
     }
+    if let Some(ref args) = sess.opts.debugging_opts.pre_link_args {
+        cmd.args(args);
+    }
+    cmd.args(&sess.opts.debugging_opts.pre_link_arg);
 
     let pre_link_objects = if crate_type == config::CrateTypeExecutable {
         &sess.target.target.options.pre_link_objects_exe
@@ -1141,8 +1146,7 @@ fn link_sanitizer_runtime(cmd: &mut Linker,
         archive.update_symbols();
 
         for f in archive.src_files() {
-            if f.ends_with("bytecode.deflate") ||
-                f == sess.cstore.metadata_filename() {
+            if f.ends_with("bytecode.deflate") || f == METADATA_FILENAME {
                     archive.remove_file(&f);
                     continue
                 }
@@ -1217,8 +1221,7 @@ fn add_static_crate(cmd: &mut Linker,
 
             let mut any_objects = false;
             for f in archive.src_files() {
-                if f.ends_with("bytecode.deflate") ||
-                   f == sess.cstore.metadata_filename() {
+                if f.ends_with("bytecode.deflate") || f == METADATA_FILENAME {
                     archive.remove_file(&f);
                     continue
                 }
index 16aef6ee8ca3543047ba07c85d867f9eae1de881..31f3415b1ecd026424e2de1baf2444e0e7edbe7f 100644 (file)
@@ -32,6 +32,7 @@
 //! comments can also be found below leading through the various code paths.
 
 // A simple macro to make this option mess easier to read
+#[cfg(windows)]
 macro_rules! otry {
     ($expr:expr) => (match $expr {
         Some(val) => val,
index aef9140ba4556cf9b14f927daaf13d12bbadc4a7..1aed2932948020f87e990c1f675aa46c413d39f0 100644 (file)
@@ -223,7 +223,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance
             _ => false
         }
     } else {
-        tcx.sess.cstore.is_foreign_item(def_id)
+        tcx.is_foreign_item(def_id)
     };
 
     if let Some(name) = weak_lang_items::link_name(&attrs) {
index 56ff5ebb069ea4a5f044a912fda677f656d726c1..437ced85b2e4ad48ec97d7186ea54f5d50820764 100644 (file)
@@ -34,6 +34,7 @@
 use back::symbol_export::{self, ExportedSymbols};
 use llvm::{ContextRef, Linkage, ModuleRef, ValueRef, Vector, get_param};
 use llvm;
+use metadata;
 use rustc::hir::def_id::LOCAL_CRATE;
 use middle::lang_items::StartFnLangItem;
 use middle::cstore::EncodedMetadata;
@@ -754,10 +755,7 @@ enum MetadataKind {
     }).max().unwrap();
 
     if kind == MetadataKind::None {
-        return (metadata_llcx, metadata_llmod, EncodedMetadata {
-            raw_data: vec![],
-            hashes: vec![],
-        });
+        return (metadata_llcx, metadata_llmod, EncodedMetadata::new());
     }
 
     let cstore = &tcx.sess.cstore;
@@ -781,8 +779,7 @@ enum MetadataKind {
     };
     unsafe {
         llvm::LLVMSetInitializer(llglobal, llconst);
-        let section_name =
-            tcx.sess.cstore.metadata_section_name(&tcx.sess.target.target);
+        let section_name = metadata::metadata_section_name(&tcx.sess.target.target);
         let name = CString::new(section_name).unwrap();
         llvm::LLVMSetSection(llglobal, name.as_ptr());
 
index 6d7d95f54872105ea12b790ee9cd1b8e656777a8..5f8b79a994a554755bbd0b93cb336c0a5f8985a7 100644 (file)
@@ -652,8 +652,8 @@ fn should_trans_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: &Instan
         }
         Some(_) => true,
         None => {
-            if tcx.sess.cstore.is_exported_symbol(def_id) ||
-                tcx.sess.cstore.is_foreign_item(def_id)
+            if tcx.is_exported_symbol(def_id) ||
+                tcx.is_foreign_item(def_id)
             {
                 // We can link to the item in question, no instance needed
                 // in this crate
index 025062f7ddef92e36e22a8a867ac1f5f6461b086..efd4f13678502e3e556fa06050e5e9e61de8b36f 100644 (file)
@@ -537,6 +537,12 @@ pub fn requests_inline<'a, 'tcx>(
     if is_inline_instance(tcx, instance) {
         return true
     }
+    if let ty::InstanceDef::DropGlue(..) = instance.def {
+        // Drop glue wants to be instantiated at every translation
+        // unit, but without an #[inline] hint. We should make this
+        // available to normal end-users.
+        return true
+    }
     attr::requests_inline(&instance.def.attrs(tcx)[..])
 }
 
index 6afb340107d6661aa1c3a5ad517319757942f887..eac0a062567194cd056253b4ff0a320cae3d0a47 100644 (file)
@@ -186,7 +186,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
                 llvm::set_thread_local(g, true);
             }
         }
-        if ccx.use_dll_storage_attrs() && !ccx.sess().cstore.is_foreign_item(def_id) {
+        if ccx.use_dll_storage_attrs() && !ccx.tcx().is_foreign_item(def_id) {
             // This item is external but not foreign, i.e. it originates from an external Rust
             // crate. Since we don't know whether this crate will be linked dynamically or
             // statically in the final application, we always mark such symbols as 'dllimport'.
index 111c2547721663decc75b17ae753e0576c5c204f..3ac0d88b90d7b7be0f6894313951a6b6595cf235 100644 (file)
@@ -15,7 +15,6 @@
 //! This API is completely unstable and subject to change.
 
 #![crate_name = "rustc_trans"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 #![feature(libc)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
 #![feature(slice_patterns)]
-#![feature(staged_api)]
 #![feature(unicode)]
 #![feature(conservative_impl_trait)]
 
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;
 
 extern crate flate;
 extern crate libc;
+extern crate owning_ref;
 #[macro_use] extern crate rustc;
 extern crate rustc_back;
 extern crate rustc_data_structures;
@@ -69,6 +71,9 @@
 pub use base::trans_crate;
 pub use back::symbol_names::provide;
 
+pub use metadata::LlvmMetadataLoader;
+pub use llvm_util::{init, target_features, print_version, print_passes, print, enable_llvm_debug};
+
 pub mod back {
     pub use rustc::hir::svh;
 
@@ -85,9 +90,6 @@ pub mod back {
 
 pub mod diagnostics;
 
-#[macro_use]
-mod macros;
-
 mod abi;
 mod adt;
 mod asm;
@@ -121,7 +123,9 @@ pub mod back {
 mod declare;
 mod glue;
 mod intrinsic;
+mod llvm_util;
 mod machine;
+mod metadata;
 mod meth;
 mod mir;
 mod monomorphize;
diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs
new file mode 100644 (file)
index 0000000..15f5603
--- /dev/null
@@ -0,0 +1,127 @@
+// 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 syntax_pos::symbol::Symbol;
+use back::write::create_target_machine;
+use llvm;
+use rustc::session::Session;
+use rustc::session::config::PrintRequest;
+use libc::{c_int, c_char};
+use std::ffi::CString;
+
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::Once;
+
+pub fn init(sess: &Session) {
+    unsafe {
+        // Before we touch LLVM, make sure that multithreading is enabled.
+        static POISONED: AtomicBool = AtomicBool::new(false);
+        static INIT: Once = Once::new();
+        INIT.call_once(|| {
+            if llvm::LLVMStartMultithreaded() != 1 {
+                // use an extra bool to make sure that all future usage of LLVM
+                // cannot proceed despite the Once not running more than once.
+                POISONED.store(true, Ordering::SeqCst);
+            }
+
+            configure_llvm(sess);
+        });
+
+        if POISONED.load(Ordering::SeqCst) {
+            bug!("couldn't enable multi-threaded LLVM");
+        }
+    }
+}
+
+unsafe fn configure_llvm(sess: &Session) {
+    let mut llvm_c_strs = Vec::new();
+    let mut llvm_args = Vec::new();
+
+    {
+        let mut add = |arg: &str| {
+            let s = CString::new(arg).unwrap();
+            llvm_args.push(s.as_ptr());
+            llvm_c_strs.push(s);
+        };
+        add("rustc"); // fake program name
+        if sess.time_llvm_passes() { add("-time-passes"); }
+        if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
+
+        for arg in &sess.opts.cg.llvm_args {
+            add(&(*arg));
+        }
+    }
+
+    llvm::LLVMInitializePasses();
+
+    llvm::initialize_available_targets();
+
+    llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
+                                 llvm_args.as_ptr());
+}
+
+// WARNING: the features must be known to LLVM or the feature
+// detection code will walk past the end of the feature array,
+// leading to crashes.
+
+const ARM_WHITELIST: &'static [&'static str] = &["neon\0", "vfp2\0", "vfp3\0", "vfp4\0"];
+
+const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0",
+                                                 "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0",
+                                                 "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0",
+                                                 "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0"];
+
+const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx\0", "hvx-double\0"];
+
+pub fn target_features(sess: &Session) -> Vec<Symbol> {
+    let target_machine = create_target_machine(sess);
+
+    let whitelist = match &*sess.target.target.arch {
+        "arm" => ARM_WHITELIST,
+        "x86" | "x86_64" => X86_WHITELIST,
+        "hexagon" => HEXAGON_WHITELIST,
+        _ => &[],
+    };
+
+    let mut features = Vec::new();
+    for feat in whitelist {
+        assert_eq!(feat.chars().last(), Some('\0'));
+        if unsafe { llvm::LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } {
+            features.push(Symbol::intern(&feat[..feat.len() - 1]));
+        }
+    }
+    features
+}
+
+pub fn print_version() {
+    unsafe {
+        println!("LLVM version: {}.{}",
+                 llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
+    }
+}
+
+pub fn print_passes() {
+    unsafe { llvm::LLVMRustPrintPasses(); }
+}
+
+pub fn print(req: PrintRequest, sess: &Session) {
+    let tm = create_target_machine(sess);
+    unsafe {
+        match req {
+            PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),
+            PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm),
+            _ => bug!("rustc_trans can't handle print request: {:?}", req),
+        }
+    }
+}
+
+pub fn enable_llvm_debug() {
+    unsafe { llvm::LLVMRustSetDebug(1); }
+}
diff --git a/src/librustc_trans/macros.rs b/src/librustc_trans/macros.rs
deleted file mode 100644 (file)
index 77efcc6..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// 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.
-
-macro_rules! unpack_datum {
-    ($bcx: ident, $inp: expr) => (
-        {
-            let db = $inp;
-            $bcx = db.bcx;
-            db.datum
-        }
-    )
-}
-
-macro_rules! unpack_result {
-    ($bcx: ident, $inp: expr) => (
-        {
-            let db = $inp;
-            $bcx = db.bcx;
-            db.val
-        }
-    )
-}
diff --git a/src/librustc_trans/metadata.rs b/src/librustc_trans/metadata.rs
new file mode 100644 (file)
index 0000000..2c0148d
--- /dev/null
@@ -0,0 +1,122 @@
+// 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::util::common;
+use rustc::middle::cstore::MetadataLoader;
+use rustc_back::target::Target;
+use llvm;
+use llvm::{False, ObjectFile, mk_section_iter};
+use llvm::archive_ro::ArchiveRO;
+
+use owning_ref::{ErasedBoxRef, OwningRef};
+use std::path::Path;
+use std::ptr;
+use std::slice;
+
+pub const METADATA_FILENAME: &str = "rust.metadata.bin";
+
+pub struct LlvmMetadataLoader;
+
+impl MetadataLoader for LlvmMetadataLoader {
+    fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
+        // Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
+        // internally to read the file. We also avoid even using a memcpy by
+        // just keeping the archive along while the metadata is in use.
+        let archive = ArchiveRO::open(filename)
+            .map(|ar| OwningRef::new(box ar))
+            .ok_or_else(|| {
+                            debug!("llvm didn't like `{}`", filename.display());
+                            format!("failed to read rlib metadata: '{}'", filename.display())
+                        })?;
+        let buf: OwningRef<_, [u8]> = archive
+            .try_map(|ar| {
+                ar.iter()
+                    .filter_map(|s| s.ok())
+                    .find(|sect| sect.name() == Some(METADATA_FILENAME))
+                    .map(|s| s.data())
+                    .ok_or_else(|| {
+                                    debug!("didn't find '{}' in the archive", METADATA_FILENAME);
+                                    format!("failed to read rlib metadata: '{}'",
+                                            filename.display())
+                                })
+            })?;
+        Ok(buf.erase_owner())
+    }
+
+    fn get_dylib_metadata(&self,
+                          target: &Target,
+                          filename: &Path)
+                          -> Result<ErasedBoxRef<[u8]>, String> {
+        unsafe {
+            let buf = common::path2cstr(filename);
+            let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
+            if mb as isize == 0 {
+                return Err(format!("error reading library: '{}'", filename.display()));
+            }
+            let of = ObjectFile::new(mb)
+                .map(|of| OwningRef::new(box of))
+                .ok_or_else(|| format!("provided path not an object file: '{}'",
+                                        filename.display()))?;
+            let buf = of.try_map(|of| search_meta_section(of, target, filename))?;
+            Ok(buf.erase_owner())
+        }
+    }
+}
+
+fn search_meta_section<'a>(of: &'a ObjectFile,
+                           target: &Target,
+                           filename: &Path)
+                           -> Result<&'a [u8], String> {
+    unsafe {
+        let si = mk_section_iter(of.llof);
+        while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
+            let mut name_buf = ptr::null();
+            let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
+            let name = slice::from_raw_parts(name_buf as *const u8, name_len as usize).to_vec();
+            let name = String::from_utf8(name).unwrap();
+            debug!("get_metadata_section: name {}", name);
+            if read_metadata_section_name(target) == name {
+                let cbuf = llvm::LLVMGetSectionContents(si.llsi);
+                let csz = llvm::LLVMGetSectionSize(si.llsi) as usize;
+                // The buffer is valid while the object file is around
+                let buf: &'a [u8] = slice::from_raw_parts(cbuf as *const u8, csz);
+                return Ok(buf);
+            }
+            llvm::LLVMMoveToNextSection(si.llsi);
+        }
+    }
+    Err(format!("metadata not found: '{}'", filename.display()))
+}
+
+pub fn metadata_section_name(target: &Target) -> &'static str {
+    // Historical note:
+    //
+    // When using link.exe it was seen that the section name `.note.rustc`
+    // was getting shortened to `.note.ru`, and according to the PE and COFF
+    // specification:
+    //
+    // > Executable images do not use a string table and do not support
+    // > section names longer than 8 characters
+    //
+    // https://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx
+    //
+    // As a result, we choose a slightly shorter name! As to why
+    // `.note.rustc` works on MinGW, that's another good question...
+
+    if target.options.is_like_osx {
+        "__DATA,.rustc"
+    } else {
+        ".rustc"
+    }
+}
+
+fn read_metadata_section_name(_target: &Target) -> &'static str {
+    ".rustc"
+}
index 889f9dc4cded5880f85a9c2171a7b24e708d350c..96ef26d3f6f833aa87a2a56c2eef37ac01d8c74f 100644 (file)
@@ -108,7 +108,7 @@ fn visit_terminator_kind(&mut self,
                              location: Location) {
         match *kind {
             mir::TerminatorKind::Call {
-                func: mir::Operand::Constant(mir::Constant {
+                func: mir::Operand::Constant(box mir::Constant {
                     literal: Literal::Value {
                         value: ConstVal::Function(def_id, _), ..
                     }, ..
index 040194e63d07e0ec6f549244ec495d3f3951abae..cd27ddda1b15bdb5151f2baa5806dd1a78b3727e 100644 (file)
@@ -415,8 +415,11 @@ fn const_lvalue(&self, lvalue: &mir::Lvalue<'tcx>, span: Span)
                                           Value(base));
                             }
                             if projected_ty.is_bool() {
-                                unsafe {
-                                    val = llvm::LLVMConstTrunc(val, Type::i1(self.ccx).to_ref());
+                                let i1_type = Type::i1(self.ccx);
+                                if val_ty(val) != i1_type {
+                                    unsafe {
+                                        val = llvm::LLVMConstTrunc(val, i1_type.to_ref());
+                                    }
                                 }
                             }
                             (Base::Value(val), extra)
@@ -537,7 +540,7 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
                 }
                 failure?;
 
-                match *kind {
+                match **kind {
                     mir::AggregateKind::Array(_) => {
                         self.const_array(dest_ty, &fields)
                     }
index b8e9a490b0e7cffa36b0ce40812131c19ebd8382..667075e6970e184c010e55ef7f9c6ab1de8f4ac8 100644 (file)
@@ -104,7 +104,7 @@ pub fn trans_rvalue(&mut self,
             }
 
             mir::Rvalue::Aggregate(ref kind, ref operands) => {
-                match *kind {
+                match **kind {
                     mir::AggregateKind::Adt(adt_def, variant_index, substs, active_field_index) => {
                         let discr = adt_def.discriminant_for_variant(bcx.tcx(), variant_index)
                            .to_u128_unchecked() as u64;
index 33b0aa3dbfffe3bcb2df7c0ebc34f4562de967c4..9e8352fde80617f1d7fb084e66b5ba1811897a15 100644 (file)
@@ -41,12 +41,6 @@ pub trait AstConv<'gcx, 'tcx> {
     fn get_type_parameter_bounds(&self, span: Span, def_id: DefId)
                                  -> ty::GenericPredicates<'tcx>;
 
-    /// Return an (optional) substitution to convert bound type parameters that
-    /// are in scope into free ones. This function should only return Some
-    /// within a fn body.
-    /// See ParameterEnvironment::free_substs for more information.
-    fn get_free_substs(&self) -> Option<&Substs<'tcx>>;
-
     /// What lifetime should we use when a lifetime is omitted (and not elided)?
     fn re_infer(&self, span: Span, _def: Option<&ty::RegionParameterDef>)
                 -> Option<ty::Region<'tcx>>;
@@ -121,6 +115,7 @@ pub fn ast_region_to_region(&self,
             Some(&rl::Region::EarlyBound(index, id)) => {
                 let name = tcx.hir.name(id);
                 tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
+                    def_id: tcx.hir.local_def_id(id),
                     index: index,
                     name: name
                 }))
@@ -129,7 +124,7 @@ pub fn ast_region_to_region(&self,
             Some(&rl::Region::Free(scope, id)) => {
                 let name = tcx.hir.name(id);
                 tcx.mk_region(ty::ReFree(ty::FreeRegion {
-                    scope: Some(scope.to_code_extent(tcx)),
+                    scope,
                     bound_region: ty::BrNamed(tcx.hir.local_def_id(id), name)
                 }))
 
@@ -163,7 +158,7 @@ pub fn ast_path_substs_for_ty(&self,
             hir::ParenthesizedParameters(..) => {
                 struct_span_err!(tcx.sess, span, E0214,
                           "parenthesized parameters may only be used with a trait")
-                    .span_label(span, &format!("only traits may use parentheses"))
+                    .span_label(span, "only traits may use parentheses")
                     .emit();
 
                 return Substs::for_item(tcx, def_id, |_, _| {
@@ -294,7 +289,7 @@ fn create_substs_for_ast_path(&self,
                     struct_span_err!(tcx.sess, span, E0393,
                                      "the type parameter `{}` must be explicitly specified",
                                      def.name)
-                        .span_label(span, &format!("missing reference to `{}`", def.name))
+                        .span_label(span, format!("missing reference to `{}`", def.name))
                         .note(&format!("because of the default `Self` reference, \
                                         type parameters must be specified on object types"))
                         .emit();
@@ -635,7 +630,7 @@ fn conv_object_ty_poly_trait_ref(&self,
             let span = b.trait_ref.path.span;
             struct_span_err!(self.tcx().sess, span, E0225,
                 "only Send/Sync traits can be used as additional traits in a trait object")
-                .span_label(span, &format!("non-Send/Sync additional trait"))
+                .span_label(span, "non-Send/Sync additional trait")
                 .emit();
         }
 
@@ -684,7 +679,7 @@ fn conv_object_ty_poly_trait_ref(&self,
                 "the value of the associated type `{}` (from the trait `{}`) must be specified",
                         name,
                         tcx.item_path_str(trait_def_id))
-                        .span_label(span, &format!(
+                        .span_label(span, format!(
                             "missing associated type `{}` value", name))
                         .emit();
         }
@@ -730,7 +725,7 @@ fn report_ambiguous_associated_type(&self,
                                         trait_str: &str,
                                         name: &str) {
         struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type")
-            .span_label(span, &format!("ambiguous associated type"))
+            .span_label(span, "ambiguous associated type")
             .note(&format!("specify the type using the syntax `<{} as {}>::{}`",
                   type_str, trait_str, name))
             .emit();
@@ -784,7 +779,7 @@ fn one_bound_for_assoc_type<I>(&self,
                           "associated type `{}` not found for `{}`",
                           assoc_name,
                           ty_param_name)
-                  .span_label(span, &format!("associated type `{}` not found", assoc_name))
+                  .span_label(span, format!("associated type `{}` not found", assoc_name))
                   .emit();
                 return Err(ErrorReported);
             }
@@ -797,7 +792,7 @@ fn one_bound_for_assoc_type<I>(&self,
                 "ambiguous associated type `{}` in bounds of `{}`",
                 assoc_name,
                 ty_param_name);
-            err.span_label(span, &format!("ambiguous associated type `{}`", assoc_name));
+            err.span_label(span, format!("ambiguous associated type `{}`", assoc_name));
 
             for bound in bounds {
                 let bound_span = self.tcx().associated_items(bound.def_id()).find(|item| {
@@ -806,7 +801,7 @@ fn one_bound_for_assoc_type<I>(&self,
                 .and_then(|item| self.tcx().hir.span_if_local(item.def_id));
 
                 if let Some(span) = bound_span {
-                    err.span_label(span, &format!("ambiguous `{}` from `{}`",
+                    err.span_label(span, format!("ambiguous `{}` from `{}`",
                                                   assoc_name,
                                                   bound));
                 } else {
@@ -857,12 +852,6 @@ pub fn associated_path_def_to_ty(&self,
                     }
                 };
 
-                let trait_ref = if let Some(free_substs) = self.get_free_substs() {
-                    trait_ref.subst(tcx, free_substs)
-                } else {
-                    trait_ref
-                };
-
                 let candidates =
                     traits::supertraits(tcx, ty::Binder(trait_ref))
                     .filter(|r| self.trait_defines_associated_type_named(r.def_id(),
@@ -951,7 +940,7 @@ pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
             for typ in segment.parameters.types() {
                 struct_span_err!(self.tcx().sess, typ.span, E0109,
                                  "type parameters are not allowed on this type")
-                    .span_label(typ.span, &format!("type parameter not allowed"))
+                    .span_label(typ.span, "type parameter not allowed")
                     .emit();
                 break;
             }
@@ -959,7 +948,7 @@ pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
                 struct_span_err!(self.tcx().sess, lifetime.span, E0110,
                                  "lifetime parameters are not allowed on this type")
                     .span_label(lifetime.span,
-                                &format!("lifetime parameter not allowed on this type"))
+                                "lifetime parameter not allowed on this type")
                     .emit();
                 break;
             }
@@ -973,7 +962,7 @@ pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
     pub fn prohibit_projection(&self, span: Span) {
         let mut err = struct_span_err!(self.tcx().sess, span, E0229,
                                        "associated type bindings are not allowed here");
-        err.span_label(span, &format!("associate type not allowed here")).emit();
+        err.span_label(span, "associate type not allowed here").emit();
     }
 
     // Check a type Path and convert it to a Ty.
@@ -1020,12 +1009,7 @@ pub fn def_to_ty(&self,
                 assert_eq!(opt_self_ty, None);
                 self.prohibit_type_params(&path.segments);
 
-                let ty = tcx.at(span).type_of(def_id);
-                if let Some(free_substs) = self.get_free_substs() {
-                    ty.subst(tcx, free_substs)
-                } else {
-                    ty
-                }
+                tcx.at(span).type_of(def_id)
             }
             Def::SelfTy(Some(_), None) => {
                 // Self in trait.
@@ -1214,7 +1198,7 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
             hir::TyTypeof(ref _e) => {
                 struct_span_err!(tcx.sess, ast_ty.span, E0516,
                                  "`typeof` is a reserved keyword but unimplemented")
-                    .span_label(ast_ty.span, &format!("reserved keyword"))
+                    .span_label(ast_ty.span, "reserved keyword")
                     .emit();
 
                 tcx.types.err
@@ -1426,7 +1410,7 @@ fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize,
                 "wrong number of type arguments: {} {}, found {}",
                 expected, required, supplied)
             .span_label(span,
-                &format!("{} {} type argument{}",
+                format!("{} {} type argument{}",
                     expected,
                     required,
                     arguments_plural))
@@ -1444,7 +1428,7 @@ fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize,
                 expected, supplied)
             .span_label(
                 span,
-                &format!("{} type argument{}",
+                format!("{} type argument{}",
                     if accepted == 0 { "expected no" } else { &expected },
                     arguments_plural)
             )
@@ -1470,7 +1454,7 @@ fn report_lifetime_number_error(tcx: TyCtxt, span: Span, number: usize, expected
     struct_span_err!(tcx.sess, span, E0107,
                      "wrong number of lifetime parameters: expected {}, found {}",
                      expected, number)
-        .span_label(span, &label)
+        .span_label(span, label)
         .emit();
 }
 
index ac10dfd36e25dba5034f9795e807d7e8e5991fc0..bbe34f37950dc6b7b9238092cf87891785b01654 100644 (file)
@@ -97,7 +97,7 @@ pub fn check_pat_arg(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>, is_arg: boo
 
                     struct_span_err!(tcx.sess, span, E0029,
                         "only char and numeric types are allowed in range patterns")
-                        .span_label(span, &format!("ranges require char or numeric types"))
+                        .span_label(span, "ranges require char or numeric types")
                         .note(&format!("start type: {}", self.ty_to_string(lhs_ty)))
                         .note(&format!("end type: {}", self.ty_to_string(rhs_ty)))
                         .emit();
@@ -263,7 +263,7 @@ pub fn check_pat_arg(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>, is_arg: boo
                                     tcx.sess, pat.span, E0527,
                                     "pattern requires {} elements but array has {}",
                                     min_len, size)
-                                    .span_label(pat.span, &format!("expected {} elements",size))
+                                    .span_label(pat.span, format!("expected {} elements",size))
                                     .emit();
                             }
                             (inner_ty, tcx.types.err)
@@ -274,7 +274,7 @@ pub fn check_pat_arg(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>, is_arg: boo
                                     "pattern requires at least {} elements but array has {}",
                                     min_len, size)
                                 .span_label(pat.span,
-                                    &format!("pattern cannot match array of {} elements", size))
+                                    format!("pattern cannot match array of {} elements", size))
                                 .emit();
                             (inner_ty, tcx.types.err)
                         }
@@ -297,7 +297,7 @@ pub fn check_pat_arg(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>, is_arg: boo
                             }
 
                             err.span_label( pat.span,
-                                &format!("pattern cannot match with input type `{}`", expected_ty)
+                                format!("pattern cannot match with input type `{}`", expected_ty)
                             ).emit();
                         }
                         (tcx.types.err, tcx.types.err)
@@ -379,7 +379,7 @@ pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::
                     let type_str = self.ty_to_string(expected);
                     struct_span_err!(self.tcx.sess, span, E0033,
                               "type `{}` cannot be dereferenced", type_str)
-                        .span_label(span, &format!("type `{}` cannot be dereferenced", type_str))
+                        .span_label(span, format!("type `{}` cannot be dereferenced", type_str))
                         .emit();
                     return false
                 }
@@ -593,7 +593,7 @@ fn check_pat_tuple_struct(&self,
                               def.kind_name(),
                               hir::print::to_string(&tcx.hir, |s| s.print_qpath(qpath, false)));
             struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
-                .span_label(pat.span, &format!("not a tuple variant or struct")).emit();
+                .span_label(pat.span, "not a tuple variant or struct").emit();
             on_error();
         };
 
@@ -642,7 +642,7 @@ fn check_pat_tuple_struct(&self,
                              "this pattern has {} field{}, but the corresponding {} has {} field{}",
                              subpats.len(), subpats_ending, def.kind_name(),
                              variant.fields.len(),  fields_ending)
-                .span_label(pat.span, &format!("expected {} field{}, found {}",
+                .span_label(pat.span, format!("expected {} field{}, found {}",
                                                variant.fields.len(), fields_ending, subpats.len()))
                 .emit();
             on_error();
@@ -683,8 +683,8 @@ fn check_struct_pat_fields(&self,
                                       in the pattern",
                                      field.name)
                         .span_label(span,
-                                    &format!("multiple uses of `{}` in pattern", field.name))
-                        .span_label(*occupied.get(), &format!("first use of `{}`", field.name))
+                                    format!("multiple uses of `{}` in pattern", field.name))
+                        .span_label(*occupied.get(), format!("first use of `{}`", field.name))
                         .emit();
                     tcx.types.err
                 }
@@ -703,7 +703,7 @@ fn check_struct_pat_fields(&self,
                                              tcx.item_path_str(variant.did),
                                              field.name)
                                 .span_label(span,
-                                            &format!("{} `{}` does not have field `{}`",
+                                            format!("{} `{}` does not have field `{}`",
                                                      kind_name,
                                                      tcx.item_path_str(variant.did),
                                                      field.name))
@@ -732,7 +732,7 @@ fn check_struct_pat_fields(&self,
                 struct_span_err!(tcx.sess, span, E0027,
                                 "pattern does not mention field `{}`",
                                 field.name)
-                                .span_label(span, &format!("missing field `{}`", field.name))
+                                .span_label(span, format!("missing field `{}`", field.name))
                                 .emit();
             }
         }
index c9584f1d9e1e0968a057f4c6875058788a6ebb75..f03451c04ed004a19d5d38c0bc0295b2fa84ce49 100644 (file)
@@ -62,7 +62,7 @@ fn next(&mut self) -> Option<Self::Item> {
                              E0055,
                              "reached the recursion limit while auto-dereferencing {:?}",
                              self.cur_ty)
-                .span_label(self.span, &format!("deref recursion limit reached"))
+                .span_label(self.span, "deref recursion limit reached")
                 .help(&format!(
                         "consider adding a `#[recursion_limit=\"{}\"]` attribute to your crate",
                         suggested_limit))
index 7a49309e005a11de55a0dbaadb085a1ccf4d309f..dde5f598a68329ec77a3e91c858fdcfb46575085 100644 (file)
@@ -27,7 +27,7 @@
 pub fn check_legal_trait_for_method_call(tcx: TyCtxt, span: Span, trait_id: DefId) {
     if tcx.lang_items.drop_trait() == Some(trait_id) {
         struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method")
-            .span_label(span, &format!("explicit destructor calls not allowed"))
+            .span_label(span, "explicit destructor calls not allowed")
             .emit();
     }
 }
index 32b363ed755f4cca5860c4f333b11db273e72386..72ce7d3b5ed711abe4cb6539cd5380fb19108af9 100644 (file)
@@ -155,7 +155,7 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
                                        },
                                        self.expr_ty);
                 err.span_label(error_span,
-                               &format!("cannot cast `{}` as `{}`",
+                               format!("cannot cast `{}` as `{}`",
                                         fcx.ty_to_string(self.expr_ty),
                                         cast_ty));
                 if let Ok(snippet) = fcx.sess().codemap().span_to_snippet(self.expr.span) {
@@ -200,7 +200,7 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
             }
             CastError::CastToBool => {
                 struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`")
-                    .span_label(self.span, &format!("unsupported cast"))
+                    .span_label(self.span, "unsupported cast")
                     .help("compare with zero instead")
                     .emit();
             }
index 45b0a571bd08afd7b7e5827e57bb1078c5174a47..4c3d5c8aaca7fdffc54382d53bb5e65a59eb965c 100644 (file)
@@ -15,6 +15,7 @@
 use astconv::AstConv;
 use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc::ty::{self, ToPolyTraitRef, Ty};
+use rustc::ty::subst::Substs;
 use std::cmp;
 use std::iter;
 use syntax::abi::Abi;
@@ -60,12 +61,17 @@ fn check_closure(&self,
                                          decl,
                                          Abi::RustCall,
                                          expected_sig);
+        // `deduce_expectations_from_expected_type` introduces late-bound
+        // lifetimes defined elsewhere, which we need to anonymize away.
+        let sig = self.tcx.anonymize_late_bound_regions(&sig);
 
         // Create type variables (for now) to represent the transformed
         // types of upvars. These will be unified during the upvar
         // inference phase (`upvar.rs`).
+        let base_substs = Substs::identity_for_item(self.tcx,
+            self.tcx.closure_base_def_id(expr_def_id));
         let closure_type = self.tcx.mk_closure(expr_def_id,
-            self.parameter_environment.free_substs.extend_to(self.tcx, expr_def_id,
+            base_substs.extend_to(self.tcx, expr_def_id,
                 |_, _| span_bug!(expr.span, "closure has region param"),
                 |_, _| self.infcx.next_ty_var(TypeVariableOrigin::TransformedUpvar(expr.span))
             )
@@ -73,8 +79,7 @@ fn check_closure(&self,
 
         debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type);
 
-        let extent = self.tcx.call_site_extent(expr.id, body.value.id);
-        let fn_sig = self.tcx.liberate_late_bound_regions(Some(extent), &sig);
+        let fn_sig = self.liberate_late_bound_regions(expr_def_id, &sig);
         let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
                                                             body.value.id, &fn_sig);
 
@@ -126,6 +131,7 @@ fn deduce_expectations_from_expected_type
                 (sig, kind)
             }
             ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
+            ty::TyFnPtr(sig) => (Some(sig.skip_binder().clone()), Some(ty::ClosureKind::Fn)),
             _ => (None, None),
         }
     }
index b0b57aee5b2537c1652ef0e7dc7b72e26f7795cd..c228fc6b24abde730be51c16c4ae0618176e0a79 100644 (file)
@@ -1144,7 +1144,7 @@ fn coerce_inner<'a>(&mut self,
                         db = struct_span_err!(
                             fcx.tcx.sess, cause.span, E0069,
                             "`return;` in a function whose return type is not `()`");
-                        db.span_label(cause.span, &format!("return type is not ()"));
+                        db.span_label(cause.span, "return type is not ()");
                     }
                     _ => {
                         db = fcx.report_mismatched_types(cause, expected, found, err);
index 9ed5528e86783905c6e2c46e477c4c1aa6235778..d9f77e8f04f1ccbfa595b19195f286a8a942b34a 100644 (file)
@@ -167,16 +167,15 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     // Create a parameter environment that represents the implementation's
     // method.
-    let impl_param_env = ty::ParameterEnvironment::for_item(tcx, impl_m_node_id);
+    let impl_param_env = tcx.parameter_environment(impl_m.def_id);
 
     // Create mapping from impl to skolemized.
-    let impl_to_skol_substs = &impl_param_env.free_substs;
+    let impl_to_skol_substs = Substs::identity_for_item(tcx, impl_m.def_id);
 
     // Create mapping from trait to skolemized.
     let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx,
                                                                impl_m.container.id(),
-                                                               trait_to_impl_substs.subst(tcx,
-                                                                          impl_to_skol_substs));
+                                                               trait_to_impl_substs);
     debug!("compare_impl_method: trait_to_skol_substs={:?}",
            trait_to_skol_substs);
 
@@ -191,8 +190,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        impl_m,
                                        &trait_m_generics,
                                        &impl_m_generics,
-                                       trait_to_skol_substs,
-                                       impl_to_skol_substs)?;
+                                       trait_to_skol_substs)?;
 
     // Create obligations for each predicate declared by the impl
     // definition in the context of the trait's parameter
@@ -200,7 +198,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // however, because we want to replace all late-bound regions with
     // region variables.
     let impl_predicates = tcx.predicates_of(impl_m_predicates.parent.unwrap());
-    let mut hybrid_preds = impl_predicates.instantiate(tcx, impl_to_skol_substs);
+    let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
 
     debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds);
 
@@ -226,7 +224,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                                normalize_cause.clone());
 
     tcx.infer_ctxt(trait_param_env, Reveal::UserFacing).enter(|infcx| {
-        let inh = Inherited::new(infcx);
+        let inh = Inherited::new(infcx, impl_m.def_id);
         let infcx = &inh.infcx;
 
         debug!("compare_impl_method: caller_bounds={:?}",
@@ -273,8 +271,6 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
                                                             infer::HigherRankedType,
                                                             &m_sig(impl_m));
-        let impl_sig =
-            impl_sig.subst(tcx, impl_to_skol_substs);
         let impl_sig =
             inh.normalize_associated_types_in(impl_m_span,
                                               impl_m_node_id,
@@ -282,8 +278,8 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let impl_fty = tcx.mk_fn_ptr(ty::Binder(impl_sig));
         debug!("compare_impl_method: impl_fty={:?}", impl_fty);
 
-        let trait_sig = tcx.liberate_late_bound_regions(
-            infcx.parameter_environment.free_id_outlive,
+        let trait_sig = inh.liberate_late_bound_regions(
+            impl_m.def_id,
             &m_sig(trait_m));
         let trait_sig =
             trait_sig.subst(tcx, trait_to_skol_substs);
@@ -370,8 +366,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 impl_m: &ty::AssociatedItem,
                                                 trait_generics: &ty::Generics,
                                                 impl_generics: &ty::Generics,
-                                                trait_to_skol_substs: &Substs<'tcx>,
-                                                impl_to_skol_substs: &Substs<'tcx>)
+                                                trait_to_skol_substs: &Substs<'tcx>)
                                                 -> Result<(), ErrorReported> {
     let trait_params = &trait_generics.regions[..];
     let impl_params = &impl_generics.regions[..];
@@ -379,12 +374,10 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("check_region_bounds_on_impl_method: \
             trait_generics={:?} \
             impl_generics={:?} \
-            trait_to_skol_substs={:?} \
-            impl_to_skol_substs={:?}",
+            trait_to_skol_substs={:?}",
            trait_generics,
            impl_generics,
-           trait_to_skol_substs,
-           impl_to_skol_substs);
+           trait_to_skol_substs);
 
     // Must have same number of early-bound lifetime parameters.
     // Unfortunately, if the user screws up the bounds, then this
@@ -402,7 +395,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          "lifetime parameters or bounds on method `{}` do not match the \
                           trait declaration",
                          impl_m.name)
-            .span_label(span, &format!("lifetimes do not match trait"))
+            .span_label(span, "lifetimes do not match trait")
             .emit();
         return Err(ErrorReported);
     }
@@ -534,9 +527,9 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                             not in the trait",
                                            trait_m.name,
                                            self_descr);
-            err.span_label(impl_m_span, &format!("`{}` used in impl", self_descr));
+            err.span_label(impl_m_span, format!("`{}` used in impl", self_descr));
             if let Some(span) = tcx.hir.span_if_local(trait_m.def_id) {
-                err.span_label(span, &format!("trait declared without `{}`", self_descr));
+                err.span_label(span, format!("trait declared without `{}`", self_descr));
             }
             err.emit();
             return Err(ErrorReported);
@@ -552,9 +545,9 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            trait_m.name,
                                            self_descr);
             err.span_label(impl_m_span,
-                           &format!("expected `{}` in impl", self_descr));
+                           format!("expected `{}` in impl", self_descr));
             if let Some(span) = tcx.hir.span_if_local(trait_m.def_id) {
-                err.span_label(span, &format!("`{}` used in trait", self_descr));
+                err.span_label(span, format!("`{}` used in trait", self_descr));
             }
             err.emit();
             return Err(ErrorReported);
@@ -606,7 +599,7 @@ fn compare_number_of_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         if let Some(span) = trait_item_span {
             err.span_label(span,
-                           &format!("expected {}",
+                           format!("expected {}",
                                     &if num_trait_m_type_params != 1 {
                                         format!("{} type parameters", num_trait_m_type_params)
                                     } else {
@@ -617,7 +610,7 @@ fn compare_number_of_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
 
         err.span_label(span,
-                       &format!("found {}{}",
+                       format!("found {}{}",
                                 &if num_impl_m_type_params != 1 {
                                     format!("{} type parameters", num_impl_m_type_params)
                                 } else {
@@ -696,7 +689,7 @@ trait `{}` has {}",
                                        trait_number_args);
         if let Some(trait_span) = trait_span {
             err.span_label(trait_span,
-                           &format!("trait requires {}",
+                           format!("trait requires {}",
                                     &if trait_number_args != 1 {
                                         format!("{} parameters", trait_number_args)
                                     } else {
@@ -704,7 +697,7 @@ trait `{}` has {}",
                                     }));
         }
         err.span_label(impl_span,
-                       &format!("expected {}, found {}",
+                       format!("expected {}, found {}",
                                 &if trait_number_args != 1 {
                                     format!("{} parameters", trait_number_args)
                                 } else {
@@ -726,7 +719,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
 
     tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
-        let inh = Inherited::new(infcx);
+        let inh = Inherited::new(infcx, impl_c.def_id);
         let infcx = &inh.infcx;
 
         // The below is for the most part highly similar to the procedure
@@ -739,22 +732,10 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Create a parameter environment that represents the implementation's
         // method.
         let impl_c_node_id = tcx.hir.as_local_node_id(impl_c.def_id).unwrap();
-        let impl_param_env = ty::ParameterEnvironment::for_item(tcx, impl_c_node_id);
-
-        // Create mapping from impl to skolemized.
-        let impl_to_skol_substs = &impl_param_env.free_substs;
-
-        // Create mapping from trait to skolemized.
-        let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx,
-                                                                   impl_c.container.id(),
-                                                                   trait_to_impl_substs.subst(tcx,
-                                                                              impl_to_skol_substs));
-        debug!("compare_const_impl: trait_to_skol_substs={:?}",
-               trait_to_skol_substs);
 
         // Compute skolemized form of impl and trait const tys.
-        let impl_ty = tcx.type_of(impl_c.def_id).subst(tcx, impl_to_skol_substs);
-        let trait_ty = tcx.type_of(trait_c.def_id).subst(tcx, trait_to_skol_substs);
+        let impl_ty = tcx.type_of(impl_c.def_id);
+        let trait_ty = tcx.type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs);
         let mut cause = ObligationCause::misc(impl_c_span, impl_c_node_id);
 
         // There is no "body" here, so just pass dummy id.
index c20777a403aac7a2b36f97e54b88da7826ede900..e029332559635663b46b12b696e9a466aa25dea2 100644 (file)
@@ -76,17 +76,15 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
     -> Result<(), ErrorReported>
 {
     let drop_impl_node_id = tcx.hir.as_local_node_id(drop_impl_did).unwrap();
-    let self_type_node_id = tcx.hir.as_local_node_id(self_type_did).unwrap();
 
     // check that the impl type can be made to match the trait type.
 
-    let impl_param_env = ty::ParameterEnvironment::for_item(tcx, self_type_node_id);
+    let impl_param_env = tcx.parameter_environment(self_type_did);
     tcx.infer_ctxt(impl_param_env, Reveal::UserFacing).enter(|ref infcx| {
         let tcx = infcx.tcx;
         let mut fulfillment_cx = traits::FulfillmentContext::new();
 
         let named_type = tcx.type_of(self_type_did);
-        let named_type = named_type.subst(tcx, &infcx.parameter_environment.free_substs);
 
         let drop_impl_span = tcx.def_span(drop_impl_did);
         let fresh_impl_substs =
@@ -99,7 +97,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
                 fulfillment_cx.register_predicate_obligations(infcx, obligations);
             }
             Err(_) => {
-                let item_span = tcx.hir.span(self_type_node_id);
+                let item_span = tcx.def_span(self_type_did);
                 struct_span_err!(tcx.sess, drop_impl_span, E0366,
                                  "Implementations of Drop cannot be specialized")
                     .span_note(item_span,
@@ -272,7 +270,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>(
     rcx: &mut RegionCtxt<'a, 'gcx, 'tcx>,
     ty: ty::Ty<'tcx>,
     span: Span,
-    scope: region::CodeExtent<'tcx>)
+    scope: region::CodeExtent)
     -> Result<(), ErrorReported>
 {
     debug!("check_safety_of_destructor_if_necessary typ: {:?} scope: {:?}",
index 2a97bc1d98fe95e83326d218096dbe4bd3fdc36b..60067e6a6ec0238e9c8da62e73ec9f60ed71e31c 100644 (file)
@@ -57,7 +57,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         "intrinsic has wrong number of type \
                         parameters: found {}, expected {}",
                         i_n_tps, n_tps)
-            .span_label(span, &format!("expected {} type parameter", n_tps))
+            .span_label(span, format!("expected {} type parameter", n_tps))
             .emit();
     } else {
         require_same_types(tcx,
@@ -101,7 +101,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             op => {
                 struct_span_err!(tcx.sess, it.span, E0092,
                       "unrecognized atomic operation function: `{}`", op)
-                  .span_label(it.span, &format!("unrecognized atomic operation"))
+                  .span_label(it.span, "unrecognized atomic operation")
                   .emit();
                 return;
             }
@@ -305,7 +305,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 struct_span_err!(tcx.sess, it.span, E0093,
                                 "unrecognized intrinsic function: `{}`",
                                 *other)
-                                .span_label(it.span, &format!("unrecognized intrinsic"))
+                                .span_label(it.span, "unrecognized intrinsic")
                                 .emit();
                 return;
             }
@@ -505,7 +505,7 @@ fn match_intrinsic_type_to_type<'a, 'tcx>(
                     }
                 }
                 _ => simple_error(&format!("`{}`", t),
-                                  &format!("tuple")),
+                                  "tuple"),
             }
         }
     }
index aad14bc975de5af618d7f9a5e9f36c35d554f450..a9e82a0601feeafe8784bba5458cb49e51271399 100644 (file)
@@ -285,7 +285,7 @@ fn instantiate_method_substs(&mut self,
                                  self.span,
                                  E0035,
                                  "does not take type parameters")
-                    .span_label(self.span, &"called with unneeded type parameters")
+                    .span_label(self.span, "called with unneeded type parameters")
                     .emit();
             } else {
                 struct_span_err!(self.tcx.sess,
@@ -296,7 +296,7 @@ fn instantiate_method_substs(&mut self,
                                  num_method_types,
                                  num_supplied_types)
                     .span_label(self.span,
-                                &format!("Passed {} type argument{}, expected {}",
+                                format!("Passed {} type argument{}, expected {}",
                                          num_supplied_types,
                                          if num_supplied_types != 1 { "s" } else { "" },
                                          num_method_types))
@@ -433,22 +433,11 @@ fn convert_lvalue_derefs_to_mutable(&self) {
         for (i, &expr) in exprs.iter().rev().enumerate() {
             debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?}", i, expr);
 
-            // Fix up the adjustment.
-            let autoderefs = match self.tables.borrow_mut().adjustments.get_mut(&expr.id) {
-                Some(&mut Adjustment {
-                    kind: Adjust::DerefRef { autoderefs, ref mut autoref, .. }, ref mut target
-                }) => {
-                    if let &mut Some(AutoBorrow::Ref(_, ref mut mutbl)) = autoref {
-                        *mutbl = hir::Mutability::MutMutable;
-                        *target = match target.sty {
-                            ty::TyRef(r, ty::TypeAndMut { ty, .. }) =>
-                                self.tcx.mk_ref(r, ty::TypeAndMut { ty, mutbl: *mutbl }),
-                            _ => span_bug!(expr.span, "AutoBorrow::Ref resulted in non-ref {:?}",
-                                           target)
-                        };
-                    }
-                    autoderefs
-                }
+            // Fix up the autoderefs. Autorefs can only occur immediately preceding
+            // overloaded lvalue ops, and will be fixed by them in order to get
+            // the correct region.
+            let autoderefs = match self.tables.borrow().adjustments.get(&expr.id) {
+                Some(&Adjustment { kind: Adjust::DerefRef { autoderefs, .. }, .. }) => autoderefs,
                 Some(_) | None => 0
             };
 
@@ -502,10 +491,35 @@ fn convert_lvalue_op_to_mutable(&self,
 
         let method = self.try_overloaded_lvalue_op(
             expr.span, None, base_ty, arg_tys, PreferMutLvalue, op);
-        let ok = method.expect("re-trying op failed");
+        let ok = match method {
+            Some(method) => method,
+            None => return self.tcx.sess.delay_span_bug(expr.span, "re-trying op failed")
+        };
         let method = self.register_infer_ok_obligations(ok);
         debug!("convert_lvalue_op_to_mutable: method={:?}", method);
         self.tables.borrow_mut().method_map.insert(method_call, method);
+
+        // Convert the autoref in the base expr to mutable with the correct
+        // region and mutability.
+        if let Some(&mut Adjustment {
+            ref mut target, kind: Adjust::DerefRef {
+                autoref: Some(AutoBorrow::Ref(ref mut r, ref mut mutbl)), ..
+            }
+        }) = self.tables.borrow_mut().adjustments.get_mut(&base_expr.id) {
+            debug!("convert_lvalue_op_to_mutable: converting autoref of {:?}", target);
+
+            // extract method return type, which will be &mut T;
+            // all LB regions should have been instantiated during method lookup
+            let method_sig = self.tcx.no_late_bound_regions(&method.ty.fn_sig()).unwrap();
+
+            *target = method_sig.inputs()[0];
+            if let ty::TyRef(r_, mt) = target.sty {
+                *r = r_;
+                *mutbl = mt.mutbl;
+            } else {
+                span_bug!(expr.span, "input to lvalue op is not a ref?");
+            }
+        }
     }
 
     ///////////////////////////////////////////////////////////////////////////
index 4b975d7b324f99c492ef96ab3d2a448db289fadf..7e70bb92cd6e0f011b57c3baf236412490b09641 100644 (file)
@@ -209,9 +209,9 @@ pub fn report_method_error(&self,
                                                               expr_string,
                                                               item_name));
                                         }
-                                        err.span_label(span, &"field, not a method");
+                                        err.span_label(span, "field, not a method");
                                     } else {
-                                        err.span_label(span, &"private field, not a method");
+                                        err.span_label(span, "private field, not a method");
                                     }
                                     break;
                                 }
@@ -251,9 +251,9 @@ macro_rules! report_function {
                     let bound_list = unsatisfied_predicates.iter()
                         .map(|p| format!("`{} : {}`", p.self_ty(), p))
                         .collect::<Vec<_>>()
-                        .join("");
+                        .join("\n");
                     err.note(&format!("the method `{}` exists but the following trait bounds \
-                                       were not satisfied: {}",
+                                       were not satisfied:\n{}",
                                       item_name,
                                       bound_list));
                 }
@@ -272,7 +272,7 @@ macro_rules! report_function {
                                                span,
                                                E0034,
                                                "multiple applicable items in scope");
-                err.span_label(span, &format!("multiple `{}` found", item_name));
+                err.span_label(span, format!("multiple `{}` found", item_name));
 
                 report_candidates(&mut err, sources);
                 err.emit();
index 2e29aeeb02214b89d65729919dbbed0e13c06339..d304d79bc52c8342b8ce1ad65cf1226f2cfb277a 100644 (file)
 use rustc_back::slice::ref_slice;
 use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin};
 use rustc::infer::type_variable::{TypeVariableOrigin};
+use rustc::middle::region::CodeExtent;
 use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal};
-use rustc::ty::{ParamTy, ParameterEnvironment};
-use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
+use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue};
 use rustc::ty::{self, Ty, TyCtxt, Visibility};
 use rustc::ty::{MethodCall, MethodCallee};
 use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
@@ -177,6 +177,14 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     // variables to get the concrete type, which can be used to
     // deanonymize TyAnon, after typeck is done with all functions.
     anon_types: RefCell<NodeMap<Ty<'tcx>>>,
+
+    /// Each type parameter has an implicit region bound that
+    /// indicates it must outlive at least the function body (the user
+    /// may specify stronger requirements). This field indicates the
+    /// region of the callee. If it is `None`, then the parameter
+    /// environment is for an item or something where the "callee" is
+    /// not clear.
+    implicit_region_bound: Option<ty::Region<'tcx>>,
 }
 
 impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> {
@@ -523,16 +531,18 @@ fn deref(&self) -> &Self::Target {
 /// Necessary because we can't write the following bound:
 /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Inherited<'b, 'gcx, 'tcx>).
 pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
-    infcx: infer::InferCtxtBuilder<'a, 'gcx, 'tcx>
+    infcx: infer::InferCtxtBuilder<'a, 'gcx, 'tcx>,
+    def_id: DefId,
 }
 
 impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
-    pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId)
+    pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId)
                  -> InheritedBuilder<'a, 'gcx, 'tcx> {
         let tables = ty::TypeckTables::empty();
-        let param_env = ParameterEnvironment::for_item(tcx, id);
+        let param_env = tcx.parameter_environment(def_id);
         InheritedBuilder {
-            infcx: tcx.infer_ctxt((tables, param_env), Reveal::UserFacing)
+            infcx: tcx.infer_ctxt((tables, param_env), Reveal::UserFacing),
+            def_id,
         }
     }
 }
@@ -541,12 +551,20 @@ impl<'a, 'gcx, 'tcx> InheritedBuilder<'a, 'gcx, 'tcx> {
     fn enter<F, R>(&'tcx mut self, f: F) -> R
         where F: for<'b> FnOnce(Inherited<'b, 'gcx, 'tcx>) -> R
     {
-        self.infcx.enter(|infcx| f(Inherited::new(infcx)))
+        let def_id = self.def_id;
+        self.infcx.enter(|infcx| f(Inherited::new(infcx, def_id)))
     }
 }
 
 impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
-    fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self {
+    fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> Self {
+        let tcx = infcx.tcx;
+        let item_id = tcx.hir.as_local_node_id(def_id);
+        let body_id = item_id.and_then(|id| tcx.hir.maybe_body_owned_by(id));
+        let implicit_region_bound = body_id.map(|body| {
+            tcx.mk_region(ty::ReScope(CodeExtent::CallSiteScope(body)))
+        });
+
         Inherited {
             infcx: infcx,
             fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
@@ -554,6 +572,7 @@ fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self {
             deferred_call_resolutions: RefCell::new(DefIdMap()),
             deferred_cast_checks: RefCell::new(Vec::new()),
             anon_types: RefCell::new(NodeMap()),
+            implicit_region_bound,
         }
     }
 
@@ -606,6 +625,22 @@ fn normalize_associated_types_in_as_infer_ok<T>(&self,
             obligations);
         InferOk { value, obligations }
     }
+
+    /// Replace any late-bound regions bound in `value` with
+    /// free variants attached to `all_outlive_scope`.
+    fn liberate_late_bound_regions<T>(&self,
+        all_outlive_scope: DefId,
+        value: &ty::Binder<T>)
+        -> T
+        where T: TypeFoldable<'tcx>
+    {
+        self.tcx.replace_late_bound_regions(value, |br| {
+            self.tcx.mk_region(ty::ReFree(ty::FreeRegion {
+                scope: all_outlive_scope,
+                bound_region: br
+            }))
+        }).0
+    }
 }
 
 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> }
@@ -772,18 +807,15 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     });
     let body = tcx.hir.body(body_id);
 
-    Inherited::build(tcx, id).enter(|inh| {
+    Inherited::build(tcx, def_id).enter(|inh| {
         let fcx = if let Some(decl) = fn_decl {
             let fn_sig = tcx.type_of(def_id).fn_sig();
 
             check_abi(tcx, span, fn_sig.abi());
 
             // Compute the fty from point of view of inside fn.
-            let fn_scope = inh.tcx.call_site_extent(id, body_id.node_id);
-            let fn_sig =
-                fn_sig.subst(inh.tcx, &inh.parameter_environment.free_substs);
             let fn_sig =
-                inh.tcx.liberate_late_bound_regions(Some(fn_scope), &fn_sig);
+                inh.liberate_late_bound_regions(def_id, &fn_sig);
             let fn_sig =
                 inh.normalize_associated_types_in(body.value.span, body_id.node_id, &fn_sig);
 
@@ -1130,7 +1162,7 @@ fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             struct_span_err!(
                 tcx.sess, attr.span, E0232,
                 "this attribute must have a value")
-                .span_label(attr.span, &format!("attribute requires a value"))
+                .span_label(attr.span, "attribute requires a value")
                 .note(&format!("eg `#[rustc_on_unimplemented = \"foo\"]`"))
                 .emit();
         }
@@ -1146,12 +1178,12 @@ fn report_forbidden_specialization<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         "`{}` specializes an item from a parent `impl`, but \
          that item is not marked `default`",
         impl_item.name);
-    err.span_label(impl_item.span, &format!("cannot specialize default item `{}`",
+    err.span_label(impl_item.span, format!("cannot specialize default item `{}`",
                                             impl_item.name));
 
     match tcx.span_of_impl(parent_impl) {
         Ok(span) => {
-            err.span_label(span, &"parent `impl` is here");
+            err.span_label(span, "parent `impl` is here");
             err.note(&format!("to specialize, `{}` in the parent `impl` must be marked `default`",
                               impl_item.name));
         }
@@ -1168,7 +1200,7 @@ fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            impl_id: DefId,
                                            impl_item: &hir::ImplItem)
 {
-    let ancestors = trait_def.ancestors(impl_id);
+    let ancestors = trait_def.ancestors(tcx, impl_id);
 
     let kind = match impl_item.node {
         hir::ImplItemKind::Const(..) => ty::AssociatedKind::Const,
@@ -1226,11 +1258,11 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   which doesn't match its trait `{}`",
                                   ty_impl_item.name,
                                   impl_trait_ref);
-                         err.span_label(impl_item.span, &format!("does not match trait"));
+                         err.span_label(impl_item.span, "does not match trait");
                          // We can only get the spans from local trait definition
                          // Same for E0324 and E0325
                          if let Some(trait_span) = tcx.hir.span_if_local(ty_trait_item.def_id) {
-                            err.span_label(trait_span, &format!("item in trait"));
+                            err.span_label(trait_span, "item in trait");
                          }
                          err.emit()
                     }
@@ -1262,9 +1294,9 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   which doesn't match its trait `{}`",
                                   ty_impl_item.name,
                                   impl_trait_ref);
-                         err.span_label(impl_item.span, &format!("does not match trait"));
+                         err.span_label(impl_item.span, "does not match trait");
                          if let Some(trait_span) = tcx.hir.span_if_local(ty_trait_item.def_id) {
-                            err.span_label(trait_span, &format!("item in trait"));
+                            err.span_label(trait_span, "item in trait");
                          }
                          err.emit()
                     }
@@ -1280,9 +1312,9 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   which doesn't match its trait `{}`",
                                   ty_impl_item.name,
                                   impl_trait_ref);
-                         err.span_label(impl_item.span, &format!("does not match trait"));
+                         err.span_label(impl_item.span, "does not match trait");
                          if let Some(trait_span) = tcx.hir.span_if_local(ty_trait_item.def_id) {
-                            err.span_label(trait_span, &format!("item in trait"));
+                            err.span_label(trait_span, "item in trait");
                          }
                          err.emit()
                     }
@@ -1298,7 +1330,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut invalidated_items = Vec::new();
     let associated_type_overridden = overridden_associated_type.is_some();
     for trait_item in tcx.associated_items(impl_trait_ref.def_id) {
-        let is_implemented = trait_def.ancestors(impl_id)
+        let is_implemented = trait_def.ancestors(tcx, impl_id)
             .defs(tcx, trait_item.name, trait_item.kind)
             .next()
             .map(|node_item| !node_item.node.is_from_trait())
@@ -1331,13 +1363,13 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             missing_items.iter()
                   .map(|trait_item| trait_item.name.to_string())
                   .collect::<Vec<_>>().join("`, `"));
-        err.span_label(impl_span, &format!("missing `{}` in implementation",
+        err.span_label(impl_span, format!("missing `{}` in implementation",
                 missing_items.iter()
                     .map(|trait_item| trait_item.name.to_string())
                     .collect::<Vec<_>>().join("`, `")));
         for trait_item in missing_items {
             if let Some(span) = tcx.hir.span_if_local(trait_item.def_id) {
-                err.span_label(span, &format!("`{}` from trait", trait_item.name));
+                err.span_label(span, format!("`{}` from trait", trait_item.name));
             } else {
                 err.note(&format!("`{}` from trait: `{}`",
                                   trait_item.name,
@@ -1377,7 +1409,7 @@ fn check_representable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         Representability::SelfRecursive(spans) => {
             let mut err = tcx.recursive_type_with_infinite_size_error(item_def_id);
             for span in spans {
-                err.span_label(span, &"recursive without indirection");
+                err.span_label(span, "recursive without indirection");
             }
             err.emit();
             return false
@@ -1399,7 +1431,7 @@ pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId
             let e = fields[0].ty(tcx, substs);
             if !fields.iter().all(|f| f.ty(tcx, substs) == e) {
                 struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous")
-                                .span_label(sp, &format!("SIMD elements must have the same type"))
+                                .span_label(sp, "SIMD elements must have the same type")
                                 .emit();
                 return;
             }
@@ -1471,7 +1503,7 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         struct_span_err!(
             tcx.sess, sp, E0084,
             "unsupported representation for zero-variant enum")
-            .span_label(sp, &format!("unsupported enum representation"))
+            .span_label(sp, "unsupported enum representation")
             .emit();
     }
 
@@ -1505,8 +1537,8 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             };
             struct_span_err!(tcx.sess, span, E0081,
                              "discriminant value `{}` already exists", disr_vals[i])
-                .span_label(i_span, &format!("first use of `{}`", disr_vals[i]))
-                .span_label(span , &format!("enum already has `{}`", disr_vals[i]))
+                .span_label(i_span, format!("first use of `{}`", disr_vals[i]))
+                .span_label(span , format!("enum already has `{}`", disr_vals[i]))
                 .emit();
         }
         disr_vals.push(discr);
@@ -1518,10 +1550,6 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
 
-    fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
-        Some(&self.parameter_environment.free_substs)
-    }
-
     fn get_type_parameter_bounds(&self, _: Span, def_id: DefId)
                                  -> ty::GenericPredicates<'tcx>
     {
@@ -2401,12 +2429,12 @@ fn parameter_count_error<'tcx>(sess: &Session, sp: Span, expected_count: usize,
                     if arg_count == 1 {" was"} else {"s were"}),
                 error_code);
 
-            err.span_label(sp, &format!("expected {}{} parameter{}",
+            err.span_label(sp, format!("expected {}{} parameter{}",
                                         if variadic {"at least "} else {""},
                                         expected_count,
                                         if expected_count == 1 {""} else {"s"}));
             if let Some(def_s) = def_span {
-                err.span_label(def_s, &format!("defined here"));
+                err.span_label(def_s, "defined here");
             }
             err.emit();
         }
@@ -2938,10 +2966,10 @@ fn check_field(&self,
                     if let Some(suggested_field_name) =
                         Self::suggest_field_name(def.struct_variant(), field, vec![]) {
                             err.span_label(field.span,
-                                           &format!("did you mean `{}`?", suggested_field_name));
+                                           format!("did you mean `{}`?", suggested_field_name));
                         } else {
                             err.span_label(field.span,
-                                           &format!("unknown field"));
+                                           "unknown field");
                         };
                 }
                 ty::TyRawPtr(..) => {
@@ -3076,15 +3104,15 @@ fn report_unknown_field(&self,
                                                            &field.name,
                                                            skip_fields.collect()) {
             err.span_label(field.name.span,
-                           &format!("field does not exist - did you mean `{}`?", field_name));
+                           format!("field does not exist - did you mean `{}`?", field_name));
         } else {
             match ty.sty {
                 ty::TyAdt(adt, ..) if adt.is_enum() => {
-                    err.span_label(field.name.span, &format!("`{}::{}` does not have this field",
+                    err.span_label(field.name.span, format!("`{}::{}` does not have this field",
                                                              ty, variant.name));
                 }
                 _ => {
-                    err.span_label(field.name.span, &format!("`{}` does not have this field", ty));
+                    err.span_label(field.name.span, format!("`{}` does not have this field", ty));
                 }
             }
         };
@@ -3149,10 +3177,10 @@ fn check_expr_struct_fields(&self,
                                                 "field `{}` specified more than once",
                                                 field.name.node);
 
-                    err.span_label(field.name.span, &format!("used more than once"));
+                    err.span_label(field.name.span, "used more than once");
 
                     if let Some(prev_span) = seen_fields.get(&field.name.node) {
-                        err.span_label(*prev_span, &format!("first use of `{}`", field.name.node));
+                        err.span_label(*prev_span, format!("first use of `{}`", field.name.node));
                     }
 
                     err.emit();
@@ -3199,7 +3227,7 @@ fn check_expr_struct_fields(&self,
                         remaining_fields_names,
                         truncated_fields_error,
                         adt_ty)
-                        .span_label(span, &format!("missing {}{}",
+                        .span_label(span, format!("missing {}{}",
                             remaining_fields_names,
                             truncated_fields_error))
                         .emit();
@@ -3266,7 +3294,7 @@ pub fn check_struct_path(&self,
             struct_span_err!(self.tcx.sess, path_span, E0071,
                              "expected struct, variant or union type, found {}",
                              ty.sort_string(self.tcx))
-                .span_label(path_span, &format!("not a struct"))
+                .span_label(path_span, "not a struct")
                 .emit();
             None
         }
@@ -3625,7 +3653,7 @@ fn check_expr_kind(&self,
                     "invalid left-hand side expression")
                 .span_label(
                     expr.span,
-                    &format!("left-hand of expression not valid"))
+                    "left-hand of expression not valid")
                 .emit();
             }
 
@@ -4517,7 +4545,7 @@ fn check_path_parameter_count(&self,
                              "too many lifetime parameters provided: \
                               expected at most {}, found {}",
                              expected_text, actual_text)
-                .span_label(span, &format!("expected {}", expected_text))
+                .span_label(span, format!("expected {}", expected_text))
                 .emit();
         } else if lifetimes.len() > 0 && lifetimes.len() < lifetime_defs.len() {
             let expected_text = count_lifetime_params(lifetime_defs.len());
@@ -4526,7 +4554,7 @@ fn check_path_parameter_count(&self,
                              "too few lifetime parameters provided: \
                               expected {}, found {}",
                              expected_text, actual_text)
-                .span_label(span, &format!("expected {}", expected_text))
+                .span_label(span, format!("expected {}", expected_text))
                 .emit();
         }
 
@@ -4551,7 +4579,7 @@ fn check_path_parameter_count(&self,
                              "too many type parameters provided: \
                               expected at most {}, found {}",
                              expected_text, actual_text)
-                .span_label(span, &format!("expected {}", expected_text))
+                .span_label(span, format!("expected {}", expected_text))
                 .emit();
 
             // To prevent derived errors to accumulate due to extra
@@ -4565,7 +4593,7 @@ fn check_path_parameter_count(&self,
                              "too few type parameters provided: \
                               expected {}, found {}",
                              expected_text, actual_text)
-                .span_label(span, &format!("expected {}", expected_text))
+                .span_label(span, format!("expected {}", expected_text))
                 .emit();
         }
 
@@ -4654,7 +4682,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             struct_span_err!(tcx.sess, param.span, E0091,
                 "type parameter `{}` is unused",
                 param.name)
-                .span_label(param.span, &format!("unused type parameter"))
+                .span_label(param.span, "unused type parameter")
                 .emit();
         }
     }
index d3d65ce4a626e10f5d0ecc3faa7410b5883fdeae..59cb61d9b97f0b3196126eb3637a6daca34a0c29 100644 (file)
@@ -50,7 +50,7 @@ pub fn check_binop_assign(&self,
                 E0067, "invalid left-hand side expression")
             .span_label(
                 lhs_expr.span,
-                &format!("invalid expression for left-hand side"))
+                "invalid expression for left-hand side")
             .emit();
         }
         ty
@@ -203,7 +203,7 @@ fn check_overloaded_binop(&self,
                                          op.node.as_str(),
                                          lhs_ty)
                             .span_label(lhs_expr.span,
-                                        &format!("cannot use `{}=` on type `{}`",
+                                        format!("cannot use `{}=` on type `{}`",
                                         op.node.as_str(), lhs_ty))
                             .emit();
                     } else {
@@ -278,7 +278,7 @@ fn check_str_addition(&self,
             if let TyRef(_, r_ty) = rhs_ty.sty {
                 if l_ty.ty.sty == TyStr && r_ty.ty.sty == TyStr {
                     err.span_label(expr.span,
-                        &"`+` can't be used to concatenate two `&str` strings");
+                        "`+` can't be used to concatenate two `&str` strings");
                     let codemap = self.tcx.sess.codemap();
                     let suggestion =
                         match codemap.span_to_snippet(lhs_expr.span) {
index e4936dfc47bc749f2980dd79545bf98630377843..754bd288bfaa70c995624c1358dbc3ffcd7e284f 100644 (file)
@@ -87,7 +87,7 @@
 use middle::free_region::FreeRegionMap;
 use middle::mem_categorization as mc;
 use middle::mem_categorization::Categorization;
-use middle::region::{self, CodeExtent, RegionMaps};
+use middle::region::{CodeExtent, RegionMaps};
 use rustc::hir::def_id::DefId;
 use rustc::ty::subst::Substs;
 use rustc::traits;
@@ -178,7 +178,7 @@ pub struct RegionCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 
     region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,
 
-    pub region_maps: Rc<RegionMaps<'tcx>>,
+    pub region_maps: Rc<RegionMaps>,
 
     free_region_map: FreeRegionMap<'tcx>,
 
@@ -186,7 +186,7 @@ pub struct RegionCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     body_id: ast::NodeId,
 
     // call_site scope of innermost fn
-    call_site_scope: Option<CodeExtent<'tcx>>,
+    call_site_scope: Option<CodeExtent>,
 
     // id of innermost fn or loop
     repeating_scope: ast::NodeId,
@@ -224,8 +224,8 @@ pub fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
         }
     }
 
-    fn set_call_site_scope(&mut self, call_site_scope: Option<CodeExtent<'tcx>>)
-                           -> Option<CodeExtent<'tcx>> {
+    fn set_call_site_scope(&mut self, call_site_scope: Option<CodeExtent>)
+                           -> Option<CodeExtent> {
         mem::replace(&mut self.call_site_scope, call_site_scope)
     }
 
@@ -286,8 +286,7 @@ fn visit_fn_body(&mut self,
 
         let body_id = body.id();
 
-        let call_site = self.tcx.intern_code_extent(
-            region::CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id });
+        let call_site = CodeExtent::CallSiteScope(body_id);
         let old_call_site_scope = self.set_call_site_scope(Some(call_site));
 
         let fn_sig = {
@@ -312,7 +311,7 @@ fn visit_fn_body(&mut self,
 
         let old_body_id = self.set_body_id(body_id.node_id);
         self.relate_free_regions(&fn_sig_tys[..], body_id.node_id, span);
-        self.link_fn_args(self.tcx.node_extent(body_id.node_id), &body.arguments);
+        self.link_fn_args(CodeExtent::Misc(body_id.node_id), &body.arguments);
         self.visit_body(body);
         self.visit_region_obligations(body_id.node_id);
 
@@ -398,9 +397,11 @@ fn relate_free_regions(&mut self,
             for implication in implied_bounds {
                 debug!("implication: {:?}", implication);
                 match implication {
-                    ImpliedBound::RegionSubRegion(&ty::ReFree(free_a),
+                    ImpliedBound::RegionSubRegion(r_a @ &ty::ReEarlyBound(_),
+                                                  &ty::ReVar(vid_b)) |
+                    ImpliedBound::RegionSubRegion(r_a @ &ty::ReFree(_),
                                                   &ty::ReVar(vid_b)) => {
-                        self.add_given(free_a, vid_b);
+                        self.add_given(r_a, vid_b);
                     }
                     ImpliedBound::RegionSubParam(r_a, param_b) => {
                         self.region_bound_pairs.push((r_a, GenericKind::Param(param_b)));
@@ -876,7 +877,7 @@ fn constrain_call<'b, I: Iterator<Item=&'b hir::Expr>>(&mut self,
         // call occurs.
         //
         // FIXME(#6268) to support nested method calls, should be callee_id
-        let callee_scope = self.tcx.node_extent(call_expr.id);
+        let callee_scope = CodeExtent::Misc(call_expr.id);
         let callee_region = self.tcx.mk_region(ty::ReScope(callee_scope));
 
         debug!("callee_region={:?}", callee_region);
@@ -1029,7 +1030,7 @@ fn constrain_index(&mut self,
         debug!("constrain_index(index_expr=?, indexed_ty={}",
                self.ty_to_string(indexed_ty));
 
-        let r_index_expr = ty::ReScope(self.tcx.node_extent(index_expr.id));
+        let r_index_expr = ty::ReScope(CodeExtent::Misc(index_expr.id));
         if let ty::TyRef(r_ptr, mt) = indexed_ty.sty {
             match mt.ty.sty {
                 ty::TySlice(_) | ty::TyStr => {
@@ -1109,7 +1110,7 @@ fn link_match(&self, discr: &hir::Expr, arms: &[hir::Arm]) {
     /// Computes the guarantors for any ref bindings in a match and
     /// then ensures that the lifetime of the resulting pointer is
     /// linked to the lifetime of its guarantor (if any).
-    fn link_fn_args(&self, body_scope: CodeExtent<'tcx>, args: &[hir::Arg]) {
+    fn link_fn_args(&self, body_scope: CodeExtent, args: &[hir::Arg]) {
         debug!("regionck::link_fn_args(body_scope={:?})", body_scope);
         let mc = &mc::MemCategorizationContext::new(self, &self.region_maps);
         for arg in args {
@@ -1175,7 +1176,7 @@ fn link_autoref(&self,
     /// must outlive `callee_scope`.
     fn link_by_ref(&self,
                    expr: &hir::Expr,
-                   callee_scope: CodeExtent<'tcx>) {
+                   callee_scope: CodeExtent) {
         debug!("link_by_ref(expr={:?}, callee_scope={:?})",
                expr, callee_scope);
         let mc = mc::MemCategorizationContext::new(self, &self.region_maps);
@@ -1613,8 +1614,6 @@ fn type_bound(&self, span: Span, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
     }
 
     fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
-        let param_env = &self.parameter_environment;
-
         debug!("param_bound(param_ty={:?})",
                param_ty);
 
@@ -1622,7 +1621,7 @@ fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
 
         // Add in the default bound of fn body that applies to all in
         // scope type parameters:
-        param_bounds.extend(param_env.implicit_region_bound);
+        param_bounds.extend(self.implicit_region_bound);
 
         VerifyBound::AnyRegion(param_bounds)
     }
@@ -1667,7 +1666,7 @@ fn recursive_type_bound(&self, span: Span, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
         }
 
         let mut regions = ty.regions();
-        regions.retain(|r| !r.is_bound()); // ignore late-bound regions
+        regions.retain(|r| !r.is_late_bound()); // ignore late-bound regions
         bounds.push(VerifyBound::AllRegions(regions));
 
         // remove bounds that must hold, since they are not interesting
index 1887eaef3604438340db63a690356cce992eec59..6895d7386256247d96527d88fa6bb42902c5ea13 100644 (file)
@@ -13,7 +13,6 @@
 use constrained_type_params::{identify_constrained_type_params, Parameter};
 
 use hir::def_id::DefId;
-use middle::region::{CodeExtent};
 use rustc::traits::{self, ObligationCauseCode};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
@@ -117,8 +116,8 @@ fn check_item_well_formed(&mut self, item: &hir::Item) {
                     error_192(tcx, item.span);
                 }
             }
-            hir::ItemFn(.., body_id) => {
-                self.check_item_fn(item, body_id);
+            hir::ItemFn(..) => {
+                self.check_item_fn(item);
             }
             hir::ItemStatic(..) => {
                 self.check_item_type(item);
@@ -160,9 +159,6 @@ fn check_associated_item(&mut self,
                              sig_if_method: Option<&hir::MethodSig>) {
         let code = self.code.clone();
         self.for_id(item_id, span).with_fcx(|fcx, this| {
-            let free_substs = &fcx.parameter_environment.free_substs;
-            let free_id_outlive = fcx.parameter_environment.free_id_outlive;
-
             let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
 
             let (mut implied_bounds, self_ty) = match item.container {
@@ -174,25 +170,26 @@ fn check_associated_item(&mut self,
             match item.kind {
                 ty::AssociatedKind::Const => {
                     let ty = fcx.tcx.type_of(item.def_id);
-                    let ty = fcx.instantiate_type_scheme(span, free_substs, &ty);
+                    let ty = fcx.normalize_associated_types_in(span, &ty);
                     fcx.register_wf_obligation(ty, span, code.clone());
                 }
                 ty::AssociatedKind::Method => {
                     reject_shadowing_type_parameters(fcx.tcx, item.def_id);
                     let method_ty = fcx.tcx.type_of(item.def_id);
-                    let method_ty = fcx.instantiate_type_scheme(span, free_substs, &method_ty);
-                    let predicates = fcx.instantiate_bounds(span, item.def_id, free_substs);
+                    let method_ty = fcx.normalize_associated_types_in(span, &method_ty);
+                    let predicates = fcx.tcx.predicates_of(item.def_id)
+                        .instantiate_identity(fcx.tcx);
+                    let predicates = fcx.normalize_associated_types_in(span, &predicates);
                     let sig = method_ty.fn_sig();
                     this.check_fn_or_method(fcx, span, sig, &predicates,
-                                            free_id_outlive, &mut implied_bounds);
+                                            item.def_id, &mut implied_bounds);
                     let sig_if_method = sig_if_method.expect("bad signature for method");
-                    this.check_method_receiver(fcx, sig_if_method, &item,
-                                               free_id_outlive, self_ty);
+                    this.check_method_receiver(fcx, sig_if_method, &item, self_ty);
                 }
                 ty::AssociatedKind::Type => {
                     if item.defaultness.has_value() {
                         let ty = fcx.tcx.type_of(item.def_id);
-                        let ty = fcx.instantiate_type_scheme(span, free_substs, &ty);
+                        let ty = fcx.normalize_associated_types_in(span, &ty);
                         fcx.register_wf_obligation(ty, span, code.clone());
                     }
                 }
@@ -210,7 +207,7 @@ fn for_item<'tcx>(&self, item: &hir::Item)
     fn for_id<'tcx>(&self, id: ast::NodeId, span: Span)
                     -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
         CheckWfFcxBuilder {
-            inherited: Inherited::build(self.tcx, id),
+            inherited: Inherited::build(self.tcx, self.tcx.hir.local_def_id(id)),
             code: self.code.clone(),
             id: id,
             span: span
@@ -242,9 +239,9 @@ fn check_type_defn<F>(&mut self, item: &hir::Item, all_sized: bool, mut lookup_f
                 }
             }
 
-            let free_substs = &fcx.parameter_environment.free_substs;
             let def_id = fcx.tcx.hir.local_def_id(item.id);
-            let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
+            let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx);
+            let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
             this.check_where_clauses(fcx, item.span, &predicates);
 
             vec![] // no implied bounds in a struct def'n
@@ -320,30 +317,26 @@ fn check_trait(&mut self, item: &hir::Item) {
         }
 
         self.for_item(item).with_fcx(|fcx, this| {
-            let free_substs = &fcx.parameter_environment.free_substs;
-            let predicates = fcx.instantiate_bounds(item.span, trait_def_id, free_substs);
+            let predicates = fcx.tcx.predicates_of(trait_def_id).instantiate_identity(fcx.tcx);
+            let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
             this.check_where_clauses(fcx, item.span, &predicates);
             vec![]
         });
     }
 
-    fn check_item_fn(&mut self,
-                     item: &hir::Item,
-                     body_id: hir::BodyId)
-    {
+    fn check_item_fn(&mut self, item: &hir::Item) {
         self.for_item(item).with_fcx(|fcx, this| {
-            let free_substs = &fcx.parameter_environment.free_substs;
             let def_id = fcx.tcx.hir.local_def_id(item.id);
             let ty = fcx.tcx.type_of(def_id);
-            let item_ty = fcx.instantiate_type_scheme(item.span, free_substs, &ty);
+            let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
             let sig = item_ty.fn_sig();
 
-            let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
+            let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx);
+            let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
 
             let mut implied_bounds = vec![];
-            let free_id_outlive = fcx.tcx.call_site_extent(item.id, body_id.node_id);
             this.check_fn_or_method(fcx, item.span, sig, &predicates,
-                                    Some(free_id_outlive), &mut implied_bounds);
+                                    def_id, &mut implied_bounds);
             implied_bounds
         })
     }
@@ -355,10 +348,7 @@ fn check_item_type(&mut self,
 
         self.for_item(item).with_fcx(|fcx, this| {
             let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id));
-            let item_ty = fcx.instantiate_type_scheme(item.span,
-                                                      &fcx.parameter_environment
-                                                          .free_substs,
-                                                      &ty);
+            let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
 
             fcx.register_wf_obligation(item_ty, item.span, this.code.clone());
 
@@ -374,15 +364,14 @@ fn check_impl(&mut self,
         debug!("check_impl: {:?}", item);
 
         self.for_item(item).with_fcx(|fcx, this| {
-            let free_substs = &fcx.parameter_environment.free_substs;
             let item_def_id = fcx.tcx.hir.local_def_id(item.id);
 
             match *ast_trait_ref {
                 Some(ref ast_trait_ref) => {
                     let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
                     let trait_ref =
-                        fcx.instantiate_type_scheme(
-                            ast_trait_ref.path.span, free_substs, &trait_ref);
+                        fcx.normalize_associated_types_in(
+                            ast_trait_ref.path.span, &trait_ref);
                     let obligations =
                         ty::wf::trait_obligations(fcx,
                                                   fcx.body_id,
@@ -394,12 +383,13 @@ fn check_impl(&mut self,
                 }
                 None => {
                     let self_ty = fcx.tcx.type_of(item_def_id);
-                    let self_ty = fcx.instantiate_type_scheme(item.span, free_substs, &self_ty);
+                    let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty);
                     fcx.register_wf_obligation(self_ty, ast_self_ty.span, this.code.clone());
                 }
             }
 
-            let predicates = fcx.instantiate_bounds(item.span, item_def_id, free_substs);
+            let predicates = fcx.tcx.predicates_of(item_def_id).instantiate_identity(fcx.tcx);
+            let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
             this.check_where_clauses(fcx, item.span, &predicates);
 
             fcx.impl_implied_bounds(item_def_id, item.span)
@@ -429,12 +419,11 @@ fn check_fn_or_method<'fcx, 'tcx>(&mut self,
                                       span: Span,
                                       sig: ty::PolyFnSig<'tcx>,
                                       predicates: &ty::InstantiatedPredicates<'tcx>,
-                                      free_id_outlive: Option<CodeExtent<'tcx>>,
+                                      def_id: DefId,
                                       implied_bounds: &mut Vec<Ty<'tcx>>)
     {
-        let free_substs = &fcx.parameter_environment.free_substs;
-        let sig = fcx.instantiate_type_scheme(span, free_substs, &sig);
-        let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &sig);
+        let sig = fcx.normalize_associated_types_in(span, &sig);
+        let sig = fcx.liberate_late_bound_regions(def_id, &sig);
 
         for input_ty in sig.inputs() {
             fcx.register_wf_obligation(&input_ty, span, self.code.clone());
@@ -453,7 +442,6 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
                                          fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
                                          method_sig: &hir::MethodSig,
                                          method: &ty::AssociatedItem,
-                                         free_id_outlive: Option<CodeExtent<'tcx>>,
                                          self_ty: ty::Ty<'tcx>)
     {
         // check that the type of the method's receiver matches the
@@ -467,10 +455,9 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
 
         let span = method_sig.decl.inputs[0].span;
 
-        let free_substs = &fcx.parameter_environment.free_substs;
         let method_ty = fcx.tcx.type_of(method.def_id);
-        let fty = fcx.instantiate_type_scheme(span, free_substs, &method_ty);
-        let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.fn_sig());
+        let fty = fcx.normalize_associated_types_in(span, &method_ty);
+        let sig = fcx.liberate_late_bound_regions(method.def_id, &fty.fn_sig());
 
         debug!("check_method_receiver: sig={:?}", sig);
 
@@ -485,9 +472,9 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
             }
             ExplicitSelf::ByBox => fcx.tcx.mk_box(self_ty)
         };
-        let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty);
-        let rcvr_ty = fcx.tcx.liberate_late_bound_regions(free_id_outlive,
-                                                          &ty::Binder(rcvr_ty));
+        let rcvr_ty = fcx.normalize_associated_types_in(span, &rcvr_ty);
+        let rcvr_ty = fcx.liberate_late_bound_regions(method.def_id,
+                                                      &ty::Binder(rcvr_ty));
 
         debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
 
@@ -632,10 +619,8 @@ fn struct_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> {
             struct_def.fields().iter()
             .map(|field| {
                 let field_ty = self.tcx.type_of(self.tcx.hir.local_def_id(field.id));
-                let field_ty = self.instantiate_type_scheme(field.span,
-                                                            &self.parameter_environment
-                                                                 .free_substs,
-                                                            &field_ty);
+                let field_ty = self.normalize_associated_types_in(field.span,
+                                                                  &field_ty);
                 AdtField { ty: field_ty, span: field.span }
             })
             .collect();
@@ -649,19 +634,18 @@ fn enum_variants(&self, enum_def: &hir::EnumDef) -> Vec<AdtVariant<'tcx>> {
     }
 
     fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'tcx>> {
-        let free_substs = &self.parameter_environment.free_substs;
         match self.tcx.impl_trait_ref(impl_def_id) {
             Some(ref trait_ref) => {
                 // Trait impl: take implied bounds from all types that
                 // appear in the trait reference.
-                let trait_ref = self.instantiate_type_scheme(span, free_substs, trait_ref);
+                let trait_ref = self.normalize_associated_types_in(span, trait_ref);
                 trait_ref.substs.types().collect()
             }
 
             None => {
                 // Inherent impl: take implied bounds from the self type.
                 let self_ty = self.tcx.type_of(impl_def_id);
-                let self_ty = self.instantiate_type_scheme(span, free_substs, &self_ty);
+                let self_ty = self.normalize_associated_types_in(span, &self_ty);
                 vec![self_ty]
             }
         }
@@ -684,7 +668,7 @@ fn error_392<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, param_name: ast:
                        -> DiagnosticBuilder<'tcx> {
     let mut err = struct_span_err!(tcx.sess, span, E0392,
                   "parameter `{}` is never used", param_name);
-    err.span_label(span, &format!("unused type parameter"));
+    err.span_label(span, "unused type parameter");
     err
 }
 
@@ -692,7 +676,7 @@ fn error_194(tcx: TyCtxt, span: Span, trait_decl_span: Span, name: ast::Name) {
     struct_span_err!(tcx.sess, span, E0194,
               "type parameter `{}` shadows another type parameter of the same name",
               name)
-        .span_label(span, &format!("shadows another type parameter"))
-        .span_label(trait_decl_span, &format!("first `{}` declared here", name))
+        .span_label(span, "shadows another type parameter")
+        .span_label(trait_decl_span, format!("first `{}` declared here", name))
         .emit();
 }
index 49440037af57572f5f6f81fb7d244a32f820dd14..b43e2423757d1faef9df751445363881339760d5 100644 (file)
@@ -19,7 +19,7 @@
 use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee};
 use rustc::ty::adjustment;
 use rustc::ty::fold::{TypeFolder,TypeFoldable};
-use rustc::util::nodemap::{DefIdMap, DefIdSet};
+use rustc::util::nodemap::DefIdSet;
 use syntax::ast;
 use syntax_pos::Span;
 use std::mem;
@@ -71,55 +71,17 @@ struct WritebackCx<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
 
     tables: ty::TypeckTables<'gcx>,
 
-    // Mapping from free regions of the function to the
-    // early-bound versions of them, visible from the
-    // outside of the function. This is needed by, and
-    // only populated if there are any `impl Trait`.
-    free_to_bound_regions: DefIdMap<ty::Region<'gcx>>,
-
     body: &'gcx hir::Body,
 }
 
 impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
     fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, body: &'gcx hir::Body)
         -> WritebackCx<'cx, 'gcx, 'tcx> {
-        let mut wbcx = WritebackCx {
+        WritebackCx {
             fcx: fcx,
             tables: ty::TypeckTables::empty(),
-            free_to_bound_regions: DefIdMap(),
             body: body
-        };
-
-        // Only build the reverse mapping if `impl Trait` is used.
-        if fcx.anon_types.borrow().is_empty() {
-            return wbcx;
         }
-
-        let gcx = fcx.tcx.global_tcx();
-        let free_substs = fcx.parameter_environment.free_substs;
-        for (i, k) in free_substs.iter().enumerate() {
-            let r = if let Some(r) = k.as_region() {
-                r
-            } else {
-                continue;
-            };
-            match *r {
-                ty::ReFree(ty::FreeRegion {
-                    bound_region: ty::BoundRegion::BrNamed(def_id, name), ..
-                }) => {
-                    let bound_region = gcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
-                        index: i as u32,
-                        name: name,
-                    }));
-                    wbcx.free_to_bound_regions.insert(def_id, bound_region);
-                }
-                _ => {
-                    bug!("{:?} is not a free region for an early-bound lifetime", r);
-                }
-            }
-        }
-
-        wbcx
     }
 
     fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> {
@@ -285,22 +247,16 @@ fn visit_anon_types(&mut self) {
             let inside_ty = self.resolve(&concrete_ty, &node_id);
 
             // Convert the type from the function into a type valid outside
-            // the function, by replacing free regions with early-bound ones.
+            // the function, by replacing invalid regions with 'static,
+            // after producing an error for each of them.
             let outside_ty = gcx.fold_regions(&inside_ty, &mut false, |r, _| {
                 match *r {
-                    // 'static is valid everywhere.
-                    ty::ReStatic => gcx.types.re_static,
-                    ty::ReEmpty => gcx.types.re_empty,
-
-                    // Free regions that come from early-bound regions are valid.
-                    ty::ReFree(ty::FreeRegion {
-                        bound_region: ty::BoundRegion::BrNamed(def_id, ..), ..
-                    }) if self.free_to_bound_regions.contains_key(&def_id) => {
-                        self.free_to_bound_regions[&def_id]
-                    }
+                    // 'static and early-bound regions are valid.
+                    ty::ReStatic |
+                    ty::ReEarlyBound(_) |
+                    ty::ReEmpty => r,
 
                     ty::ReFree(_) |
-                    ty::ReEarlyBound(_) |
                     ty::ReLateBound(..) |
                     ty::ReScope(_) |
                     ty::ReSkolemized(..) => {
index 49785d8850f4de72595df5d4eb08904edef7e1d9..556bd618c78cbb22e49b90b503f1daad2577d4a6 100644 (file)
 
 use rustc::traits::{self, ObligationCause, Reveal};
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::ParameterEnvironment;
 use rustc::ty::TypeFoldable;
 use rustc::ty::adjustment::CoerceUnsizedInfo;
-use rustc::ty::subst::Subst;
 use rustc::ty::util::CopyImplementationError;
 use rustc::infer;
 
@@ -74,7 +72,7 @@ fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                          E0120,
                                          "the Drop trait may only be implemented on \
                                          structures")
-                            .span_label(span, &format!("implementing Drop requires a struct"))
+                            .span_label(span, "implementing Drop requires a struct")
                             .emit();
                     }
                     _ => {
@@ -107,8 +105,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            self_type);
 
     let span = tcx.hir.span(impl_node_id);
-    let param_env = ParameterEnvironment::for_item(tcx, impl_node_id);
-    let self_type = self_type.subst(tcx, &param_env.free_substs);
+    let param_env = tcx.parameter_environment(impl_did);
     assert!(!self_type.has_escaping_regions());
 
     debug!("visit_implementation_of_copy: self_type={:?} (free)",
@@ -130,7 +127,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              "the trait `Copy` may not be implemented for this type")
                 .span_label(
                     tcx.def_span(field.did),
-                    &"this field does not implement `Copy`")
+                    "this field does not implement `Copy`")
                 .emit()
         }
         Err(CopyImplementationError::NotAnAdt) => {
@@ -145,7 +142,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              span,
                              E0206,
                              "the trait `Copy` may not be implemented for this type")
-                .span_label(span, &format!("type is not a structure or enumeration"))
+                .span_label(span, "type is not a structure or enumeration")
                 .emit();
         }
         Err(CopyImplementationError::HasDestructor) => {
@@ -154,7 +151,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              E0184,
                              "the trait `Copy` may not be implemented for this type; the \
                               type has a destructor")
-                .span_label(span, &format!("Copy not allowed on types with destructors"))
+                .span_label(span, "Copy not allowed on types with destructors")
                 .emit();
         }
     }
@@ -202,9 +199,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            target);
 
     let span = tcx.hir.span(impl_node_id);
-    let param_env = ParameterEnvironment::for_item(tcx, impl_node_id);
-    let source = source.subst(tcx, &param_env.free_substs);
-    let target = target.subst(tcx, &param_env.free_substs);
+    let param_env = tcx.parameter_environment(impl_did);
     assert!(!source.has_escaping_regions());
 
     let err_info = CoerceUnsizedInfo { custom_kind: None };
@@ -254,6 +249,45 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     return err_info;
                 }
 
+                // Here we are considering a case of converting
+                // `S<P0...Pn>` to S<Q0...Qn>`. As an example, let's imagine a struct `Foo<T, U>`,
+                // which acts like a pointer to `U`, but carries along some extra data of type `T`:
+                //
+                //     struct Foo<T, U> {
+                //         extra: T,
+                //         ptr: *mut U,
+                //     }
+                //
+                // We might have an impl that allows (e.g.) `Foo<T, [i32; 3]>` to be unsized
+                // to `Foo<T, [i32]>`. That impl would look like:
+                //
+                //   impl<T, U: Unsize<V>, V> CoerceUnsized<Foo<T, V>> for Foo<T, U> {}
+                //
+                // Here `U = [i32; 3]` and `V = [i32]`. At runtime,
+                // when this coercion occurs, we would be changing the
+                // field `ptr` from a thin pointer of type `*mut [i32;
+                // 3]` to a fat pointer of type `*mut [i32]` (with
+                // extra data `3`).  **The purpose of this check is to
+                // make sure that we know how to do this conversion.**
+                //
+                // To check if this impl is legal, we would walk down
+                // the fields of `Foo` and consider their types with
+                // both substitutes. We are looking to find that
+                // exactly one (non-phantom) field has changed its
+                // type, which we will expect to be the pointer that
+                // is becoming fat (we could probably generalize this
+                // to mutiple thin pointers of the same type becoming
+                // fat, but we don't). In this case:
+                //
+                // - `extra` has type `T` before and type `T` after
+                // - `ptr` has type `*mut U` before and type `*mut V` after
+                //
+                // Since just one field changed, we would then check
+                // that `*mut U: CoerceUnsized<*mut V>` is implemented
+                // (in other words, that we know how to do this
+                // conversion). This will work out because `U:
+                // Unsize<V>`, and we have a builtin rule that `*mut
+                // U` can be coerced to `*mut V` if `U: Unsize<V>`.
                 let fields = &def_a.struct_variant().fields;
                 let diff_fields = fields.iter()
                     .enumerate()
@@ -265,8 +299,16 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             return None;
                         }
 
-                        // Ignore fields that aren't significantly changed
-                        if let Ok(ok) = infcx.sub_types(false, &cause, b, a) {
+                        // Ignore fields that aren't changed; it may
+                        // be that we could get away with subtyping or
+                        // something more accepting, but we use
+                        // equality because we want to be able to
+                        // perform this check without computing
+                        // variance where possible. (This is because
+                        // we may have to evaluate constraint
+                        // expressions in the course of execution.)
+                        // See e.g. #41936.
+                        if let Ok(ok) = infcx.eq_types(false, &cause, b, a) {
                             if ok.obligations.is_empty() {
                                 return None;
                             }
@@ -310,7 +352,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                           })
                                           .collect::<Vec<_>>()
                                           .join(", ")));
-                    err.span_label(span, &format!("requires multiple coercions"));
+                    err.span_label(span, "requires multiple coercions");
                     err.emit();
                     return err_info;
                 }
index 238952865c7bd91e3525e19fc3e6b5e8e8471c37..f7ebc21044222d28c90c309c62903e235656018c 100644 (file)
@@ -259,7 +259,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                  ty.span,
                                  E0118,
                                  "no base type found for inherent implementation")
-                    .span_label(ty.span, &format!("impl requires a base type"))
+                    .span_label(ty.span, "impl requires a base type")
                     .note(&format!("either implement a trait on it or create a newtype \
                                     to wrap it instead"))
                     .emit();
@@ -296,7 +296,7 @@ fn check_def_id(&mut self, item: &hir::Item, def_id: DefId) {
                              "cannot define inherent `impl` for a type outside of the crate \
                               where the type is defined")
                 .span_label(item.span,
-                            &format!("impl for type defined outside of crate."))
+                            "impl for type defined outside of crate.")
                 .note("define and implement a trait or new type instead")
                 .emit();
         }
index 34aec8ef1ac8c1f8e9961228ecdad38afd357aed..2751e1ff38a5090620344d49ded167658087a8e5 100644 (file)
@@ -56,9 +56,9 @@ enum Namespace {
                                      "duplicate definitions with name `{}`",
                                      name)
                         .span_label(self.tcx.span_of_impl(item1).unwrap(),
-                                    &format!("duplicate definitions for `{}`", name))
+                                    format!("duplicate definitions for `{}`", name))
                         .span_label(self.tcx.span_of_impl(item2).unwrap(),
-                                    &format!("other definition for `{}`", name))
+                                    format!("other definition for `{}`", name))
                         .emit();
                 }
             }
index 56ae9d545751f56c1eae0aed72d6e8592ca70a87..165be49f7603de1d73ff00a03519187585980996 100644 (file)
@@ -46,8 +46,6 @@ fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
         }
 
         enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id);
-        let trait_def = tcx.trait_def(trait_ref.def_id);
-        trait_def.record_local_impl(tcx, impl_def_id, trait_ref);
     }
 }
 
@@ -62,7 +60,7 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_d
                          span,
                          E0322,
                          "explicit impls for the `Sized` trait are not permitted")
-            .span_label(span, &format!("impl of 'Sized' not allowed"))
+            .span_label(span, "impl of 'Sized' not allowed")
             .emit();
         return;
     }
@@ -117,8 +115,6 @@ pub fn provide(providers: &mut Providers) {
 
 fn coherent_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             (_, def_id): (CrateNum, DefId)) {
-    tcx.populate_implementations_for_trait_if_necessary(def_id);
-
     let impls = tcx.hir.trait_impls(def_id);
     for &impl_id in impls {
         check_impl(tcx, impl_id);
index 8ded3003c78eb312fa943f79f6f287d71156b5d8..097720adad447ee15bcee5fa4daf5c6d47345d6c 100644 (file)
@@ -48,7 +48,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                          E0117,
                                          "only traits defined in the current crate can be \
                                           implemented for arbitrary types")
-                            .span_label(item.span, &format!("impl doesn't use types inside crate"))
+                            .span_label(item.span, "impl doesn't use types inside crate")
                             .note(&format!("the impl does not reference any types defined in \
                                             this crate"))
                             .note("define and implement a trait or new type instead")
@@ -153,7 +153,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                      "cannot create default implementations for traits outside \
                                       the crate they're defined in; define a new trait instead")
                         .span_label(item_trait_ref.path.span,
-                                    &format!("`{}` trait not defined in this crate",
+                                    format!("`{}` trait not defined in this crate",
                             self.tcx.hir.node_to_pretty_string(item_trait_ref.ref_id)))
                         .emit();
                     return;
index 383a9e0e69542caeadd47d406d3d3d76f90d69b5..ba1d7b18e8c7faeb29dcc40e41f84cf13426d211 100644 (file)
@@ -41,39 +41,10 @@ pub fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
     let _task =
         tcx.dep_graph.in_task(DepNode::CoherenceOverlapCheck(trait_def_id));
 
-    let def = tcx.trait_def(trait_def_id);
-
-    // attempt to insert into the specialization graph
-    let insert_result = def.add_impl_for_specialization(tcx, impl_def_id);
-
-    // insertion failed due to overlap
-    if let Err(overlap) = insert_result {
-        let mut err = struct_span_err!(tcx.sess,
-                                       tcx.span_of_impl(impl_def_id).unwrap(),
-                                       E0119,
-                                       "conflicting implementations of trait `{}`{}:",
-                                       overlap.trait_desc,
-                                       overlap.self_desc.clone().map_or(String::new(),
-                                                                        |ty| {
-            format!(" for type `{}`", ty)
-        }));
-
-        match tcx.span_of_impl(overlap.with_impl) {
-            Ok(span) => {
-                err.span_label(span, &format!("first implementation here"));
-                err.span_label(tcx.span_of_impl(impl_def_id).unwrap(),
-                               &format!("conflicting implementation{}",
-                                        overlap.self_desc
-                                            .map_or(String::new(),
-                                                    |ty| format!(" for `{}`", ty))));
-            }
-            Err(cname) => {
-                err.note(&format!("conflicting implementation in crate `{}`", cname));
-            }
-        }
+    // Trigger building the specialization graph for the trait of this impl.
+    // This will detect any overlap errors.
+    tcx.specialization_graph_of(trait_def_id);
 
-        err.emit();
-    }
 
     // check for overlap with the automatic `impl Trait for Trait`
     if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty {
index f44f74830cbb99849d144c48585feaa882a2e818..cb1bd3e099d54c31ef6b468cf0cc619a1cb69e4a 100644 (file)
@@ -205,10 +205,6 @@ fn get_type_parameter_bounds(&self,
         self.tcx.at(span).type_param_predicates((self.item_def_id, def_id))
     }
 
-    fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
-        None
-    }
-
     fn re_infer(&self, _span: Span, _def: Option<&ty::RegionParameterDef>)
                 -> Option<ty::Region<'tcx>> {
         None
@@ -220,7 +216,7 @@ fn ty_infer(&self, span: Span) -> Ty<'tcx> {
             span,
             E0121,
             "the type placeholder `_` is not allowed within types on item signatures"
-        ).span_label(span, &format!("not allowed in type signatures"))
+        ).span_label(span, "not allowed in type signatures")
         .emit();
         self.tcx().types.err
     }
@@ -568,7 +564,7 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         } else {
             struct_span_err!(tcx.sess, variant.span, E0370,
                              "enum discriminant overflowed")
-                .span_label(variant.span, &format!("overflowed on value after {}",
+                .span_label(variant.span, format!("overflowed on value after {}",
                                                    prev_discr.unwrap()))
                 .note(&format!("explicitly set `{} = {}` if that is desired outcome",
                                variant.node.name, wrapped_discr))
@@ -604,8 +600,8 @@ fn convert_struct_variant<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             struct_span_err!(tcx.sess, f.span, E0124,
                              "field `{}` is already declared",
                              f.name)
-                .span_label(f.span, &"field already declared")
-                .span_label(prev_span, &format!("`{}` first declared here", f.name))
+                .span_label(f.span, "field already declared")
+                .span_label(prev_span, format!("`{}` first declared here", f.name))
                 .emit();
         } else {
             seen_fields.insert(f.name, f.span);
@@ -753,12 +749,12 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     let def_path_hash = tcx.def_path_hash(def_id);
-    let def = ty::TraitDef::new(def_id, unsafety, paren_sugar, def_path_hash);
-
-    if tcx.hir.trait_is_auto(def_id) {
-        def.record_has_default_impl();
-    }
-
+    let has_default_impl = tcx.hir.trait_is_auto(def_id);
+    let def = ty::TraitDef::new(def_id,
+                                unsafety,
+                                paren_sugar,
+                                has_default_impl,
+                                def_path_hash);
     tcx.alloc_trait_def(def)
 }
 
@@ -1299,6 +1295,7 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut index = parent_count + has_own_self as u32;
     for param in early_bound_lifetimes_from_generics(tcx, ast_generics) {
         let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
+            def_id: tcx.hir.local_def_id(param.lifetime.id),
             index: index,
             name: param.lifetime.name
         }));
index 0f42ee15ecf6fea1110144fa55135cd10dc15f78..f9ebe3fff5beb951478ecbe9f8442cc48b8cf679 100644 (file)
@@ -1524,67 +1524,6 @@ fn get_state(&self) -> String {
 ```
 "##,
 
-E0119: r##"
-There are conflicting trait implementations for the same type.
-Example of erroneous code:
-
-```compile_fail,E0119
-trait MyTrait {
-    fn get(&self) -> usize;
-}
-
-impl<T> MyTrait for T {
-    fn get(&self) -> usize { 0 }
-}
-
-struct Foo {
-    value: usize
-}
-
-impl MyTrait for Foo { // error: conflicting implementations of trait
-                       //        `MyTrait` for type `Foo`
-    fn get(&self) -> usize { self.value }
-}
-```
-
-When looking for the implementation for the trait, the compiler finds
-both the `impl<T> MyTrait for T` where T is all types and the `impl
-MyTrait for Foo`. Since a trait cannot be implemented multiple times,
-this is an error. So, when you write:
-
-```
-trait MyTrait {
-    fn get(&self) -> usize;
-}
-
-impl<T> MyTrait for T {
-    fn get(&self) -> usize { 0 }
-}
-```
-
-This makes the trait implemented on all types in the scope. So if you
-try to implement it on another one after that, the implementations will
-conflict. Example:
-
-```
-trait MyTrait {
-    fn get(&self) -> usize;
-}
-
-impl<T> MyTrait for T {
-    fn get(&self) -> usize { 0 }
-}
-
-struct Foo;
-
-fn main() {
-    let f = Foo;
-
-    f.get(); // the trait is implemented so we can use it
-}
-```
-"##,
-
 E0120: r##"
 An attempt was made to implement Drop on a trait, which is not allowed: only
 structs and enums can implement Drop. An example causing this error:
index 1c44572fbb4af3e828d23e25254788202e710c00..6b4f08d3d4c8d73aca47443d934014ec687f4d07 100644 (file)
@@ -166,7 +166,7 @@ fn report_unused_parameter(tcx: TyCtxt,
         "the {} parameter `{}` is not constrained by the \
         impl trait, self type, or predicates",
         kind, name)
-        .span_label(span, &format!("unconstrained {} parameter", kind))
+        .span_label(span, format!("unconstrained {} parameter", kind))
         .emit();
 }
 
@@ -188,9 +188,9 @@ fn enforce_impl_items_are_distinct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                "duplicate definitions with name `{}`:",
                                                impl_item.name);
                 err.span_label(*entry.get(),
-                               &format!("previous definition of `{}` here",
+                               format!("previous definition of `{}` here",
                                         impl_item.name));
-                err.span_label(impl_item.span, &format!("duplicate definition"));
+                err.span_label(impl_item.span, "duplicate definition");
                 err.emit();
             }
             Vacant(entry) => {
index c1456e7978280cce003fbe8e6f855a36600653f9..99ee1cff7fd22ab9c2883eb49ac6346931c71c89 100644 (file)
@@ -64,7 +64,6 @@
 */
 
 #![crate_name = "rustc_typeck"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 #![feature(never_type)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
@@ -143,7 +144,7 @@ fn require_c_abi_if_variadic(tcx: TyCtxt,
     if decl.variadic && abi != Abi::C {
         let mut err = struct_span_err!(tcx.sess, span, E0045,
                   "variadic function must have C calling convention");
-        err.span_label(span, &("variadics require C calling conventions").to_string())
+        err.span_label(span, "variadics require C calling conventions")
             .emit();
     }
 }
@@ -190,7 +191,7 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 struct_span_err!(tcx.sess, generics.span, E0131,
                                          "main function is not allowed to have type parameters")
                                     .span_label(generics.span,
-                                                &format!("main cannot have type parameters"))
+                                                "main cannot have type parameters")
                                     .emit();
                                 return;
                             }
@@ -240,7 +241,7 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             struct_span_err!(tcx.sess, ps.span, E0132,
                                 "start function is not allowed to have type parameters")
                                 .span_label(ps.span,
-                                            &format!("start function cannot have type parameters"))
+                                            "start function cannot have type parameters")
                                 .emit();
                             return;
                         }
index e986a381cd963df034968e27a66fa463c2a5c2e6..cb2ee7dd1bcda5c7b89bcc4fda7a95e6d543f81c 100644 (file)
@@ -27,7 +27,6 @@
 
 use super::terms::*;
 use super::terms::VarianceTerm::*;
-use super::xform::*;
 
 pub struct ConstraintContext<'a, 'tcx: 'a> {
     pub terms_cx: TermsContext<'a, 'tcx>,
index 507734ce35e44fdcf1695911ac48b7c7190b6293..7106ca4d420a86100bebc22a21d4e64a8f98dd81 100644 (file)
 
 use rustc::ty;
 
-pub trait Xform {
-    fn xform(self, v: Self) -> Self;
-}
-
-impl Xform for ty::Variance {
-    fn xform(self, v: ty::Variance) -> ty::Variance {
-        // "Variance transformation", Figure 1 of The Paper
-        match (self, v) {
-            // Figure 1, column 1.
-            (ty::Covariant, ty::Covariant) => ty::Covariant,
-            (ty::Covariant, ty::Contravariant) => ty::Contravariant,
-            (ty::Covariant, ty::Invariant) => ty::Invariant,
-            (ty::Covariant, ty::Bivariant) => ty::Bivariant,
-
-            // Figure 1, column 2.
-            (ty::Contravariant, ty::Covariant) => ty::Contravariant,
-            (ty::Contravariant, ty::Contravariant) => ty::Covariant,
-            (ty::Contravariant, ty::Invariant) => ty::Invariant,
-            (ty::Contravariant, ty::Bivariant) => ty::Bivariant,
-
-            // Figure 1, column 3.
-            (ty::Invariant, _) => ty::Invariant,
-
-            // Figure 1, column 4.
-            (ty::Bivariant, _) => ty::Bivariant,
-        }
-    }
-}
-
 pub fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance {
     // Greatest lower bound of the variance lattice as
     // defined in The Paper:
index 24d056035ceec541da0eea065acee215154dbd58..61f941e57b2d8c6a61481e6ba7c819d0ded0604d 100644 (file)
@@ -820,7 +820,7 @@ fn clean(&self, _: &DocContext) -> Lifetime {
     }
 }
 
-impl<'tcx> Clean<Option<Lifetime>> for ty::RegionKind<'tcx> {
+impl Clean<Option<Lifetime>> for ty::RegionKind {
     fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
         match *self {
             ty::ReStatic => Some(Lifetime::statik()),
@@ -1180,7 +1180,7 @@ fn clean(&self, cx: &DocContext) -> FnDecl {
         let mut names = if cx.tcx.hir.as_local_node_id(did).is_some() {
             vec![].into_iter()
         } else {
-            cx.tcx.sess.cstore.fn_arg_names(did).into_iter()
+            cx.tcx.fn_arg_names(did).into_iter()
         }.peekable();
         FnDecl {
             output: Return(sig.skip_binder().output().clean(cx)),
index 9e2d85163335c6f066a493070c8b53aa968e2ef0..9a689ed079ee259f8240a652942966c3ddd7ec57 100644 (file)
@@ -19,6 +19,7 @@
 use rustc::hir::map as hir_map;
 use rustc::lint;
 use rustc::util::nodemap::FxHashMap;
+use rustc_trans;
 use rustc_trans::back::link;
 use rustc_resolve as resolve;
 use rustc_metadata::cstore::CStore;
@@ -138,10 +139,11 @@ pub fn run_core(search_paths: SearchPaths,
 
     let dep_graph = DepGraph::new(false);
     let _ignore = dep_graph.in_ignore();
-    let cstore = Rc::new(CStore::new(&dep_graph));
+    let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
         sessopts, &dep_graph, cpath, diagnostic_handler, codemap, cstore.clone()
     );
+    rustc_trans::init(&sess);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
     let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs));
index d78f00497ca557694b44a8f19b82218f382c6342..111ae4ede277a9fb820dd64bb9db956b898180db 100644 (file)
@@ -13,6 +13,7 @@
 use std::io;
 use std::path::Path;
 use std::str;
+use html::markdown::{Markdown, RenderType};
 
 #[derive(Clone)]
 pub struct ExternalHtml{
@@ -28,17 +29,26 @@ pub struct ExternalHtml{
 }
 
 impl ExternalHtml {
-    pub fn load(in_header: &[String], before_content: &[String], after_content: &[String])
+    pub fn load(in_header: &[String], before_content: &[String], after_content: &[String],
+                md_before_content: &[String], md_after_content: &[String], render: RenderType)
             -> Option<ExternalHtml> {
         load_external_files(in_header)
             .and_then(|ih|
                 load_external_files(before_content)
                     .map(|bc| (ih, bc))
             )
+            .and_then(|(ih, bc)|
+                load_external_files(md_before_content)
+                    .map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, render))))
+            )
             .and_then(|(ih, bc)|
                 load_external_files(after_content)
                     .map(|ac| (ih, bc, ac))
             )
+            .and_then(|(ih, bc, ac)|
+                load_external_files(md_after_content)
+                    .map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, render))))
+            )
             .map(|(ih, bc, ac)|
                 ExternalHtml {
                     in_header: ih,
index 0f47265a1aa6630e3620a8da230aff5141b91e87..612793e2567f1c35dbf5bd47684578559e0d8fde 100644 (file)
@@ -687,9 +687,9 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool,
             }
         }
         clean::Vector(ref t) if is_not_debug => {
-            primitive_link(f, PrimitiveType::Slice, &format!("["))?;
+            primitive_link(f, PrimitiveType::Slice, "[")?;
             fmt::Display::fmt(t, f)?;
-            primitive_link(f, PrimitiveType::Slice, &format!("]"))
+            primitive_link(f, PrimitiveType::Slice, "]")
         }
         clean::Vector(ref t) => write!(f, "[{:?}]", t),
         clean::FixedVector(ref t, ref s) if is_not_debug => {
@@ -1177,7 +1177,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let quot = if f.alternate() { "\"" } else { "&quot;" };
         match self.0 {
             Abi::Rust => Ok(()),
-            Abi::C => write!(f, "extern "),
             abi => write!(f, "extern {0}{1}{0} ", quot, abi.name()),
         }
     }
index fbc7615588eed2fe4b820a9d5e30ffe43e2c9e8c..c115a6ccba609b3b0788dc2e9a6e288090985a0f 100644 (file)
                         if (hasClass(main, 'content')) {
                             removeClass(main, 'hidden');
                         }
-                        var search = document.getElementById('search');
-                        if (hasClass(main, 'content')) {
-                            addClass(main, 'hidden');
+                        var search_c = document.getElementById('search');
+                        if (hasClass(search_c, 'content')) {
+                            addClass(search_c, 'hidden');
                         }
                     }
                     // Revert to the previous title manually since the History
                     // perform the search. This will empty the bar if there's
                     // nothing there, which lets you really go back to a
                     // previous state with nothing in the bar.
-                    document.getElementsByClassName('search-input')[0].value = params.search;
+                    if (params.search) {
+                        document.getElementsByClassName('search-input')[0].value = params.search;
+                    } else {
+                        document.getElementsByClassName('search-input')[0].value = '';
+                    }
                     // Some browsers fire 'onpopstate' for every page load
                     // (Chrome), while others fire the event only when actually
                     // popping a state (Firefox), which is why search() is
index ddaa00aa4fb1446c5da00c571e6b2a6e7635359c..570a1980782131131ff3c05dbe52e6ad0fa621a1 100644 (file)
@@ -193,6 +193,7 @@ nav.sub {
        font-size: 17px;
        margin: 30px 0 20px 0;
        text-align: center;
+       word-wrap: break-word;
 }
 
 .location:empty {
@@ -236,6 +237,9 @@ nav.sub {
        overflow: auto;
        padding-left: 0;
 }
+#search {
+       margin-left: 230px;
+}
 .content pre.line-numbers {
        float: left;
        border: none;
@@ -613,6 +617,11 @@ a.test-arrow:hover{
        top: 0;
 }
 
+h3 > .collapse-toggle, h4 > .collapse-toggle {
+       font-size: 0.8em;
+       top: 5px;
+}
+
 .toggle-wrapper > .collapse-toggle {
        left: -24px;
        margin-top: 0px;
index 1156fadf8c02c146dd01b4b5539c067dc67745fb..bbaa7bc2fb65e99492db0f4c85dc1b7575a528f0 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![crate_name = "rustdoc"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(libc)]
-#![feature(rustc_private)]
 #![feature(set_stdio)]
 #![feature(slice_patterns)]
-#![feature(staged_api)]
 #![feature(test)]
 #![feature(unicode)]
 #![feature(vec_remove_item)]
 
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
 extern crate arena;
 extern crate getopts;
 extern crate env_logger;
@@ -159,6 +160,14 @@ pub fn opts() -> Vec<RustcOptGroup> {
                         "files to include inline between the content and </body> of a rendered \
                          Markdown file or generated documentation",
                         "FILES")),
+        unstable(optmulti("", "markdown-before-content",
+                          "files to include inline between <body> and the content of a rendered \
+                           Markdown file or generated documentation",
+                          "FILES")),
+        unstable(optmulti("", "markdown-after-content",
+                          "files to include inline between the content and </body> of a rendered \
+                           Markdown file or generated documentation",
+                          "FILES")),
         stable(optopt("", "markdown-playground-url",
                       "URL to send code snippets to", "URL")),
         stable(optflag("", "markdown-no-toc", "don't include table of contents")),
@@ -274,7 +283,10 @@ pub fn main_args(args: &[String]) -> isize {
     let external_html = match ExternalHtml::load(
             &matches.opt_strs("html-in-header"),
             &matches.opt_strs("html-before-content"),
-            &matches.opt_strs("html-after-content")) {
+            &matches.opt_strs("html-after-content"),
+            &matches.opt_strs("markdown-before-content"),
+            &matches.opt_strs("markdown-after-content"),
+            render_type) {
         Some(eh) => eh,
         None => return 3,
     };
index d5237d629cfc1e7f8f40f2a9c3c9b53c6bdb0825..cfe2fad0fa4695a59d1b840da41c493305086a6c 100644 (file)
@@ -34,6 +34,7 @@
 use rustc_driver::driver::phase_2_configure_and_expand;
 use rustc_metadata::cstore::CStore;
 use rustc_resolve::MakeGlobMap;
+use rustc_trans;
 use rustc_trans::back::link;
 use syntax::ast;
 use syntax::codemap::CodeMap;
@@ -81,10 +82,11 @@ pub fn run(input: &str,
 
     let dep_graph = DepGraph::new(false);
     let _ignore = dep_graph.in_ignore();
-    let cstore = Rc::new(CStore::new(&dep_graph));
+    let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
         sessopts, &dep_graph, Some(input_path.clone()), handler, codemap.clone(), cstore.clone(),
     );
+    rustc_trans::init(&sess);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
     sess.parse_sess.config =
         config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
@@ -229,10 +231,11 @@ fn drop(&mut self) {
     let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter);
 
     let dep_graph = DepGraph::new(false);
-    let cstore = Rc::new(CStore::new(&dep_graph));
+    let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
         sessopts, &dep_graph, None, diagnostic_handler, codemap, cstore.clone(),
     );
+    rustc_trans::init(&sess);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
     let outdir = Mutex::new(TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir"));
index 2b31e2f4108063a7b7f88b1a370317ff3434e2a3..4eb2cad5c91b9178e0d817220aeb6dfce93fca7c 100644 (file)
@@ -15,9 +15,9 @@
 */
 
 #![crate_name = "serialize"]
-#![unstable(feature = "rustc_private",
+#![cfg_attr(stage0, unstable(feature = "rustc_private",
             reason = "deprecated in favor of rustc-serialize on crates.io",
-            issue = "27812")]
+            issue = "27812"))]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -32,7 +32,7 @@
 #![feature(core_intrinsics)]
 #![feature(i128_type)]
 #![feature(specialization)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
 #![cfg_attr(test, feature(test))]
 
 extern crate collections;
index 29f977ecd8c33101c655425c565e6c491a4cf969..44b62593fa3a69add0ce5065004b12fca4098f77 100644 (file)
 /// type is a static guarantee that the underlying bytes contain no interior 0
 /// bytes and the final byte is 0.
 ///
-/// A `CString` is created from either a byte slice or a byte vector. After
-/// being created, a `CString` predominately inherits all of its methods from
-/// the `Deref` implementation to `[c_char]`. Note that the underlying array
-/// is represented as an array of `c_char` as opposed to `u8`. A `u8` slice
-/// can be obtained with the `as_bytes` method.  Slices produced from a `CString`
-/// do *not* contain the trailing nul terminator unless otherwise specified.
+/// A `CString` is created from either a byte slice or a byte vector.  A `u8`
+/// slice can be obtained with the `as_bytes` method.  Slices produced from a
+/// `CString` do *not* contain the trailing nul terminator unless otherwise
+/// specified.
 ///
 /// # Examples
 ///
index 6b1267d89b6d5730246c2f7d0ce6d797ded38968..528d903b8b0187ba155995fb79754ed302ff043e 100644 (file)
@@ -2412,7 +2412,7 @@ fn unicode_path_exists() {
 
         let tmpdir = tmpdir();
         let unicode = tmpdir.path();
-        let unicode = unicode.join(&format!("test-각丁ー再见"));
+        let unicode = unicode.join("test-각丁ー再见");
         check!(fs::create_dir(&unicode));
         assert!(unicode.exists());
         assert!(!Path::new("test/unicode-bogus-path-각丁ー再见").exists());
index e2832873e2e674a83d2e80d67503fd2ff83471ce..c872a8e52611408c64218569acd378e167cbc5cc 100644 (file)
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::util::{copy, sink, Sink, empty, Empty, repeat, Repeat};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use self::stdio::{stdin, stdout, stderr, _print, Stdin, Stdout, Stderr};
+pub use self::stdio::{stdin, stdout, stderr, Stdin, Stdout, Stderr};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::stdio::{StdoutLock, StderrLock, StdinLock};
+#[unstable(feature = "print_internals", issue = "0")]
+pub use self::stdio::{_print, _eprint};
 #[unstable(feature = "libstd_io_internals", issue = "0")]
 #[doc(no_inline, hidden)]
 pub use self::stdio::{set_panic, set_print};
index 38ad23e14b3ebc01a174787c05a06a1b94687094..a8b0bf0071a22465ddc0882d1196715ceed728b7 100644 (file)
@@ -17,7 +17,7 @@
 use sync::{Arc, Mutex, MutexGuard};
 use sys::stdio;
 use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
-use thread::LocalKeyState;
+use thread::{LocalKey, LocalKeyState};
 
 /// Stdout used by print! and println! macros
 thread_local! {
@@ -659,41 +659,56 @@ pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
     })
 }
 
-#[unstable(feature = "print",
-           reason = "implementation detail which may disappear or be replaced at any time",
-           issue = "0")]
-#[doc(hidden)]
-pub fn _print(args: fmt::Arguments) {
-    // As an implementation of the `println!` macro, we want to try our best to
-    // not panic wherever possible and get the output somewhere. There are
-    // currently two possible vectors for panics we take care of here:
-    //
-    // 1. If the TLS key for the local stdout has been destroyed, accessing it
-    //    would cause a panic. Note that we just lump in the uninitialized case
-    //    here for convenience, we're not trying to avoid a panic.
-    // 2. If the local stdout is currently in use (e.g. we're in the middle of
-    //    already printing) then accessing again would cause a panic.
-    //
-    // If, however, the actual I/O causes an error, we do indeed panic.
-    let result = match LOCAL_STDOUT.state() {
+/// Write `args` to output stream `local_s` if possible, `global_s`
+/// otherwise. `label` identifies the stream in a panic message.
+///
+/// This function is used to print error messages, so it takes extra
+/// care to avoid causing a panic when `local_stream` is unusable.
+/// For instance, if the TLS key for the local stream is uninitialized
+/// or already destroyed, or if the local stream is locked by another
+/// thread, it will just fall back to the global stream.
+///
+/// However, if the actual I/O causes an error, this function does panic.
+fn print_to<T>(args: fmt::Arguments,
+               local_s: &'static LocalKey<RefCell<Option<Box<Write+Send>>>>,
+               global_s: fn() -> T,
+               label: &str) where T: Write {
+    let result = match local_s.state() {
         LocalKeyState::Uninitialized |
-        LocalKeyState::Destroyed => stdout().write_fmt(args),
+        LocalKeyState::Destroyed => global_s().write_fmt(args),
         LocalKeyState::Valid => {
-            LOCAL_STDOUT.with(|s| {
+            local_s.with(|s| {
                 if let Ok(mut borrowed) = s.try_borrow_mut() {
                     if let Some(w) = borrowed.as_mut() {
                         return w.write_fmt(args);
                     }
                 }
-                stdout().write_fmt(args)
+                global_s().write_fmt(args)
             })
         }
     };
     if let Err(e) = result {
-        panic!("failed printing to stdout: {}", e);
+        panic!("failed printing to {}: {}", label, e);
     }
 }
 
+#[unstable(feature = "print_internals",
+           reason = "implementation detail which may disappear or be replaced at any time",
+           issue = "0")]
+#[doc(hidden)]
+pub fn _print(args: fmt::Arguments) {
+    print_to(args, &LOCAL_STDOUT, stdout, "stdout");
+}
+
+#[unstable(feature = "print_internals",
+           reason = "implementation detail which may disappear or be replaced at any time",
+           issue = "0")]
+#[doc(hidden)]
+pub fn _eprint(args: fmt::Arguments) {
+    use panicking::LOCAL_STDERR;
+    print_to(args, &LOCAL_STDERR, stderr, "stderr");
+}
+
 #[cfg(test)]
 mod tests {
     use thread;
index a1f092621cb44f506c8e8b2e360e1fe5068f3c32..ef78ea6dfe8ee72c047315f07e3b2be4e96a8739 100644 (file)
@@ -68,6 +68,9 @@ macro_rules! panic {
 /// necessary to use `io::stdout().flush()` to ensure the output is emitted
 /// immediately.
 ///
+/// Use `print!` only for the primary output of your program.  Use
+/// `eprint!` instead to print error and progress messages.
+///
 /// # Panics
 ///
 /// Panics if writing to `io::stdout()` fails.
@@ -105,9 +108,12 @@ macro_rules! print {
 /// Use the `format!` syntax to write data to the standard output.
 /// See `std::fmt` for more information.
 ///
+/// Use `println!` only for the primary output of your program.  Use
+/// `eprintln!` instead to print error and progress messages.
+///
 /// # Panics
 ///
-/// Panics if writing to `io::stdout()` fails.
+/// Panics if writing to `io::stdout` fails.
 ///
 /// # Examples
 ///
@@ -124,6 +130,45 @@ macro_rules! println {
     ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
 }
 
+/// Macro for printing to the standard error.
+///
+/// Equivalent to the `print!` macro, except that output goes to
+/// `io::stderr` instead of `io::stdout`.  See `print!` for
+/// example usage.
+///
+/// Use `eprint!` only for error and progress messages.  Use `print!`
+/// instead for the primary output of your program.
+///
+/// # Panics
+///
+/// Panics if writing to `io::stderr` fails.
+#[macro_export]
+#[stable(feature = "eprint", since="1.18.0")]
+#[allow_internal_unstable]
+macro_rules! eprint {
+    ($($arg:tt)*) => ($crate::io::_eprint(format_args!($($arg)*)));
+}
+
+/// Macro for printing to the standard error, with a newline.
+///
+/// Equivalent to the `println!` macro, except that output goes to
+/// `io::stderr` instead of `io::stdout`.  See `println!` for
+/// example usage.
+///
+/// Use `eprintln!` only for error and progress messages.  Use `println!`
+/// instead for the primary output of your program.
+///
+/// # Panics
+///
+/// Panics if writing to `io::stderr` fails.
+#[macro_export]
+#[stable(feature = "eprint", since="1.18.0")]
+macro_rules! eprintln {
+    () => (eprint!("\n"));
+    ($fmt:expr) => (eprint!(concat!($fmt, "\n")));
+    ($fmt:expr, $($arg:tt)*) => (eprint!(concat!($fmt, "\n"), $($arg)*));
+}
+
 /// A macro to select an event from a number of receivers.
 ///
 /// This macro is used to wait for the first event to occur on a number of
index 9d66430bc93032a59bf5953027646bd9730bc07a..f4b9a8972e3abb93f8dcfbceead1a6096d76d509 100644 (file)
 //! ```
 //! use std::path::PathBuf;
 //!
+//! // This way works...
 //! let mut path = PathBuf::from("c:\\");
+//!
 //! path.push("windows");
 //! path.push("system32");
+//!
 //! path.set_extension("dll");
+//!
+//! // ... but push is best used if you don't know everything up
+//! // front. If you do, this way is better:
+//! let path: PathBuf = ["c:\\", "windows", "system32.dll"].iter().collect();
 //! ```
 //!
 //! [`Component`]: ../../std/path/enum.Component.html
@@ -63,6 +70,7 @@
 //! [`Path`]: ../../std/path/struct.Path.html
 //! [`push`]: ../../std/path/struct.PathBuf.html#method.push
 //! [`String`]: ../../std/string/struct.String.html
+//!
 //! [`str`]: ../../std/primitive.str.html
 //! [`OsString`]: ../../std/ffi/struct.OsString.html
 //! [`OsStr`]: ../../std/ffi/struct.OsStr.html
@@ -1036,14 +1044,40 @@ fn cmp(&self, other: &Components<'a>) -> cmp::Ordering {
 ///
 /// # Examples
 ///
+/// You can use [`push`] to build up a `PathBuf` from
+/// components:
+///
 /// ```
 /// use std::path::PathBuf;
 ///
-/// let mut path = PathBuf::from("c:\\");
+/// let mut path = PathBuf::new();
+///
+/// path.push(r"C:\");
 /// path.push("windows");
 /// path.push("system32");
+///
 /// path.set_extension("dll");
 /// ```
+///
+/// However, [`push`] is best used for dynamic situations. This is a better way
+/// to do this when you know all of the components ahead of time:
+///
+/// ```
+/// use std::path::PathBuf;
+///
+/// let path: PathBuf = [r"C:\", "windows", "system32.dll"].iter().collect();
+/// ```
+///
+/// We can still do better than this! Since these are all strings, we can use
+/// `From::from`:
+///
+/// ```
+/// use std::path::PathBuf;
+///
+/// let path = PathBuf::from(r"C:\windows\system32.dll");
+/// ```
+///
+/// Which method works best depends on what kind of situation you're in.
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct PathBuf {
index 6c791cd336ded6b20ff19a5fb2715cb958f48206..acff7faf8a7d0a853bf3d09e903f360db7c8f721 100644 (file)
@@ -29,8 +29,7 @@
 
 #[cfg(not(test))]
 #[lang = "start"]
-fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
-    use mem;
+fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize {
     use panic;
     use sys;
     use sys_common;
@@ -54,7 +53,9 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
         sys::args::init(argc, argv);
 
         // Let's run some code!
-        let res = panic::catch_unwind(mem::transmute::<_, fn()>(main));
+        let res = panic::catch_unwind(|| {
+            ::sys_common::backtrace::__rust_begin_short_backtrace(main)
+        });
         sys_common::cleanup();
         res.is_err()
     };
index 5e46069cf7ddfb2257eb8d4f5423cb1d153f83fb..1646f8cce72326e05c778bf88933b892479f6695 100644 (file)
@@ -199,7 +199,10 @@ fn clone(&self) -> Self { *self }
 
 pub const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE;
 
+pub const FACILITY_NT_BIT: DWORD = 0x1000_0000;
+
 pub const FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
+pub const FORMAT_MESSAGE_FROM_HMODULE: DWORD = 0x00000800;
 pub const FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;
 
 pub const TLS_OUT_OF_INDEXES: DWORD = 0xFFFFFFFF;
index 253787546c1dc75c3d7340a107b52777eacd4263..3f6c2827a3f937242b2522ccf29904545e6b39d8 100644 (file)
@@ -26,8 +26,22 @@ pub trait OsStringExt {
     /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of
     /// 16-bit code units.
     ///
-    /// This is lossless: calling `.encode_wide()` on the resulting string
+    /// This is lossless: calling [`encode_wide`] on the resulting string
     /// will always return the original code units.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::OsString;
+    /// use std::os::windows::prelude::*;
+    ///
+    /// // UTF-16 encoding for "Unicode".
+    /// let source = [0x0055, 0x006E, 0x0069, 0x0063, 0x006F, 0x0064, 0x0065];
+    ///
+    /// let string = OsString::from_wide(&source[..]);
+    /// ```
+    ///
+    /// [`encode_wide`]: ./trait.OsStrExt.html#tymethod.encode_wide
     #[stable(feature = "rust1", since = "1.0.0")]
     fn from_wide(wide: &[u16]) -> Self;
 }
@@ -42,11 +56,29 @@ fn from_wide(wide: &[u16]) -> OsString {
 /// Windows-specific extensions to `OsStr`.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStrExt {
-    /// Re-encodes an `OsStr` as a wide character sequence,
-    /// i.e. potentially ill-formed UTF-16.
+    /// Re-encodes an `OsStr` as a wide character sequence, i.e. potentially
+    /// ill-formed UTF-16.
+    ///
+    /// This is lossless: calling [`OsString::from_wide`] and then
+    /// `encode_wide` on the result will yield the original code units.
+    /// Note that the encoding does not add a final null terminator.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::OsString;
+    /// use std::os::windows::prelude::*;
+    ///
+    /// // UTF-16 encoding for "Unicode".
+    /// let source = [0x0055, 0x006E, 0x0069, 0x0063, 0x006F, 0x0064, 0x0065];
+    ///
+    /// let string = OsString::from_wide(&source[..]);
+    ///
+    /// let result: Vec<u16> = string.encode_wide().collect();
+    /// assert_eq!(&source[..], &result[..]);
+    /// ```
     ///
-    /// This is lossless. Note that the encoding does not include a final
-    /// null.
+    /// [`OsString::from_wide`]: ./trait.OsStringExt.html#tymethod.from_wide
     #[stable(feature = "rust1", since = "1.0.0")]
     fn encode_wide(&self) -> EncodeWide;
 }
index d6e2fed56be96b1d5b640dacc05aecc73fe2295f..2d00cb38ec4fcb9ba20d85f642c60c1c6140f22d 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Windows-specific extensions for the primitives in `std::fs`
+//! Windows-specific extensions for the primitives in the `std::fs` module.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -18,7 +18,9 @@
 use sys;
 use sys_common::{AsInnerMut, AsInner};
 
-/// Windows-specific extensions to `File`
+/// Windows-specific extensions to [`File`].
+///
+/// [`File`]: ../../../fs/struct.File.html
 #[stable(feature = "file_offset", since = "1.15.0")]
 pub trait FileExt {
     /// Seeks to a given position and reads a number of bytes.
@@ -35,6 +37,24 @@ pub trait FileExt {
     /// Note that similar to `File::read`, it is not an error to return with a
     /// short read. When returning from such a short read, the file pointer is
     /// still updated.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::fs::File;
+    /// use std::os::windows::prelude::*;
+    ///
+    /// # fn foo() -> io::Result<()> {
+    /// let mut file = File::open("foo.txt")?;
+    /// let mut buffer = [0; 10];
+    ///
+    /// // Read 10 bytes, starting 72 bytes from the
+    /// // start of the file.
+    /// file.seek_read(&mut buffer[..], 72)?;
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
 
@@ -52,6 +72,22 @@ pub trait FileExt {
     /// Note that similar to `File::write`, it is not an error to return a
     /// short write. When returning from such a short write, the file pointer
     /// is still updated.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    /// use std::os::windows::prelude::*;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut buffer = File::create("foo.txt")?;
+    ///
+    /// // Write a byte string starting 72 bytes from
+    /// // the start of the file.
+    /// buffer.seek_write(b"some bytes", 72)?;
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
 }
@@ -67,81 +103,94 @@ fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
     }
 }
 
-/// Windows-specific extensions to `OpenOptions`
+/// Windows-specific extensions to [`OpenOptions`].
+///
+/// [`OpenOptions`]: ../../../fs/struct.OpenOptions.html
 #[stable(feature = "open_options_ext", since = "1.10.0")]
 pub trait OpenOptionsExt {
-    /// Overrides the `dwDesiredAccess` argument to the call to `CreateFile`
+    /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`]
     /// with the specified value.
     ///
     /// This will override the `read`, `write`, and `append` flags on the
     /// `OpenOptions` structure. This method provides fine-grained control over
     /// the permissions to read, write and append data, attributes (like hidden
-    /// and system) and extended attributes.
+    /// and system), and extended attributes.
     ///
     /// # Examples
     ///
     /// ```no_run
     /// use std::fs::OpenOptions;
-    /// use std::os::windows::fs::OpenOptionsExt;
+    /// use std::os::windows::prelude::*;
     ///
     /// // Open without read and write permission, for example if you only need
-    /// // to call `stat()` on the file
+    /// // to call `stat` on the file
     /// let file = OpenOptions::new().access_mode(0).open("foo.txt");
     /// ```
+    ///
+    /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
     #[stable(feature = "open_options_ext", since = "1.10.0")]
     fn access_mode(&mut self, access: u32) -> &mut Self;
 
-    /// Overrides the `dwShareMode` argument to the call to `CreateFile` with
+    /// Overrides the `dwShareMode` argument to the call to [`CreateFile`] with
     /// the specified value.
     ///
     /// By default `share_mode` is set to
-    /// `FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE`. Specifying
-    /// less permissions denies others to read from, write to and/or delete the
-    /// file while it is open.
+    /// `FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE`. This allows
+    /// other processes to to read, write, and delete/rename the same file
+    /// while it is open. Removing any of the flags will prevent other
+    /// processes from performing the corresponding operation until the file
+    /// handle is closed.
     ///
     /// # Examples
     ///
     /// ```no_run
     /// use std::fs::OpenOptions;
-    /// use std::os::windows::fs::OpenOptionsExt;
+    /// use std::os::windows::prelude::*;
     ///
     /// // Do not allow others to read or modify this file while we have it open
-    /// // for writing
-    /// let file = OpenOptions::new().write(true)
-    ///                              .share_mode(0)
-    ///                              .open("foo.txt");
+    /// // for writing.
+    /// let file = OpenOptions::new()
+    ///     .write(true)
+    ///     .share_mode(0)
+    ///     .open("foo.txt");
     /// ```
+    ///
+    /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
     #[stable(feature = "open_options_ext", since = "1.10.0")]
     fn share_mode(&mut self, val: u32) -> &mut Self;
 
     /// Sets extra flags for the `dwFileFlags` argument to the call to
-    /// `CreateFile2` (or combines it with `attributes` and `security_qos_flags`
-    /// to set the `dwFlagsAndAttributes` for `CreateFile`).
+    /// [`CreateFile2`] to the specified value (or combines it with
+    /// `attributes` and `security_qos_flags` to set the `dwFlagsAndAttributes`
+    /// for [`CreateFile`]).
     ///
-    /// Custom flags can only set flags, not remove flags set by Rusts options.
-    /// This options overwrites any previously set custom flags.
+    /// Custom flags can only set flags, not remove flags set by Rust's options.
+    /// This option overwrites any previously set custom flags.
     ///
     /// # Examples
     ///
-    /// ```rust,ignore
+    /// ```ignore
     /// extern crate winapi;
+    ///
     /// use std::fs::OpenOptions;
-    /// use std::os::windows::fs::OpenOptionsExt;
-    ///
-    /// let mut options = OpenOptions::new();
-    /// options.create(true).write(true);
-    /// if cfg!(windows) {
-    ///     options.custom_flags(winapi::FILE_FLAG_DELETE_ON_CLOSE);
-    /// }
-    /// let file = options.open("foo.txt");
+    /// use std::os::windows::prelude::*;
+    ///
+    /// let file = OpenOptions::new()
+    ///     .create(true)
+    ///     .write(true)
+    ///     .custom_flags(winapi::FILE_FLAG_DELETE_ON_CLOSE)
+    ///     .open("foo.txt");
     /// ```
+    ///
+    /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
+    /// [`CreateFile2`]: https://msdn.microsoft.com/en-us/library/windows/desktop/hh449422.aspx
     #[stable(feature = "open_options_ext", since = "1.10.0")]
     fn custom_flags(&mut self, flags: u32) -> &mut Self;
 
-    /// Sets the `dwFileAttributes` argument to the call to `CreateFile2` to
+    /// Sets the `dwFileAttributes` argument to the call to [`CreateFile2`] to
     /// the specified value (or combines it with `custom_flags` and
     /// `security_qos_flags` to set the `dwFlagsAndAttributes` for
-    /// `CreateFile`).
+    /// [`CreateFile`]).
     ///
     /// If a _new_ file is created because it does not yet exist and
     /// `.create(true)` or `.create_new(true)` are specified, the new file is
@@ -155,21 +204,52 @@ pub trait OpenOptionsExt {
     ///
     /// # Examples
     ///
-    /// ```rust,ignore
+    /// ```ignore
     /// extern crate winapi;
+    ///
     /// use std::fs::OpenOptions;
-    /// use std::os::windows::fs::OpenOptionsExt;
+    /// use std::os::windows::prelude::*;
     ///
-    /// let file = OpenOptions::new().write(true).create(true)
-    ///                              .attributes(winapi::FILE_ATTRIBUTE_HIDDEN)
-    ///                              .open("foo.txt");
+    /// let file = OpenOptions::new()
+    ///     .write(true)
+    ///     .create(true)
+    ///     .attributes(winapi::FILE_ATTRIBUTE_HIDDEN)
+    ///     .open("foo.txt");
     /// ```
+    ///
+    /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
+    /// [`CreateFile2`]: https://msdn.microsoft.com/en-us/library/windows/desktop/hh449422.aspx
     #[stable(feature = "open_options_ext", since = "1.10.0")]
     fn attributes(&mut self, val: u32) -> &mut Self;
 
-    /// Sets the `dwSecurityQosFlags` argument to the call to `CreateFile2` to
+    /// Sets the `dwSecurityQosFlags` argument to the call to [`CreateFile2`] to
     /// the specified value (or combines it with `custom_flags` and `attributes`
-    /// to set the `dwFlagsAndAttributes` for `CreateFile`).
+    /// to set the `dwFlagsAndAttributes` for [`CreateFile`]).
+    ///
+    /// By default, `security_qos_flags` is set to `SECURITY_ANONYMOUS`. For
+    /// information about possible values, see [Impersonation Levels] on the
+    /// Windows Dev Center site.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::OpenOptions;
+    /// use std::os::windows::prelude::*;
+    ///
+    /// let file = OpenOptions::new()
+    ///     .write(true)
+    ///     .create(true)
+    ///
+    ///     // Sets the flag value to `SecurityIdentification`.
+    ///     .security_qos_flags(1)
+    ///
+    ///     .open("foo.txt");
+    /// ```
+    ///
+    /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
+    /// [`CreateFile2`]: https://msdn.microsoft.com/en-us/library/windows/desktop/hh449422.aspx
+    /// [Impersonation Levels]:
+    ///     https://msdn.microsoft.com/en-us/library/windows/desktop/aa379572.aspx
     #[stable(feature = "open_options_ext", since = "1.10.0")]
     fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions;
 }
@@ -197,35 +277,136 @@ fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions {
     }
 }
 
-/// Extension methods for `fs::Metadata` to access the raw fields contained
+/// Extension methods for [`fs::Metadata`] to access the raw fields contained
 /// within.
+///
+/// The data members that this trait exposes correspond to the members
+/// of the [`BY_HANDLE_FILE_INFORMATION`] structure.
+///
+/// [`fs::Metadata`]: ../../../fs/struct.Metadata.html
+/// [`BY_HANDLE_FILE_INFORMATION`]:
+///     https://msdn.microsoft.com/en-us/library/windows/desktop/aa363788.aspx
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Returns the value of the `dwFileAttributes` field of this metadata.
     ///
     /// This field contains the file system attribute information for a file
-    /// or directory.
+    /// or directory. For possible values and their descriptions, see
+    /// [File Attribute Constants] in the Windows Dev Center.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::fs;
+    /// use std::os::windows::prelude::*;
+    ///
+    /// # fn foo() -> io::Result<()> {
+    /// let metadata = fs::metadata("foo.txt")?;
+    /// let attributes = metadata.file_attributes();
+    /// # Ok(())
+    /// # }
+    /// ```
+    ///
+    /// [File Attribute Constants]:
+    ///     https://msdn.microsoft.com/en-us/library/windows/desktop/gg258117.aspx
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn file_attributes(&self) -> u32;
 
     /// Returns the value of the `ftCreationTime` field of this metadata.
     ///
-    /// The returned 64-bit value represents the number of 100-nanosecond
-    /// intervals since January 1, 1601 (UTC).
+    /// The returned 64-bit value is equivalent to a [`FILETIME`] struct,
+    /// which represents the number of 100-nanosecond intervals since
+    /// January 1, 1601 (UTC). The struct is automatically
+    /// converted to a `u64` value, as that is the recommended way
+    /// to use it.
+    ///
+    /// If the underlying filesystem does not support creation time, the
+    /// returned value is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::fs;
+    /// use std::os::windows::prelude::*;
+    ///
+    /// # fn foo() -> io::Result<()> {
+    /// let metadata = fs::metadata("foo.txt")?;
+    /// let creation_time = metadata.creation_time();
+    /// # Ok(())
+    /// # }
+    /// ```
+    ///
+    /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn creation_time(&self) -> u64;
 
     /// Returns the value of the `ftLastAccessTime` field of this metadata.
     ///
-    /// The returned 64-bit value represents the number of 100-nanosecond
-    /// intervals since January 1, 1601 (UTC).
+    /// The returned 64-bit value is equivalent to a [`FILETIME`] struct,
+    /// which represents the number of 100-nanosecond intervals since
+    /// January 1, 1601 (UTC). The struct is automatically
+    /// converted to a `u64` value, as that is the recommended way
+    /// to use it.
+    ///
+    /// For a file, the value specifies the last time that a file was read
+    /// from or written to. For a directory, the value specifies when
+    /// the directory was created. For both files and directories, the
+    /// specified date is correct, but the time of day is always set to
+    /// midnight.
+    ///
+    /// If the underlying filesystem does not support last access time, the
+    /// returned value is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::fs;
+    /// use std::os::windows::prelude::*;
+    ///
+    /// # fn foo() -> io::Result<()> {
+    /// let metadata = fs::metadata("foo.txt")?;
+    /// let last_access_time = metadata.last_access_time();
+    /// # Ok(())
+    /// # }
+    /// ```
+    ///
+    /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn last_access_time(&self) -> u64;
 
     /// Returns the value of the `ftLastWriteTime` field of this metadata.
     ///
-    /// The returned 64-bit value represents the number of 100-nanosecond
-    /// intervals since January 1, 1601 (UTC).
+    /// The returned 64-bit value is equivalent to a [`FILETIME`] struct,
+    /// which represents the number of 100-nanosecond intervals since
+    /// January 1, 1601 (UTC). The struct is automatically
+    /// converted to a `u64` value, as that is the recommended way
+    /// to use it.
+    ///
+    /// For a file, the value specifies the last time that a file was written
+    /// to. For a directory, the structure specifies when the directory was
+    /// created.
+    ///
+    /// If the underlying filesystem does not support the last write time
+    /// time, the returned value is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::fs;
+    /// use std::os::windows::prelude::*;
+    ///
+    /// # fn foo() -> io::Result<()> {
+    /// let metadata = fs::metadata("foo.txt")?;
+    /// let last_write_time = metadata.last_write_time();
+    /// # Ok(())
+    /// # }
+    /// ```
+    ///
+    /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn last_write_time(&self) -> u64;
 
@@ -233,6 +414,20 @@ pub trait MetadataExt {
     /// metadata.
     ///
     /// The returned value does not have meaning for directories.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::fs;
+    /// use std::os::windows::prelude::*;
+    ///
+    /// # fn foo() -> io::Result<()> {
+    /// let metadata = fs::metadata("foo.txt")?;
+    /// let file_size = metadata.file_size();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn file_size(&self) -> u64;
 }
@@ -253,7 +448,7 @@ fn file_size(&self) -> u64 { self.as_inner().size() }
 ///
 /// # Examples
 ///
-/// ```ignore
+/// ```no_run
 /// use std::os::windows::fs;
 ///
 /// # fn foo() -> std::io::Result<()> {
@@ -274,7 +469,7 @@ pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
 ///
 /// # Examples
 ///
-/// ```ignore
+/// ```no_run
 /// use std::os::windows::fs;
 ///
 /// # fn foo() -> std::io::Result<()> {
index f12e50cc92317d80496a67ecb3bd03fddc2f8a11..11b1337a8aec0b933965d39c9cb1b070ad0a44a5 100644 (file)
@@ -8,11 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Experimental extensions to `std` for Windows.
+//! Platform-specific extensions to `std` for Windows.
 //!
-//! For now, this module is limited to extracting handles, file
-//! descriptors, and sockets, but its functionality will grow over
-//! time.
+//! Provides access to platform-level information for Windows, and exposes
+//! Windows-specific idioms that would otherwise be inappropriate as part
+//! the core `std` library. These extensions allow developers to use
+//! `std` types and idioms with Windows in a way that the normal
+//! platform-agnostic idioms would not normally support.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 7e28dd1e259c8c1551e7f73fc97d2daaecc09501..a51b458451e8623ff3fd397956f276cf6e5e4604 100644 (file)
@@ -32,7 +32,7 @@ pub fn errno() -> i32 {
 }
 
 /// Gets a detailed string description for the given error number.
-pub fn error_string(errnum: i32) -> String {
+pub fn error_string(mut errnum: i32) -> String {
     // This value is calculated from the macro
     // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
     let langId = 0x0800 as c::DWORD;
@@ -40,9 +40,27 @@ pub fn error_string(errnum: i32) -> String {
     let mut buf = [0 as c::WCHAR; 2048];
 
     unsafe {
-        let res = c::FormatMessageW(c::FORMAT_MESSAGE_FROM_SYSTEM |
+        let mut module = ptr::null_mut();
+        let mut flags = 0;
+
+        // NTSTATUS errors may be encoded as HRESULT, which may returned from
+        // GetLastError. For more information about Windows error codes, see
+        // `[MS-ERREF]`: https://msdn.microsoft.com/en-us/library/cc231198.aspx
+        if (errnum & c::FACILITY_NT_BIT as i32) != 0 {
+            // format according to https://support.microsoft.com/en-us/help/259693
+            const NTDLL_DLL: &'static [u16] = &['N' as _, 'T' as _, 'D' as _, 'L' as _, 'L' as _,
+                                                '.' as _, 'D' as _, 'L' as _, 'L' as _, 0];
+            module = c::GetModuleHandleW(NTDLL_DLL.as_ptr());
+
+            if module != ptr::null_mut() {
+                errnum ^= c::FACILITY_NT_BIT as i32;
+                flags = c::FORMAT_MESSAGE_FROM_HMODULE;
+            }
+        }
+
+        let res = c::FormatMessageW(flags | c::FORMAT_MESSAGE_FROM_SYSTEM |
                                         c::FORMAT_MESSAGE_IGNORE_INSERTS,
-                                    ptr::null_mut(),
+                                    module,
                                     errnum as c::DWORD,
                                     langId,
                                     buf.as_mut_ptr(),
@@ -299,3 +317,17 @@ pub fn home_dir() -> Option<PathBuf> {
 pub fn exit(code: i32) -> ! {
     unsafe { c::ExitProcess(code as c::UINT) }
 }
+
+#[cfg(test)]
+mod tests {
+    use io::Error;
+    use sys::c;
+
+    // tests `error_string` above
+    #[test]
+    fn ntstatus_error() {
+        const STATUS_UNSUCCESSFUL: u32 = 0xc000_0001;
+        assert!(!Error::from_raw_os_error((STATUS_UNSUCCESSFUL | c::FACILITY_NT_BIT) as _)
+            .to_string().contains("FormatMessageW() returned error"));
+    }
+}
index 04fe5f78b03ce71bc99654739c2433e14d162d5c..617218fe7a5a6989d64a3d0a0fe0a7396a7883f3 100644 (file)
@@ -93,11 +93,47 @@ fn _print(w: &mut Write, format: PrintFormat) -> io::Result<()> {
     Ok(())
 }
 
-fn filter_frames(_frames: &[Frame],
-                 _format: PrintFormat,
-                 _context: &BacktraceContext) -> (usize, usize)
+/// Returns a number of frames to remove at the beginning and at the end of the
+/// backtrace, according to the backtrace format.
+fn filter_frames(frames: &[Frame],
+                 format: PrintFormat,
+                 context: &BacktraceContext) -> (usize, usize)
 {
-    (0, 0)
+    if format == PrintFormat::Full {
+        return (0, 0);
+    }
+
+    let skipped_before = 0;
+
+    let skipped_after = frames.len() - frames.iter().position(|frame| {
+        let mut is_marker = false;
+        let _ = resolve_symname(*frame, |symname| {
+            if let Some(mangled_symbol_name) = symname {
+                // Use grep to find the concerned functions
+                if mangled_symbol_name.contains("__rust_begin_short_backtrace") {
+                    is_marker = true;
+                }
+            }
+            Ok(())
+        }, context);
+        is_marker
+    }).unwrap_or(frames.len());
+
+    if skipped_before + skipped_after >= frames.len() {
+        // Avoid showing completely empty backtraces
+        return (0, 0);
+    }
+
+    (skipped_before, skipped_after)
+}
+
+
+/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
+#[inline(never)]
+pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
+    where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
+{
+    f()
 }
 
 /// Controls how the backtrace should be formated.
index 79aaf34ce2e0f5d68d18ea134f7cefa4275b20f2..df5e4ef1d886e9f589e413b2ba46d54beb4be1be 100644 (file)
@@ -750,6 +750,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
     }
 }
 
+/// Generates a wide character sequence for potentially ill-formed UTF-16.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
 pub struct EncodeWide<'a> {
index e2b22b1d89f045496e267eed902d2b8e3adf2fe4..c2c6e6cf87dff4ad71fcde7e8f721f342ef3d37c 100644 (file)
 /// A thread local storage key which owns its contents.
 ///
 /// This key uses the fastest possible implementation available to it for the
-/// target platform. It is instantiated with the `thread_local!` macro and the
-/// primary method is the `with` method.
+/// target platform. It is instantiated with the [`thread_local!`] macro and the
+/// primary method is the [`with`] method.
 ///
-/// The `with` method yields a reference to the contained value which cannot be
+/// The [`with`] method yields a reference to the contained value which cannot be
 /// sent across threads or escape the given closure.
 ///
 /// # Initialization and Destruction
 ///
-/// Initialization is dynamically performed on the first call to `with()`
-/// within a thread, and values that implement `Drop` get destructed when a
+/// Initialization is dynamically performed on the first call to [`with`]
+/// within a thread, and values that implement [`Drop`] get destructed when a
 /// thread exits. Some caveats apply, which are explained below.
 ///
 /// # Examples
 /// 3. On macOS, initializing TLS during destruction of other TLS slots can
 ///    sometimes cancel *all* destructors for the current thread, whether or not
 ///    the slots have already had their destructors run or not.
+///
+/// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
+/// [`thread_local!`]: ../../std/macro.thread_local.html
+/// [`Drop`]: ../../std/ops/trait.Drop.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct LocalKey<T: 'static> {
     // This outer `LocalKey<T>` type is what's going to be stored in statics,
@@ -106,7 +110,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-/// Declare a new thread local storage key of type `std::thread::LocalKey`.
+/// Declare a new thread local storage key of type [`std::thread::LocalKey`].
 ///
 /// # Syntax
 ///
@@ -124,8 +128,10 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 /// # fn main() {}
 /// ```
 ///
-/// See [LocalKey documentation](thread/struct.LocalKey.html) for more
+/// See [LocalKey documentation][`std::thread::LocalKey`] for more
 /// information.
+///
+/// [`std::thread::LocalKey`]: ../std/thread/struct.LocalKey.html
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable]
@@ -195,11 +201,13 @@ fn __getit() -> $crate::option::Option<
 #[derive(Debug, Eq, PartialEq, Copy, Clone)]
 pub enum LocalKeyState {
     /// All keys are in this state whenever a thread starts. Keys will
-    /// transition to the `Valid` state once the first call to `with` happens
+    /// transition to the `Valid` state once the first call to [`with`] happens
     /// and the initialization expression succeeds.
     ///
     /// Keys in the `Uninitialized` state will yield a reference to the closure
-    /// passed to `with` so long as the initialization routine does not panic.
+    /// passed to [`with`] so long as the initialization routine does not panic.
+    ///
+    /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
     Uninitialized,
 
     /// Once a key has been accessed successfully, it will enter the `Valid`
@@ -208,7 +216,9 @@ pub enum LocalKeyState {
     /// `Destroyed` state.
     ///
     /// Keys in the `Valid` state will be guaranteed to yield a reference to the
-    /// closure passed to `with`.
+    /// closure passed to [`with`].
+    ///
+    /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
     Valid,
 
     /// When a thread exits, the destructors for keys will be run (if
@@ -216,7 +226,9 @@ pub enum LocalKeyState {
     /// destructor has run, a key is in the `Destroyed` state.
     ///
     /// Keys in the `Destroyed` states will trigger a panic when accessed via
-    /// `with`.
+    /// [`with`].
+    ///
+    /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
     Destroyed,
 }
 
@@ -283,23 +295,26 @@ unsafe fn init(&self, slot: &UnsafeCell<Option<T>>) -> &T {
     /// Query the current state of this key.
     ///
     /// A key is initially in the `Uninitialized` state whenever a thread
-    /// starts. It will remain in this state up until the first call to `with`
+    /// starts. It will remain in this state up until the first call to [`with`]
     /// within a thread has run the initialization expression successfully.
     ///
     /// Once the initialization expression succeeds, the key transitions to the
-    /// `Valid` state which will guarantee that future calls to `with` will
+    /// `Valid` state which will guarantee that future calls to [`with`] will
     /// succeed within the thread.
     ///
     /// When a thread exits, each key will be destroyed in turn, and as keys are
     /// destroyed they will enter the `Destroyed` state just before the
     /// destructor starts to run. Keys may remain in the `Destroyed` state after
     /// destruction has completed. Keys without destructors (e.g. with types
-    /// that are `Copy`), may never enter the `Destroyed` state.
+    /// that are [`Copy`]), may never enter the `Destroyed` state.
     ///
     /// Keys in the `Uninitialized` state can be accessed so long as the
     /// initialization does not panic. Keys in the `Valid` state are guaranteed
     /// to be able to be accessed. Keys in the `Destroyed` state will panic on
-    /// any call to `with`.
+    /// any call to [`with`].
+    ///
+    /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
+    /// [`Copy`]: ../../std/marker/trait.Copy.html
     #[unstable(feature = "thread_local_state",
                reason = "state querying was recently added",
                issue = "27716")]
index 04cd28df4459d09d7dd5389e56e4bc488a47565f..154406a1d8bd78ca29965e9f54f49f4af51fc896 100644 (file)
 //! The [`thread::current`] function is available even for threads not spawned
 //! by the APIs of this module.
 //!
-//! ## Blocking support: park and unpark
-//!
-//! Every thread is equipped with some basic low-level blocking support, via the
-//! [`thread::park`][`park`] function and [`thread::Thread::unpark()`][`unpark`]
-//! method. [`park`] blocks the current thread, which can then be resumed from
-//! another thread by calling the [`unpark`] method on the blocked thread's handle.
-//!
-//! Conceptually, each [`Thread`] handle has an associated token, which is
-//! initially not present:
-//!
-//! * The [`thread::park`][`park`] function blocks the current thread unless or until
-//!   the token is available for its thread handle, at which point it atomically
-//!   consumes the token. It may also return *spuriously*, without consuming the
-//!   token. [`thread::park_timeout`] does the same, but allows specifying a
-//!   maximum time to block the thread for.
-//!
-//! * The [`unpark`] method on a [`Thread`] atomically makes the token available
-//!   if it wasn't already.
-//!
-//! In other words, each [`Thread`] acts a bit like a semaphore with initial count
-//! 0, except that the semaphore is *saturating* (the count cannot go above 1),
-//! and can return spuriously.
-//!
-//! The API is typically used by acquiring a handle to the current thread,
-//! placing that handle in a shared data structure so that other threads can
-//! find it, and then `park`ing. When some desired condition is met, another
-//! thread calls [`unpark`] on the handle.
-//!
-//! The motivation for this design is twofold:
-//!
-//! * It avoids the need to allocate mutexes and condvars when building new
-//!   synchronization primitives; the threads already provide basic blocking/signaling.
-//!
-//! * It can be implemented very efficiently on many platforms.
-//!
 //! ## Thread-local storage
 //!
 //! This module also provides an implementation of thread-local storage for Rust
 // Builder
 ////////////////////////////////////////////////////////////////////////////////
 
-/// Thread configuration. Provides detailed control over the properties
-/// and behavior of new threads.
+/// Thread factory, which can be used in order to configure the properties of
+/// a new thread.
+///
+/// Methods can be chained on it in order to configure it.
+///
+/// The two configurations available are:
+///
+/// - [`name`]: allows to give a name to the thread which is currently
+///   only used in `panic` messages.
+/// - [`stack_size`]: specifies the desired stack size. Note that this can
+///   be overriden by the OS.
+///
+/// If the [`stack_size`] field is not specified, the stack size
+/// will be the `RUST_MIN_STACK` environment variable. If it is
+/// not specified either, a sensible default will be set.
+///
+/// If the [`name`] field is not specified, the thread will not be named.
+///
+/// The [`spawn`] method will take ownership of the builder and create an
+/// [`io::Result`] to the thread handle with the given configuration.
+///
+/// The [`thread::spawn`] free function uses a `Builder` with default
+/// configuration and [`unwrap`]s its return value.
+///
+/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want
+/// to recover from a failure to launch a thread, indeed the free function will
+/// panick where the `Builder` method will return a [`io::Result`].
 ///
 /// # Examples
 ///
 ///
 /// handler.join().unwrap();
 /// ```
+///
+/// [`thread::spawn`]: ../../std/thread/fn.spawn.html
+/// [`stack_size`]: ../../std/thread/struct.Builder.html#method.stack_size
+/// [`name`]: ../../std/thread/struct.Builder.html#method.name
+/// [`spawn`]: ../../std/thread/struct.Builder.html#method.spawn
+/// [`io::Result`]: ../../std/io/type.Result.html
+/// [`unwrap`]: ../../std/result/enum.Result.html#method.unwrap
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Builder {
@@ -308,13 +305,16 @@ pub fn stack_size(mut self, size: usize) -> Builder {
         self
     }
 
-    /// Spawns a new thread, and returns a join handle for it.
+    /// Spawns a new thread by taking ownership of the `Builder`, and returns an
+    /// [`io::Result`] to its [`JoinHandle`].
     ///
-    /// The child thread may outlive the parent (unless the parent thread
+    /// The spawned thread may outlive the caller (unless the caller thread
     /// is the main thread; the whole process is terminated when the main
     /// thread finishes). The join handle can be used to block on
     /// termination of the child thread, including recovering its panics.
     ///
+    /// For a more complete documentation see [`thread::spawn`][`spawn`].
+    ///
     /// # Errors
     ///
     /// Unlike the [`spawn`] free function, this method yields an
@@ -323,6 +323,7 @@ pub fn stack_size(mut self, size: usize) -> Builder {
     ///
     /// [`spawn`]: ../../std/thread/fn.spawn.html
     /// [`io::Result`]: ../../std/io/type.Result.html
+    /// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
     ///
     /// # Examples
     ///
@@ -358,7 +359,9 @@ pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
             }
             unsafe {
                 thread_info::set(imp::guard::current(), their_thread);
-                let try_result = panic::catch_unwind(panic::AssertUnwindSafe(f));
+                let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
+                    ::sys_common::backtrace::__rust_begin_short_backtrace(f)
+                }));
                 *their_packet.get() = Some(try_result);
             }
         };
@@ -387,19 +390,19 @@ pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
 /// panics, [`join`] will return an [`Err`] containing the argument given to
 /// [`panic`].
 ///
+/// This will create a thread using default parameters of [`Builder`], if you
+/// want to specify the stack size or the name of the thread, use this API
+/// instead.
+///
 /// # Panics
 ///
 /// Panics if the OS fails to create a thread; use [`Builder::spawn`]
 /// to recover from such errors.
 ///
-/// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
-/// [`join`]: ../../std/thread/struct.JoinHandle.html#method.join
-/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
-/// [`panic`]: ../../std/macro.panic.html
-/// [`Builder::spawn`]: ../../std/thread/struct.Builder.html#method.spawn
-///
 /// # Examples
 ///
+/// Creating a thread.
+///
 /// ```
 /// use std::thread;
 ///
@@ -409,6 +412,54 @@ pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
 ///
 /// handler.join().unwrap();
 /// ```
+///
+/// As mentioned in the module documentation, threads are usually made to
+/// communicate using [`channels`], here is how it usually looks.
+///
+/// This example also shows how to use `move`, in order to give ownership
+/// of values to a thread.
+///
+/// ```
+/// use std::thread;
+/// use std::sync::mpsc::channel;
+///
+/// let (tx, rx) = channel();
+///
+/// let sender = thread::spawn(move || {
+///     let _ = tx.send("Hello, thread".to_owned());
+/// });
+///
+/// let receiver = thread::spawn(move || {
+///     println!("{}", rx.recv().unwrap());
+/// });
+///
+/// let _ = sender.join();
+/// let _ = receiver.join();
+/// ```
+///
+/// A thread can also return a value through its [`JoinHandle`], you can use
+/// this to make asynchronous computations (futures might be more appropriate
+/// though).
+///
+/// ```
+/// use std::thread;
+///
+/// let computation = thread::spawn(|| {
+///     // Some expensive computation.
+///     42
+/// });
+///
+/// let result = computation.join().unwrap();
+/// println!("{}", result);
+/// ```
+///
+/// [`channels`]: ../../std/sync/mpsc/index.html
+/// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
+/// [`join`]: ../../std/thread/struct.JoinHandle.html#method.join
+/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+/// [`panic`]: ../../std/macro.panic.html
+/// [`Builder::spawn`]: ../../std/thread/struct.Builder.html#method.spawn
+/// [`Builder`]: ../../std/thread/struct.Builder.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn spawn<F, T>(f: F) -> JoinHandle<T> where
     F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
@@ -444,6 +495,23 @@ pub fn current() -> Thread {
 
 /// Cooperatively gives up a timeslice to the OS scheduler.
 ///
+/// This is used when the programmer knows that the thread will have nothing
+/// to do for some time, and thus avoid wasting computing time.
+///
+/// For example when polling on a resource, it is common to check that it is
+/// available, and if not to yield in order to avoid busy waiting.
+///
+/// Thus the pattern of `yield`ing after a failed poll is rather common when
+/// implementing low-level shared resources or synchronization primitives.
+///
+/// However programmers will usualy prefer to use, [`channel`]s, [`Condvar`]s,
+/// [`Mutex`]es or [`join`] for their synchronisation routines, as they avoid
+/// thinking about thread schedulling.
+///
+/// Note that [`channel`]s for example are implemented using this primitive.
+/// Indeed when you call `send` or `recv`, which are blocking, they will yield
+/// if the channel is not available.
+///
 /// # Examples
 ///
 /// ```
@@ -451,6 +519,12 @@ pub fn current() -> Thread {
 ///
 /// thread::yield_now();
 /// ```
+///
+/// [`channel`]: ../../std/sync/mpsc/index.html
+/// [`spawn`]: ../../std/thread/fn.spawn.html
+/// [`join`]: ../../std/thread/struct.JoinHandle.html#method.join
+/// [`Mutex`]: ../../std/sync/struct.Mutex.html
+/// [`Condvar`]: ../../std/sync/struct.Condvar.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn yield_now() {
     imp::Thread::yield_now()
@@ -559,23 +633,72 @@ pub fn sleep(dur: Duration) {
 
 /// Blocks unless or until the current thread's token is made available.
 ///
-/// Every thread is equipped with some basic low-level blocking support, via
-/// the `park()` function and the [`unpark`][unpark] method. These can be
-/// used as a more CPU-efficient implementation of a spinlock.
+/// A call to `park` does not guarantee that the thread will remain parked
+/// forever, and callers should be prepared for this possibility.
+///
+/// # park and unpark
+///
+/// Every thread is equipped with some basic low-level blocking support, via the
+/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`]
+/// method. [`park`] blocks the current thread, which can then be resumed from
+/// another thread by calling the [`unpark`] method on the blocked thread's
+/// handle.
+///
+/// Conceptually, each [`Thread`] handle has an associated token, which is
+/// initially not present:
 ///
-/// [unpark]: struct.Thread.html#method.unpark
+/// * The [`thread::park`][`park`] function blocks the current thread unless or
+///   until the token is available for its thread handle, at which point it
+///   atomically consumes the token. It may also return *spuriously*, without
+///   consuming the token. [`thread::park_timeout`] does the same, but allows
+///   specifying a maximum time to block the thread for.
+///
+/// * The [`unpark`] method on a [`Thread`] atomically makes the token available
+///   if it wasn't already.
+///
+/// In other words, each [`Thread`] acts a bit like a spinlock that can be
+/// locked and unlocked using `park` and `unpark`.
 ///
 /// The API is typically used by acquiring a handle to the current thread,
 /// placing that handle in a shared data structure so that other threads can
-/// find it, and then parking (in a loop with a check for the token actually
-/// being acquired).
+/// find it, and then `park`ing. When some desired condition is met, another
+/// thread calls [`unpark`] on the handle.
 ///
-/// A call to `park` does not guarantee that the thread will remain parked
-/// forever, and callers should be prepared for this possibility.
+/// The motivation for this design is twofold:
+///
+/// * It avoids the need to allocate mutexes and condvars when building new
+///   synchronization primitives; the threads already provide basic
+///   blocking/signaling.
 ///
-/// See the [module documentation][thread] for more detail.
+/// * It can be implemented very efficiently on many platforms.
 ///
-/// [thread]: index.html
+/// # Examples
+///
+/// ```
+/// use std::thread;
+/// use std::time::Duration;
+///
+/// let parked_thread = thread::Builder::new()
+///     .spawn(|| {
+///         println!("Parking thread");
+///         thread::park();
+///         println!("Thread unparked");
+///     })
+///     .unwrap();
+///
+/// // Let some time pass for the thread to be spawned.
+/// thread::sleep(Duration::from_millis(10));
+///
+/// println!("Unpark the thread");
+/// parked_thread.thread().unpark();
+///
+/// parked_thread.join().unwrap();
+/// ```
+///
+/// [`Thread`]: ../../std/thread/struct.Thread.html
+/// [`park`]: ../../std/thread/fn.park.html
+/// [`unpark`]: ../../std/thread/struct.Thread.html#method.unpark
+/// [`thread::park_timeout`]: ../../std/thread/fn.park_timeout.html
 //
 // The implementation currently uses the trivial strategy of a Mutex+Condvar
 // with wakeup flag, which does not actually allow spurious wakeups. In the
@@ -592,21 +715,21 @@ pub fn park() {
     *guard = false;
 }
 
-/// Use [park_timeout].
+/// Use [`park_timeout`].
 ///
 /// Blocks unless or until the current thread's token is made available or
 /// the specified duration has been reached (may wake spuriously).
 ///
-/// The semantics of this function are equivalent to `park()` except that the
-/// thread will be blocked for roughly no longer than `ms`. This method
-/// should not be used for precise timing due to anomalies such as
+/// The semantics of this function are equivalent to [`park`] except
+/// that the thread will be blocked for roughly no longer than `dur`. This
+/// method should not be used for precise timing due to anomalies such as
 /// preemption or platform differences that may not cause the maximum
 /// amount of time waited to be precisely `ms` long.
 ///
-/// See the [module documentation][thread] for more detail.
+/// See the [park documentation][`park`] for more detail.
 ///
-/// [thread]: index.html
-/// [park_timeout]: fn.park_timeout.html
+/// [`park_timeout`]: fn.park_timeout.html
+/// [`park`]: ../../std/thread/fn.park.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_deprecated(since = "1.6.0", reason = "replaced by `std::thread::park_timeout`")]
 pub fn park_timeout_ms(ms: u32) {
@@ -616,13 +739,13 @@ pub fn park_timeout_ms(ms: u32) {
 /// Blocks unless or until the current thread's token is made available or
 /// the specified duration has been reached (may wake spuriously).
 ///
-/// The semantics of this function are equivalent to `park()` except that the
-/// thread will be blocked for roughly no longer than `dur`. This method
-/// should not be used for precise timing due to anomalies such as
+/// The semantics of this function are equivalent to [`park`][park] except
+/// that the thread will be blocked for roughly no longer than `dur`. This
+/// method should not be used for precise timing due to anomalies such as
 /// preemption or platform differences that may not cause the maximum
 /// amount of time waited to be precisely `dur` long.
 ///
-/// See the module doc for more detail.
+/// See the [park dococumentation][park] for more details.
 ///
 /// # Platform behavior
 ///
@@ -647,6 +770,8 @@ pub fn park_timeout_ms(ms: u32) {
 ///     park_timeout(timeout);
 /// }
 /// ```
+///
+/// [park]: fn.park.html
 #[stable(feature = "park_timeout", since = "1.4.0")]
 pub fn park_timeout(dur: Duration) {
     let thread = current();
@@ -728,31 +853,21 @@ struct Inner {
 #[stable(feature = "rust1", since = "1.0.0")]
 /// A handle to a thread.
 ///
-/// You can use it to identify a thread (by name, for example). Most of the
-/// time, there is no need to directly create a `Thread` struct using the
-/// constructor, instead you should use a function like `spawn` to create
-/// new threads, see the docs of [`Builder`] and [`spawn`] for more.
+/// Threads are represented via the `Thread` type, which you can get in one of
+/// two ways:
 ///
-/// # Examples
+/// * By spawning a new thread, e.g. using the [`thread::spawn`][`spawn`]
+///   function, and calling [`thread`][`JoinHandle::thread`] on the
+///   [`JoinHandle`].
+/// * By requesting the current thread, using the [`thread::current`] function.
+///
+/// The [`thread::current`] function is available even for threads not spawned
+/// by the APIs of this module.
+///
+/// There is usualy no need to create a `Thread` struct yourself, one
+/// should instead use a function like `spawn` to create new threads, see the
+/// docs of [`Builder`] and [`spawn`] for more details.
 ///
-/// ```no_run
-/// # // Note that this example isn't executed by default because it causes
-/// # // deadlocks on Windows unfortunately (see #25824)
-/// use std::thread::Builder;
-///
-/// for i in 0..5 {
-///     let thread_name = format!("thread_{}", i);
-///     Builder::new()
-///         .name(thread_name) // Now you can identify which thread panicked
-///                            // thanks to the handle's name
-///         .spawn(move || {
-///             if i == 3 {
-///                  panic!("I'm scared!!!");
-///             }
-///         })
-///         .unwrap();
-/// }
-/// ```
 /// [`Builder`]: ../../std/thread/struct.Builder.html
 /// [`spawn`]: ../../std/thread/fn.spawn.html
 
@@ -778,22 +893,36 @@ pub(crate) fn new(name: Option<String>) -> Thread {
 
     /// Atomically makes the handle's token available if it is not already.
     ///
-    /// See the module doc for more detail.
+    /// Every thread is equipped with some basic low-level blocking support, via
+    /// the [`park`][park] function and the `unpark()` method. These can be
+    /// used as a more CPU-efficient implementation of a spinlock.
+    ///
+    /// See the [park documentation][park] for more details.
     ///
     /// # Examples
     ///
     /// ```
     /// use std::thread;
+    /// use std::time::Duration;
     ///
-    /// let handler = thread::Builder::new()
+    /// let parked_thread = thread::Builder::new()
     ///     .spawn(|| {
-    ///         let thread = thread::current();
-    ///         thread.unpark();
+    ///         println!("Parking thread");
+    ///         thread::park();
+    ///         println!("Thread unparked");
     ///     })
     ///     .unwrap();
     ///
-    /// handler.join().unwrap();
+    /// // Let some time pass for the thread to be spawned.
+    /// thread::sleep(Duration::from_millis(10));
+    ///
+    /// println!("Unpark the thread");
+    /// parked_thread.thread().unpark();
+    ///
+    /// parked_thread.join().unwrap();
     /// ```
+    ///
+    /// [park]: fn.park.html
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unpark(&self) {
         let mut guard = self.inner.lock.lock().unwrap();
index 7e5ab1a54ab3afa16ed4bc5da100d8c8631092b2..d63878a7a7c2442916ca6563937ea414e3180450 100644 (file)
 #![feature(core_char_ext)]
 #![feature(decode_utf8)]
 #![feature(fused)]
+#![feature(fn_traits)]
 #![feature(lang_items)]
 #![feature(staged_api)]
 #![feature(try_from)]
+#![feature(unboxed_closures)]
 
 mod tables;
 mod u_str;
index 770b67acd49efef51e16942aaaf36ce13e505b10..1454168d2d5cc76419a6dd20bdb27f553a705d07 100644 (file)
@@ -26,8 +26,9 @@
 /// [`split_whitespace`]: ../../std/primitive.str.html#method.split_whitespace
 /// [`str`]: ../../std/primitive.str.html
 #[stable(feature = "split_whitespace", since = "1.1.0")]
+#[derive(Clone)]
 pub struct SplitWhitespace<'a> {
-    inner: Filter<Split<'a, fn(char) -> bool>, fn(&&str) -> bool>,
+    inner: Filter<Split<'a, IsWhitespace>, IsNotEmpty>,
 }
 
 /// Methods for Unicode string slices
@@ -44,17 +45,7 @@ pub trait UnicodeStr {
 impl UnicodeStr for str {
     #[inline]
     fn split_whitespace(&self) -> SplitWhitespace {
-        fn is_not_empty(s: &&str) -> bool {
-            !s.is_empty()
-        }
-        let is_not_empty: fn(&&str) -> bool = is_not_empty; // coerce to fn pointer
-
-        fn is_whitespace(c: char) -> bool {
-            c.is_whitespace()
-        }
-        let is_whitespace: fn(char) -> bool = is_whitespace; // coerce to fn pointer
-
-        SplitWhitespace { inner: self.split(is_whitespace).filter(is_not_empty) }
+        SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) }
     }
 
     #[inline]
@@ -139,6 +130,45 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 impl<I> FusedIterator for Utf16Encoder<I>
     where I: FusedIterator<Item = char> {}
 
+#[derive(Clone)]
+struct IsWhitespace;
+
+impl FnOnce<(char, )> for IsWhitespace {
+    type Output = bool;
+
+    #[inline]
+    extern "rust-call" fn call_once(mut self, arg: (char, )) -> bool {
+        self.call_mut(arg)
+    }
+}
+
+impl FnMut<(char, )> for IsWhitespace {
+    #[inline]
+    extern "rust-call" fn call_mut(&mut self, arg: (char, )) -> bool {
+        arg.0.is_whitespace()
+    }
+}
+
+#[derive(Clone)]
+struct IsNotEmpty;
+
+impl<'a, 'b> FnOnce<(&'a &'b str, )> for IsNotEmpty {
+    type Output = bool;
+
+    #[inline]
+    extern "rust-call" fn call_once(mut self, arg: (&&str, )) -> bool {
+        self.call_mut(arg)
+    }
+}
+
+impl<'a, 'b> FnMut<(&'a &'b str, )> for IsNotEmpty {
+    #[inline]
+    extern "rust-call" fn call_mut(&mut self, arg: (&&str, )) -> bool {
+        !arg.0.is_empty()
+    }
+}
+
+
 #[stable(feature = "split_whitespace", since = "1.1.0")]
 impl<'a> Iterator for SplitWhitespace<'a> {
     type Item = &'a str;
index e5bb02fe08230253ddfa15006aa864a9879c0a9d..24ce99208ed11bc9e89cda6408003e12fa3207d2 100644 (file)
@@ -715,7 +715,7 @@ pub fn add_trailing_semicolon(mut self) -> Self {
             StmtKind::Mac(mac) => StmtKind::Mac(mac.map(|(mac, _style, attrs)| {
                 (mac, MacStmtStyle::Semicolon, attrs)
             })),
-            node @ _ => node,
+            node => node,
         };
         self
     }
@@ -1076,16 +1076,16 @@ pub fn is_str(&self) -> bool {
     pub fn is_unsuffixed(&self) -> bool {
         match *self {
             // unsuffixed variants
-            LitKind::Str(..) => true,
-            LitKind::ByteStr(..) => true,
-            LitKind::Byte(..) => true,
-            LitKind::Char(..) => true,
-            LitKind::Int(_, LitIntType::Unsuffixed) => true,
-            LitKind::FloatUnsuffixed(..) => true,
+            LitKind::Str(..) |
+            LitKind::ByteStr(..) |
+            LitKind::Byte(..) |
+            LitKind::Char(..) |
+            LitKind::Int(_, LitIntType::Unsuffixed) |
+            LitKind::FloatUnsuffixed(..) |
             LitKind::Bool(..) => true,
             // suffixed variants
-            LitKind::Int(_, LitIntType::Signed(..)) => false,
-            LitKind::Int(_, LitIntType::Unsigned(..)) => false,
+            LitKind::Int(_, LitIntType::Signed(..)) |
+            LitKind::Int(_, LitIntType::Unsigned(..)) |
             LitKind::Float(..) => false,
         }
     }
index 82492d976276e05d6ed6d758872c48acc17405ee..45f891d8dc56db911f325fd6ff90b4034066e834 100644 (file)
@@ -112,7 +112,7 @@ impl NestedMetaItem {
     /// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem.
     pub fn meta_item(&self) -> Option<&MetaItem> {
         match self.node {
-            NestedMetaItemKind::MetaItem(ref item) => Some(&item),
+            NestedMetaItemKind::MetaItem(ref item) => Some(item),
             _ => None
         }
     }
@@ -120,7 +120,7 @@ pub fn meta_item(&self) -> Option<&MetaItem> {
     /// Returns the Lit if self is a NestedMetaItemKind::Literal.
     pub fn literal(&self) -> Option<&Lit> {
         match self.node {
-            NestedMetaItemKind::Literal(ref lit) => Some(&lit),
+            NestedMetaItemKind::Literal(ref lit) => Some(lit),
             _ => None
         }
     }
@@ -259,7 +259,7 @@ pub fn value_str(&self) -> Option<Symbol> {
         match self.node {
             MetaItemKind::NameValue(ref v) => {
                 match v.node {
-                    LitKind::Str(ref s, _) => Some((*s).clone()),
+                    LitKind::Str(ref s, _) => Some(*s),
                     _ => None,
                 }
             },
@@ -511,8 +511,7 @@ pub fn find_export_name_attr(diag: &Handler, attrs: &[Attribute]) -> Option<Symb
             } else {
                 struct_span_err!(diag, attr.span, E0558,
                                  "export_name attribute has invalid format")
-                    .span_label(attr.span,
-                                &format!("did you mean #[export_name=\"*\"]?"))
+                    .span_label(attr.span, "did you mean #[export_name=\"*\"]?")
                     .emit();
                 None
             }
@@ -1218,9 +1217,10 @@ fn token(&self) -> Token {
                 Token::Literal(token::Lit::Float(symbol), Some(Symbol::intern(ty.ty_to_string())))
             }
             LitKind::FloatUnsuffixed(symbol) => Token::Literal(token::Lit::Float(symbol), None),
-            LitKind::Bool(value) => Token::Ident(Ident::with_empty_ctxt(Symbol::intern(match value {
-                true => "true",
-                false => "false",
+            LitKind::Bool(value) => Token::Ident(Ident::with_empty_ctxt(Symbol::intern(if value {
+                "true"
+            } else {
+                "false"
             }))),
         }
     }
@@ -1262,7 +1262,7 @@ fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F)
 
 impl HasAttrs for Vec<Attribute> {
     fn attrs(&self) -> &[Attribute] {
-        &self
+        self
     }
     fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
         f(self)
@@ -1271,7 +1271,7 @@ fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
 
 impl HasAttrs for ThinVec<Attribute> {
     fn attrs(&self) -> &[Attribute] {
-        &self
+        self
     }
     fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
         f(self.into()).into()
index 8a88ec3a6724fc0df57382592d07b0c5f1c17553..d32c3ec5f46b1f063bbcfa26ebea609d7b158178 100644 (file)
@@ -21,8 +21,8 @@
 pub use syntax_pos::hygiene::{ExpnFormat, ExpnInfo, NameAndSpan};
 pub use self::ExpnFormat::*;
 
-use std::cell::RefCell;
-use std::path::{Path,PathBuf};
+use std::cell::{RefCell, Ref};
+use std::path::{Path, PathBuf};
 use std::rc::Rc;
 
 use std::env;
@@ -103,11 +103,18 @@ fn read_file(&self, path: &Path) -> io::Result<String> {
 //
 
 pub struct CodeMap {
-    pub files: RefCell<Vec<Rc<FileMap>>>,
+    // The `files` field should not be visible outside of libsyntax so that we
+    // can do proper dependency tracking.
+    pub(super) files: RefCell<Vec<Rc<FileMap>>>,
     file_loader: Box<FileLoader>,
     // This is used to apply the file path remapping as specified via
     // -Zremap-path-prefix to all FileMaps allocated within this CodeMap.
     path_mapping: FilePathMapping,
+    // The CodeMap will invoke this callback whenever a specific FileMap is
+    // accessed. The callback starts out as a no-op but when the dependency
+    // graph becomes available later during the compilation process, it is
+    // be replaced with something that notifies the dep-tracking system.
+    dep_tracking_callback: RefCell<Box<Fn(&FileMap)>>,
 }
 
 impl CodeMap {
@@ -116,6 +123,7 @@ pub fn new(path_mapping: FilePathMapping) -> CodeMap {
             files: RefCell::new(Vec::new()),
             file_loader: Box::new(RealFileLoader),
             path_mapping: path_mapping,
+            dep_tracking_callback: RefCell::new(Box::new(|_| {})),
         }
     }
 
@@ -126,6 +134,7 @@ pub fn with_file_loader(file_loader: Box<FileLoader>,
             files: RefCell::new(Vec::new()),
             file_loader: file_loader,
             path_mapping: path_mapping,
+            dep_tracking_callback: RefCell::new(Box::new(|_| {})),
         }
     }
 
@@ -133,6 +142,10 @@ pub fn path_mapping(&self) -> &FilePathMapping {
         &self.path_mapping
     }
 
+    pub fn set_dep_tracking_callback(&self, cb: Box<Fn(&FileMap)>) {
+        *self.dep_tracking_callback.borrow_mut() = cb;
+    }
+
     pub fn file_exists(&self, path: &Path) -> bool {
         self.file_loader.file_exists(path)
     }
@@ -142,6 +155,19 @@ pub fn load_file(&self, path: &Path) -> io::Result<Rc<FileMap>> {
         Ok(self.new_filemap(path.to_str().unwrap().to_string(), src))
     }
 
+    pub fn files(&self) -> Ref<Vec<Rc<FileMap>>> {
+        let files = self.files.borrow();
+        for file in files.iter() {
+            (self.dep_tracking_callback.borrow())(file);
+        }
+        files
+    }
+
+    /// Only use this if you do your own dependency tracking!
+    pub fn files_untracked(&self) -> Ref<Vec<Rc<FileMap>>> {
+        self.files.borrow()
+    }
+
     fn next_start_pos(&self) -> usize {
         let files = self.files.borrow();
         match files.last() {
@@ -170,6 +196,7 @@ pub fn new_filemap(&self, filename: FileName, mut src: String) -> Rc<FileMap> {
         let filemap = Rc::new(FileMap {
             name: filename,
             name_was_remapped: was_remapped,
+            crate_of_origin: 0,
             src: Some(Rc::new(src)),
             start_pos: Pos::from_usize(start_pos),
             end_pos: Pos::from_usize(end_pos),
@@ -204,6 +231,7 @@ pub fn new_filemap_and_lines(&self, filename: &str, src: &str) -> Rc<FileMap> {
     pub fn new_imported_filemap(&self,
                                 filename: FileName,
                                 name_was_remapped: bool,
+                                crate_of_origin: u32,
                                 source_len: usize,
                                 mut file_local_lines: Vec<BytePos>,
                                 mut file_local_multibyte_chars: Vec<MultiByteChar>)
@@ -225,6 +253,7 @@ pub fn new_imported_filemap(&self,
         let filemap = Rc::new(FileMap {
             name: filename,
             name_was_remapped: name_was_remapped,
+            crate_of_origin: crate_of_origin,
             src: None,
             start_pos: start_pos,
             end_pos: end_pos,
@@ -282,6 +311,8 @@ fn lookup_line(&self, pos: BytePos) -> Result<FileMapAndLine, Rc<FileMap>> {
         let files = self.files.borrow();
         let f = (*files)[idx].clone();
 
+        (self.dep_tracking_callback.borrow())(&f);
+
         match f.lookup_line(pos) {
             Some(line) => Ok(FileMapAndLine { fm: f, line: line }),
             None => Err(f)
@@ -454,7 +485,7 @@ pub fn span_until_char(&self, sp: Span, c: char) -> Span {
         match self.span_to_snippet(sp) {
             Ok(snippet) => {
                 let snippet = snippet.split(c).nth(0).unwrap_or("").trim_right();
-                if snippet.len() > 0 && !snippet.contains('\n') {
+                if !snippet.is_empty() && !snippet.contains('\n') {
                     Span { hi: BytePos(sp.lo.0 + snippet.len() as u32), ..sp }
                 } else {
                     sp
@@ -471,6 +502,7 @@ pub fn def_span(&self, sp: Span) -> Span {
     pub fn get_filemap(&self, filename: &str) -> Option<Rc<FileMap>> {
         for fm in self.files.borrow().iter() {
             if filename == fm.name {
+               (self.dep_tracking_callback.borrow())(fm);
                 return Some(fm.clone());
             }
         }
@@ -481,6 +513,7 @@ pub fn get_filemap(&self, filename: &str) -> Option<Rc<FileMap>> {
     pub fn lookup_byte_offset(&self, bpos: BytePos) -> FileMapAndBytePos {
         let idx = self.lookup_filemap_idx(bpos);
         let fm = (*self.files.borrow())[idx].clone();
+        (self.dep_tracking_callback.borrow())(&fm);
         let offset = bpos - fm.start_pos;
         FileMapAndBytePos {fm: fm, pos: offset}
     }
@@ -491,6 +524,8 @@ pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
         let files = self.files.borrow();
         let map = &(*files)[idx];
 
+        (self.dep_tracking_callback.borrow())(map);
+
         // The number of extra bytes due to multibyte chars in the FileMap
         let mut total_extra_bytes = 0;
 
@@ -536,7 +571,7 @@ pub fn lookup_filemap_idx(&self, pos: BytePos) -> usize {
     }
 
     pub fn count_lines(&self) -> usize {
-        self.files.borrow().iter().fold(0, |a, f| a + f.count_lines())
+        self.files().iter().fold(0, |a, f| a + f.count_lines())
     }
 }
 
index ede8a33df6546db821b3681f93758aa362e43a29..2e98c7d962606cf524f7cbd718f008f507591b4e 100644 (file)
@@ -123,7 +123,7 @@ pub fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool {
                 return false;
             }
 
-            let mis = if !is_cfg(&attr) {
+            let mis = if !is_cfg(attr) {
                 return true;
             } else if let Some(mis) = attr.meta_item_list() {
                 mis
@@ -150,7 +150,7 @@ fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) {
         // flag the offending attributes
         for attr in attrs.iter() {
             if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) {
-                let mut err = feature_err(&self.sess,
+                let mut err = feature_err(self.sess,
                                           "stmt_expr_attributes",
                                           attr.span,
                                           GateIssue::Language,
@@ -258,7 +258,7 @@ pub fn configure_stmt(&mut self, stmt: ast::Stmt) -> Option<ast::Stmt> {
     pub fn configure_struct_expr_field(&mut self, field: ast::Field) -> Option<ast::Field> {
         if !self.features.map(|features| features.struct_field_attributes).unwrap_or(true) {
             if !field.attrs.is_empty() {
-                let mut err = feature_err(&self.sess,
+                let mut err = feature_err(self.sess,
                                           "struct_field_attributes",
                                           field.span,
                                           GateIssue::Language,
@@ -290,7 +290,7 @@ fn visit_struct_field_attrs(&mut self, attrs: &[ast::Attribute]) {
         for attr in attrs.iter() {
             if !self.features.map(|features| features.struct_field_attributes).unwrap_or(true) {
                 let mut err = feature_err(
-                    &self.sess,
+                    self.sess,
                     "struct_field_attributes",
                     attr.span,
                     GateIssue::Language,
index fe5cb87ad59b5c89370490754c45576b6bcad900..73aeb40df840064ae0ffd2ea79ee369a9939d498 100644 (file)
@@ -120,7 +120,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
 
         // URLs can be unavoidably longer than the line limit, so we allow them.
         // Allowed format is: `[name]: https://www.rust-lang.org/`
-        let is_url = |l: &str| l.starts_with('[') && l.contains("]:") && l.contains("http");
+        let is_url = |l: &str| l.starts_with("[") && l.contains("]:") && l.contains("http");
 
         if msg.lines().any(|line| line.len() > MAX_DESCRIPTION_WIDTH && !is_url(line)) {
             ecx.span_err(span, &format!(
@@ -177,7 +177,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
             if let Err(e) = output_metadata(ecx,
                                             &target_triple,
                                             &crate_name.name.as_str(),
-                                            &diagnostics) {
+                                            diagnostics) {
                 ecx.span_bug(span, &format!(
                     "error writing metadata for triple `{}` and crate `{}`, error: {}, \
                      cause: {:?}",
@@ -227,7 +227,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
 
     MacEager::items(SmallVector::many(vec![
         P(ast::Item {
-            ident: name.clone(),
+            ident: *name,
             attrs: Vec::new(),
             id: ast::DUMMY_NODE_ID,
             node: ast::ItemKind::Const(
index 1f279cc9c80cdbd8cb339997071f26b5b1d56337..1930f61121bb028113f2dc37d5b037f6ca9f2a47 100644 (file)
@@ -24,6 +24,7 @@
 use symbol::Symbol;
 use util::small_vector::SmallVector;
 
+use std::collections::HashMap;
 use std::path::PathBuf;
 use std::rc::Rc;
 use std::default::Default;
@@ -534,7 +535,7 @@ pub enum SyntaxExtension {
     ///
     /// The `bool` dictates whether the contents of the macro can
     /// directly use `#[unstable]` things (true == yes).
-    NormalTT(Box<TTMacroExpander>, Option<Span>, bool),
+    NormalTT(Box<TTMacroExpander>, Option<(ast::NodeId, Span)>, bool),
 
     /// A function-like syntax extension that has an extra ident before
     /// the block.
@@ -588,6 +589,7 @@ fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
                      -> Result<Option<Rc<SyntaxExtension>>, Determinacy>;
     fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
                      -> Result<Rc<SyntaxExtension>, Determinacy>;
+    fn check_unused_macros(&self);
 }
 
 #[derive(Copy, Clone, Debug)]
@@ -617,6 +619,7 @@ fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _kind: MacroKind,
                      _force: bool) -> Result<Rc<SyntaxExtension>, Determinacy> {
         Err(Determinacy::Determined)
     }
+    fn check_unused_macros(&self) {}
 }
 
 #[derive(Clone)]
@@ -634,8 +637,8 @@ pub struct ExpansionData {
 }
 
 /// One of these is made during expansion and incrementally updated as we go;
-/// when a macro expansion occurs, the resulting nodes have the backtrace()
-/// -> expn_info of their expansion context stored into their span.
+/// when a macro expansion occurs, the resulting nodes have the `backtrace()
+/// -> expn_info` of their expansion context stored into their span.
 pub struct ExtCtxt<'a> {
     pub parse_sess: &'a parse::ParseSess,
     pub ecfg: expand::ExpansionConfig<'a>,
@@ -643,6 +646,7 @@ pub struct ExtCtxt<'a> {
     pub resolver: &'a mut Resolver,
     pub resolve_err_count: usize,
     pub current_expansion: ExpansionData,
+    pub expansions: HashMap<Span, Vec<String>>,
 }
 
 impl<'a> ExtCtxt<'a> {
@@ -662,6 +666,7 @@ pub fn new(parse_sess: &'a parse::ParseSess,
                 module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }),
                 directory_ownership: DirectoryOwnership::Owned,
             },
+            expansions: HashMap::new(),
         }
     }
 
@@ -706,7 +711,7 @@ pub fn expansion_cause(&self) -> Option<Span> {
                 }
                 ctxt = info.call_site.ctxt;
                 last_macro = Some(info.call_site);
-                return Some(());
+                Some(())
             }).is_none() {
                 break
             }
@@ -765,6 +770,15 @@ pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
     pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
         self.parse_sess.span_diagnostic.span_bug(sp, msg);
     }
+    pub fn trace_macros_diag(&self) {
+        for (sp, notes) in self.expansions.iter() {
+            let mut db = self.parse_sess.span_diagnostic.span_note_diag(*sp, "trace_macro");
+            for note in notes {
+                db.note(note);
+            }
+            db.emit();
+        }
+    }
     pub fn bug(&self, msg: &str) -> ! {
         self.parse_sess.span_diagnostic.bug(msg);
     }
@@ -783,11 +797,15 @@ pub fn std_path(&self, components: &[&str]) -> Vec<ast::Ident> {
             v.push(self.ident_of(s));
         }
         v.extend(components.iter().map(|s| self.ident_of(s)));
-        return v
+        v
     }
     pub fn name_of(&self, st: &str) -> ast::Name {
         Symbol::intern(st)
     }
+
+    pub fn check_unused_macros(&self) {
+        self.resolver.check_unused_macros();
+    }
 }
 
 /// Extract a string literal from the macro expanded version of `expr`,
index e811afffb2a5ee11b2354c863222aee7ffbc0bc0..25e0aed220ab3fb036e5fb37b890b95bb448d671 100644 (file)
@@ -231,7 +231,7 @@ pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
             },
             _ => unreachable!(),
         };
-
+        self.cx.trace_macros_diag();
         krate
     }
 
@@ -415,19 +415,19 @@ fn expand_attr_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
 
         match *ext {
             MultiModifier(ref mac) => {
-                let meta = panictry!(attr.parse_meta(&self.cx.parse_sess));
+                let meta = panictry!(attr.parse_meta(self.cx.parse_sess));
                 let item = mac.expand(self.cx, attr.span, &meta, item);
                 kind.expect_from_annotatables(item)
             }
             MultiDecorator(ref mac) => {
                 let mut items = Vec::new();
-                let meta = panictry!(attr.parse_meta(&self.cx.parse_sess));
+                let meta = panictry!(attr.parse_meta(self.cx.parse_sess));
                 mac.expand(self.cx, attr.span, &meta, &item, &mut |item| items.push(item));
                 items.push(item);
                 kind.expect_from_annotatables(items)
             }
             SyntaxExtension::AttrProcMacro(ref mac) => {
-                let item_toks = stream_for_item(&item, &self.cx.parse_sess);
+                let item_toks = stream_for_item(&item, self.cx.parse_sess);
 
                 let span = Span { ctxt: self.cx.backtrace(), ..attr.span };
                 let tok_result = mac.expand(self.cx, attr.span, attr.tokens, item_toks);
@@ -439,7 +439,7 @@ fn expand_attr_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
             }
             _ => {
                 let msg = &format!("macro `{}` may not be used in attributes", attr.path);
-                self.cx.span_err(attr.span, &msg);
+                self.cx.span_err(attr.span, msg);
                 kind.dummy(attr.span)
             }
         }
@@ -454,7 +454,7 @@ fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
         };
         let path = &mac.node.path;
 
-        let ident = ident.unwrap_or(keywords::Invalid.ident());
+        let ident = ident.unwrap_or_else(|| keywords::Invalid.ident());
         let marked_tts = noop_fold_tts(mac.node.stream(), &mut Marker(mark));
         let opt_expanded = match *ext {
             NormalTT(ref expandfun, exp_span, allow_internal_unstable) => {
@@ -469,7 +469,7 @@ fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
                     call_site: span,
                     callee: NameAndSpan {
                         format: MacroBang(Symbol::intern(&format!("{}", path))),
-                        span: exp_span,
+                        span: exp_span.map(|(_, s)| s),
                         allow_internal_unstable: allow_internal_unstable,
                     },
                 });
@@ -591,7 +591,7 @@ fn expand_derive_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -
             }
             _ => {
                 let msg = &format!("macro `{}` may not be used for derive attributes", attr.path);
-                self.cx.span_err(span, &msg);
+                self.cx.span_err(span, msg);
                 kind.dummy(span)
             }
         }
@@ -749,19 +749,15 @@ fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
     fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
         let features = self.cx.ecfg.features.unwrap();
         for attr in attrs.iter() {
-            feature_gate::check_attribute(&attr, &self.cx.parse_sess, features);
+            feature_gate::check_attribute(attr, self.cx.parse_sess, features);
         }
     }
 }
 
 pub fn find_attr_invoc(attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
-    for i in 0 .. attrs.len() {
-        if !attr::is_known(&attrs[i]) && !is_builtin_attr(&attrs[i]) {
-             return Some(attrs.remove(i));
-        }
-    }
-
-    None
+    attrs.iter()
+         .position(|a| !attr::is_known(a) && !is_builtin_attr(a))
+         .map(|i| attrs.remove(i))
 }
 
 // These are pretty nasty. Ideally, we would keep the tokens around, linked from
@@ -923,7 +919,7 @@ fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
                 let result = noop_fold_item(item, self);
                 self.cx.current_expansion.module = orig_module;
                 self.cx.current_expansion.directory_ownership = orig_directory_ownership;
-                return result;
+                result
             }
             // Ensure that test functions are accessible from the test harness.
             ast::ItemKind::Fn(..) if self.cx.ecfg.should_test => {
index d7a85baa3fff56b127eefdea5fcd24be5aa7a677..f8fac847a053ef63c68e00b8ca7bcb7d4c4f2ebd 100644 (file)
@@ -23,7 +23,7 @@
 ///
 /// This is registered as a set of expression syntax extension called quote!
 /// that lifts its argument token-tree to an AST representing the
-/// construction of the same token tree, with token::SubstNt interpreted
+/// construction of the same token tree, with `token::SubstNt` interpreted
 /// as antiquotes (splices).
 
 pub mod rt {
@@ -389,7 +389,7 @@ pub fn unflatten(tts: Vec<TokenTree>) -> Vec<TokenTree> {
                 result = results.pop().unwrap();
                 result.push(tree);
             }
-            tree @ _ => result.push(tree),
+            tree => result.push(tree),
         }
     }
     result
@@ -612,8 +612,11 @@ fn mk_delim(cx: &ExtCtxt, sp: Span, delim: token::DelimToken) -> P<ast::Expr> {
 #[allow(non_upper_case_globals)]
 fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
     macro_rules! mk_lit {
-        ($name: expr, $suffix: expr, $($args: expr),*) => {{
-            let inner = cx.expr_call(sp, mk_token_path(cx, sp, $name), vec![$($args),*]);
+        ($name: expr, $suffix: expr, $content: expr $(, $count: expr)*) => {{
+            let name = mk_name(cx, sp, ast::Ident::with_empty_ctxt($content));
+            let inner = cx.expr_call(sp, mk_token_path(cx, sp, $name), vec![
+                name $(, cx.expr_usize(sp, $count))*
+            ]);
             let suffix = match $suffix {
                 Some(name) => cx.expr_some(sp, mk_name(cx, sp, ast::Ident::with_empty_ctxt(name))),
                 None => cx.expr_none(sp)
@@ -621,7 +624,8 @@ macro_rules! mk_lit {
             cx.expr_call(sp, mk_token_path(cx, sp, "Literal"), vec![inner, suffix])
         }}
     }
-    match *tok {
+
+    let name = match *tok {
         token::BinOp(binop) => {
             return cx.expr_call(sp, mk_token_path(cx, sp, "BinOp"), vec![mk_binop(cx, sp, binop)]);
         }
@@ -639,34 +643,14 @@ macro_rules! mk_lit {
                                 vec![mk_delim(cx, sp, delim)]);
         }
 
-        token::Literal(token::Byte(i), suf) => {
-            let e_byte = mk_name(cx, sp, ast::Ident::with_empty_ctxt(i));
-            return mk_lit!("Byte", suf, e_byte);
-        }
-
-        token::Literal(token::Char(i), suf) => {
-            let e_char = mk_name(cx, sp, ast::Ident::with_empty_ctxt(i));
-            return mk_lit!("Char", suf, e_char);
-        }
-
-        token::Literal(token::Integer(i), suf) => {
-            let e_int = mk_name(cx, sp, ast::Ident::with_empty_ctxt(i));
-            return mk_lit!("Integer", suf, e_int);
-        }
-
-        token::Literal(token::Float(fident), suf) => {
-            let e_fident = mk_name(cx, sp, ast::Ident::with_empty_ctxt(fident));
-            return mk_lit!("Float", suf, e_fident);
-        }
-
-        token::Literal(token::Str_(ident), suf) => {
-            return mk_lit!("Str_", suf, mk_name(cx, sp, ast::Ident::with_empty_ctxt(ident)))
-        }
-
-        token::Literal(token::StrRaw(ident, n), suf) => {
-            return mk_lit!("StrRaw", suf, mk_name(cx, sp, ast::Ident::with_empty_ctxt(ident)),
-                           cx.expr_usize(sp, n))
-        }
+        token::Literal(token::Byte(i), suf) => return mk_lit!("Byte", suf, i),
+        token::Literal(token::Char(i), suf) => return mk_lit!("Char", suf, i),
+        token::Literal(token::Integer(i), suf) => return mk_lit!("Integer", suf, i),
+        token::Literal(token::Float(i), suf) => return mk_lit!("Float", suf, i),
+        token::Literal(token::Str_(i), suf) => return mk_lit!("Str_", suf, i),
+        token::Literal(token::StrRaw(i, n), suf) => return mk_lit!("StrRaw", suf, i, n),
+        token::Literal(token::ByteStr(i), suf) => return mk_lit!("ByteStr", suf, i),
+        token::Literal(token::ByteStrRaw(i, n), suf) => return mk_lit!("ByteStrRaw", suf, i, n),
 
         token::Ident(ident) => {
             return cx.expr_call(sp,
@@ -688,10 +672,6 @@ macro_rules! mk_lit {
 
         token::Interpolated(_) => panic!("quote! with interpolated token"),
 
-        _ => ()
-    }
-
-    let name = match *tok {
         token::Eq           => "Eq",
         token::Lt           => "Lt",
         token::Le           => "Le",
@@ -706,6 +686,7 @@ macro_rules! mk_lit {
         token::At           => "At",
         token::Dot          => "Dot",
         token::DotDot       => "DotDot",
+        token::DotDotDot    => "DotDotDot",
         token::Comma        => "Comma",
         token::Semi         => "Semi",
         token::Colon        => "Colon",
@@ -718,7 +699,10 @@ macro_rules! mk_lit {
         token::Question     => "Question",
         token::Underscore   => "Underscore",
         token::Eof          => "Eof",
-        _                   => panic!("unhandled token in quote!"),
+
+        token::Whitespace | token::SubstNt(_) | token::Comment | token::Shebang(_) => {
+            panic!("unhandled token in quote!");
+        }
     };
     mk_token_path(cx, sp, name)
 }
index fc557a78dda0d3f0456532889ec5deeae43d9ba9..3cdd3a4b2c31d8a313c863cde1311e5b1a5c8a17 100644 (file)
@@ -150,7 +150,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenT
             cx.span_err(sp,
                         &format!("{} wasn't a utf-8 file",
                                 file.display()));
-            return DummyResult::expr(sp);
+            DummyResult::expr(sp)
         }
     }
 }
@@ -167,7 +167,7 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::Toke
         Err(e) => {
             cx.span_err(sp,
                         &format!("couldn't read {}: {}", file.display(), e));
-            return DummyResult::expr(sp);
+            DummyResult::expr(sp)
         }
         Ok(..) => {
             // Add this input file to the code map to make it available as
index eb0b7c29f8d9ad8d74aa15a283c7b12f5ea1c608..bf66aa0f00bed42409ffbdc7ffe8cc3341d2a787 100644 (file)
 //! repetitions indicated by Kleene stars. It only advances or calls out to the
 //! real Rust parser when no `cur_eis` items remain
 //!
-//! Example: Start parsing `a a a a b` against [· a $( a )* a b].
+//! Example:
 //!
-//! Remaining input: `a a a a b`
+//! ```text, ignore
+//! Start parsing a a a a b against [· a $( a )* a b].
+//!
+//! Remaining input: a a a a b
 //! next_eis: [· a $( a )* a b]
 //!
-//! - - - Advance over an `a`. - - -
+//! - - - Advance over an a. - - -
 //!
-//! Remaining input: `a a a b`
+//! Remaining input: a a a b
 //! cur: [a · $( a )* a b]
 //! Descend/Skip (first item).
 //! next: [a $( · a )* a b]  [a $( a )* · a b].
 //!
-//! - - - Advance over an `a`. - - -
+//! - - - Advance over an a. - - -
 //!
-//! Remaining input: `a a b`
+//! Remaining input: a a b
 //! cur: [a $( a · )* a b]  next: [a $( a )* a · b]
 //! Finish/Repeat (first item)
 //! next: [a $( a )* · a b]  [a $( · a )* a b]  [a $( a )* a · b]
 //!
-//! - - - Advance over an `a`. - - - (this looks exactly like the last step)
+//! - - - Advance over an a. - - - (this looks exactly like the last step)
 //!
-//! Remaining input: `a b`
+//! Remaining input: a b
 //! cur: [a $( a · )* a b]  next: [a $( a )* a · b]
 //! Finish/Repeat (first item)
 //! next: [a $( a )* · a b]  [a $( · a )* a b]  [a $( a )* a · b]
 //!
-//! - - - Advance over an `a`. - - - (this looks exactly like the last step)
+//! - - - Advance over an a. - - - (this looks exactly like the last step)
 //!
-//! Remaining input: `b`
+//! Remaining input: b
 //! cur: [a $( a · )* a b]  next: [a $( a )* a · b]
 //! Finish/Repeat (first item)
 //! next: [a $( a )* · a b]  [a $( · a )* a b]
 //!
-//! - - - Advance over a `b`. - - -
+//! - - - Advance over a b. - - -
 //!
-//! Remaining input: ``
+//! Remaining input: ''
 //! eof: [a $( a )* a b ·]
+//! ```
 
 pub use self::NamedMatch::*;
 pub use self::ParseResult::*;
@@ -178,20 +182,20 @@ fn initial_matcher_pos(ms: Vec<TokenTree>, lo: BytePos) -> Box<MatcherPos> {
     })
 }
 
-/// NamedMatch is a pattern-match result for a single token::MATCH_NONTERMINAL:
+/// `NamedMatch` is a pattern-match result for a single `token::MATCH_NONTERMINAL`:
 /// so it is associated with a single ident in a parse, and all
-/// `MatchedNonterminal`s in the NamedMatch have the same nonterminal type
-/// (expr, item, etc). Each leaf in a single NamedMatch corresponds to a
-/// single token::MATCH_NONTERMINAL in the TokenTree that produced it.
+/// `MatchedNonterminal`s in the `NamedMatch` have the same nonterminal type
+/// (expr, item, etc). Each leaf in a single `NamedMatch` corresponds to a
+/// single `token::MATCH_NONTERMINAL` in the `TokenTree` that produced it.
 ///
-/// The in-memory structure of a particular NamedMatch represents the match
+/// The in-memory structure of a particular `NamedMatch` represents the match
 /// that occurred when a particular subset of a matcher was applied to a
 /// particular token tree.
 ///
-/// The width of each MatchedSeq in the NamedMatch, and the identity of the
-/// `MatchedNonterminal`s, will depend on the token tree it was applied to:
-/// each MatchedSeq corresponds to a single TTSeq in the originating
-/// token tree. The depth of the NamedMatch structure will therefore depend
+/// The width of each `MatchedSeq` in the `NamedMatch`, and the identity of
+/// the `MatchedNonterminal`s, will depend on the token tree it was applied
+/// to: each `MatchedSeq` corresponds to a single `TTSeq` in the originating
+/// token tree. The depth of the `NamedMatch` structure will therefore depend
 /// only on the nesting depth of `ast::TTSeq`s in the originating
 /// token tree it was derived from.
 
@@ -267,11 +271,12 @@ pub fn parse_failure_msg(tok: Token) -> String {
 
 /// Perform a token equality check, ignoring syntax context (that is, an unhygienic comparison)
 fn token_name_eq(t1 : &Token, t2 : &Token) -> bool {
-    match (t1,t2) {
-        (&token::Ident(id1),&token::Ident(id2))
-        | (&token::Lifetime(id1),&token::Lifetime(id2)) =>
-            id1.name == id2.name,
-        _ => *t1 == *t2
+    if let (Some(id1), Some(id2)) = (t1.ident(), t2.ident()) {
+        id1.name == id2.name
+    } else if let (&token::Lifetime(id1), &token::Lifetime(id2)) = (t1, t2) {
+        id1.name == id2.name
+    } else {
+        *t1 == *t2
     }
 }
 
@@ -334,7 +339,7 @@ fn inner_parse_loop(sess: &ParseSess,
                 // Check if we need a separator
                 if idx == len && ei.sep.is_some() {
                     // We have a separator, and it is the current token.
-                    if ei.sep.as_ref().map(|ref sep| token_name_eq(&token, sep)).unwrap_or(false) {
+                    if ei.sep.as_ref().map(|sep| token_name_eq(token, sep)).unwrap_or(false) {
                         ei.idx += 1;
                         next_eis.push(ei);
                     }
@@ -401,7 +406,7 @@ fn inner_parse_loop(sess: &ParseSess,
                     cur_eis.push(ei);
                 }
                 TokenTree::Token(_, ref t) => {
-                    if token_name_eq(t, &token) {
+                    if token_name_eq(t, token) {
                         ei.idx += 1;
                         next_eis.push(ei);
                     }
@@ -485,11 +490,8 @@ pub fn parse(sess: &ParseSess, tts: TokenStream, ms: &[TokenTree], directory: Op
 }
 
 fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
-    match name {
-        "tt" => {
-            return token::NtTT(p.parse_token_tree());
-        }
-        _ => {}
+    if name == "tt" {
+        return token::NtTT(p.parse_token_tree());
     }
     // check at the beginning and the parser checks after each bump
     p.process_potential_macro_variable();
index be979960725a91cfe6c7786ee0eb1d9150b9c2fb..a208f530602a5f0b05677e27c261e29971871e78 100644 (file)
@@ -27,8 +27,8 @@
 use tokenstream::{TokenStream, TokenTree};
 
 use std::cell::RefCell;
-use std::collections::{HashMap};
-use std::collections::hash_map::{Entry};
+use std::collections::HashMap;
+use std::collections::hash_map::Entry;
 use std::rc::Rc;
 
 pub struct ParserAnyMacro<'a> {
@@ -85,7 +85,7 @@ fn expand<'cx>(&self,
 }
 
 /// Given `lhses` and `rhses`, this is the new macro we create
-fn generic_extension<'cx>(cx: &'cx ExtCtxt,
+fn generic_extension<'cx>(cx: &'cx mut ExtCtxt,
                           sp: Span,
                           name: ast::Ident,
                           arg: TokenStream,
@@ -93,7 +93,9 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
                           rhses: &[quoted::TokenTree])
                           -> Box<MacResult+'cx> {
     if cx.trace_macros() {
-        println!("{}! {{ {} }}", name, arg);
+        let sp = sp.macro_backtrace().last().map(|trace| trace.call_site).unwrap_or(sp);
+        let mut values: &mut Vec<String> = cx.expansions.entry(sp).or_insert_with(Vec::new);
+        values.push(format!("expands to `{}! {{ {} }}`", name, arg));
     }
 
     // Which arm's failure should we report? (the one furthest along)
@@ -204,7 +206,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
     let mut valid = true;
 
     // Extract the arguments:
-    let lhses = match **argument_map.get(&lhs_nm).unwrap() {
+    let lhses = match *argument_map[&lhs_nm] {
         MatchedSeq(ref s, _) => {
             s.iter().map(|m| {
                 if let MatchedNonterminal(ref nt) = **m {
@@ -220,7 +222,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
         _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs")
     };
 
-    let rhses = match **argument_map.get(&rhs_nm).unwrap() {
+    let rhses = match *argument_map[&rhs_nm] {
         MatchedSeq(ref s, _) => {
             s.iter().map(|m| {
                 if let MatchedNonterminal(ref nt) = **m {
@@ -250,7 +252,9 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
         valid: valid,
     });
 
-    NormalTT(exp, Some(def.span), attr::contains_name(&def.attrs, "allow_internal_unstable"))
+    NormalTT(exp,
+             Some((def.id, def.span)),
+             attr::contains_name(&def.attrs, "allow_internal_unstable"))
 }
 
 fn check_lhs_nt_follows(sess: &ParseSess,
@@ -258,13 +262,12 @@ fn check_lhs_nt_follows(sess: &ParseSess,
                         lhs: &quoted::TokenTree) -> bool {
     // lhs is going to be like TokenTree::Delimited(...), where the
     // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
-    match lhs {
-        &quoted::TokenTree::Delimited(_, ref tts) => check_matcher(sess, features, &tts.tts),
-        _ => {
-            let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
-            sess.span_diagnostic.span_err(lhs.span(), msg);
-            false
-        }
+    if let quoted::TokenTree::Delimited(_, ref tts) = *lhs {
+        check_matcher(sess, features, &tts.tts)
+    } else {
+        let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
+        sess.span_diagnostic.span_err(lhs.span(), msg);
+        false
     }
     // we don't abort on errors on rejection, the driver will do that for us
     // after parsing/expansion. we can report every error in every macro this way.
@@ -281,17 +284,15 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool {
                 return false;
             },
             TokenTree::Sequence(span, ref seq) => {
-                if seq.separator.is_none() {
-                    if seq.tts.iter().all(|seq_tt| {
-                        match *seq_tt {
-                            TokenTree::Sequence(_, ref sub_seq) =>
-                                sub_seq.op == quoted::KleeneOp::ZeroOrMore,
-                            _ => false,
-                        }
-                    }) {
-                        sess.span_diagnostic.span_err(span, "repetition matches empty token tree");
-                        return false;
+                if seq.separator.is_none() && seq.tts.iter().all(|seq_tt| {
+                    match *seq_tt {
+                        TokenTree::Sequence(_, ref sub_seq) =>
+                            sub_seq.op == quoted::KleeneOp::ZeroOrMore,
+                        _ => false,
                     }
+                }) {
+                    sess.span_diagnostic.span_err(span, "repetition matches empty token tree");
+                    return false;
                 }
                 if !check_lhs_no_empty_seq(sess, &seq.tts) {
                     return false;
@@ -405,7 +406,7 @@ fn build_recur(sets: &mut FirstSets, tts: &[TokenTree]) -> TokenSet {
                 }
             }
 
-            return first;
+            first
         }
     }
 
@@ -467,7 +468,7 @@ fn first(&self, tts: &[quoted::TokenTree]) -> TokenSet {
         // we only exit the loop if `tts` was empty or if every
         // element of `tts` matches the empty sequence.
         assert!(first.maybe_empty);
-        return first;
+        first
     }
 }
 
@@ -577,7 +578,7 @@ fn check_matcher_core(sess: &ParseSess,
         let build_suffix_first = || {
             let mut s = first_sets.first(suffix);
             if s.maybe_empty { s.add_all(follow); }
-            return s;
+            s
         };
 
         // (we build `suffix_first` on demand below; you can tell
@@ -859,6 +860,7 @@ fn quoted_tt_to_string(tt: &quoted::TokenTree) -> String {
     match *tt {
         quoted::TokenTree::Token(_, ref tok) => ::print::pprust::token_to_string(tok),
         quoted::TokenTree::MetaVarDecl(_, name, kind) => format!("${}:{}", name, kind),
-        _ => panic!("unexpected quoted::TokenTree::{Sequence or Delimited} in follow set checker"),
+        _ => panic!("unexpected quoted::TokenTree::{{Sequence or Delimited}} \
+                     in follow set checker"),
     }
 }
index d216effbd450812502d4a1c675cb933474f6ab9c..fa65e9501c2bb793aa34c64956aaff717bb4227d 100644 (file)
@@ -96,6 +96,17 @@ pub fn len(&self) -> usize {
         }
     }
 
+    pub fn is_empty(&self) -> bool {
+        match *self {
+            TokenTree::Delimited(_, ref delimed) => match delimed.delim {
+                token::NoDelim => delimed.tts.is_empty(),
+                _ => false,
+            },
+            TokenTree::Sequence(_, ref seq) => seq.tts.is_empty(),
+            _ => true,
+        }
+    }
+
     pub fn get_tt(&self, index: usize) -> TokenTree {
         match (self, index) {
             (&TokenTree::Delimited(_, ref delimed), _) if delimed.delim == token::NoDelim => {
@@ -144,9 +155,9 @@ pub fn parse(input: tokenstream::TokenStream, expect_matchers: bool, sess: &Pars
                             }
                             _ => end_sp,
                         },
-                        tree @ _ => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(span),
+                        tree => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(span),
                     },
-                    tree @ _ => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(start_sp),
+                    tree => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(start_sp),
                 };
                 sess.missing_fragment_specifiers.borrow_mut().insert(span);
                 result.push(TokenTree::MetaVarDecl(span, ident, keywords::Invalid.ident()));
@@ -228,10 +239,10 @@ fn kleene_op(token: &token::Token) -> Option<KleeneOp> {
                     Some(op) => return (Some(tok), op),
                     None => span,
                 },
-                tree @ _ => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(span),
+                tree => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(span),
             }
         },
-        tree @ _ => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(span),
+        tree => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(span),
     };
 
     sess.span_diagnostic.span_err(span, "expected `*` or `+`");
index 947089b0b9ac4b977686c26603f47b06664545f9..2a435bdea107f2d11d2bf22a0f20005dc0f589aa 100644 (file)
@@ -121,20 +121,20 @@ pub fn transcribe(sp_diag: &Handler,
                                          &repeats) {
                     LockstepIterSize::Unconstrained => {
                         panic!(sp_diag.span_fatal(
-                            sp.clone(), /* blame macro writer */
+                            sp, /* blame macro writer */
                             "attempted to repeat an expression \
                              containing no syntax \
                              variables matched as repeating at this depth"));
                     }
                     LockstepIterSize::Contradiction(ref msg) => {
                         // FIXME #2887 blame macro invoker instead
-                        panic!(sp_diag.span_fatal(sp.clone(), &msg[..]));
+                        panic!(sp_diag.span_fatal(sp, &msg[..]));
                     }
                     LockstepIterSize::Constraint(len, _) => {
                         if len == 0 {
                             if seq.op == quoted::KleeneOp::OneOrMore {
                                 // FIXME #2887 blame invoker
-                                panic!(sp_diag.span_fatal(sp.clone(),
+                                panic!(sp_diag.span_fatal(sp,
                                                           "this must repeat at least once"));
                             }
                         } else {
index b6a2c983fd4d7fb687abc39bea3ea65ddb14a844..09090ab87313087ac393082c21f6f95a0c335a83 100644 (file)
@@ -472,7 +472,7 @@ pub enum Stability {
 impl ::std::fmt::Debug for AttributeGate {
     fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
         match *self {
-            Gated(ref stab, ref name, ref expl, _) =>
+            Gated(ref stab, name, expl, _) =>
                 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
             Ungated => write!(fmt, "Ungated")
         }
@@ -816,7 +816,7 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
 ];
 
 // cfg(...)'s that are feature gated
-const GATED_CFGS: &'static [(&'static str, &'static str, fn(&Features) -> bool)] = &[
+const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
     // (name in cfg, feature, function to check if the feature is enabled)
     ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
     ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
@@ -881,7 +881,7 @@ fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
         let name = unwrap_or!(attr.name(), return).as_str();
         for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
             if name == n {
-                if let &Gated(_, ref name, ref desc, ref has_feature) = gateage {
+                if let Gated(_, name, desc, ref has_feature) = *gateage {
                     gate_feature_fn!(self, has_feature, attr.span, name, desc);
                 }
                 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
@@ -1098,7 +1098,7 @@ fn contains_novel_literal(item: &ast::MetaItem) -> bool {
         NameValue(ref lit) => !lit.node.is_str(),
         List(ref list) => list.iter().any(|li| {
             match li.node {
-                MetaItem(ref mi) => contains_novel_literal(&mi),
+                MetaItem(ref mi) => contains_novel_literal(mi),
                 Literal(_) => true,
             }
         }),
@@ -1120,7 +1120,7 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
             return
         }
 
-        let meta = panictry!(attr.parse_meta(&self.context.parse_sess));
+        let meta = panictry!(attr.parse_meta(self.context.parse_sess));
         if contains_novel_literal(&meta) {
             gate_feature_post!(&self, attr_literals, attr.span,
                                "non-string literals in attributes, or string \
@@ -1216,14 +1216,11 @@ fn visit_item(&mut self, i: &'a ast::Item) {
             }
 
             ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
-                match polarity {
-                    ast::ImplPolarity::Negative => {
-                        gate_feature_post!(&self, optin_builtin_traits,
-                                           i.span,
-                                           "negative trait bounds are not yet fully implemented; \
-                                            use marker types for now");
-                    },
-                    _ => {}
+                if polarity == ast::ImplPolarity::Negative {
+                    gate_feature_post!(&self, optin_builtin_traits,
+                                       i.span,
+                                       "negative trait bounds are not yet fully implemented; \
+                                        use marker types for now");
                 }
 
                 if let ast::Defaultness::Default = defaultness {
@@ -1272,11 +1269,9 @@ fn visit_ty(&mut self, ty: &'a ast::Ty) {
 
     fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
         if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
-            match output_ty.node {
-                ast::TyKind::Never => return,
-                _ => (),
-            };
-            self.visit_ty(output_ty)
+            if output_ty.node != ast::TyKind::Never {
+                self.visit_ty(output_ty)
+            }
         }
     }
 
@@ -1373,17 +1368,14 @@ fn visit_fn(&mut self,
                 span: Span,
                 _node_id: NodeId) {
         // check for const fn declarations
-        match fn_kind {
-            FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) => {
-                gate_feature_post!(&self, const_fn, span, "const fn is unstable");
-            }
-            _ => {
-                // stability of const fn methods are covered in
-                // visit_trait_item and visit_impl_item below; this is
-                // because default methods don't pass through this
-                // point.
-            }
+        if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
+            fn_kind {
+            gate_feature_post!(&self, const_fn, span, "const fn is unstable");
         }
+        // stability of const fn methods are covered in
+        // visit_trait_item and visit_impl_item below; this is
+        // because default methods don't pass through this
+        // point.
 
         match fn_kind {
             FnKind::ItemFn(_, _, _, _, abi, _, _) |
index 0271ddbccbf38a75248ed418b39d4065511ba2bb..f37dcfdde8985f7594b3381e8e7cf4e57a2a889f 100644 (file)
@@ -22,9 +22,8 @@
 use codemap::{CodeMap, FilePathMapping};
 use syntax_pos::{self, MacroBacktrace, Span, SpanLabel, MultiSpan};
 use errors::registry::Registry;
-use errors::{Level, DiagnosticBuilder, SubDiagnostic, RenderSpan, CodeSuggestion, CodeMapper};
+use errors::{DiagnosticBuilder, SubDiagnostic, RenderSpan, CodeSuggestion, CodeMapper};
 use errors::emitter::Emitter;
-use errors::snippet::Style;
 
 use std::rc::Rc;
 use std::io::{self, Write};
@@ -154,23 +153,26 @@ impl Diagnostic {
     fn from_diagnostic_builder(db: &DiagnosticBuilder,
                                je: &JsonEmitter)
                                -> Diagnostic {
-        let sugg = db.suggestion.as_ref().map(|sugg| {
-            SubDiagnostic {
-                level: Level::Help,
-                message: vec![(sugg.msg.clone(), Style::NoStyle)],
-                span: MultiSpan::new(),
-                render_span: Some(RenderSpan::Suggestion(sugg.clone())),
-            }
+        let sugg = db.suggestions.iter().flat_map(|sugg| {
+            je.render(sugg).into_iter().map(move |rendered| {
+                Diagnostic {
+                    message: sugg.msg.clone(),
+                    code: None,
+                    level: "help",
+                    spans: DiagnosticSpan::from_suggestion(sugg, je),
+                    children: vec![],
+                    rendered: Some(rendered),
+                }
+            })
         });
-        let sugg = sugg.as_ref();
         Diagnostic {
             message: db.message(),
             code: DiagnosticCode::map_opt_string(db.code.clone(), je),
             level: db.level.to_str(),
             spans: DiagnosticSpan::from_multispan(&db.span, je),
-            children: db.children.iter().chain(sugg).map(|c| {
+            children: db.children.iter().map(|c| {
                 Diagnostic::from_sub_diagnostic(c, je)
-            }).collect(),
+            }).chain(sugg).collect(),
             rendered: None,
         }
     }
@@ -184,8 +186,7 @@ fn from_sub_diagnostic(db: &SubDiagnostic, je: &JsonEmitter) -> Diagnostic {
                      .map(|sp| DiagnosticSpan::from_render_span(sp, je))
                      .unwrap_or_else(|| DiagnosticSpan::from_multispan(&db.span, je)),
             children: vec![],
-            rendered: db.render_span.as_ref()
-                                    .and_then(|rsp| je.render(rsp)),
+            rendered: None,
         }
     }
 }
@@ -278,14 +279,19 @@ fn from_multispan(msp: &MultiSpan, je: &JsonEmitter) -> Vec<DiagnosticSpan> {
 
     fn from_suggestion(suggestion: &CodeSuggestion, je: &JsonEmitter)
                        -> Vec<DiagnosticSpan> {
-        assert_eq!(suggestion.msp.span_labels().len(), suggestion.substitutes.len());
-        suggestion.msp.span_labels()
-                      .into_iter()
-                      .zip(&suggestion.substitutes)
-                      .map(|(span_label, suggestion)| {
-                          DiagnosticSpan::from_span_label(span_label,
-                                                          Some(suggestion),
-                                                          je)
+        suggestion.substitution_parts
+                      .iter()
+                      .flat_map(|substitution| {
+                          substitution.substitutions.iter().map(move |suggestion| {
+                              let span_label = SpanLabel {
+                                  span: substitution.span,
+                                  is_primary: true,
+                                  label: None,
+                              };
+                              DiagnosticSpan::from_span_label(span_label,
+                                                              Some(suggestion),
+                                                              je)
+                          })
                       })
                       .collect()
     }
@@ -294,8 +300,9 @@ fn from_render_span(rsp: &RenderSpan, je: &JsonEmitter) -> Vec<DiagnosticSpan> {
         match *rsp {
             RenderSpan::FullSpan(ref msp) =>
                 DiagnosticSpan::from_multispan(msp, je),
-            RenderSpan::Suggestion(ref suggestion) =>
-                DiagnosticSpan::from_suggestion(suggestion, je),
+            // regular diagnostics don't produce this anymore
+            // FIXME(oli_obk): remove it entirely
+            RenderSpan::Suggestion(_) => unreachable!(),
         }
     }
 }
@@ -330,7 +337,7 @@ fn from_span(span: Span, je: &JsonEmitter) -> Vec<DiagnosticSpanLine> {
                       })
                      .collect()
              })
-            .unwrap_or(vec![])
+            .unwrap_or_else(|_| vec![])
     }
 }
 
@@ -351,17 +358,8 @@ fn map_opt_string(s: Option<String>, je: &JsonEmitter) -> Option<DiagnosticCode>
 }
 
 impl JsonEmitter {
-    fn render(&self, render_span: &RenderSpan) -> Option<String> {
-        use std::borrow::Borrow;
-
-        match *render_span {
-            RenderSpan::FullSpan(_) => {
-                None
-            }
-            RenderSpan::Suggestion(ref suggestion) => {
-                Some(suggestion.splice_lines(self.cm.borrow()))
-            }
-        }
+    fn render(&self, suggestion: &CodeSuggestion) -> Vec<String> {
+        suggestion.splice_lines(&*self.cm)
     }
 }
 
index 89c67b88cbde6dccaa7c0006cefc9152aac9a747..32dafcdb582f0ca04a010c348aa11eedd29bdabf 100644 (file)
@@ -15,7 +15,6 @@
 //! This API is completely unstable and subject to change.
 
 #![crate_name = "syntax"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        test(attr(deny(warnings))))]
 #![deny(warnings)]
 
-#![feature(rustc_private)]
-#![feature(staged_api)]
 #![feature(unicode)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(i128_type)]
 
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
 extern crate serialize;
 #[macro_use] extern crate log;
 #[macro_use] extern crate bitflags;
index 92cec462ffb7cefbdd623490c125dab5a4e5f4bf..082930777e598cfe4a9392e1dd7e18106ff648fa 100644 (file)
@@ -62,7 +62,7 @@ pub fn parse_outer_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
                 _ => break,
             }
         }
-        return Ok(attrs);
+        Ok(attrs)
     }
 
     /// Matches `attribute = # ! [ meta_item ]`
@@ -182,7 +182,7 @@ pub fn parse_inner_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
                     }
 
                     let attr = self.parse_attribute(true)?;
-                    assert!(attr.style == ast::AttrStyle::Inner);
+                    assert_eq!(attr.style, ast::AttrStyle::Inner);
                     attrs.push(attr);
                 }
                 token::DocComment(s) => {
index 4fe4ec7e4c0ed3f785fb498ded087152b4b67892..0c6f09ba7666cb0ed6b5896194c75794f1f2d5d1 100644 (file)
@@ -43,14 +43,14 @@ pub fn expr_is_simple_block(e: &ast::Expr) -> bool {
 }
 
 /// this statement requires a semicolon after it.
-/// note that in one case (stmt_semi), we've already
+/// note that in one case (`stmt_semi`), we've already
 /// seen the semicolon, and thus don't need another.
 pub fn stmt_ends_with_semi(stmt: &ast::StmtKind) -> bool {
     match *stmt {
         ast::StmtKind::Local(_) => true,
-        ast::StmtKind::Item(_) => false,
         ast::StmtKind::Expr(ref e) => expr_requires_semi_to_be_stmt(e),
-        ast::StmtKind::Semi(..) => false,
+        ast::StmtKind::Item(_) |
+        ast::StmtKind::Semi(..) |
         ast::StmtKind::Mac(..) => false,
     }
 }
index b57708f9193a39c4daed2ba0be23ce010c1ee45f..fe931f7cf6a645f4025baea781dc4e5a89ac2460 100644 (file)
@@ -12,7 +12,7 @@
 
 use parse::token;
 
-/// SeqSep : a sequence separator (token)
+/// `SeqSep` : a sequence separator (token)
 /// and whether a trailing separator is allowed.
 pub struct SeqSep {
     pub sep: Option<token::Token>,
index 7ac322b144c7ea46c9641fbb719f87909e0f6998..8b545d3b909e823c472a1224219a723ce53731cf 100644 (file)
@@ -77,7 +77,7 @@ fn vertical_trim(lines: Vec<String>) -> Vec<String> {
         while j > i && lines[j - 1].trim().is_empty() {
             j -= 1;
         }
-        lines[i..j].iter().cloned().collect()
+        lines[i..j].to_vec()
     }
 
     /// remove a "[ \t]*\*" block from each line, if possible
index 7d2a1b3c4a4d21084689fc507f21aaa8c102b3b4..0bcd457851890c6db66ecbae0d988c990cbf3865 100644 (file)
@@ -144,7 +144,7 @@ pub fn peek(&self) -> TokenAndSpan {
 
 impl<'a> StringReader<'a> {
     /// For comments.rs, which hackily pokes into next_pos and ch
-    pub fn new_raw<'b>(sess: &'a ParseSess, filemap: Rc<syntax_pos::FileMap>) -> Self {
+    pub fn new_raw(sess: &'a ParseSess, filemap: Rc<syntax_pos::FileMap>) -> Self {
         let mut sr = StringReader::new_raw_internal(sess, filemap);
         sr.bump();
         sr
@@ -180,7 +180,7 @@ fn new_raw_internal(sess: &'a ParseSess, filemap: Rc<syntax_pos::FileMap>) -> Se
 
     pub fn new(sess: &'a ParseSess, filemap: Rc<syntax_pos::FileMap>) -> Self {
         let mut sr = StringReader::new_raw(sess, filemap);
-        if let Err(_) = sr.advance_token() {
+        if sr.advance_token().is_err() {
             sr.emit_fatal_errors();
             panic!(FatalError);
         }
@@ -205,7 +205,7 @@ pub fn retokenize(sess: &'a ParseSess, mut span: Span) -> Self {
 
         sr.bump();
 
-        if let Err(_) = sr.advance_token() {
+        if sr.advance_token().is_err() {
             sr.emit_fatal_errors();
             panic!(FatalError);
         }
@@ -504,7 +504,7 @@ fn scan_comment(&mut self) -> Option<TokenAndSpan> {
                     self.bump();
 
                     // line comments starting with "///" or "//!" are doc-comments
-                    let doc_comment = self.ch_is('/') || self.ch_is('!');
+                    let doc_comment = (self.ch_is('/') && !self.nextch_is('/')) || self.ch_is('!');
                     let start_bpos = self.pos - BytePos(2);
 
                     while !self.is_eof() {
@@ -525,7 +525,7 @@ fn scan_comment(&mut self) -> Option<TokenAndSpan> {
                         self.bump();
                     }
 
-                    return if doc_comment {
+                    if doc_comment {
                         self.with_str_from(start_bpos, |string| {
                             // comments with only more "/"s are not doc comments
                             let tok = if is_doc_comment(string) {
@@ -544,7 +544,7 @@ fn scan_comment(&mut self) -> Option<TokenAndSpan> {
                             tok: token::Comment,
                             sp: mk_sp(start_bpos, self.pos),
                         })
-                    };
+                    }
                 }
                 Some('*') => {
                     self.bump();
@@ -754,9 +754,7 @@ fn scan_number(&mut self, c: char) -> token::Lit {
         // integer literal followed by field/method access or a range pattern
         // (`0..2` and `12.foo()`)
         if self.ch_is('.') && !self.nextch_is('.') &&
-           !self.nextch()
-                .unwrap_or('\0')
-                .is_xid_start() {
+           !ident_start(self.nextch()) {
             // might have stuff after the ., and if it does, it needs to start
             // with a number
             self.bump();
@@ -766,7 +764,7 @@ fn scan_number(&mut self, c: char) -> token::Lit {
             }
             let pos = self.pos;
             self.check_float_base(start_bpos, pos, base);
-            return token::Float(self.name_from(start_bpos));
+            token::Float(self.name_from(start_bpos))
         } else {
             // it might be a float if it has an exponent
             if self.ch_is('e') || self.ch_is('E') {
@@ -776,7 +774,7 @@ fn scan_number(&mut self, c: char) -> token::Lit {
                 return token::Float(self.name_from(start_bpos));
             }
             // but we certainly have an integer!
-            return token::Integer(self.name_from(start_bpos));
+            token::Integer(self.name_from(start_bpos))
         }
     }
 
@@ -1053,9 +1051,9 @@ fn binop(&mut self, op: token::BinOpToken) -> token::Token {
         self.bump();
         if self.ch_is('=') {
             self.bump();
-            return token::BinOpEq(op);
+            token::BinOpEq(op)
         } else {
-            return token::BinOp(op);
+            token::BinOp(op)
         }
     }
 
@@ -1102,15 +1100,15 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
             // One-byte tokens.
             ';' => {
                 self.bump();
-                return Ok(token::Semi);
+                Ok(token::Semi)
             }
             ',' => {
                 self.bump();
-                return Ok(token::Comma);
+                Ok(token::Comma)
             }
             '.' => {
                 self.bump();
-                return if self.ch_is('.') {
+                if self.ch_is('.') {
                     self.bump();
                     if self.ch_is('.') {
                         self.bump();
@@ -1120,61 +1118,61 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                     }
                 } else {
                     Ok(token::Dot)
-                };
+                }
             }
             '(' => {
                 self.bump();
-                return Ok(token::OpenDelim(token::Paren));
+                Ok(token::OpenDelim(token::Paren))
             }
             ')' => {
                 self.bump();
-                return Ok(token::CloseDelim(token::Paren));
+                Ok(token::CloseDelim(token::Paren))
             }
             '{' => {
                 self.bump();
-                return Ok(token::OpenDelim(token::Brace));
+                Ok(token::OpenDelim(token::Brace))
             }
             '}' => {
                 self.bump();
-                return Ok(token::CloseDelim(token::Brace));
+                Ok(token::CloseDelim(token::Brace))
             }
             '[' => {
                 self.bump();
-                return Ok(token::OpenDelim(token::Bracket));
+                Ok(token::OpenDelim(token::Bracket))
             }
             ']' => {
                 self.bump();
-                return Ok(token::CloseDelim(token::Bracket));
+                Ok(token::CloseDelim(token::Bracket))
             }
             '@' => {
                 self.bump();
-                return Ok(token::At);
+                Ok(token::At)
             }
             '#' => {
                 self.bump();
-                return Ok(token::Pound);
+                Ok(token::Pound)
             }
             '~' => {
                 self.bump();
-                return Ok(token::Tilde);
+                Ok(token::Tilde)
             }
             '?' => {
                 self.bump();
-                return Ok(token::Question);
+                Ok(token::Question)
             }
             ':' => {
                 self.bump();
                 if self.ch_is(':') {
                     self.bump();
-                    return Ok(token::ModSep);
+                    Ok(token::ModSep)
                 } else {
-                    return Ok(token::Colon);
+                    Ok(token::Colon)
                 }
             }
 
             '$' => {
                 self.bump();
-                return Ok(token::Dollar);
+                Ok(token::Dollar)
             }
 
             // Multi-byte tokens.
@@ -1182,21 +1180,21 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                 self.bump();
                 if self.ch_is('=') {
                     self.bump();
-                    return Ok(token::EqEq);
+                    Ok(token::EqEq)
                 } else if self.ch_is('>') {
                     self.bump();
-                    return Ok(token::FatArrow);
+                    Ok(token::FatArrow)
                 } else {
-                    return Ok(token::Eq);
+                    Ok(token::Eq)
                 }
             }
             '!' => {
                 self.bump();
                 if self.ch_is('=') {
                     self.bump();
-                    return Ok(token::Ne);
+                    Ok(token::Ne)
                 } else {
-                    return Ok(token::Not);
+                    Ok(token::Not)
                 }
             }
             '<' => {
@@ -1204,21 +1202,21 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                 match self.ch.unwrap_or('\x00') {
                     '=' => {
                         self.bump();
-                        return Ok(token::Le);
+                        Ok(token::Le)
                     }
                     '<' => {
-                        return Ok(self.binop(token::Shl));
+                        Ok(self.binop(token::Shl))
                     }
                     '-' => {
                         self.bump();
                         match self.ch.unwrap_or('\x00') {
                             _ => {
-                                return Ok(token::LArrow);
+                                Ok(token::LArrow)
                             }
                         }
                     }
                     _ => {
-                        return Ok(token::Lt);
+                        Ok(token::Lt)
                     }
                 }
             }
@@ -1227,13 +1225,13 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                 match self.ch.unwrap_or('\x00') {
                     '=' => {
                         self.bump();
-                        return Ok(token::Ge);
+                        Ok(token::Ge)
                     }
                     '>' => {
-                        return Ok(self.binop(token::Shr));
+                        Ok(self.binop(token::Shr))
                     }
                     _ => {
-                        return Ok(token::Gt);
+                        Ok(token::Gt)
                     }
                 }
             }
@@ -1303,7 +1301,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                 };
                 self.bump(); // advance ch past token
                 let suffix = self.scan_optional_raw_name();
-                return Ok(token::Literal(token::Char(id), suffix));
+                Ok(token::Literal(token::Char(id), suffix))
             }
             'b' => {
                 self.bump();
@@ -1314,7 +1312,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                     _ => unreachable!(),  // Should have been a token::Ident above.
                 };
                 let suffix = self.scan_optional_raw_name();
-                return Ok(token::Literal(lit, suffix));
+                Ok(token::Literal(lit, suffix))
             }
             '"' => {
                 let start_bpos = self.pos;
@@ -1345,7 +1343,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                 };
                 self.bump();
                 let suffix = self.scan_optional_raw_name();
-                return Ok(token::Literal(token::Str_(id), suffix));
+                Ok(token::Literal(token::Str_(id), suffix))
             }
             'r' => {
                 let start_bpos = self.pos;
@@ -1416,24 +1414,24 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                     Symbol::intern("??")
                 };
                 let suffix = self.scan_optional_raw_name();
-                return Ok(token::Literal(token::StrRaw(id, hash_count), suffix));
+                Ok(token::Literal(token::StrRaw(id, hash_count), suffix))
             }
             '-' => {
                 if self.nextch_is('>') {
                     self.bump();
                     self.bump();
-                    return Ok(token::RArrow);
+                    Ok(token::RArrow)
                 } else {
-                    return Ok(self.binop(token::Minus));
+                    Ok(self.binop(token::Minus))
                 }
             }
             '&' => {
                 if self.nextch_is('&') {
                     self.bump();
                     self.bump();
-                    return Ok(token::AndAnd);
+                    Ok(token::AndAnd)
                 } else {
-                    return Ok(self.binop(token::And));
+                    Ok(self.binop(token::And))
                 }
             }
             '|' => {
@@ -1441,27 +1439,27 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                     Some('|') => {
                         self.bump();
                         self.bump();
-                        return Ok(token::OrOr);
+                        Ok(token::OrOr)
                     }
                     _ => {
-                        return Ok(self.binop(token::Or));
+                        Ok(self.binop(token::Or))
                     }
                 }
             }
             '+' => {
-                return Ok(self.binop(token::Plus));
+                Ok(self.binop(token::Plus))
             }
             '*' => {
-                return Ok(self.binop(token::Star));
+                Ok(self.binop(token::Star))
             }
             '/' => {
-                return Ok(self.binop(token::Slash));
+                Ok(self.binop(token::Slash))
             }
             '^' => {
-                return Ok(self.binop(token::Caret));
+                Ok(self.binop(token::Caret))
             }
             '%' => {
-                return Ok(self.binop(token::Percent));
+                Ok(self.binop(token::Percent))
             }
             c => {
                 let last_bpos = self.pos;
@@ -1470,7 +1468,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                                                           bpos,
                                                           "unknown start of token",
                                                           c);
-                unicode_chars::check_for_substitution(&self, c, &mut err);
+                unicode_chars::check_for_substitution(self, c, &mut err);
                 self.fatal_errs.push(err);
                 Err(())
             }
@@ -1492,14 +1490,14 @@ fn read_to_eol(&mut self) -> String {
         if self.ch_is('\n') {
             self.bump();
         }
-        return val;
+        val
     }
 
     fn read_one_line_comment(&mut self) -> String {
         let val = self.read_to_eol();
         assert!((val.as_bytes()[0] == b'/' && val.as_bytes()[1] == b'/') ||
                 (val.as_bytes()[0] == b'#' && val.as_bytes()[1] == b'!'));
-        return val;
+        val
     }
 
     fn consume_non_eol_whitespace(&mut self) {
@@ -1543,7 +1541,7 @@ fn scan_byte(&mut self) -> token::Lit {
             Symbol::intern("?")
         };
         self.bump(); // advance ch past token
-        return token::Byte(id);
+        token::Byte(id)
     }
 
     fn scan_byte_escape(&mut self, delim: char, below_0x7f_only: bool) -> bool {
@@ -1576,7 +1574,7 @@ fn scan_byte_string(&mut self) -> token::Lit {
             Symbol::intern("??")
         };
         self.bump();
-        return token::ByteStr(id);
+        token::ByteStr(id)
     }
 
     fn scan_raw_byte_string(&mut self) -> token::Lit {
@@ -1629,8 +1627,8 @@ fn scan_raw_byte_string(&mut self) -> token::Lit {
             self.bump();
         }
         self.bump();
-        return token::ByteStrRaw(self.name_from_to(content_start_bpos, content_end_bpos),
-                                 hash_count);
+        token::ByteStrRaw(self.name_from_to(content_start_bpos, content_end_bpos),
+                                 hash_count)
     }
 }
 
@@ -1648,7 +1646,7 @@ fn in_range(c: Option<char>, lo: char, hi: char) -> bool {
 }
 
 fn is_dec_digit(c: Option<char>) -> bool {
-    return in_range(c, '0', '9');
+    in_range(c, '0', '9')
 }
 
 pub fn is_doc_comment(s: &str) -> bool {
index fe3ca1cf2305c0341ae3fb50db3616cb0e581c1b..1eff819d755493f33f713b6281100591bab78413 100644 (file)
@@ -107,18 +107,18 @@ pub fn parse_crate_attrs_from_file<'a>(input: &Path, sess: &'a ParseSess)
     parser.parse_inner_attributes()
 }
 
-pub fn parse_crate_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess)
-                                       -> PResult<'a, ast::Crate> {
+pub fn parse_crate_from_source_str(name: String, source: String, sess: &ParseSess)
+                                       -> PResult<ast::Crate> {
     new_parser_from_source_str(sess, name, source).parse_crate_mod()
 }
 
-pub fn parse_crate_attrs_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess)
-                                             -> PResult<'a, Vec<ast::Attribute>> {
+pub fn parse_crate_attrs_from_source_str(name: String, source: String, sess: &ParseSess)
+                                             -> PResult<Vec<ast::Attribute>> {
     new_parser_from_source_str(sess, name, source).parse_inner_attributes()
 }
 
-pub fn parse_expr_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess)
-                                      -> PResult<'a, P<ast::Expr>> {
+pub fn parse_expr_from_source_str(name: String, source: String, sess: &ParseSess)
+                                      -> PResult<P<ast::Expr>> {
     new_parser_from_source_str(sess, name, source).parse_expr()
 }
 
@@ -126,29 +126,29 @@ pub fn parse_expr_from_source_str<'a>(name: String, source: String, sess: &'a Pa
 ///
 /// Returns `Ok(Some(item))` when successful, `Ok(None)` when no item was found, and`Err`
 /// when a syntax error occurred.
-pub fn parse_item_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess)
-                                      -> PResult<'a, Option<P<ast::Item>>> {
+pub fn parse_item_from_source_str(name: String, source: String, sess: &ParseSess)
+                                      -> PResult<Option<P<ast::Item>>> {
     new_parser_from_source_str(sess, name, source).parse_item()
 }
 
-pub fn parse_meta_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess)
-                                      -> PResult<'a, ast::MetaItem> {
+pub fn parse_meta_from_source_str(name: String, source: String, sess: &ParseSess)
+                                      -> PResult<ast::MetaItem> {
     new_parser_from_source_str(sess, name, source).parse_meta_item()
 }
 
-pub fn parse_stmt_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess)
-                                      -> PResult<'a, Option<ast::Stmt>> {
+pub fn parse_stmt_from_source_str(name: String, source: String, sess: &ParseSess)
+                                      -> PResult<Option<ast::Stmt>> {
     new_parser_from_source_str(sess, name, source).parse_stmt()
 }
 
-pub fn parse_stream_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess)
+pub fn parse_stream_from_source_str(name: String, source: String, sess: &ParseSess)
                                         -> TokenStream {
     filemap_to_stream(sess, sess.codemap().new_filemap(name, source))
 }
 
 // Create a new parser from a source string
-pub fn new_parser_from_source_str<'a>(sess: &'a ParseSess, name: String, source: String)
-                                      -> Parser<'a> {
+pub fn new_parser_from_source_str(sess: &ParseSess, name: String, source: String)
+                                      -> Parser {
     filemap_to_parser(sess, sess.codemap().new_filemap(name, source))
 }
 
@@ -173,7 +173,7 @@ pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess,
 }
 
 /// Given a filemap and config, return a parser
-pub fn filemap_to_parser<'a>(sess: &'a ParseSess, filemap: Rc<FileMap>, ) -> Parser<'a> {
+pub fn filemap_to_parser(sess: & ParseSess, filemap: Rc<FileMap>, ) -> Parser {
     let end_pos = filemap.end_pos;
     let mut parser = stream_to_parser(sess, filemap_to_stream(sess, filemap));
 
@@ -186,7 +186,7 @@ pub fn filemap_to_parser<'a>(sess: &'a ParseSess, filemap: Rc<FileMap>, ) -> Par
 
 // must preserve old name for now, because quote! from the *existing*
 // compiler expands into it
-pub fn new_parser_from_tts<'a>(sess: &'a ParseSess, tts: Vec<TokenTree>) -> Parser<'a> {
+pub fn new_parser_from_tts(sess: &ParseSess, tts: Vec<TokenTree>) -> Parser {
     stream_to_parser(sess, tts.into_iter().collect())
 }
 
@@ -216,8 +216,8 @@ pub fn filemap_to_stream(sess: &ParseSess, filemap: Rc<FileMap>) -> TokenStream
     panictry!(srdr.parse_all_token_trees())
 }
 
-/// Given stream and the ParseSess, produce a parser
-pub fn stream_to_parser<'a>(sess: &'a ParseSess, stream: TokenStream) -> Parser<'a> {
+/// Given stream and the `ParseSess`, produce a parser
+pub fn stream_to_parser(sess: &ParseSess, stream: TokenStream) -> Parser {
     Parser::new(sess, stream, None, false)
 }
 
@@ -251,7 +251,7 @@ pub fn char_lit(lit: &str) -> (char, isize) {
             (c, 4)
         }
         'u' => {
-            assert!(lit.as_bytes()[2] == b'{');
+            assert_eq!(lit.as_bytes()[2], b'{');
             let idx = lit.find('}').unwrap();
             let v = u32::from_str_radix(&lit[3..idx], 16).unwrap();
             let c = char::from_u32(v).unwrap();
@@ -287,51 +287,46 @@ fn eat<'a>(it: &mut iter::Peekable<str::CharIndices<'a>>) {
     }
 
     let mut chars = lit.char_indices().peekable();
-    loop {
-        match chars.next() {
-            Some((i, c)) => {
-                match c {
-                    '\\' => {
-                        let ch = chars.peek().unwrap_or_else(|| {
-                            panic!("{}", error(i))
-                        }).1;
-
-                        if ch == '\n' {
-                            eat(&mut chars);
-                        } else if ch == '\r' {
-                            chars.next();
-                            let ch = chars.peek().unwrap_or_else(|| {
-                                panic!("{}", error(i))
-                            }).1;
-
-                            if ch != '\n' {
-                                panic!("lexer accepted bare CR");
-                            }
-                            eat(&mut chars);
-                        } else {
-                            // otherwise, a normal escape
-                            let (c, n) = char_lit(&lit[i..]);
-                            for _ in 0..n - 1 { // we don't need to move past the first \
-                                chars.next();
-                            }
-                            res.push(c);
-                        }
-                    },
-                    '\r' => {
-                        let ch = chars.peek().unwrap_or_else(|| {
-                            panic!("{}", error(i))
-                        }).1;
+    while let Some((i, c)) = chars.next() {
+        match c {
+            '\\' => {
+                let ch = chars.peek().unwrap_or_else(|| {
+                    panic!("{}", error(i))
+                }).1;
+
+                if ch == '\n' {
+                    eat(&mut chars);
+                } else if ch == '\r' {
+                    chars.next();
+                    let ch = chars.peek().unwrap_or_else(|| {
+                        panic!("{}", error(i))
+                    }).1;
 
-                        if ch != '\n' {
-                            panic!("lexer accepted bare CR");
-                        }
+                    if ch != '\n' {
+                        panic!("lexer accepted bare CR");
+                    }
+                    eat(&mut chars);
+                } else {
+                    // otherwise, a normal escape
+                    let (c, n) = char_lit(&lit[i..]);
+                    for _ in 0..n - 1 { // we don't need to move past the first \
                         chars.next();
-                        res.push('\n');
                     }
-                    c => res.push(c),
+                    res.push(c);
                 }
             },
-            None => break
+            '\r' => {
+                let ch = chars.peek().unwrap_or_else(|| {
+                    panic!("{}", error(i))
+                }).1;
+
+                if ch != '\n' {
+                    panic!("lexer accepted bare CR");
+                }
+                chars.next();
+                res.push('\n');
+            }
+            c => res.push(c),
         }
     }
 
@@ -346,22 +341,16 @@ pub fn raw_str_lit(lit: &str) -> String {
     debug!("raw_str_lit: given {}", escape_default(lit));
     let mut res = String::with_capacity(lit.len());
 
-    // FIXME #8372: This could be a for-loop if it didn't borrow the iterator
     let mut chars = lit.chars().peekable();
-    loop {
-        match chars.next() {
-            Some(c) => {
-                if c == '\r' {
-                    if *chars.peek().unwrap() != '\n' {
-                        panic!("lexer accepted bare CR");
-                    }
-                    chars.next();
-                    res.push('\n');
-                } else {
-                    res.push(c);
-                }
-            },
-            None => break
+    while let Some(c) = chars.next() {
+        if c == '\r' {
+            if *chars.peek().unwrap() != '\n' {
+                panic!("lexer accepted bare CR");
+            }
+            chars.next();
+            res.push('\n');
+        } else {
+            res.push(c);
         }
     }
 
@@ -459,7 +448,7 @@ pub fn byte_lit(lit: &str) -> (u8, usize) {
     if lit.len() == 1 {
         (lit.as_bytes()[0], 1)
     } else {
-        assert!(lit.as_bytes()[0] == b'\\', err(0));
+        assert_eq!(lit.as_bytes()[0], b'\\', "{}", err(0));
         let b = match lit.as_bytes()[1] {
             b'"' => b'"',
             b'n' => b'\n',
@@ -480,7 +469,7 @@ pub fn byte_lit(lit: &str) -> (u8, usize) {
                 }
             }
         };
-        return (b, 2);
+        (b, 2)
     }
 }
 
@@ -491,7 +480,7 @@ pub fn byte_str_lit(lit: &str) -> Rc<Vec<u8>> {
     let error = |i| format!("lexer should have rejected {} at {}", lit, i);
 
     /// Eat everything up to a non-whitespace
-    fn eat<'a, I: Iterator<Item=(usize, u8)>>(it: &mut iter::Peekable<I>) {
+    fn eat<I: Iterator<Item=(usize, u8)>>(it: &mut iter::Peekable<I>) {
         loop {
             match it.peek().map(|x| x.1) {
                 Some(b' ') | Some(b'\n') | Some(b'\r') | Some(b'\t') => {
@@ -578,7 +567,7 @@ pub fn integer_lit(s: &str, suffix: Option<Symbol>, diag: Option<(Span, &Handler
             if let Some(err) = err {
                 err!(diag, |span, diag| diag.span_err(span, err));
             }
-            return filtered_float_lit(Symbol::intern(&s), Some(suf), diag)
+            return filtered_float_lit(Symbol::intern(s), Some(suf), diag)
         }
     }
 
index d5baec675e44f2116ee1707c94315c7ba11ba2c7..078e86aa2941f36a8c28332986dcf3772177c15a 100644 (file)
@@ -59,7 +59,7 @@ fn report(&mut self,
 
         if !self.obsolete_set.contains(&kind) &&
             (error || self.sess.span_diagnostic.can_emit_warnings) {
-            err.note(&format!("{}", desc));
+            err.note(desc);
             self.obsolete_set.insert(kind);
         }
         err.emit();
index c09ddb4d1c9e039a9cc98654183867fe6667cef1..4741f896d3cc0c8c6ce38501dd2e1cb1a7dcfe0e 100644 (file)
@@ -248,7 +248,7 @@ fn next(&mut self) -> TokenAndSpan {
     fn next_desugared(&mut self) -> TokenAndSpan {
         let (sp, name) = match self.next() {
             TokenAndSpan { sp, tok: token::DocComment(name) } => (sp, name),
-            tok @ _ => return tok,
+            tok => return tok,
         };
 
         let stripped = strip_doc_comment_decoration(&name.as_str());
@@ -354,7 +354,7 @@ pub enum Error {
 }
 
 impl Error {
-    pub fn span_err<'a>(self, sp: Span, handler: &'a errors::Handler) -> DiagnosticBuilder<'a> {
+    pub fn span_err(self, sp: Span, handler: &errors::Handler) -> DiagnosticBuilder {
         match self {
             Error::FileNotFoundForModule { ref mod_name,
                                            ref default_path,
@@ -478,9 +478,10 @@ pub fn new(sess: &'a ParseSess,
     }
 
     fn next_tok(&mut self) -> TokenAndSpan {
-        let mut next = match self.desugar_doc_comments {
-            true => self.token_cursor.next_desugared(),
-            false => self.token_cursor.next(),
+        let mut next = if self.desugar_doc_comments {
+            self.token_cursor.next_desugared()
+        } else {
+            self.token_cursor.next()
         };
         if next.sp == syntax_pos::DUMMY_SP {
             next.sp = self.prev_span;
@@ -551,7 +552,7 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
             // This might be a sign we need a connect method on Iterator.
             let b = i.next()
                      .map_or("".to_string(), |t| t.to_string());
-            i.enumerate().fold(b, |mut b, (i, ref a)| {
+            i.enumerate().fold(b, |mut b, (i, a)| {
                 if tokens.len() > 2 && i == tokens.len() - 2 {
                     b.push_str(", or ");
                 } else if tokens.len() == 2 && i == tokens.len() - 2 {
@@ -602,10 +603,10 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
                 label_sp
             };
             if self.span.contains(sp) {
-                err.span_label(self.span, &label_exp);
+                err.span_label(self.span, label_exp);
             } else {
-                err.span_label(sp, &label_exp);
-                err.span_label(self.span, &"unexpected token");
+                err.span_label(sp, label_exp);
+                err.span_label(self.span, "unexpected token");
             }
             Err(err)
         }
@@ -985,18 +986,15 @@ fn parse_seq_to_before_tokens<T, F, Fe>(&mut self,
                 token::CloseDelim(..) | token::Eof => break,
                 _ => {}
             };
-            match sep.sep {
-                Some(ref t) => {
-                    if first {
-                        first = false;
-                    } else {
-                        if let Err(e) = self.expect(t) {
-                            fe(e);
-                            break;
-                        }
+            if let Some(ref t) = sep.sep {
+                if first {
+                    first = false;
+                } else {
+                    if let Err(e) = self.expect(t) {
+                        fe(e);
+                        break;
                     }
                 }
-                _ => ()
             }
             if sep.trailing_sep_allowed && kets.iter().any(|k| self.check(k)) {
                 break;
@@ -1493,7 +1491,7 @@ fn maybe_recover_from_bad_type_plus(&mut self, allow_plus: bool, ty: &Ty) -> PRe
         let sum_span = ty.span.to(self.prev_span);
 
         let mut err = struct_span_err!(self.sess.span_diagnostic, sum_span, E0178,
-            "expected a path on the left-hand side of `+`, not `{}`", pprust::ty_to_string(&ty));
+            "expected a path on the left-hand side of `+`, not `{}`", pprust::ty_to_string(ty));
 
         match ty.node {
             TyKind::Rptr(ref lifetime, ref mut_ty) => {
@@ -1512,10 +1510,10 @@ fn maybe_recover_from_bad_type_plus(&mut self, allow_plus: bool, ty: &Ty) -> PRe
                 err.span_suggestion(sum_span, "try adding parentheses:", sum_with_parens);
             }
             TyKind::Ptr(..) | TyKind::BareFn(..) => {
-                err.span_label(sum_span, &"perhaps you forgot parentheses?");
+                err.span_label(sum_span, "perhaps you forgot parentheses?");
             }
             _ => {
-                err.span_label(sum_span, &"expected a path");
+                err.span_label(sum_span, "expected a path");
             },
         }
         err.emit();
@@ -1547,7 +1545,7 @@ pub fn parse_ptr(&mut self) -> PResult<'a, MutTy> {
 
     pub fn is_named_argument(&mut self) -> bool {
         let offset = match self.token {
-            token::BinOp(token::And) => 1,
+            token::BinOp(token::And) |
             token::AndAnd => 1,
             _ if self.token.is_keyword(keywords::Mut) => 1,
             _ => 0
@@ -2556,7 +2554,7 @@ fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: Span) -> PResult<'a,
                     let fstr = n.as_str();
                     let mut err = self.diagnostic().struct_span_err(self.prev_span,
                         &format!("unexpected token: `{}`", n));
-                    err.span_label(self.prev_span, &"unexpected token");
+                    err.span_label(self.prev_span, "unexpected token");
                     if fstr.chars().all(|x| "0123456789.".contains(x)) {
                         let float = match fstr.parse::<f64>().ok() {
                             Some(f) => f,
@@ -2708,7 +2706,7 @@ pub fn parse_prefix_expr(&mut self,
                 let span_of_tilde = lo;
                 let mut err = self.diagnostic().struct_span_err(span_of_tilde,
                         "`~` can not be used as a unary operator");
-                err.span_label(span_of_tilde, &"did you mean `!`?");
+                err.span_label(span_of_tilde, "did you mean `!`?");
                 err.help("use `!` instead of `~` if you meant to perform bitwise negation");
                 err.emit();
                 (span, self.mk_unary(UnOp::Not, e))
@@ -3154,10 +3152,11 @@ pub fn parse_arm(&mut self) -> PResult<'a, Arm> {
 
         let attrs = self.parse_outer_attributes()?;
         let pats = self.parse_pats()?;
-        let mut guard = None;
-        if self.eat_keyword(keywords::If) {
-            guard = Some(self.parse_expr()?);
-        }
+        let guard = if self.eat_keyword(keywords::If) {
+            Some(self.parse_expr()?)
+        } else {
+            None
+        };
         self.expect(&token::FatArrow)?;
         let expr = self.parse_expr_res(RESTRICTION_STMT_EXPR, None)?;
 
@@ -3600,10 +3599,11 @@ fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> {
         let lo = self.span;
         let pat = self.parse_pat()?;
 
-        let mut ty = None;
-        if self.eat(&token::Colon) {
-            ty = Some(self.parse_ty()?);
-        }
+        let ty = if self.eat(&token::Colon) {
+            Some(self.parse_ty()?)
+        } else {
+            None
+        };
         let init = self.parse_initializer()?;
         Ok(P(ast::Local {
             ty: ty,
@@ -3929,7 +3929,7 @@ fn parse_stmt_without_recovery(&mut self,
                 },
                 None => {
                     let unused_attrs = |attrs: &[_], s: &mut Self| {
-                        if attrs.len() > 0 {
+                        if !attrs.is_empty() {
                             if s.prev_token_kind == PrevTokenKind::DocComment {
                                 s.span_fatal_err(s.prev_span, Error::UselessDocComment).emit();
                             } else {
@@ -4792,7 +4792,7 @@ fn missing_assoc_item_kind_err(&mut self, item_type: &str, prev_span: Span)
             sp,
             &format!("missing `fn`, `type`, or `const` for {}-item declaration",
                      item_type));
-        err.span_label(sp, &"missing `fn`, `type`, or `const`");
+        err.span_label(sp, "missing `fn`, `type`, or `const`");
         err
     }
 
@@ -4815,7 +4815,7 @@ fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
                 self.expect(&token::Not)?;
             }
 
-            self.complain_if_pub_macro(&vis, prev_span);
+            self.complain_if_pub_macro(vis, prev_span);
 
             // eat a matched-delimiter token tree:
             *at_end = true;
@@ -4917,13 +4917,10 @@ fn parse_item_impl(&mut self,
                 }
             }
         } else {
-            match polarity {
-                ast::ImplPolarity::Negative => {
-                    // This is a negated type implementation
-                    // `impl !MyType {}`, which is not allowed.
-                    self.span_err(neg_span, "inherent implementation can't be negated");
-                },
-                _ => {}
+            if polarity == ast::ImplPolarity::Negative {
+                // This is a negated type implementation
+                // `impl !MyType {}`, which is not allowed.
+                self.span_err(neg_span, "inherent implementation can't be negated");
             }
             None
         };
@@ -5185,7 +5182,7 @@ pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibili
                 let path_span = self.prev_span;
                 let help_msg = format!("make this visible only to module `{}` with `in`:", path);
                 self.expect(&token::CloseDelim(token::Paren))?;  // `)`
-                let mut err = self.span_fatal_help(path_span, &msg, &suggestion);
+                let mut err = self.span_fatal_help(path_span, msg, suggestion);
                 err.span_suggestion(path_span, &help_msg, format!("in {}", path));
                 err.emit();  // emit diagnostic, but continue with public visibility
             }
index 25cabef70c15b5765b89a916db34a457a62a6e95..77db604c56e118c0596364536b3b1ed3674a2f24 100644 (file)
@@ -53,6 +53,10 @@ impl DelimToken {
     pub fn len(self) -> usize {
         if self == NoDelim { 0 } else { 1 }
     }
+
+    pub fn is_empty(self) -> bool {
+        self == NoDelim
+    }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
@@ -198,17 +202,17 @@ pub fn is_like_gt(&self) -> bool {
     pub fn can_begin_expr(&self) -> bool {
         match *self {
             Ident(ident)                => ident_can_begin_expr(ident), // value name or keyword
-            OpenDelim(..)               => true, // tuple, array or block
-            Literal(..)                 => true, // literal
-            Not                         => true, // operator not
-            BinOp(Minus)                => true, // unary minus
-            BinOp(Star)                 => true, // dereference
-            BinOp(Or) | OrOr            => true, // closure
-            BinOp(And)                  => true, // reference
-            AndAnd                      => true, // double reference
-            DotDot | DotDotDot          => true, // range notation
-            Lt | BinOp(Shl)             => true, // associated path
-            ModSep                      => true, // global path
+            OpenDelim(..)               | // tuple, array or block
+            Literal(..)                 | // literal
+            Not                         | // operator not
+            BinOp(Minus)                | // unary minus
+            BinOp(Star)                 | // dereference
+            BinOp(Or) | OrOr            | // closure
+            BinOp(And)                  | // reference
+            AndAnd                      | // double reference
+            DotDot | DotDotDot          | // range notation
+            Lt | BinOp(Shl)             | // associated path
+            ModSep                      | // global path
             Pound                       => true, // expression attributes
             Interpolated(ref nt) => match **nt {
                 NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) => true,
@@ -222,16 +226,16 @@ pub fn can_begin_expr(&self) -> bool {
     pub fn can_begin_type(&self) -> bool {
         match *self {
             Ident(ident)                => ident_can_begin_type(ident), // type name or keyword
-            OpenDelim(Paren)            => true, // tuple
-            OpenDelim(Bracket)          => true, // array
-            Underscore                  => true, // placeholder
-            Not                         => true, // never
-            BinOp(Star)                 => true, // raw pointer
-            BinOp(And)                  => true, // reference
-            AndAnd                      => true, // double reference
-            Question                    => true, // maybe bound in trait object
-            Lifetime(..)                => true, // lifetime bound in trait object
-            Lt | BinOp(Shl)             => true, // associated path
+            OpenDelim(Paren)            | // tuple
+            OpenDelim(Bracket)          | // array
+            Underscore                  | // placeholder
+            Not                         | // never
+            BinOp(Star)                 | // raw pointer
+            BinOp(And)                  | // reference
+            AndAnd                      | // double reference
+            Question                    | // maybe bound in trait object
+            Lifetime(..)                | // lifetime bound in trait object
+            Lt | BinOp(Shl)             | // associated path
             ModSep                      => true, // global path
             Interpolated(ref nt) => match **nt {
                 NtIdent(..) | NtTy(..) | NtPath(..) => true,
index 1d67c2a2c2b74023c8f1fa1c7c5e4dc4ca8d9e6b..e893c859247c6110790921f528c04c99f9403fae 100644 (file)
 //! between using 'left' and 'right' terms to denote the wrapped-to-ring-buffer
 //! and point-in-infinite-stream senses freely.
 //!
-//! There is a parallel ring buffer, 'size', that holds the calculated size of
+//! There is a parallel ring buffer, `size`, that holds the calculated size of
 //! each token. Why calculated? Because for Begin/End pairs, the "size"
 //! includes everything between the pair. That is, the "size" of Begin is
 //! actually the sum of the sizes of everything between Begin and the paired
-//! End that follows. Since that is arbitrarily far in the future, 'size' is
+//! End that follows. Since that is arbitrarily far in the future, `size` is
 //! being rewritten regularly while the printer runs; in fact most of the
-//! machinery is here to work out 'size' entries on the fly (and give up when
+//! machinery is here to work out `size` entries on the fly (and give up when
 //! they're so obviously over-long that "infinity" is a good enough
 //! approximation for purposes of line breaking).
 //!
 //! The "input side" of the printer is managed as an abstract process called
-//! SCAN, which uses 'scan_stack', to manage calculating 'size'. SCAN is, in
+//! SCAN, which uses `scan_stack`, to manage calculating `size`. SCAN is, in
 //! other words, the process of calculating 'size' entries.
 //!
 //! The "output side" of the printer is managed by an abstract process called
-//! PRINT, which uses 'print_stack', 'margin' and 'space' to figure out what to
+//! PRINT, which uses `print_stack`, `margin` and `space` to figure out what to
 //! do with each token/size pair it consumes as it goes. It's trying to consume
 //! the entire buffered window, but can't output anything until the size is >=
 //! 0 (sizes are set to negative while they're pending calculation).
@@ -409,7 +409,7 @@ pub fn scan_pop_bottom(&mut self) -> usize {
     pub fn advance_right(&mut self) {
         self.right += 1;
         self.right %= self.buf_len;
-        assert!(self.right != self.left);
+        assert_ne!(self.right, self.left);
     }
     pub fn advance_left(&mut self) -> io::Result<()> {
         debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right,
index 0c7e8fda83766cbdbc8f4f0df87c1e42b5f9c523..83c289ff80b9251bd2df854ebed1207b7f5a09f0 100644 (file)
@@ -233,7 +233,7 @@ pub fn token_to_string(tok: &Token) -> String {
         token::CloseDelim(token::Bracket) => "]".to_string(),
         token::OpenDelim(token::Brace) => "{".to_string(),
         token::CloseDelim(token::Brace) => "}".to_string(),
-        token::OpenDelim(token::NoDelim) => " ".to_string(),
+        token::OpenDelim(token::NoDelim) |
         token::CloseDelim(token::NoDelim) => " ".to_string(),
         token::Pound                => "#".to_string(),
         token::Dollar               => "$".to_string(),
@@ -244,7 +244,7 @@ pub fn token_to_string(tok: &Token) -> String {
             let mut out = match lit {
                 token::Byte(b)           => format!("b'{}'", b),
                 token::Char(c)           => format!("'{}'", c),
-                token::Float(c)          => c.to_string(),
+                token::Float(c)          |
                 token::Integer(c)        => c.to_string(),
                 token::Str_(s)           => format!("\"{}\"", s),
                 token::StrRaw(s, n)      => format!("r{delim}\"{string}\"{delim}",
@@ -277,23 +277,23 @@ pub fn token_to_string(tok: &Token) -> String {
         token::Shebang(s)           => format!("/* shebang: {}*/", s),
 
         token::Interpolated(ref nt) => match **nt {
-            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::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)       => 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)    => generics_to_string(&e),
-            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::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)    => generics_to_string(e),
+            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),
         }
     }
 }
@@ -520,8 +520,7 @@ fn next_lit(&mut self, pos: BytePos) -> Option<comments::Literal> {
 
         let mut result = None;
 
-        if let &Some(ref lits) = self.literals()
-        {
+        if let Some(ref lits) = *self.literals() {
             while cur_lit < lits.len() {
                 let ltrl = (*lits)[cur_lit].clone();
                 if ltrl.pos > pos { break; }
@@ -618,11 +617,8 @@ fn next_comment(&mut self) -> Option<comments::Comment> {
 
     fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
         self.maybe_print_comment(lit.span.lo)?;
-        match self.next_lit(lit.span.lo) {
-            Some(ref ltrl) => {
-                return word(self.writer(), &(*ltrl).lit);
-            }
-            _ => ()
+        if let Some(ref ltrl) = self.next_lit(lit.span.lo) {
+            return word(self.writer(), &(*ltrl).lit);
         }
         match lit.node {
             ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style),
@@ -799,7 +795,7 @@ fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
                 self.popen()?;
                 self.commasep(Consistent,
                               &items[..],
-                              |s, i| s.print_meta_list_item(&i))?;
+                              |s, i| s.print_meta_list_item(i))?;
                 self.pclose()?;
             }
         }
@@ -982,14 +978,14 @@ pub fn commasep_cmnt<T, F, G>(&mut self,
 
     pub fn commasep_exprs(&mut self, b: Breaks,
                           exprs: &[P<ast::Expr>]) -> io::Result<()> {
-        self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span)
+        self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span)
     }
 
     pub fn print_mod(&mut self, _mod: &ast::Mod,
                      attrs: &[ast::Attribute]) -> io::Result<()> {
         self.print_inner_attributes(attrs)?;
         for item in &_mod.items {
-            self.print_item(&item)?;
+            self.print_item(item)?;
         }
         Ok(())
     }
@@ -1018,7 +1014,7 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
         match ty.node {
             ast::TyKind::Slice(ref ty) => {
                 word(&mut self.s, "[")?;
-                self.print_type(&ty)?;
+                self.print_type(ty)?;
                 word(&mut self.s, "]")?;
             }
             ast::TyKind::Ptr(ref mt) => {
@@ -1040,7 +1036,7 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
             ast::TyKind::Tup(ref elts) => {
                 self.popen()?;
                 self.commasep(Inconsistent, &elts[..],
-                              |s, ty| s.print_type(&ty))?;
+                              |s, ty| s.print_type(ty))?;
                 if elts.len() == 1 {
                     word(&mut self.s, ",")?;
                 }
@@ -1048,7 +1044,7 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
             }
             ast::TyKind::Paren(ref typ) => {
                 self.popen()?;
-                self.print_type(&typ)?;
+                self.print_type(typ)?;
                 self.pclose()?;
             }
             ast::TyKind::BareFn(ref f) => {
@@ -1081,14 +1077,14 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
             }
             ast::TyKind::Array(ref ty, ref v) => {
                 word(&mut self.s, "[")?;
-                self.print_type(&ty)?;
+                self.print_type(ty)?;
                 word(&mut self.s, "; ")?;
-                self.print_expr(&v)?;
+                self.print_expr(v)?;
                 word(&mut self.s, "]")?;
             }
             ast::TyKind::Typeof(ref e) => {
                 word(&mut self.s, "typeof(")?;
-                self.print_expr(&e)?;
+                self.print_expr(e)?;
                 word(&mut self.s, ")")?;
             }
             ast::TyKind::Infer => {
@@ -1130,7 +1126,7 @@ pub fn print_foreign_item(&mut self,
                 }
                 self.print_ident(item.ident)?;
                 self.word_space(":")?;
-                self.print_type(&t)?;
+                self.print_type(t)?;
                 word(&mut self.s, ";")?;
                 self.end()?; // end the head-ibox
                 self.end() // end the outer cbox
@@ -1187,7 +1183,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 self.head(&visibility_qualified(&item.vis, "extern crate"))?;
                 if let Some(p) = *optional_path {
                     let val = p.as_str();
-                    if val.contains("-") {
+                    if val.contains('-') {
                         self.print_string(&val, ast::StrStyle::Cooked)?;
                     } else {
                         self.print_name(p)?;
@@ -1203,7 +1199,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
             }
             ast::ItemKind::Use(ref vp) => {
                 self.head(&visibility_qualified(&item.vis, "use"))?;
-                self.print_view_path(&vp)?;
+                self.print_view_path(vp)?;
                 word(&mut self.s, ";")?;
                 self.end()?; // end inner head-block
                 self.end()?; // end outer head-block
@@ -1215,12 +1211,12 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 }
                 self.print_ident(item.ident)?;
                 self.word_space(":")?;
-                self.print_type(&ty)?;
+                self.print_type(ty)?;
                 space(&mut self.s)?;
                 self.end()?; // end the head-ibox
 
                 self.word_space("=")?;
-                self.print_expr(&expr)?;
+                self.print_expr(expr)?;
                 word(&mut self.s, ";")?;
                 self.end()?; // end the outer cbox
             }
@@ -1228,12 +1224,12 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 self.head(&visibility_qualified(&item.vis, "const"))?;
                 self.print_ident(item.ident)?;
                 self.word_space(":")?;
-                self.print_type(&ty)?;
+                self.print_type(ty)?;
                 space(&mut self.s)?;
                 self.end()?; // end the head-ibox
 
                 self.word_space("=")?;
-                self.print_expr(&expr)?;
+                self.print_expr(expr)?;
                 word(&mut self.s, ";")?;
                 self.end()?; // end the outer cbox
             }
@@ -1249,7 +1245,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                     &item.vis
                 )?;
                 word(&mut self.s, " ")?;
-                self.print_block_with_attrs(&body, &item.attrs)?;
+                self.print_block_with_attrs(body, &item.attrs)?;
             }
             ast::ItemKind::Mod(ref _mod) => {
                 self.head(&visibility_qualified(&item.vis, "mod"))?;
@@ -1282,7 +1278,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 self.print_where_clause(&params.where_clause)?;
                 space(&mut self.s)?;
                 self.word_space("=")?;
-                self.print_type(&ty)?;
+                self.print_type(ty)?;
                 word(&mut self.s, ";")?;
                 self.end()?; // end the outer ibox
             }
@@ -1297,11 +1293,11 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
             }
             ast::ItemKind::Struct(ref struct_def, ref generics) => {
                 self.head(&visibility_qualified(&item.vis, "struct"))?;
-                self.print_struct(&struct_def, generics, item.ident, item.span, true)?;
+                self.print_struct(struct_def, generics, item.ident, item.span, true)?;
             }
             ast::ItemKind::Union(ref struct_def, ref generics) => {
                 self.head(&visibility_qualified(&item.vis, "union"))?;
-                self.print_struct(&struct_def, generics, item.ident, item.span, true)?;
+                self.print_struct(struct_def, generics, item.ident, item.span, true)?;
             }
             ast::ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
                 self.head("")?;
@@ -1333,11 +1329,8 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                     space(&mut self.s)?;
                 }
 
-                match polarity {
-                    ast::ImplPolarity::Negative => {
-                        word(&mut self.s, "!")?;
-                    },
-                    _ => {}
+                if polarity == ast::ImplPolarity::Negative {
+                    word(&mut self.s, "!")?;
                 }
 
                 if let Some(ref t) = *opt_trait {
@@ -1346,7 +1339,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                     self.word_space("for")?;
                 }
 
-                self.print_type(&ty)?;
+                self.print_type(ty)?;
                 self.print_where_clause(&generics.where_clause)?;
 
                 space(&mut self.s)?;
@@ -1543,7 +1536,7 @@ pub fn print_variant(&mut self, v: &ast::Variant) -> io::Result<()> {
             Some(ref d) => {
                 space(&mut self.s)?;
                 self.word_space("=")?;
-                self.print_expr(&d)
+                self.print_expr(d)
             }
             _ => Ok(())
         }
@@ -1571,7 +1564,7 @@ pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
         self.print_outer_attributes(&ti.attrs)?;
         match ti.node {
             ast::TraitItemKind::Const(ref ty, ref default) => {
-                self.print_associated_const(ti.ident, &ty,
+                self.print_associated_const(ti.ident, ty,
                                             default.as_ref().map(|expr| &**expr),
                                             &ast::Visibility::Inherited)?;
             }
@@ -1614,7 +1607,7 @@ pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
         self.print_defaultness(ii.defaultness)?;
         match ii.node {
             ast::ImplItemKind::Const(ref ty, ref expr) => {
-                self.print_associated_const(ii.ident, &ty, Some(&expr), &ii.vis)?;
+                self.print_associated_const(ii.ident, ty, Some(expr), &ii.vis)?;
             }
             ast::ImplItemKind::Method(ref sig, ref body) => {
                 self.head("")?;
@@ -1650,38 +1643,38 @@ pub fn print_stmt(&mut self, st: &ast::Stmt) -> io::Result<()> {
                 self.word_nbsp("let")?;
 
                 self.ibox(INDENT_UNIT)?;
-                self.print_local_decl(&loc)?;
+                self.print_local_decl(loc)?;
                 self.end()?;
                 if let Some(ref init) = loc.init {
                     self.nbsp()?;
                     self.word_space("=")?;
-                    self.print_expr(&init)?;
+                    self.print_expr(init)?;
                 }
                 word(&mut self.s, ";")?;
                 self.end()?;
             }
-            ast::StmtKind::Item(ref item) => self.print_item(&item)?,
+            ast::StmtKind::Item(ref item) => self.print_item(item)?,
             ast::StmtKind::Expr(ref expr) => {
                 self.space_if_not_bol()?;
-                self.print_expr_outer_attr_style(&expr, false)?;
+                self.print_expr_outer_attr_style(expr, false)?;
                 if parse::classify::expr_requires_semi_to_be_stmt(expr) {
                     word(&mut self.s, ";")?;
                 }
             }
             ast::StmtKind::Semi(ref expr) => {
                 self.space_if_not_bol()?;
-                self.print_expr_outer_attr_style(&expr, false)?;
+                self.print_expr_outer_attr_style(expr, false)?;
                 word(&mut self.s, ";")?;
             }
             ast::StmtKind::Mac(ref mac) => {
                 let (ref mac, style, ref attrs) = **mac;
                 self.space_if_not_bol()?;
-                self.print_outer_attributes(&attrs)?;
+                self.print_outer_attributes(attrs)?;
                 let delim = match style {
                     ast::MacStmtStyle::Braces => token::Brace,
                     _ => token::Paren
                 };
-                self.print_mac(&mac, delim)?;
+                self.print_mac(mac, delim)?;
                 if style == ast::MacStmtStyle::Semicolon {
                     word(&mut self.s, ";")?;
                 }
@@ -1735,7 +1728,7 @@ pub fn print_block_maybe_unclosed(&mut self,
                 ast::StmtKind::Expr(ref expr) if i == blk.stmts.len() - 1 => {
                     self.maybe_print_comment(st.span.lo)?;
                     self.space_if_not_bol()?;
-                    self.print_expr_outer_attr_style(&expr, false)?;
+                    self.print_expr_outer_attr_style(expr, false)?;
                     self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi))?;
                 }
                 _ => self.print_stmt(st)?,
@@ -1755,9 +1748,9 @@ fn print_else(&mut self, els: Option<&ast::Expr>) -> io::Result<()> {
                         self.cbox(INDENT_UNIT - 1)?;
                         self.ibox(0)?;
                         word(&mut self.s, " else if ")?;
-                        self.print_expr(&i)?;
+                        self.print_expr(i)?;
                         space(&mut self.s)?;
-                        self.print_block(&then)?;
+                        self.print_block(then)?;
                         self.print_else(e.as_ref().map(|e| &**e))
                     }
                     // "another else-if-let"
@@ -1765,12 +1758,12 @@ fn print_else(&mut self, els: Option<&ast::Expr>) -> io::Result<()> {
                         self.cbox(INDENT_UNIT - 1)?;
                         self.ibox(0)?;
                         word(&mut self.s, " else if let ")?;
-                        self.print_pat(&pat)?;
+                        self.print_pat(pat)?;
                         space(&mut self.s)?;
                         self.word_space("=")?;
-                        self.print_expr(&expr)?;
+                        self.print_expr(expr)?;
                         space(&mut self.s)?;
-                        self.print_block(&then)?;
+                        self.print_block(then)?;
                         self.print_else(e.as_ref().map(|e| &**e))
                     }
                     // "final else"
@@ -1778,7 +1771,7 @@ fn print_else(&mut self, els: Option<&ast::Expr>) -> io::Result<()> {
                         self.cbox(INDENT_UNIT - 1)?;
                         self.ibox(0)?;
                         word(&mut self.s, " else ")?;
-                        self.print_block(&b)
+                        self.print_block(b)
                     }
                     // BLEAH, constraints would be great here
                     _ => {
@@ -1844,12 +1837,8 @@ pub fn check_expr_bin_needs_paren(&mut self, sub_expr: &ast::Expr,
                                       binop: ast::BinOp) -> bool {
         match sub_expr.node {
             ast::ExprKind::Binary(ref sub_op, _, _) => {
-                if AssocOp::from_ast_binop(sub_op.node).precedence() <
-                    AssocOp::from_ast_binop(binop.node).precedence() {
-                    true
-                } else {
-                    false
-                }
+                AssocOp::from_ast_binop(sub_op.node).precedence() <
+                    AssocOp::from_ast_binop(binop.node).precedence()
             }
             _ => true
         }
@@ -1929,7 +1918,7 @@ fn print_expr_struct(&mut self,
                     space(&mut self.s)?;
                 }
                 word(&mut self.s, "..")?;
-                self.print_expr(&expr)?;
+                self.print_expr(expr)?;
                 self.end()?;
             }
             _ => if !fields.is_empty() {
@@ -1969,7 +1958,7 @@ fn print_expr_method_call(&mut self,
         if !tys.is_empty() {
             word(&mut self.s, "::<")?;
             self.commasep(Inconsistent, tys,
-                          |s, ty| s.print_type(&ty))?;
+                          |s, ty| s.print_type(ty))?;
             word(&mut self.s, ">")?;
         }
         self.print_call_post(base_args)
@@ -2038,7 +2027,7 @@ fn print_expr_outer_attr_style(&mut self,
                 self.print_expr_vec(&exprs[..], attrs)?;
             }
             ast::ExprKind::Repeat(ref element, ref count) => {
-                self.print_expr_repeat(&element, &count, attrs)?;
+                self.print_expr_repeat(element, count, attrs)?;
             }
             ast::ExprKind::Struct(ref path, ref fields, ref wth) => {
                 self.print_expr_struct(path, &fields[..], wth, attrs)?;
@@ -2047,43 +2036,43 @@ fn print_expr_outer_attr_style(&mut self,
                 self.print_expr_tup(&exprs[..], attrs)?;
             }
             ast::ExprKind::Call(ref func, ref args) => {
-                self.print_expr_call(&func, &args[..])?;
+                self.print_expr_call(func, &args[..])?;
             }
             ast::ExprKind::MethodCall(ident, ref tys, ref args) => {
                 self.print_expr_method_call(ident, &tys[..], &args[..])?;
             }
             ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
-                self.print_expr_binary(op, &lhs, &rhs)?;
+                self.print_expr_binary(op, lhs, rhs)?;
             }
             ast::ExprKind::Unary(op, ref expr) => {
-                self.print_expr_unary(op, &expr)?;
+                self.print_expr_unary(op, expr)?;
             }
             ast::ExprKind::AddrOf(m, ref expr) => {
-                self.print_expr_addr_of(m, &expr)?;
+                self.print_expr_addr_of(m, expr)?;
             }
             ast::ExprKind::Lit(ref lit) => {
-                self.print_literal(&lit)?;
+                self.print_literal(lit)?;
             }
             ast::ExprKind::Cast(ref expr, ref ty) => {
                 if let ast::ExprKind::Cast(..) = expr.node {
-                    self.print_expr(&expr)?;
+                    self.print_expr(expr)?;
                 } else {
-                    self.print_expr_maybe_paren(&expr)?;
+                    self.print_expr_maybe_paren(expr)?;
                 }
                 space(&mut self.s)?;
                 self.word_space("as")?;
-                self.print_type(&ty)?;
+                self.print_type(ty)?;
             }
             ast::ExprKind::Type(ref expr, ref ty) => {
-                self.print_expr(&expr)?;
+                self.print_expr(expr)?;
                 self.word_space(":")?;
-                self.print_type(&ty)?;
+                self.print_type(ty)?;
             }
             ast::ExprKind::If(ref test, ref blk, ref elseopt) => {
-                self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?;
+                self.print_if(test, blk, elseopt.as_ref().map(|e| &**e))?;
             }
             ast::ExprKind::IfLet(ref pat, ref expr, ref blk, ref elseopt) => {
-                self.print_if_let(&pat, &expr, &blk, elseopt.as_ref().map(|e| &**e))?;
+                self.print_if_let(pat, expr, blk, elseopt.as_ref().map(|e| &**e))?;
             }
             ast::ExprKind::While(ref test, ref blk, opt_ident) => {
                 if let Some(ident) = opt_ident {
@@ -2091,9 +2080,9 @@ fn print_expr_outer_attr_style(&mut self,
                     self.word_space(":")?;
                 }
                 self.head("while")?;
-                self.print_expr(&test)?;
+                self.print_expr(test)?;
                 space(&mut self.s)?;
-                self.print_block_with_attrs(&blk, attrs)?;
+                self.print_block_with_attrs(blk, attrs)?;
             }
             ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_ident) => {
                 if let Some(ident) = opt_ident {
@@ -2101,12 +2090,12 @@ fn print_expr_outer_attr_style(&mut self,
                     self.word_space(":")?;
                 }
                 self.head("while let")?;
-                self.print_pat(&pat)?;
+                self.print_pat(pat)?;
                 space(&mut self.s)?;
                 self.word_space("=")?;
-                self.print_expr(&expr)?;
+                self.print_expr(expr)?;
                 space(&mut self.s)?;
-                self.print_block_with_attrs(&blk, attrs)?;
+                self.print_block_with_attrs(blk, attrs)?;
             }
             ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_ident) => {
                 if let Some(ident) = opt_ident {
@@ -2114,12 +2103,12 @@ fn print_expr_outer_attr_style(&mut self,
                     self.word_space(":")?;
                 }
                 self.head("for")?;
-                self.print_pat(&pat)?;
+                self.print_pat(pat)?;
                 space(&mut self.s)?;
                 self.word_space("in")?;
-                self.print_expr(&iter)?;
+                self.print_expr(iter)?;
                 space(&mut self.s)?;
-                self.print_block_with_attrs(&blk, attrs)?;
+                self.print_block_with_attrs(blk, attrs)?;
             }
             ast::ExprKind::Loop(ref blk, opt_ident) => {
                 if let Some(ident) = opt_ident {
@@ -2128,13 +2117,13 @@ fn print_expr_outer_attr_style(&mut self,
                 }
                 self.head("loop")?;
                 space(&mut self.s)?;
-                self.print_block_with_attrs(&blk, attrs)?;
+                self.print_block_with_attrs(blk, attrs)?;
             }
             ast::ExprKind::Match(ref expr, ref arms) => {
                 self.cbox(INDENT_UNIT)?;
                 self.ibox(4)?;
                 self.word_nbsp("match")?;
-                self.print_expr(&expr)?;
+                self.print_expr(expr)?;
                 space(&mut self.s)?;
                 self.bopen()?;
                 self.print_inner_attributes_no_trailing_hardbreak(attrs)?;
@@ -2146,7 +2135,7 @@ fn print_expr_outer_attr_style(&mut self,
             ast::ExprKind::Closure(capture_clause, ref decl, ref body, _) => {
                 self.print_capture_clause(capture_clause)?;
 
-                self.print_fn_block_args(&decl)?;
+                self.print_fn_block_args(decl)?;
                 space(&mut self.s)?;
                 self.print_expr(body)?;
                 self.end()?; // need to close a box
@@ -2161,48 +2150,48 @@ fn print_expr_outer_attr_style(&mut self,
                 self.cbox(INDENT_UNIT)?;
                 // head-box, will be closed by print-block after {
                 self.ibox(0)?;
-                self.print_block_with_attrs(&blk, attrs)?;
+                self.print_block_with_attrs(blk, attrs)?;
             }
             ast::ExprKind::Assign(ref lhs, ref rhs) => {
-                self.print_expr(&lhs)?;
+                self.print_expr(lhs)?;
                 space(&mut self.s)?;
                 self.word_space("=")?;
-                self.print_expr(&rhs)?;
+                self.print_expr(rhs)?;
             }
             ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
-                self.print_expr(&lhs)?;
+                self.print_expr(lhs)?;
                 space(&mut self.s)?;
                 word(&mut self.s, op.node.to_string())?;
                 self.word_space("=")?;
-                self.print_expr(&rhs)?;
+                self.print_expr(rhs)?;
             }
             ast::ExprKind::Field(ref expr, id) => {
-                self.print_expr(&expr)?;
+                self.print_expr(expr)?;
                 word(&mut self.s, ".")?;
                 self.print_ident(id.node)?;
             }
             ast::ExprKind::TupField(ref expr, id) => {
-                self.print_expr(&expr)?;
+                self.print_expr(expr)?;
                 word(&mut self.s, ".")?;
                 self.print_usize(id.node)?;
             }
             ast::ExprKind::Index(ref expr, ref index) => {
-                self.print_expr(&expr)?;
+                self.print_expr(expr)?;
                 word(&mut self.s, "[")?;
-                self.print_expr(&index)?;
+                self.print_expr(index)?;
                 word(&mut self.s, "]")?;
             }
             ast::ExprKind::Range(ref start, ref end, limits) => {
-                if let &Some(ref e) = start {
-                    self.print_expr(&e)?;
+                if let Some(ref e) = *start {
+                    self.print_expr(e)?;
                 }
                 if limits == ast::RangeLimits::HalfOpen {
                     word(&mut self.s, "..")?;
                 } else {
                     word(&mut self.s, "...")?;
                 }
-                if let &Some(ref e) = end {
-                    self.print_expr(&e)?;
+                if let Some(ref e) = *end {
+                    self.print_expr(e)?;
                 }
             }
             ast::ExprKind::Path(None, ref path) => {
@@ -2233,12 +2222,9 @@ fn print_expr_outer_attr_style(&mut self,
             }
             ast::ExprKind::Ret(ref result) => {
                 word(&mut self.s, "return")?;
-                match *result {
-                    Some(ref expr) => {
-                        word(&mut self.s, " ")?;
-                        self.print_expr(&expr)?;
-                    }
-                    _ => ()
+                if let Some(ref expr) = *result {
+                    word(&mut self.s, " ")?;
+                    self.print_expr(expr)?;
                 }
             }
             ast::ExprKind::InlineAsm(ref a) => {
@@ -2268,7 +2254,7 @@ fn print_expr_outer_attr_style(&mut self,
                 self.commasep(Inconsistent, &a.inputs, |s, &(co, ref o)| {
                     s.print_string(&co.as_str(), ast::StrStyle::Cooked)?;
                     s.popen()?;
-                    s.print_expr(&o)?;
+                    s.print_expr(o)?;
                     s.pclose()?;
                     Ok(())
                 })?;
@@ -2308,7 +2294,7 @@ fn print_expr_outer_attr_style(&mut self,
             ast::ExprKind::Paren(ref e) => {
                 self.popen()?;
                 self.print_inner_attributes_inline(attrs)?;
-                self.print_expr(&e)?;
+                self.print_expr(e)?;
                 self.pclose()?;
             },
             ast::ExprKind::Try(ref e) => {
@@ -2318,7 +2304,7 @@ fn print_expr_outer_attr_style(&mut self,
             ast::ExprKind::Catch(ref blk) => {
                 self.head("do catch")?;
                 space(&mut self.s)?;
-                self.print_block_with_attrs(&blk, attrs)?
+                self.print_block_with_attrs(blk, attrs)?
             }
         }
         self.ann.post(self, NodeExpr(expr))?;
@@ -2329,7 +2315,7 @@ pub fn print_local_decl(&mut self, loc: &ast::Local) -> io::Result<()> {
         self.print_pat(&loc.pat)?;
         if let Some(ref ty) = loc.ty {
             self.word_space(":")?;
-            self.print_type(&ty)?;
+            self.print_type(ty)?;
         }
         Ok(())
     }
@@ -2397,7 +2383,7 @@ fn print_qpath(&mut self,
             space(&mut self.s)?;
             self.word_space("as")?;
             let depth = path.segments.len() - qself.position;
-            self.print_path(&path, false, depth, false)?;
+            self.print_path(path, false, depth, false)?;
         }
         word(&mut self.s, ">")?;
         word(&mut self.s, "::")?;
@@ -2438,7 +2424,7 @@ fn print_path_parameters(&mut self,
                     self.commasep(
                         Inconsistent,
                         &data.types,
-                        |s, ty| s.print_type(&ty))?;
+                        |s, ty| s.print_type(ty))?;
                         comma = true;
                 }
 
@@ -2461,13 +2447,13 @@ fn print_path_parameters(&mut self,
                 self.commasep(
                     Inconsistent,
                     &data.inputs,
-                    |s, ty| s.print_type(&ty))?;
+                    |s, ty| s.print_type(ty))?;
                 word(&mut self.s, ")")?;
 
                 if let Some(ref ty) = data.output {
                     self.space_if_not_bol()?;
                     self.word_space("->")?;
-                    self.print_type(&ty)?;
+                    self.print_type(ty)?;
                 }
             }
         }
@@ -2496,24 +2482,24 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
                 self.print_ident(path1.node)?;
                 if let Some(ref p) = *sub {
                     word(&mut self.s, "@")?;
-                    self.print_pat(&p)?;
+                    self.print_pat(p)?;
                 }
             }
             PatKind::TupleStruct(ref path, ref elts, ddpos) => {
                 self.print_path(path, true, 0, false)?;
                 self.popen()?;
                 if let Some(ddpos) = ddpos {
-                    self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
+                    self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p))?;
                     if ddpos != 0 {
                         self.word_space(",")?;
                     }
                     word(&mut self.s, "..")?;
                     if ddpos != elts.len() {
                         word(&mut self.s, ",")?;
-                        self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?;
+                        self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p))?;
                     }
                 } else {
-                    self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?;
+                    self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p))?;
                 }
                 self.pclose()?;
             }
@@ -2549,17 +2535,17 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
             PatKind::Tuple(ref elts, ddpos) => {
                 self.popen()?;
                 if let Some(ddpos) = ddpos {
-                    self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
+                    self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p))?;
                     if ddpos != 0 {
                         self.word_space(",")?;
                     }
                     word(&mut self.s, "..")?;
                     if ddpos != elts.len() {
                         word(&mut self.s, ",")?;
-                        self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?;
+                        self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p))?;
                     }
                 } else {
-                    self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?;
+                    self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p))?;
                     if elts.len() == 1 {
                         word(&mut self.s, ",")?;
                     }
@@ -2568,41 +2554,41 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
             }
             PatKind::Box(ref inner) => {
                 word(&mut self.s, "box ")?;
-                self.print_pat(&inner)?;
+                self.print_pat(inner)?;
             }
             PatKind::Ref(ref inner, mutbl) => {
                 word(&mut self.s, "&")?;
                 if mutbl == ast::Mutability::Mutable {
                     word(&mut self.s, "mut ")?;
                 }
-                self.print_pat(&inner)?;
+                self.print_pat(inner)?;
             }
             PatKind::Lit(ref e) => self.print_expr(&**e)?,
             PatKind::Range(ref begin, ref end, ref end_kind) => {
-                self.print_expr(&begin)?;
+                self.print_expr(begin)?;
                 space(&mut self.s)?;
                 match *end_kind {
                     RangeEnd::Included => word(&mut self.s, "...")?,
                     RangeEnd::Excluded => word(&mut self.s, "..")?,
                 }
-                self.print_expr(&end)?;
+                self.print_expr(end)?;
             }
             PatKind::Slice(ref before, ref slice, ref after) => {
                 word(&mut self.s, "[")?;
                 self.commasep(Inconsistent,
                                    &before[..],
-                                   |s, p| s.print_pat(&p))?;
+                                   |s, p| s.print_pat(p))?;
                 if let Some(ref p) = *slice {
                     if !before.is_empty() { self.word_space(",")?; }
                     if p.node != PatKind::Wild {
-                        self.print_pat(&p)?;
+                        self.print_pat(p)?;
                     }
                     word(&mut self.s, "..")?;
                     if !after.is_empty() { self.word_space(",")?; }
                 }
                 self.commasep(Inconsistent,
                                    &after[..],
-                                   |s, p| s.print_pat(&p))?;
+                                   |s, p| s.print_pat(p))?;
                 word(&mut self.s, "]")?;
             }
             PatKind::Mac(ref m) => self.print_mac(m, token::Paren)?,
@@ -2628,12 +2614,12 @@ fn print_arm(&mut self, arm: &ast::Arm) -> io::Result<()> {
                 space(&mut self.s)?;
                 self.word_space("|")?;
             }
-            self.print_pat(&p)?;
+            self.print_pat(p)?;
         }
         space(&mut self.s)?;
         if let Some(ref e) = arm.guard {
             self.word_space("if")?;
-            self.print_expr(&e)?;
+            self.print_expr(e)?;
             space(&mut self.s)?;
         }
         self.word_space("=>")?;
@@ -2641,7 +2627,7 @@ fn print_arm(&mut self, arm: &ast::Arm) -> io::Result<()> {
         match arm.body.node {
             ast::ExprKind::Block(ref blk) => {
                 // the block will close the pattern's ibox
-                self.print_block_unclosed_indent(&blk, INDENT_UNIT)?;
+                self.print_block_unclosed_indent(blk, INDENT_UNIT)?;
 
                 // If it is a user-provided unsafe block, print a comma after it
                 if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules {
@@ -2673,7 +2659,7 @@ fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) -> io::Resu
                 self.print_mutability(m)?;
                 word(&mut self.s, "self")?;
                 self.word_space(":")?;
-                self.print_type(&typ)
+                self.print_type(typ)
             }
         }
     }
@@ -2725,7 +2711,7 @@ pub fn print_fn_block_args(
         self.word_space("->")?;
         match decl.output {
             ast::FunctionRetTy::Ty(ref ty) => {
-                self.print_type(&ty)?;
+                self.print_type(ty)?;
                 self.maybe_print_comment(ty.span.lo)
             }
             ast::FunctionRetTy::Default(..) => unreachable!(),
@@ -2839,7 +2825,7 @@ pub fn print_ty_param(&mut self, param: &ast::TyParam) -> io::Result<()> {
             Some(ref default) => {
                 space(&mut self.s)?;
                 self.word_space("=")?;
-                self.print_type(&default)
+                self.print_type(default)
             }
             _ => Ok(())
         }
@@ -2865,7 +2851,7 @@ pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause)
                                                                              ref bounds,
                                                                              ..}) => {
                     self.print_formal_lifetime_list(bound_lifetimes)?;
-                    self.print_type(&bounded_ty)?;
+                    self.print_type(bounded_ty)?;
                     self.print_bounds(":", bounds)?;
                 }
                 ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
@@ -2977,7 +2963,7 @@ pub fn print_fn_output(&mut self, decl: &ast::FnDecl) -> io::Result<()> {
         match decl.output {
             ast::FunctionRetTy::Default(..) => unreachable!(),
             ast::FunctionRetTy::Ty(ref ty) =>
-                self.print_type(&ty)?
+                self.print_type(ty)?
         }
         self.end()?;
 
@@ -3044,14 +3030,9 @@ pub fn print_remaining_comments(&mut self) -> io::Result<()> {
         if self.next_comment().is_none() {
             hardbreak(&mut self.s)?;
         }
-        loop {
-            match self.next_comment() {
-                Some(ref cmnt) => {
-                    self.print_comment(cmnt)?;
-                    self.cur_cmnt_and_lit.cur_cmnt += 1;
-                }
-                _ => break
-            }
+        while let Some(ref cmnt) = self.next_comment() {
+            self.print_comment(cmnt)?;
+            self.cur_cmnt_and_lit.cur_cmnt += 1;
         }
         Ok(())
     }
index c7820a15fb3d23d9f8c0a6fb41c59e2e2af45012..8e257102e1c13367d281d01cce701e94bb0bacf5 100644 (file)
@@ -18,7 +18,7 @@
 use tokenstream::TokenStream;
 
 /// Craft a span that will be ignored by the stability lint's
-/// call to codemap's is_internal check.
+/// call to codemap's `is_internal` check.
 /// The expanded code uses the unstable `#[prelude_import]` attribute.
 fn ignored_span(sp: Span) -> Span {
     let mark = Mark::fresh();
@@ -49,7 +49,7 @@ pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<Strin
         None => return krate,
     };
 
-    let crate_name = Symbol::intern(&alt_std_name.unwrap_or(name.to_string()));
+    let crate_name = Symbol::intern(&alt_std_name.unwrap_or_else(|| name.to_string()));
 
     krate.module.items.insert(0, P(ast::Item {
         attrs: vec![attr::mk_attr_outer(DUMMY_SP,
index 91746a2edd9b2a62abc70b84d7647ce277b5174a..bb1a6ff65a596018a263bc7aa94e941e24da1b78 100644 (file)
@@ -106,9 +106,8 @@ fn fold_crate(&mut self, c: ast::Crate) -> ast::Crate {
         // Add a special __test module to the crate that will contain code
         // generated for the test harness
         let (mod_, reexport) = mk_test_module(&mut self.cx);
-        match reexport {
-            Some(re) => folded.module.items.push(re),
-            None => {}
+        if let Some(re) = reexport {
+            folded.module.items.push(re)
         }
         folded.module.items.push(mod_);
         folded
@@ -257,7 +256,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt,
     let parent = if parent == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { parent };
     cx.ext_cx.current_expansion.mark = cx.ext_cx.resolver.get_module_scope(parent);
     let it = cx.ext_cx.monotonic_expander().fold_item(P(ast::Item {
-        ident: sym.clone(),
+        ident: sym,
         attrs: Vec::new(),
         id: ast::DUMMY_NODE_ID,
         node: ast::ItemKind::Mod(reexport_mod),
@@ -308,7 +307,7 @@ fn generate_test_harness(sess: &ParseSess,
 }
 
 /// Craft a span that will be ignored by the stability lint's
-/// call to codemap's is_internal check.
+/// call to codemap's `is_internal` check.
 /// The expanded code calls some unstable functions in the test crate.
 fn ignored_span(cx: &TestCtxt, sp: Span) -> Span {
     Span { ctxt: cx.ctxt, ..sp }
@@ -354,7 +353,7 @@ fn has_test_signature(i: &ast::Item) -> HasTestSignature {
         }
     }
 
-    return has_test_attr && has_test_signature(i) == Yes;
+    has_test_attr && has_test_signature(i) == Yes
 }
 
 fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
@@ -385,7 +384,7 @@ fn has_test_signature(i: &ast::Item) -> bool {
                       `fn(&mut Bencher) -> ()`");
     }
 
-    return has_bench_attr && has_test_signature(i);
+    has_bench_attr && has_test_signature(i)
 }
 
 fn is_ignored(i: &ast::Item) -> bool {
@@ -504,16 +503,14 @@ fn mk_main(cx: &mut TestCtxt) -> P<ast::Item> {
                            ast::Unsafety::Normal,
                            dummy_spanned(ast::Constness::NotConst),
                            ::abi::Abi::Rust, ast::Generics::default(), main_body);
-    let main = P(ast::Item {
+    P(ast::Item {
         ident: Ident::from_str("main"),
         attrs: vec![main_attr],
         id: ast::DUMMY_NODE_ID,
         node: main,
         vis: ast::Visibility::Public,
         span: sp
-    });
-
-    return main;
+    })
 }
 
 fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<P<ast::Item>>) {
index 86bfdebe42b0082e206b6a836b66916ce4061846..9c1371a31fec7a9287f9f874c5d59defe042056e 100644 (file)
 
 //! # Token Streams
 //!
-//! TokenStreams represent syntactic objects before they are converted into ASTs.
+//! `TokenStream`s represent syntactic objects before they are converted into ASTs.
 //! A `TokenStream` is, roughly speaking, a sequence (eg stream) of `TokenTree`s,
 //! which are themselves a single `Token` or a `Delimited` subsequence of tokens.
 //!
 //! ## Ownership
-//! TokenStreams are persistent data structures constructed as ropes with reference
-//! counted-children. In general, this means that calling an operation on a TokenStream
-//! (such as `slice`) produces an entirely new TokenStream from the borrowed reference to
-//! the original. This essentially coerces TokenStreams into 'views' of their subparts,
-//! and a borrowed TokenStream is sufficient to build an owned TokenStream without taking
+//! `TokenStreams` are persistent data structures constructed as ropes with reference
+//! counted-children. In general, this means that calling an operation on a `TokenStream`
+//! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to
+//! the original. This essentially coerces `TokenStream`s into 'views' of their subparts,
+//! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking
 //! ownership of the original.
 
 use syntax_pos::{BytePos, Span, DUMMY_SP};
@@ -88,7 +88,7 @@ pub fn stream(&self) -> TokenStream {
 /// If the syntax extension is an MBE macro, it will attempt to match its
 /// LHS token tree against the provided token tree, and if it finds a
 /// match, will transcribe the RHS token tree, splicing in any captured
-/// macro_parser::matched_nonterminals into the `SubstNt`s it finds.
+/// `macro_parser::matched_nonterminals` into the `SubstNt`s it finds.
 ///
 /// The RHS of an MBE macro is the only place `SubstNt`s are substituted.
 /// Nothing special happens to misnamed or misplaced `SubstNt`s.
index a6fff2d707469ffd2d4d1607dfb658b62b4a1139..9307f3c58d4b0eb5d6942e9e8e6ee5ac23769688 100644 (file)
@@ -53,9 +53,10 @@ pub fn find_best_match_for_name<'a, T>(iter_names: T,
     iter_names
     .filter_map(|&name| {
         let dist = lev_distance(lookup, &name.as_str());
-        match dist <= max_dist {    // filter the unwanted cases
-            true => Some((name, dist)),
-            false => None,
+        if dist <= max_dist {    // filter the unwanted cases
+            Some((name, dist))
+        } else {
+            None
         }
     })
     .min_by_key(|&(_, val)| val)    // extract the tuple containing the minimum edit distance
index fe05e2958b3a851dd1e6828a99560cf07b3e082a..8cc37afa354ffbeed217349ae7d96cf01f1f0f28 100644 (file)
@@ -37,10 +37,10 @@ fn move_flat_map<F, I>(mut self, mut f: F) -> Self
                 // move the read_i'th item out of the vector and map it
                 // to an iterator
                 let e = ptr::read(self.get_unchecked(read_i));
-                let mut iter = f(e).into_iter();
+                let iter = f(e).into_iter();
                 read_i += 1;
 
-                while let Some(e) = iter.next() {
+                for e in iter {
                     if write_i < read_i {
                         ptr::write(self.get_unchecked_mut(write_i), e);
                         write_i += 1;
@@ -93,10 +93,10 @@ fn move_flat_map<F, I>(mut self, mut f: F) -> Self
                 // move the read_i'th item out of the vector and map it
                 // to an iterator
                 let e = ptr::read(self.get_unchecked(read_i));
-                let mut iter = f(e).into_iter();
+                let iter = f(e).into_iter();
                 read_i += 1;
 
-                while let Some(e) = iter.next() {
+                for e in iter {
                     if write_i < read_i {
                         ptr::write(self.get_unchecked_mut(write_i), e);
                         write_i += 1;
index 9d9957a0f45341c06746f44d886b842b1caa0c28..0a5d0c2e7fe010d54514fbcae37a727762cc32d2 100644 (file)
@@ -31,7 +31,7 @@ fn visit_ident(&mut self, span: Span, ident: Ident) {
         self.count += 1;
         walk_ident(self, span, ident);
     }
-    fn visit_mod(&mut self, m: &Mod, _s: Span, _n: NodeId) {
+    fn visit_mod(&mut self, m: &Mod, _s: Span, _a: &[Attribute], _n: NodeId) {
         self.count += 1;
         walk_mod(self, m)
     }
index 2e42c6986e64e1d527af2b5699958e6c98e144c5..0fa0753b22c8298276987aa44eff0d5d6c39f5bd 100644 (file)
@@ -27,6 +27,7 @@
 use ast::*;
 use syntax_pos::Span;
 use codemap::Spanned;
+use tokenstream::ThinTokenStream;
 
 #[derive(Copy, Clone, PartialEq, Eq)]
 pub enum FnKind<'a> {
@@ -56,7 +57,9 @@ fn visit_name(&mut self, _span: Span, _name: Name) {
     fn visit_ident(&mut self, span: Span, ident: Ident) {
         walk_ident(self, span, ident);
     }
-    fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _n: NodeId) { walk_mod(self, m) }
+    fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _attrs: &[Attribute], _n: NodeId) {
+        walk_mod(self, m);
+    }
     fn visit_foreign_item(&mut self, i: &'ast ForeignItem) { walk_foreign_item(self, i) }
     fn visit_global_asm(&mut self, ga: &'ast GlobalAsm) { walk_global_asm(self, ga) }
     fn visit_item(&mut self, i: &'ast Item) { walk_item(self, i) }
@@ -110,6 +113,9 @@ fn visit_mac(&mut self, _mac: &'ast Mac) {
         // definition in your trait impl:
         // visit::walk_mac(self, _mac)
     }
+    fn visit_mac_def(&mut self, _mac: &'ast ThinTokenStream, _id: NodeId) {
+        // Nothing to do
+    }
     fn visit_path(&mut self, path: &'ast Path, _id: NodeId) {
         walk_path(self, path)
     }
@@ -172,7 +178,7 @@ pub fn walk_ident<'a, V: Visitor<'a>>(visitor: &mut V, span: Span, ident: Ident)
 }
 
 pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) {
-    visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
+    visitor.visit_mod(&krate.module, krate.span, &krate.attrs, CRATE_NODE_ID);
     walk_list!(visitor, visit_attribute, &krate.attrs);
 }
 
@@ -249,7 +255,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
                              item.id)
         }
         ItemKind::Mod(ref module) => {
-            visitor.visit_mod(module, item.span, item.id)
+            visitor.visit_mod(module, item.span, &item.attrs, item.id)
         }
         ItemKind::ForeignMod(ref foreign_module) => {
             walk_list!(visitor, visit_foreign_item, &foreign_module.items);
@@ -288,7 +294,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             walk_list!(visitor, visit_trait_item, methods);
         }
         ItemKind::Mac(ref mac) => visitor.visit_mac(mac),
-        ItemKind::MacroDef(..) => {},
+        ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id),
     }
     walk_list!(visitor, visit_attribute, &item.attrs);
 }
@@ -343,9 +349,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
             visitor.visit_ty(ty);
             visitor.visit_expr(expression)
         }
-        TyKind::TraitObject(ref bounds) => {
-            walk_list!(visitor, visit_ty_param_bound, bounds);
-        }
+        TyKind::TraitObject(ref bounds) |
         TyKind::ImplTrait(ref bounds) => {
             walk_list!(visitor, visit_ty_param_bound, bounds);
         }
@@ -540,7 +544,7 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl
             walk_fn_decl(visitor, declaration);
             visitor.visit_block(body);
         }
-        FnKind::Method(_, ref sig, _, body) => {
+        FnKind::Method(_, sig, _, body) => {
             visitor.visit_generics(&sig.generics);
             walk_fn_decl(visitor, declaration);
             visitor.visit_block(body);
@@ -776,7 +780,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
         }
         ExprKind::InlineAsm(ref ia) => {
             for &(_, ref input) in &ia.inputs {
-                visitor.visit_expr(&input)
+                visitor.visit_expr(input)
             }
             for output in &ia.outputs {
                 visitor.visit_expr(&output.expr)
index b2bb43e41ed9ee0763c67208736cf36e558ee556..31c7cc33676776487a41e6247add158c0edf673a 100644 (file)
@@ -25,12 +25,6 @@ macro_rules! pathvec {
     )
 }
 
-macro_rules! path {
-    ($($x:tt)*) => (
-        ::ext::deriving::generic::ty::Path::new( pathvec![ $($x)* ] )
-    )
-}
-
 macro_rules! path_local {
     ($x:ident) => (
         ::deriving::generic::ty::Path::new_local(stringify!($x))
index e35e79df5852066cea8c85a228e3c89b9a40aa65..60f5d24ac97552533141eff4b4ccffe2d44d5b05 100644 (file)
@@ -11,7 +11,6 @@
 //! Syntax extensions in the Rust compiler.
 
 #![crate_name = "syntax_ext"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 #![deny(warnings)]
 
 #![feature(proc_macro_internals)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
 
 extern crate fmt_macros;
 extern crate log;
index bb89caab709b0e8831c0eee51d742c7e4c120e9a..6318abec69f06526c158e74da6454a12fa36b364 100644 (file)
@@ -329,7 +329,7 @@ fn visit_item(&mut self, item: &'a ast::Item) {
         visit::walk_item(self, item);
     }
 
-    fn visit_mod(&mut self, m: &'a ast::Mod, _s: Span, id: NodeId) {
+    fn visit_mod(&mut self, m: &'a ast::Mod, _s: Span, _a: &[ast::Attribute], id: NodeId) {
         let mut prev_in_root = self.in_root;
         if id != ast::CRATE_NODE_ID {
             prev_in_root = mem::replace(&mut self.in_root, false);
index f46b4fcb715b088da96a2c7bf2aa277deb9dc192..25f74aeecf4046eed1ce357fb435ed246a002203 100644 (file)
@@ -15,7 +15,6 @@
 //! This API is completely unstable and subject to change.
 
 #![crate_name = "syntax_pos"]
-#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 #![feature(custom_attribute)]
 #![feature(optin_builtin_traits)]
 #![allow(unused_attributes)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
 #![feature(specialization)]
 
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
 use std::cell::{Cell, RefCell};
 use std::ops::{Add, Sub};
 use std::rc::Rc;
@@ -377,6 +378,8 @@ pub struct FileMap {
     pub name: FileName,
     /// True if the `name` field above has been modified by -Zremap-path-prefix
     pub name_was_remapped: bool,
+    /// Indicates which crate this FileMap was imported from.
+    pub crate_of_origin: u32,
     /// The complete source code
     pub src: Option<Rc<String>>,
     /// The start position of this source in the CodeMap
@@ -491,6 +494,10 @@ fn decode<D: Decoder>(d: &mut D) -> Result<FileMap, D::Error> {
             Ok(FileMap {
                 name: name,
                 name_was_remapped: name_was_remapped,
+                // `crate_of_origin` has to be set by the importer.
+                // This value matches up with rustc::hir::def_id::INVALID_CRATE.
+                // That constant is not available here unfortunately :(
+                crate_of_origin: ::std::u32::MAX - 1,
                 start_pos: start_pos,
                 end_pos: end_pos,
                 src: None,
index 370757c06091013b53892579cc0d24fc686b8afd..eb0ee6ba154a187bb390b08fdf780231412a5d32 100644 (file)
@@ -41,9 +41,6 @@
 //! [ti]: https://en.wikipedia.org/wiki/Terminfo
 
 #![crate_name = "term"]
-#![unstable(feature = "rustc_private",
-            reason = "use the crates.io `term` library instead",
-            issue = "27812")]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
 #![deny(missing_docs)]
 #![deny(warnings)]
 
-#![feature(box_syntax)]
 #![feature(staged_api)]
 #![cfg_attr(windows, feature(libc))]
 // Handle rustfmt skips
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
 
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(staged_api))]
+
 use std::io::prelude::*;
 
 pub use terminfo::TerminfoTerminal;
index 35f2fbca69f8df2613da9e0ca38174e7002459a9..ef048ac8ca355f9ea0e43f3bc5c1cb9774de0fb4 100644 (file)
@@ -542,6 +542,7 @@ struct ConsoleTestState<T> {
     passed: usize,
     failed: usize,
     ignored: usize,
+    filtered_out: usize,
     measured: usize,
     metrics: MetricMap,
     failures: Vec<(TestDesc, Vec<u8>)>,
@@ -570,6 +571,7 @@ pub fn new(opts: &TestOpts, _: Option<T>) -> io::Result<ConsoleTestState<io::Std
             passed: 0,
             failed: 0,
             ignored: 0,
+            filtered_out: 0,
             measured: 0,
             metrics: MetricMap::new(),
             failures: Vec::new(),
@@ -775,11 +777,12 @@ pub fn write_run_finish(&mut self) -> io::Result<bool> {
         } else {
             self.write_pretty("FAILED", term::color::RED)?;
         }
-        let s = format!(". {} passed; {} failed; {} ignored; {} measured\n\n",
+        let s = format!(". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n",
                         self.passed,
                         self.failed,
                         self.ignored,
-                        self.measured);
+                        self.measured,
+                        self.filtered_out);
         self.write_plain(&s)?;
         return Ok(success);
     }
@@ -875,6 +878,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
     fn callback<T: Write>(event: &TestEvent, st: &mut ConsoleTestState<T>) -> io::Result<()> {
         match (*event).clone() {
             TeFiltered(ref filtered_tests) => st.write_run_start(filtered_tests.len()),
+            TeFilteredOut(filtered_out) => Ok(st.filtered_out = filtered_out),
             TeWait(ref test, padding) => st.write_test_start(test, padding),
             TeTimeout(ref test) => st.write_timeout(test),
             TeResult(test, result, stdout) => {
@@ -957,6 +961,7 @@ fn should_sort_failures_before_printing_them() {
         passed: 0,
         failed: 0,
         ignored: 0,
+        filtered_out: 0,
         measured: 0,
         max_name_len: 10,
         metrics: MetricMap::new(),
@@ -1017,6 +1022,7 @@ pub enum TestEvent {
     TeWait(TestDesc, NamePadding),
     TeResult(TestDesc, TestResult, Vec<u8>),
     TeTimeout(TestDesc),
+    TeFilteredOut(usize),
 }
 
 pub type MonitorMsg = (TestDesc, TestResult, Vec<u8>);
@@ -1028,11 +1034,16 @@ pub fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut callback: F)
     use std::collections::HashMap;
     use std::sync::mpsc::RecvTimeoutError;
 
+    let tests_len = tests.len();
+
     let mut filtered_tests = filter_tests(opts, tests);
     if !opts.bench_benchmarks {
         filtered_tests = convert_benchmarks_to_tests(filtered_tests);
     }
 
+    let filtered_out = tests_len - filtered_tests.len();
+    callback(TeFilteredOut(filtered_out))?;
+
     let filtered_descs = filtered_tests.iter()
                                        .map(|t| t.desc.clone())
                                        .collect();
@@ -1314,12 +1325,16 @@ pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAnd
         let testfn = match x.testfn {
             DynBenchFn(bench) => {
                 DynTestFn(Box::new(move |()| {
-                    bench::run_once(|b| bench.run(b))
+                    bench::run_once(|b| {
+                        __rust_begin_short_backtrace(|| bench.run(b))
+                    })
                 }))
             }
             StaticBenchFn(benchfn) => {
                 DynTestFn(Box::new(move |()| {
-                    bench::run_once(|b| benchfn(b))
+                    bench::run_once(|b| {
+                        __rust_begin_short_backtrace(|| benchfn(b))
+                    })
                 }))
             }
             f => f,
@@ -1425,12 +1440,24 @@ fn flush(&mut self) -> io::Result<()> {
             monitor_ch.send((desc, TrMetrics(mm), Vec::new())).unwrap();
             return;
         }
-        DynTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, f),
-        StaticTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture,
-                                          Box::new(move |()| f())),
+        DynTestFn(f) => {
+            let cb = move |()| {
+                __rust_begin_short_backtrace(|| f.call_box(()))
+            };
+            run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(cb))
+        }
+        StaticTestFn(f) =>
+            run_test_inner(desc, monitor_ch, opts.nocapture,
+                           Box::new(move |()| __rust_begin_short_backtrace(f))),
     }
 }
 
+/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
+#[inline(never)]
+fn __rust_begin_short_backtrace<F: FnOnce()>(f: F) {
+    f()
+}
+
 fn calc_result(desc: &TestDesc, task_result: Result<(), Box<Any + Send>>) -> TestResult {
     match (&desc.should_panic, task_result) {
         (&ShouldPanic::No, Ok(())) |
index cf85b5a8da7853c4de5cc57766da8b7988c06461..1ef3b9128e1baaed61b42d5b0de79dee100acf17 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit cf85b5a8da7853c4de5cc57766da8b7988c06461
+Subproject commit 1ef3b9128e1baaed61b42d5b0de79dee100acf17
diff --git a/src/rust-installer b/src/rust-installer
deleted file mode 160000 (submodule)
index 2e6417f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 2e6417f6af5218a29a8ee72ed17af085560b9b9c
index d73d1c25e5bdb6ec1cc14b9acef626db7e433145..70663f30e8f9e1a579ea103b1eb9492b277b7d39 100644 (file)
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2017-05-06
+2017-05-13
index e0066dd43be89f13cb3d8ec3a8abf80d302ce5a6..ddd8631f02e62b4c0f4974539847f41b7afadb9a 100644 (file)
@@ -14,6 +14,7 @@
 // aux-build:bang_proc_macro.rs
 
 #![feature(proc_macro)]
+#![allow(unused_macros)]
 
 #[macro_use]
 extern crate derive_foo;
index f687633d34d86c4cb59af93ee989fae152616a6f..b15bf44fbd063dcdbd0c5af28929d175a731cb6e 100644 (file)
@@ -10,6 +10,6 @@
 
 fn main () {
     let foo = 42u32;
-    const FOO : u32 = foo; //~ ERROR E0435
+    let _: [u8; foo]; //~ ERROR E0435
     //~| NOTE non-constant used with constant
 }
index 7fd9605ef2cdc6323b7177cd822272e9e1e748a0..e284a61eb2daa3bf9d74c9d079629681749a4efa 100644 (file)
@@ -26,7 +26,7 @@ impl Foo for Def {
 
 pub fn test<A: Foo, B: Foo>() {
     let _array = [4; <A as Foo>::Y];
-    //~^ ERROR cannot use an outer type parameter in this context [E0402]
+    //~^ ERROR the trait bound `A: Foo` is not satisfied [E0277]
 }
 
 fn main() {
index 71c7a3965ec3c8c5af96d6211de60b14cf3ca692..848ea65a9cfd15d9a6d1a2f8e9213ef7cac55a27 100644 (file)
@@ -26,7 +26,7 @@ impl Foo for Def {
 
 pub fn test<A: Foo, B: Foo>() {
     let _array: [u32; <A as Foo>::Y];
-    //~^ ERROR cannot use an outer type parameter in this context [E0402]
+    //~^ ERROR the trait bound `A: Foo` is not satisfied [E0277]
 }
 
 fn main() {
diff --git a/src/test/compile-fail/closure-no-fn-1.rs b/src/test/compile-fail/closure-no-fn-1.rs
new file mode 100644 (file)
index 0000000..10c9970
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+// Ensure that capturing closures are never coerced to fns
+// Especially interesting as non-capturing closures can be.
+
+fn main() {
+    let mut a = 0u8;
+    let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/compile-fail/closure-no-fn-2.rs b/src/test/compile-fail/closure-no-fn-2.rs
new file mode 100644 (file)
index 0000000..a6438bb
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+// Ensure that capturing closures are never coerced to fns
+// Especially interesting as non-capturing closures can be.
+
+fn main() {
+    let b = 0u8;
+    let bar: fn() -> u8 = || { b };
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/compile-fail/closure-no-fn-3.rs b/src/test/compile-fail/closure-no-fn-3.rs
new file mode 100644 (file)
index 0000000..85dbc89
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+// Ensure that capturing closures are never coerced to fns
+// Especially interesting as non-capturing closures can be.
+
+fn main() {
+    let b = 0u8;
+    let baz: fn() -> u8 = (|| { b }) as fn() -> u8;
+    //~^ ERROR non-scalar cast
+}
diff --git a/src/test/compile-fail/closure-no-fn.rs b/src/test/compile-fail/closure-no-fn.rs
deleted file mode 100644 (file)
index fe179e8..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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.
-
-// Ensure that capturing closures are never coerced to fns
-// Especially interesting as non-capturing closures can be.
-
-fn main() {
-    let mut a = 0u8;
-    let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
-    //~^ ERROR mismatched types
-    let b = 0u8;
-    let bar: fn() -> u8 = || { b };
-    //~^ ERROR mismatched types
-    let baz: fn() -> u8 = || { b } as fn() -> u8;
-    //~^ ERROR mismatched types
-    //~^^ ERROR non-scalar cast
-}
diff --git a/src/test/compile-fail/coherence-inherited-assoc-ty-cycle-err.rs b/src/test/compile-fail/coherence-inherited-assoc-ty-cycle-err.rs
new file mode 100644 (file)
index 0000000..5d7f339
--- /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.
+
+// Formerly this ICEd with the following message:
+// Tried to project an inherited associated type during coherence checking,
+// which is currently not supported.
+//
+// No we expect to run into a more user-friendly cycle error instead.
+
+#![feature(specialization)]
+
+trait Trait<T> { type Assoc; }
+//~^ unsupported cyclic reference between types/traits detected [E0391]
+
+impl<T> Trait<T> for Vec<T> {
+    type Assoc = ();
+}
+
+impl Trait<u8> for Vec<u8> {}
+
+impl<T> Trait<T> for String {
+    type Assoc = ();
+}
+
+impl Trait<<Vec<u8> as Trait<u8>>::Assoc> for String {}
+
+fn main() {}
diff --git a/src/test/compile-fail/crt-static-gated.rs b/src/test/compile-fail/crt-static-gated.rs
deleted file mode 100644 (file)
index 6c7c60b..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags:-C target-feature=+crt-static
-// error-pattern: specifying the `crt-static` target feature is only allowed
-
-fn main() {}
index 1aabe6b87dff58107870358f47adb266823c8f66..9af501b141955f97d777a210afcf40c1e0a4914e 100644 (file)
@@ -10,6 +10,8 @@
 
 // gate-test-allow_internal_unstable
 
+#![allow(unused_macros)]
+
 macro_rules! bar {
     () => {
         // more layers don't help:
index 8a2d8dddac0741fdaff21fdcb8e4e1343637ba86..61a362cb37fb2c0d8d674447ba9af2b348bcf586 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_macros)]
+
 #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps
 macro_rules! foo {
     () => {}
index a6a331984583675c99a942ea23f96347bc95f091..6fb497092d2173cc45902dd2f2c7aa83e48c1029 100644 (file)
@@ -14,7 +14,7 @@ enum Bar<T> { What } //~ ERROR parameter `T` is never used
 
 fn foo<T>() {
     static a: Bar<T> = Bar::What;
-    //~^ ERROR cannot use an outer type parameter in this context
+//~^ ERROR can't use type parameters from outer function; try using a local type parameter instead
 }
 
 fn main() {
index a0ac5d4c7204104237b06da36a47513b8e31d482..d710f5647dd9f97591f57c0740993bc551b3e4c7 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_macros)]
+
 macro_rules! invalid {
     _ => (); //~ ERROR invalid macro matcher
 }
index fefd432e22982c66c47b60f5d8ffdf56311c053b..f66c09291cc9e4b74539de7bde5193c9f7310225 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_macros)]
+
 macro_rules! test { ($wrong:t_ty ..) => () }
                   //~^ ERROR: invalid fragment specifier `t_ty`
 
index 78d96398b958710938f672921dc48ea45c8c3008..782b20574387136b062516765251a55c18b2c9dc 100644 (file)
@@ -11,5 +11,5 @@
 fn main() {
     let foo = 42u32;
     const FOO : u32 = foo;
-                   //~^ ERROR attempt to use a non-constant value in a constant
+                   //~^ ERROR can't capture dynamic environment
 }
index 595e4bfb0d705ce95f9b71e0f3bff8aaaa7038d3..22e7de3838dc153a89f3bde569ef2ebcb45eb2c6 100644 (file)
 pub trait Resources<'a> {}
 
 pub trait Buffer<'a, R: Resources<'a>> {
+    //~^ NOTE the lifetime 'a as defined on the trait at 13:0...
+    //~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the trait
+
     fn select(&self) -> BufferViewHandle<R>;
     //~^ ERROR mismatched types
     //~| lifetime mismatch
     //~| NOTE expected type `Resources<'_>`
-    //~| NOTE the lifetime 'a as defined on the method body at 14:4...
     //~| NOTE ...does not necessarily outlive the anonymous lifetime #1 defined on the method body
     //~| ERROR mismatched types
     //~| lifetime mismatch
     //~| NOTE expected type `Resources<'_>`
-    //~| NOTE the anonymous lifetime #1 defined on the method body at 14:4...
-    //~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the method body
+    //~| NOTE the anonymous lifetime #1 defined on the method body at 17:4...
 }
 
 pub struct BufferViewHandle<'a, R: 'a+Resources<'a>>(&'a R);
index 6cd2c02c417ea8ed5f8aacfd19367259ed7b72b5..1742cb4fb7214b5b243121c176d20757f419c927 100644 (file)
@@ -12,7 +12,7 @@ fn main() {
     let foo = 100;
 
     static y: isize = foo + 1;
-    //~^ ERROR attempt to use a non-constant value in a constant
+    //~^ ERROR can't capture dynamic environment
 
     println!("{}", y);
 }
index f990c2c42fe1431a266970a5837e9b7f2646dc40..001c1f2eddca1e3ccbeabaf58450b6296547847c 100644 (file)
@@ -8,7 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-enum Fruit {
+// these two HELPs are actually in a new line between this line and the `enum Fruit` line
+enum Fruit { //~ HELP possible candidate is found in another module, you can import it into scope
+    //~^ HELP possible candidate is found in another module, you can import it into scope
     Apple(i64),
     //~^ HELP there is an enum variant `Fruit::Apple`, did you mean to use `Fruit`?
     //~| HELP there is an enum variant `Fruit::Apple`, did you mean to use `Fruit`?
@@ -21,7 +23,6 @@ fn should_return_fruit() -> Apple {
     Apple(5)
     //~^ ERROR cannot find function `Apple` in this scope
     //~| NOTE not found in this scope
-    //~| HELP possible candidate is found in another module, you can import it into scope
 }
 
 fn should_return_fruit_too() -> Fruit::Apple {
@@ -30,7 +31,6 @@ fn should_return_fruit_too() -> Fruit::Apple {
     Apple(5)
     //~^ ERROR cannot find function `Apple` in this scope
     //~| NOTE not found in this scope
-    //~| HELP possible candidate is found in another module, you can import it into scope
 }
 
 fn foo() -> Ok {
index 16fb2f68133f291f9519dcb591330338e28684d8..fe46877e8d34073f868cbdc647095245b9f6839b 100644 (file)
@@ -10,7 +10,7 @@
 
 fn f(x:isize) {
     static child: isize = x + 1;
-    //~^ ERROR attempt to use a non-constant value in a constant
+    //~^ ERROR can't capture dynamic environment
 }
 
 fn main() {}
index 9c31dc1e38ef8ff312193b105a73e9346e9d0153..00f64414a9e72eaca70a8fca55f22d510e446b88 100644 (file)
@@ -16,7 +16,7 @@ trait PTrait {
 impl PTrait for P {
    fn getChildOption(&self) -> Option<Box<P>> {
        static childVal: Box<P> = self.child.get();
-       //~^ ERROR attempt to use a non-constant value in a constant
+       //~^ ERROR can't capture dynamic environment
        panic!();
    }
 }
index 6e1b9b2fbed0b4749271ca946665871ca57d6e50..6313293bf2b6aae8e42fdcb9ba8cadb45c71e2a7 100644 (file)
 struct RepeatMut<'a, T>(T, &'a ());
 
 impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
+    //~^ NOTE ...does not necessarily outlive the lifetime 'a as defined on the impl
+
     type Item = &'a mut T;
     fn next(&'a mut self) -> Option<Self::Item>
     //~^ ERROR method not compatible with trait
     //~| lifetime mismatch
     //~| NOTE expected type `fn(&mut RepeatMut<'a, T>) -> std::option::Option<&mut T>`
+    //~| NOTE the anonymous lifetime #1 defined on the method body
     {
-    //~^ NOTE the anonymous lifetime #1 defined on the body
-    //~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the body
         Some(&mut self.0)
     }
 }
index 6994d2199d276d4f7b18ff31e491659c4be83ab7..15eef429eab974667e3ea77daaada669acb10ccc 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_macros)]
+
 macro_rules! assign {
     (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected `*` or `+`
         $($a)* = $($b)*
index 0168ae7d910179ecf8a059ba923e25a7d8d4a13e..8b49772494a6687e1f34a106ec6bb5ab4ed87b91 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![deny(missing_fragment_specifier)] //~ NOTE lint level defined here
+#![allow(unused_macros)]
 
 macro_rules! m { ($i) => {} }
 //~^ ERROR missing fragment specifier
diff --git a/src/test/compile-fail/issue-39559-2.rs b/src/test/compile-fail/issue-39559-2.rs
new file mode 100644 (file)
index 0000000..aa07502
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Dim {
+    fn dim() -> usize;
+}
+
+enum Dim3 {}
+
+impl Dim for Dim3 {
+    fn dim() -> usize {
+        3
+    }
+}
+
+fn main() {
+    let array: [usize; Dim3::dim()]
+    //~^ ERROR calls in constants are limited to constant functions
+        = [0; Dim3::dim()];
+        //~^ ERROR calls in constants are limited to constant functions
+}
index b7f767f109c0c7437ce421135f1c358bb7c16cfa..871ecf269ceec4b926448bbeb08764e460ad0ba7 100644 (file)
@@ -22,12 +22,7 @@ fn dim() -> usize {
 
 pub struct Vector<T, D: Dim> {
     entries: [T; D::dim()]
-    //~^ ERROR cannot use an outer type parameter in this context
+    //~^ ERROR no associated item named `dim` found for type `D` in the current scope
 }
 
-fn main() {
-    let array: [usize; Dim3::dim()]
-    //~^ ERROR calls in constants are limited to constant functions
-        = [0; Dim3::dim()];
-        //~^ ERROR calls in constants are limited to constant functions
-}
+fn main() {}
index 9be114ebcb6e0c110cd54f7039af3a1e4a4abeb5..3ccee0f12becb63e1f84cf4bd89be3109253a3c5 100644 (file)
@@ -11,8 +11,7 @@
 #![feature(closure_to_fn_coercion)]
 
 fn main() {
-    let bar: fn(&mut u32) = |_| {}; //~ ERROR mismatched types
-    //~| expected concrete lifetime, found bound lifetime parameter
+    let bar: fn(&mut u32) = |_| {};
 
     fn foo(x: Box<Fn(&i32)>) {}
     let bar = Box::new(|x: &i32| {}) as Box<Fn(_)>;
diff --git a/src/test/compile-fail/issue-41255.rs b/src/test/compile-fail/issue-41255.rs
new file mode 100644 (file)
index 0000000..a4585f7
--- /dev/null
@@ -0,0 +1,55 @@
+// 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.
+
+// Matching against float literals should result in a linter error
+
+#![feature(slice_patterns)]
+#![feature(exclusive_range_pattern)]
+#![allow(unused)]
+#![forbid(illegal_floating_point_literal_pattern)]
+
+fn main() {
+    let x = 42.0;
+    match x {
+        5.0 => {}, //~ ERROR floating-point literals cannot be used
+                   //~| WARNING hard error
+        5.0f32 => {}, //~ ERROR floating-point literals cannot be used
+                      //~| WARNING hard error
+        -5.0 => {}, //~ ERROR floating-point literals cannot be used
+                    //~| WARNING hard error
+        1.0 .. 33.0 => {}, //~ ERROR floating-point literals cannot be used
+                           //~| WARNING hard error
+                           //~| ERROR floating-point literals cannot be used
+                           //~| WARNING hard error
+        39.0 ... 70.0 => {}, //~ ERROR floating-point literals cannot be used
+                             //~| WARNING hard error
+                             //~| ERROR floating-point literals cannot be used
+                             //~| WARNING hard error
+        _ => {},
+    };
+    let y = 5.0;
+    // Same for tuples
+    match (x, 5) {
+        (3.14, 1) => {}, //~ ERROR floating-point literals cannot be used
+                         //~| WARNING hard error
+                         //~| ERROR floating-point literals cannot be used
+                         //~| WARNING hard error
+        _ => {},
+    }
+    // Or structs
+    struct Foo { x: f32 };
+    match (Foo { x }) {
+        Foo { x: 2.0 } => {}, //~ ERROR floating-point literals cannot be used
+                              //~| WARNING hard error
+                              //~| ERROR floating-point literals cannot be used
+                              //~| WARNING hard error
+        _ => {},
+    }
+}
diff --git a/src/test/compile-fail/issue-41726.rs b/src/test/compile-fail/issue-41726.rs
new file mode 100644 (file)
index 0000000..c8cd920
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::collections::HashMap;
+fn main() {
+    let things: HashMap<String, Vec<String>> = HashMap::new();
+    for src in things.keys() {
+        things[src.as_str()].sort(); //~ ERROR cannot borrow immutable
+    }
+}
diff --git a/src/test/compile-fail/issue-41742.rs b/src/test/compile-fail/issue-41742.rs
new file mode 100644 (file)
index 0000000..067531e
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::ops::{Index, IndexMut};
+
+struct S;
+struct H;
+
+impl S {
+    fn f(&mut self) {}
+}
+
+impl Index<u32> for H {
+    type Output = S;
+    fn index(&self, index: u32) -> &S {
+        unimplemented!()
+    }
+}
+
+impl IndexMut<u32> for H {
+    fn index_mut(&mut self, index: u32) -> &mut S {
+        unimplemented!()
+    }
+}
+
+fn main() {
+    H["?"].f(); //~ ERROR mismatched types
+}
index 1c543a5fdacbba3deac22b7a66372fdb67fc4059..267362f902d720faeed69655bb5cc382215bd4db 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_macros)]
+
 macro_rules! foo {
     ( $()* ) => {};
     //~^ ERROR repetition matches empty token tree
index ada06b0b3f452cdb3c97859e3ba551d05d4d706b..06f2d86e5d9bae93be3b5e23dbeea9ba5d34aaa8 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_macros)]
+
 mod macros_cant_escape_fns {
     fn f() {
         macro_rules! m { () => { 3 + 4 } }
index 001bc42274b4daea014bfc5a56f584e27f9dff19..6e80e9b574bcfae9c3932c8551a2cecc5e621ad9 100644 (file)
@@ -10,6 +10,8 @@
 //
 // Check the macro follow sets (see corresponding rpass test).
 
+#![allow(unused_macros)]
+
 // FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), Ident(in)}
 macro_rules! follow_pat {
     ($p:pat ()) => {};       //~ERROR  `$p:pat` is followed by `(`
index 0ee2221bbc14b9658c9f5010c94be25821b54f7b..21cc946ded60563a48b5fa7ab8f713a841c23d98 100644 (file)
@@ -11,6 +11,8 @@
 // Regression test for issue #25436: check that things which can be
 // followed by any token also permit X* to come afterwards.
 
+#![allow(unused_macros)]
+
 macro_rules! foo {
   ( $a:expr $($b:tt)* ) => { }; //~ ERROR not allowed for `expr` fragments
   ( $a:ty $($b:tt)* ) => { };   //~ ERROR not allowed for `ty` fragments
index fe758a4a6310fbfe925eeb75d0a1e9c234d0209c..e5fdba63b0f152859c0a1f82614d57515b10716f 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_macros)]
+
 macro_rules! errors_everywhere {
     ($ty:ty <) => (); //~ ERROR `$ty:ty` is followed by `<`, which is not allowed for `ty`
     ($ty:ty < foo ,) => (); //~ ERROR `$ty:ty` is followed by `<`, which is not allowed for `ty`
index 8381dc34a6a15f695630b44de9be358fdbdfc825..f5e7305e4ea9e61ba37d0429cfe9a1f5e58d4ca5 100644 (file)
@@ -10,6 +10,8 @@
 
 // aux-build:two_macros.rs
 
+#![allow(unused_macros)]
+
 macro_rules! foo { () => {} }
 macro_rules! macro_one { () => {} }
 #[macro_use(macro_two)] extern crate two_macros;
diff --git a/src/test/compile-fail/method-help-unsatisfied-bound.rs b/src/test/compile-fail/method-help-unsatisfied-bound.rs
deleted file mode 100644 (file)
index 6416d54..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Foo;
-
-fn main() {
-    let a: Result<(), Foo> = Ok(());
-    a.unwrap();
-    //~^ ERROR no method named `unwrap` found for type `std::result::Result<(), Foo>`
-    //~| NOTE the following trait bounds were not satisfied: `Foo : std::fmt::Debug`
-}
index 74e728d713b1d27e8aa00899b3aa981ad332615e..13b62429f46930d3c67a17cc9d1bf63022ee9dd0 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(slice_patterns)]
+#![allow(illegal_floating_point_literal_pattern)]
 
 enum t { a, b, }
 
index d25674a74b1d37e563adcbe82728b269e3a70626..646ae8183a20ce8c93047a4dfc4d5203162f97e6 100644 (file)
@@ -13,9 +13,8 @@
 // over time, but this test used to exhibit some pretty bogus messages
 // that were not remotely helpful.
 
-// error-pattern:cannot infer
-// error-pattern:cannot outlive the lifetime 'a
-// error-pattern:must be valid for the static lifetime
+// error-pattern:the lifetime 'a
+// error-pattern:the static lifetime
 
 struct Invariant<'a>(Option<&'a mut &'a mut ()>);
 
diff --git a/src/test/compile-fail/regions-adjusted-lvalue-op.rs b/src/test/compile-fail/regions-adjusted-lvalue-op.rs
new file mode 100644 (file)
index 0000000..167c863
--- /dev/null
@@ -0,0 +1,26 @@
+// 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.
+
+// check that we link regions in mutable lvalue ops correctly - issue #41774
+
+struct Data(i32);
+
+trait OhNo {
+    fn oh_no(&mut self, other: &Vec<Data>) { loop {} }
+}
+
+impl OhNo for Data {}
+impl OhNo for [Data] {}
+
+fn main() {
+    let mut v = vec![Data(0)];
+    v[0].oh_no(&v); //~ ERROR cannot borrow `v` as immutable because
+    (*v).oh_no(&v); //~ ERROR cannot borrow `v` as immutable because
+}
index e8ada6a1755719205422e74f43591b9bf8ea138f..948fb7e1ef6c29759aed6ba0ddd3ac5db4349471 100644 (file)
@@ -22,7 +22,7 @@ fn foo2<'a:'b,'b>(x: &'b mut (Dummy+'a)) -> &'b mut (Dummy+'b) {
 
 fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
     // Without knowing 'a:'b, we can't coerce
-    x //~ ERROR cannot infer an appropriate lifetime
+    x //~ ERROR lifetime bound not satisfied
      //~^ ERROR cannot infer an appropriate lifetime
 }
 
index b868b79365d9f683755398adf8b5dc2d496d7292..28a69e6f9e29beb5f900c78dbac33655681e0a95 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_macros)]
+
 // Issue #21370
 
 macro_rules! test {
index e9d09bb6ad9cd739a7a4a700e9063a5e0ef4165f..dda0d3fc9557dd79afd0b0e895691892a816af06 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_macros)]
+
 macro_rules! test {
     ($e:expr +) => () //~ ERROR not allowed for `expr` fragments
 }
diff --git a/src/test/compile-fail/unused-macro.rs b/src/test/compile-fail/unused-macro.rs
new file mode 100644 (file)
index 0000000..5e401c0
--- /dev/null
@@ -0,0 +1,39 @@
+// 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.
+
+#![deny(unused_macros)]
+
+// Most simple case
+macro_rules! unused { //~ ERROR: unused macro definition
+    () => {};
+}
+
+// Test macros created by macros
+macro_rules! create_macro {
+    () => {
+        macro_rules! m { //~ ERROR: unused macro definition
+            () => {};
+        }
+    };
+}
+create_macro!();
+
+#[allow(unused_macros)]
+mod bar {
+    // Test that putting the #[deny] close to the macro's definition
+    // works.
+
+    #[deny(unused_macros)]
+    macro_rules! unused { //~ ERROR: unused macro definition
+        () => {};
+    }
+}
+
+fn main() {}
index d55cef434f8d3eeafd44d3e07bbe1245077df14b..02e1a585fa89d054d267c206ca636f4ff4f5c093 100644 (file)
@@ -8,4 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_macros)]
+
 macro_rules! macro_rules { () => {} } //~ ERROR user-defined macros may not be named `macro_rules`
index d3bf92e85f411a5207e03786dc844487d7417dcf..1795ac95358d7c6c29c2bde494f0212b16ad6076 100644 (file)
@@ -21,7 +21,7 @@ fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
                                 -> Box<Get<&'min i32>>
     where 'max : 'min
 {
-    v //~ ERROR cannot infer an appropriate lifetime
+    v //~ ERROR mismatched types
 }
 
 fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
@@ -29,7 +29,7 @@ fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
     where 'max : 'min
 {
     // Previously OK:
-    v //~ ERROR cannot infer an appropriate lifetime
+    v //~ ERROR mismatched types
 }
 
 fn main() { }
index 0e94e35df2839895fdc389f970eeb6396db708e0..ad059a467f570bb2d4b9e5ef872d907ff1f8522c 100644 (file)
@@ -22,14 +22,14 @@ fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
     where 'max : 'min
 {
     // Previously OK, now an error as traits are invariant.
-    v //~ ERROR cannot infer an appropriate lifetime
+    v //~ ERROR mismatched types
 }
 
 fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
                                    -> Box<Get<&'max i32>>
     where 'max : 'min
 {
-    v //~ ERROR cannot infer an appropriate lifetime
+    v //~ ERROR mismatched types
 }
 
 fn main() { }
index aa3e06c015d503829e89c839c2beb07e52a40e4e..9edb510b826a12df92df2fe2ea40966ca9ac98fa 100644 (file)
@@ -18,14 +18,14 @@ fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
                                 -> Box<Get<&'min i32>>
     where 'max : 'min
 {
-    v //~ ERROR cannot infer an appropriate lifetime
+    v //~ ERROR mismatched types
 }
 
 fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
                                    -> Box<Get<&'max i32>>
     where 'max : 'min
 {
-    v //~ ERROR cannot infer an appropriate lifetime
+    v //~ ERROR mismatched types
 }
 
 fn main() { }
index 1064c97b744a4e51a899957ed90ac8f6cf35b341..adc2b23441ef817355c6af0d2ff05a4cb878c388 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z incremental-cc
-
 pub struct Point {
     pub x: f32,
     pub y: f32,
index a02b71a753cc3bdff1f9b05b4a1e71ba4f3c6676..d802c9a8352eb675af47f076a0036fa7d2dc9ac8 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z incremental-cc
-
 #![crate_type="rlib"]
 
 #[cfg(rpass1)]
index 08eef2a73f68f21d2bdb9f72083689fb8f762b17..dcc1ced635fbf8b6a08a7c03410ef7eff95f2867 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z incremental-cc
-
 pub struct Point {
     pub x: f32,
     pub y: f32,
index e69dc51119e920e8bbdd7455c0a5356f8d538c8f..8df1cf54da2b97c3e34abb97abcba9b802f2b239 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z incremental-cc
-
 pub struct Point {
     pub x: f32,
     pub y: f32,
diff --git a/src/test/incremental/remapped_paths_cc/auxiliary/extern_crate.rs b/src/test/incremental/remapped_paths_cc/auxiliary/extern_crate.rs
new file mode 100644 (file)
index 0000000..1483bf9
--- /dev/null
@@ -0,0 +1,23 @@
+// 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.
+
+// ignore-tidy-linelength
+
+//[rpass1] compile-flags: -g
+//[rpass2] compile-flags: -g
+//[rpass3] compile-flags: -g -Zremap-path-prefix-from={{src-base}} -Zremap-path-prefix-to=/the/src
+
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+#[inline(always)]
+pub fn inline_fn() {
+    println!("test");
+}
diff --git a/src/test/incremental/remapped_paths_cc/main.rs b/src/test/incremental/remapped_paths_cc/main.rs
new file mode 100644 (file)
index 0000000..be4764c
--- /dev/null
@@ -0,0 +1,42 @@
+// 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.
+
+// revisions:rpass1 rpass2 rpass3
+// compile-flags: -Z query-dep-graph -g -Zincremental-cc
+// aux-build:extern_crate.rs
+
+
+// This test case makes sure that we detect if paths emitted into debuginfo
+// are changed, even when the change happens in an external crate.
+
+#![feature(rustc_attrs)]
+
+#![rustc_partition_reused(module="main", cfg="rpass2")]
+#![rustc_partition_reused(module="main-some_mod", cfg="rpass2")]
+#![rustc_partition_reused(module="main", cfg="rpass3")]
+#![rustc_partition_translated(module="main-some_mod", cfg="rpass3")]
+
+extern crate extern_crate;
+
+#[rustc_clean(label="TransCrateItem", cfg="rpass2")]
+#[rustc_clean(label="TransCrateItem", cfg="rpass3")]
+fn main() {
+    some_mod::some_fn();
+}
+
+mod some_mod {
+    use extern_crate;
+
+    #[rustc_clean(label="TransCrateItem", cfg="rpass2")]
+    #[rustc_dirty(label="TransCrateItem", cfg="rpass3")]
+    pub fn some_fn() {
+        extern_crate::inline_fn();
+    }
+}
index 39547fb7359f56e1ba64e78cd466b260481b71bc..4d84e844dedbbc6ff84839eff5207d872072176d 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z incremental-cc
-
 #![allow(warnings)]
 #![crate_name = "a"]
 #![crate_type = "rlib"]
diff --git a/src/test/incremental/remove_source_file/auxiliary/mod.rs b/src/test/incremental/remove_source_file/auxiliary/mod.rs
new file mode 100644 (file)
index 0000000..a2cea65
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+
+pub fn print_hello() {
+    println!("hello");
+}
diff --git a/src/test/incremental/remove_source_file/main.rs b/src/test/incremental/remove_source_file/main.rs
new file mode 100644 (file)
index 0000000..4ba33f3
--- /dev/null
@@ -0,0 +1,31 @@
+// 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.
+
+// This test case makes sure that the compiler doesn't crash due to a failing
+// table lookup when a source file is removed.
+
+// revisions:rpass1 rpass2
+
+// Note that we specify -g so that the FileMaps actually get referenced by the
+// incr. comp. cache:
+// compile-flags: -Z query-dep-graph -g
+
+#[cfg(rpass1)]
+mod auxiliary;
+
+#[cfg(rpass1)]
+fn main() {
+    auxiliary::print_hello();
+}
+
+#[cfg(rpass2)]
+fn main() {
+    println!("hello");
+}
index 3ecd9aff3f8cdc348d5f55bb415bdf7301b36f77..ff5fd634714497bf53a38f11bc1aa323844a5a8c 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z incremental-cc
 // no-prefer-dynamic
 
 #![crate_type="rlib"]
index d14ebf78d8222b452975d9d7d985f665efac1027..2ddcaf157210dfef38201bad5d729743d5527db4 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z incremental-cc
-
 #![crate_type="rlib"]
 
  #[cfg(rpass1)]
index 0393bcda991565f874e0cba700d01da027f2cca4..e1dba1317703d6c448b969d1327a3884b8cc113c 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z incremental-cc
-
 #![crate_type="rlib"]
 
 #[cfg(rpass1)]
diff --git a/src/test/mir-opt/issue-41697.rs b/src/test/mir-opt/issue-41697.rs
new file mode 100644 (file)
index 0000000..47eeffe
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #41697. Using dump-mir was triggering
+// artificial cycles: during type-checking, we had to get the MIR for
+// the constant expressions in `[u8; 2]`, which in turn would trigger
+// an attempt to get the item-path, which in turn would request the
+// types of the impl, which would trigger a cycle. We supressed this
+// cycle now by forcing mir-dump to avoid asking for types of an impl.
+
+#![feature(rustc_attrs)]
+
+use std::sync::Arc;
+
+trait Foo {
+    fn get(&self) -> [u8; 2];
+}
+
+impl Foo for [u8; 2] {
+    fn get(&self) -> [u8; 2] {
+        *self
+    }
+}
+
+struct Bar<T: ?Sized>(T);
+
+fn unsize_fat_ptr<'a>(x: &'a Bar<Foo + Send + 'a>) -> &'a Bar<Foo + 'a> {
+    x
+}
+
+fn unsize_nested_fat_ptr(x: Arc<Foo + Send>) -> Arc<Foo> {
+    x
+}
+
+fn main() {
+    let x: Box<Bar<Foo + Send>> = Box::new(Bar([1,2]));
+    assert_eq!(unsize_fat_ptr(&*x).0.get(), [1, 2]);
+
+    let x: Arc<Foo + Send> = Arc::new([3, 4]);
+    assert_eq!(unsize_nested_fat_ptr(x).get(), [3, 4]);
+}
index f894305754319d20880407201cf6f158bfdbbc2a..ac085d475114e6b4e08233ed03fc8a0c34b04c5a 100644 (file)
@@ -21,6 +21,12 @@ pub fn bar() {}
 //~^^ ERROR: bare CR not allowed in block doc-comment
 
 fn main() {
+    //! doc comment with bare CR: '\r'
+    //~^ ERROR: bare CR not allowed in doc-comment
+
+    /*! block doc comment with bare CR: '\r' */
+    //~^ ERROR: bare CR not allowed in block doc-comment
+
     // the following string literal has a bare CR in it
     let _s = "foo\rbar"; //~ ERROR: bare CR not allowed in string
 
diff --git a/src/test/parse-fail/underscore-suffix-for-float.rs b/src/test/parse-fail/underscore-suffix-for-float.rs
new file mode 100644 (file)
index 0000000..df7d9aa
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let a = 42._; //~ ERROR unexpected token: `_`
+}
index 0336fe277c51f8eb6f064d6e248d1f0d00e26653..e96588c6e5aea6a3978b4ea67d4f46ed4d903d3a 100644 (file)
@@ -15,6 +15,7 @@
 extern crate rustc_lint;
 extern crate rustc_metadata;
 extern crate rustc_errors;
+extern crate rustc_trans;
 extern crate syntax;
 
 use rustc::dep_graph::DepGraph;
@@ -58,8 +59,9 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
 
     let descriptions = Registry::new(&rustc::DIAGNOSTICS);
     let dep_graph = DepGraph::new(opts.build_dep_graph());
-    let cstore = Rc::new(CStore::new(&dep_graph));
+    let cstore = Rc::new(CStore::new(&dep_graph, Box::new(rustc_trans::LlvmMetadataLoader)));
     let sess = build_session(opts, &dep_graph, None, descriptions, cstore.clone());
+    rustc_trans::init(&sess);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
     (sess, cstore)
 }
index f77b2fca857a613e3759bb50b4fec40995186fc6..37aab2bbd059aa61579de5e914b41bdb71381abc 100644 (file)
@@ -14,6 +14,7 @@
 
 extern crate rustc;
 extern crate rustc_plugin;
+extern crate rustc_trans;
 
 #[link(name = "llvm-function-pass", kind = "static")]
 #[link(name = "llvm-module-pass", kind = "static")]
diff --git a/src/test/run-make/trace-macros-flag/Makefile b/src/test/run-make/trace-macros-flag/Makefile
deleted file mode 100644 (file)
index 3338e39..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# This test verifies that "-Z trace-macros"  works as it should. The traditional
-# "hello world" program provides a small example of this as not only println! is
-# listed, but also print! (since println! expands to this)
-
--include ../tools.mk
-
-all:
-       $(RUSTC) -Z trace-macros hello.rs > $(TMPDIR)/hello.out
-       diff -u $(TMPDIR)/hello.out hello.trace
diff --git a/src/test/run-make/trace-macros-flag/hello.rs b/src/test/run-make/trace-macros-flag/hello.rs
deleted file mode 100644 (file)
index 42d3d4c..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
-    println!("Hello, World!");
-}
diff --git a/src/test/run-make/trace-macros-flag/hello.trace b/src/test/run-make/trace-macros-flag/hello.trace
deleted file mode 100644 (file)
index cf73333..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-println! { "Hello, World!" }
-print! { concat ! ( "Hello, World!" , "\n" ) }
diff --git a/src/test/run-pass-fulldeps/issue-35829.rs b/src/test/run-pass-fulldeps/issue-35829.rs
new file mode 100644 (file)
index 0000000..0a4c15a
--- /dev/null
@@ -0,0 +1,55 @@
+// 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.
+
+// ignore-stage1
+// ignore-cross-compile
+#![feature(quote, rustc_private)]
+
+extern crate syntax;
+
+use syntax::ext::base::{ExtCtxt, DummyResolver};
+use syntax::ext::expand::ExpansionConfig;
+use syntax::parse::ParseSess;
+use syntax::codemap::{FilePathMapping, dummy_spanned};
+use syntax::print::pprust::expr_to_string;
+use syntax::ast::{Expr, ExprKind, LitKind, StrStyle, RangeLimits};
+use syntax::symbol::Symbol;
+use syntax::ptr::P;
+
+use std::rc::Rc;
+
+fn main() {
+    let parse_sess = ParseSess::new(FilePathMapping::empty());
+    let exp_cfg = ExpansionConfig::default("issue_35829".to_owned());
+    let mut resolver = DummyResolver;
+    let cx = ExtCtxt::new(&parse_sess, exp_cfg, &mut resolver);
+
+    // check byte string
+    let byte_string = quote_expr!(&cx, b"one");
+    let byte_string_lit_kind = LitKind::ByteStr(Rc::new(b"one".to_vec()));
+    assert_eq!(byte_string.node, ExprKind::Lit(P(dummy_spanned(byte_string_lit_kind))));
+
+    // check raw byte string
+    let raw_byte_string = quote_expr!(&cx, br###"#"two"#"###);
+    let raw_byte_string_lit_kind = LitKind::ByteStr(Rc::new(b"#\"two\"#".to_vec()));
+    assert_eq!(raw_byte_string.node, ExprKind::Lit(P(dummy_spanned(raw_byte_string_lit_kind))));
+
+    // check dotdotdot
+    let closed_range = quote_expr!(&cx, 0 ... 1);
+    assert_eq!(closed_range.node, ExprKind::Range(
+        Some(quote_expr!(&cx, 0)),
+        Some(quote_expr!(&cx, 1)),
+        RangeLimits::Closed
+    ));
+
+    // test case from 35829
+    let expr_35829 = quote_expr!(&cx, std::io::stdout().write(b"one"));
+    assert_eq!(expr_to_string(&expr_35829), r#"std::io::stdout().write(b"one")"#);
+}
index 01b0ed802354c74e19f15f217738caa7bf50a685..e7d0a83017be004c4128d318ea1978515e18ed22 100644 (file)
 extern crate syntax;
 extern crate syntax_pos;
 
-use syntax::ast::Ident;
-use syntax::parse::token;
+use syntax::ast::{Ident, Name};
+use syntax::parse::token::{self, Token, Lit};
 use syntax::tokenstream::TokenTree;
 
 fn main() {
     let true_tok = token::Ident(Ident::from_str("true"));
     assert!(quote!(true).eq_unspanned(&true_tok.into()));
+
+    // issue #35829, extended check to proc_macro.
+    let triple_dot_tok = Token::DotDotDot;
+    assert!(quote!(...).eq_unspanned(&triple_dot_tok.into()));
+
+    let byte_str_tok = Token::Literal(Lit::ByteStr(Name::intern("one")), None);
+    assert!(quote!(b"one").eq_unspanned(&byte_str_tok.into()));
+
+    let byte_str_raw_tok = Token::Literal(Lit::ByteStrRaw(Name::intern("#\"two\"#"), 3), None);
+    assert!(quote!(br###"#"two"#"###).eq_unspanned(&byte_str_raw_tok.into()));
+
+    let str_raw_tok = Token::Literal(Lit::StrRaw(Name::intern("#\"three\"#"), 2), None);
+    assert!(quote!(r##"#"three"#"##).eq_unspanned(&str_raw_tok.into()));
 }
index e3d1761dfffdbe6f3ce1c9029f211fea9e693f95..df2083530646e3404c7825a4e638adf8a4a6c9b6 100644 (file)
@@ -27,10 +27,20 @@ impl Foo for Def {
     const X: i32 = 97;
 }
 
+struct Proxy<T>(T);
+
+impl<T: Foo> Foo for Proxy<T> {
+    const X: i32 = T::X;
+}
+
 fn sub<A: Foo, B: Foo>() -> i32 {
     A::X - B::X
 }
 
+trait Bar: Foo {
+    const Y: i32 = Self::X;
+}
+
 fn main() {
     assert_eq!(11, Abc::X);
     assert_eq!(97, Def::X);
@@ -38,4 +48,7 @@ fn main() {
     assert_eq!(97, Def::get_x());
     assert_eq!(-86, sub::<Abc, Def>());
     assert_eq!(86, sub::<Def, Abc>());
+    assert_eq!(-86, sub::<Proxy<Abc>, Def>());
+    assert_eq!(-86, sub::<Abc, Proxy<Def>>());
+    assert_eq!(86, sub::<Proxy<Def>, Proxy<Abc>>());
 }
diff --git a/src/test/run-pass/closure_to_fn_coercion-expected-types.rs b/src/test/run-pass/closure_to_fn_coercion-expected-types.rs
new file mode 100644 (file)
index 0000000..7214ebf
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+// Ensure that we deduce expected argument types when a `fn()` type is expected (#41755)
+
+#![feature(closure_to_fn_coercion)]
+fn foo(f: fn(Vec<u32>) -> usize) { }
+
+fn main() {
+    foo(|x| x.len())
+}
diff --git a/src/test/run-pass/issue-41677.rs b/src/test/run-pass/issue-41677.rs
new file mode 100644 (file)
index 0000000..d014382
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #41677. The local variable was winding up with
+// a type `Receiver<?T, H>` where `?T` was unconstrained, because we
+// failed to enforce the WF obligations and `?T` is a bivariant type
+// parameter position.
+
+#![allow(unused_variables, dead_code)]
+
+use std::marker::PhantomData;
+
+trait Handle {
+    type Inner;
+}
+
+struct ResizingHandle<H>(PhantomData<H>);
+impl<H> Handle for ResizingHandle<H> {
+    type Inner = H;
+}
+
+struct Receiver<T, H: Handle<Inner=T>>(PhantomData<H>);
+
+fn channel<T>(size: usize) -> Receiver<T, ResizingHandle<T>> {
+    let rx = Receiver(PhantomData);
+    rx
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass/issue-41696.rs b/src/test/run-pass/issue-41696.rs
new file mode 100644 (file)
index 0000000..ae57e0c
--- /dev/null
@@ -0,0 +1,61 @@
+// 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.
+
+// this used to cause exponential code-size blowup during LLVM passes.
+// min-llvm-version 3.9
+
+#![feature(test)]
+
+extern crate test;
+
+struct MayUnwind;
+
+impl Drop for MayUnwind {
+    fn drop(&mut self) {
+        if test::black_box(false) {
+            panic!()
+        }
+    }
+}
+
+struct DS<U> {
+    may_unwind: MayUnwind,
+    name: String,
+    next: U,
+}
+
+fn add<U>(ds: DS<U>, name: String) -> DS<DS<U>> {
+    DS {
+        may_unwind: MayUnwind,
+        name: "?".to_owned(),
+        next: ds,
+    }
+}
+
+fn main() {
+    let deserializers = DS { may_unwind: MayUnwind, name: "?".to_owned(), next: () };
+    let deserializers = add(deserializers, "?".to_owned());
+    let deserializers = add(deserializers, "?".to_owned());
+    let deserializers = add(deserializers, "?".to_owned());
+    let deserializers = add(deserializers, "?".to_owned());
+    let deserializers = add(deserializers, "?".to_owned());
+    let deserializers = add(deserializers, "?".to_owned());
+    let deserializers = add(deserializers, "?".to_owned()); // 0.7s
+    let deserializers = add(deserializers, "?".to_owned()); // 1.3s
+    let deserializers = add(deserializers, "?".to_owned()); // 2.4s
+    let deserializers = add(deserializers, "?".to_owned()); // 6.7s
+    let deserializers = add(deserializers, "?".to_owned()); // 26.0s
+    let deserializers = add(deserializers, "?".to_owned()); // 114.0s
+    let deserializers = add(deserializers, "?".to_owned()); // 228.0s
+    let deserializers = add(deserializers, "?".to_owned()); // 400.0s
+    let deserializers = add(deserializers, "?".to_owned()); // 800.0s
+    let deserializers = add(deserializers, "?".to_owned()); // 1600.0s
+    let deserializers = add(deserializers, "?".to_owned()); // 3200.0s
+}
diff --git a/src/test/run-pass/issue-41744.rs b/src/test/run-pass/issue-41744.rs
new file mode 100644 (file)
index 0000000..276067d
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Tc {}
+impl Tc for bool {}
+
+fn main() {
+    let _: &[&Tc] = &[&true];
+}
diff --git a/src/test/run-pass/issue-41803.rs b/src/test/run-pass/issue-41803.rs
new file mode 100644 (file)
index 0000000..e18b420
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// A compile-time map from identifiers to arbitrary (heterogeneous) expressions
+macro_rules! ident_map {
+    ( $name:ident = { $($key:ident => $e:expr,)* } ) => {
+        macro_rules! $name {
+            $(
+                ( $key ) => { $e };
+            )*
+            // Empty invocation expands to nothing. Needed when the map is empty.
+            () => {};
+        }
+    };
+}
+
+ident_map!(my_map = {
+    main => 0,
+});
+
+fn main() {
+    my_map!(main);
+}
diff --git a/src/test/run-pass/issue-41849-variance-req.rs b/src/test/run-pass/issue-41849-variance-req.rs
new file mode 100644 (file)
index 0000000..0557a6e
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #41849.
+
+use std::ops::Mul;
+
+const C: usize = 1;
+const CAPACITY: usize = 1 * C;
+
+struct A<X> {
+    f: [X; CAPACITY],
+}
+
+struct B<T> {
+    f: T,
+}
+
+impl<T> Mul for B<T> {
+    type Output = Self;
+    fn mul(self, _rhs: B<T>) -> Self::Output {
+        self
+    }
+}
+
+impl<T> Mul<usize> for B<T> {
+    type Output = Self;
+    fn mul(self, _rhs: usize) -> Self::Output {
+        self
+    }
+}
+
+fn main() {
+    let a = A { f: [1] };
+    let _ = B { f: a };
+}
diff --git a/src/test/run-pass/issue-41936-variance-coerce-unsized-cycle.rs b/src/test/run-pass/issue-41936-variance-coerce-unsized-cycle.rs
new file mode 100644 (file)
index 0000000..bfbead8
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #41936. The coerce-unsized trait check in
+// coherence was using subtyping, which triggered variance
+// computation, which failed because it required type info for fields
+// that had not (yet) been computed.
+
+#![feature(unsize)]
+#![feature(coerce_unsized)]
+
+use std::{marker,ops};
+
+// Change the array to a non-array, and error disappears
+// Adding a new field to the end keeps the error
+struct LogDataBuf([u8;8]);
+
+struct Aref<T: ?Sized>
+{
+    // Inner structure triggers the error, removing the inner removes the message.
+    ptr: Box<ArefInner<T>>,
+}
+impl<T: ?Sized + marker::Unsize<U>, U: ?Sized> ops::CoerceUnsized<Aref<U>> for Aref<T> {}
+
+struct ArefInner<T: ?Sized>
+{
+    // Even with this field commented out, the error is raised.
+    data: T,
+}
+
+fn main(){}
diff --git a/src/test/run-pass/lex-bare-cr-nondoc-comment.rs b/src/test/run-pass/lex-bare-cr-nondoc-comment.rs
new file mode 100644 (file)
index 0000000..ba949ca
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-tidy-cr
+
+// nondoc comment with bare CR: '\r'
+//// nondoc comment with bare CR: '\r'
+/* block nondoc comment with bare CR: '\r' */
+
+fn main() {
+}
diff --git a/src/test/run-pass/print-stdout-eprint-stderr.rs b/src/test/run-pass/print-stdout-eprint-stderr.rs
new file mode 100644 (file)
index 0000000..0a0f30a
--- /dev/null
@@ -0,0 +1,40 @@
+// 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.
+
+// ignore-emscripten spawning processes is not supported
+
+use std::{env, process};
+
+fn child() {
+    print!("[stdout 0]");
+    print!("[stdout {}]", 1);
+    println!("[stdout {}]", 2);
+    println!();
+    eprint!("[stderr 0]");
+    eprint!("[stderr {}]", 1);
+    eprintln!("[stderr {}]", 2);
+    eprintln!();
+}
+
+fn parent() {
+    let this = env::args().next().unwrap();
+    let output = process::Command::new(this).arg("-").output().unwrap();
+    assert!(output.status.success());
+
+    let stdout = String::from_utf8(output.stdout).unwrap();
+    let stderr = String::from_utf8(output.stderr).unwrap();
+
+    assert_eq!(stdout, "[stdout 0][stdout 1][stdout 2]\n\n");
+    assert_eq!(stderr, "[stderr 0][stderr 1][stderr 2]\n\n");
+}
+
+fn main() {
+    if env::args().count() == 2 { child() } else { parent() }
+}
diff --git a/src/test/run-pass/specialization/assoc-ty-graph-cycle.rs b/src/test/run-pass/specialization/assoc-ty-graph-cycle.rs
new file mode 100644 (file)
index 0000000..a65dcf3
--- /dev/null
@@ -0,0 +1,33 @@
+// 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.
+
+// Make sure we don't crash with a cycle error during coherence.
+
+#![feature(specialization)]
+
+trait Trait<T> {
+    type Assoc;
+}
+
+impl<T> Trait<T> for Vec<T> {
+    default type Assoc = ();
+}
+
+impl Trait<u8> for Vec<u8> {
+    type Assoc = u8;
+}
+
+impl<T> Trait<T> for String {
+    type Assoc = ();
+}
+
+impl Trait<<Vec<u8> as Trait<u8>>::Assoc> for String {}
+
+fn main() {}
diff --git a/src/test/run-pass/underscore-method-after-integer.rs b/src/test/run-pass/underscore-method-after-integer.rs
new file mode 100644 (file)
index 0000000..af91256
--- /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.
+
+trait Tr : Sized {
+    fn _method_on_numbers(self) {}
+}
+
+impl Tr for i32 {}
+
+fn main() {
+    42._method_on_numbers();
+}
index 0e78746704fb150a838c7a885902e729a947d7f1..5c64b4118c3ab1a748e2175b3f74c82baa123efc 100644 (file)
@@ -18,9 +18,9 @@ impl Foo {
     pub fn rust0() {}
     // @has - '//code' 'fn rust1()'
     pub extern "Rust" fn rust1() {}
-    // @has - '//code' 'extern fn c0()'
+    // @has - '//code' 'extern "C" fn c0()'
     pub extern fn c0() {}
-    // @has - '//code' 'extern fn c1()'
+    // @has - '//code' 'extern "C" fn c1()'
     pub extern "C" fn c1() {}
     // @has - '//code' 'extern "system" fn system0()'
     pub extern "system" fn system0() {}
@@ -31,7 +31,7 @@ pub trait Bar {}
 
 // @has - '//code' 'impl Bar for fn()'
 impl Bar for fn() {}
-// @has - '//code' 'impl Bar for extern fn()'
+// @has - '//code' 'impl Bar for extern "C" fn()'
 impl Bar for extern fn() {}
 // @has - '//code' 'impl Bar for extern "system" fn()'
 impl Bar for extern "system" fn() {}
index 3997dcd81e153e75a20cb5a7fc2a5447e59ce788..8511d461703de58dfc9cf656656f0ec2b1839e53 100644 (file)
 
 extern crate rustdoc_ffi as lib;
 
-// @has ffi/fn.foreigner.html //pre 'pub unsafe extern fn foreigner(cold_as_ice: u32)'
+// @has ffi/fn.foreigner.html //pre 'pub unsafe extern "C" fn foreigner(cold_as_ice: u32)'
 pub use lib::foreigner;
 
 extern "C" {
-    // @has ffi/fn.another.html //pre 'pub unsafe extern fn another(cold_as_ice: u32)'
+    // @has ffi/fn.another.html //pre 'pub unsafe extern "C" fn another(cold_as_ice: u32)'
     pub fn another(cold_as_ice: u32);
 }
index 6f84428b0798ff36965118296d20a204c61fa4b3..75df53589454f6d3927e8d8fc382d9f3b4f7fc9d 100644 (file)
@@ -10,7 +10,7 @@
 
 extern {
     // @has issue_22038/fn.foo1.html \
-    //      '//*[@class="rust fn"]' 'pub unsafe extern fn foo1()'
+    //      '//*[@class="rust fn"]' 'pub unsafe extern "C" fn foo1()'
     pub fn foo1();
 }
 
@@ -21,7 +21,7 @@
 }
 
 // @has issue_22038/fn.bar.html \
-//      '//*[@class="rust fn"]' 'pub extern fn bar()'
+//      '//*[@class="rust fn"]' 'pub extern "C" fn bar()'
 pub extern fn bar() {}
 
 // @has issue_22038/fn.baz.html \
index 1b60c2a334fa5ea7ae15a4bd553a9cdd9bc791a6..6ba776ba4679f845c2dd9f3f880e586f7d056b34 100644 (file)
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 extern "C" {
-    // @has variadic/fn.foo.html //pre 'pub unsafe extern fn foo(x: i32, ...)'
+    // @has variadic/fn.foo.html //pre 'pub unsafe extern "C" fn foo(x: i32, ...)'
     pub fn foo(x: i32, ...);
 }
index cf272b63128e8a104f366212646ecac2af4cb3f1..55723ee8cd96416c7bcc572eff46b387c77519a4 100644 (file)
@@ -4,19 +4,17 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content...
 12 |     if x > y { x } else { y }
    |                           ^
    |
-note: ...the reference is valid for the lifetime 'a as defined on the body at 11:43...
-  --> $DIR/ex1-return-one-existing-name-if-else.rs:11:44
+note: ...the reference is valid for the lifetime 'a as defined on the function body at 11:0...
+  --> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
    |
-11 |   fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
-   |  ____________________________________________^
+11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
 12 | |     if x > y { x } else { y }
 13 | | }
    | |_^
-note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the body at 11:43
-  --> $DIR/ex1-return-one-existing-name-if-else.rs:11:44
+note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the function body at 11:0
+  --> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
    |
-11 |   fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
-   |  ____________________________________________^
+11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
 12 | |     if x > y { x } else { y }
 13 | | }
    | |_^
index 6e03e66dd258f18c017e63f504d9d13ca13d006e..b7d985feca9f27dfd29ebd6556b4d2184677976d 100644 (file)
@@ -6,19 +6,17 @@ error[E0308]: mismatched types
    |
    = note: expected type `Ref<'a, _>`
               found type `Ref<'_, _>`
-note: the anonymous lifetime #2 defined on the body at 15:51...
-  --> $DIR/ex2a-push-one-existing-name.rs:15:52
+note: the anonymous lifetime #2 defined on the function body at 15:0...
+  --> $DIR/ex2a-push-one-existing-name.rs:15:1
    |
-15 |   fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
-   |  ____________________________________________________^
+15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
 16 | |     x.push(y);
 17 | | }
    | |_^
-note: ...does not necessarily outlive the lifetime 'a as defined on the body at 15:51
-  --> $DIR/ex2a-push-one-existing-name.rs:15:52
+note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 15:0
+  --> $DIR/ex2a-push-one-existing-name.rs:15:1
    |
-15 |   fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
-   |  ____________________________________________________^
+15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
 16 | |     x.push(y);
 17 | | }
    | |_^
index 028f54ce97871d98251e85a182af34ec3a441428..3a6e94f2b1c2e2da70127c5a631a22516b19a026 100644 (file)
@@ -6,19 +6,17 @@ error[E0308]: mismatched types
    |
    = note: expected type `Ref<'_, _>`
               found type `Ref<'_, _>`
-note: the anonymous lifetime #3 defined on the body at 15:43...
-  --> $DIR/ex2b-push-no-existing-names.rs:15:44
+note: the anonymous lifetime #3 defined on the function body at 15:0...
+  --> $DIR/ex2b-push-no-existing-names.rs:15:1
    |
-15 |   fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
-   |  ____________________________________________^
+15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
 16 | |     x.push(y);
 17 | | }
    | |_^
-note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 15:43
-  --> $DIR/ex2b-push-no-existing-names.rs:15:44
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 15:0
+  --> $DIR/ex2b-push-no-existing-names.rs:15:1
    |
-15 |   fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
-   |  ____________________________________________^
+15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
 16 | |     x.push(y);
 17 | | }
    | |_^
index 4621214419e42c157666ddd4e72e9af0aa7f7aab..3d7064a4f71a3b45423590caebeabea3619316ae 100644 (file)
@@ -4,11 +4,10 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d
 16 |     let z = Ref { data: y.data };
    |             ^^^
    |
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66...
-  --> $DIR/ex2c-push-inference-variable.rs:15:67
+note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
+  --> $DIR/ex2c-push-inference-variable.rs:15:1
    |
-15 |   fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-   |  ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
 16 | |     let z = Ref { data: y.data };
 17 | |     x.push(z);
 18 | | }
@@ -18,11 +17,10 @@ note: ...so that reference does not outlive borrowed content
    |
 16 |     let z = Ref { data: y.data };
    |                         ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66...
-  --> $DIR/ex2c-push-inference-variable.rs:15:67
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
+  --> $DIR/ex2c-push-inference-variable.rs:15:1
    |
-15 |   fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-   |  ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
 16 | |     let z = Ref { data: y.data };
 17 | |     x.push(z);
 18 | | }
index a69694fdc2e5bb7cdbde99f8b763724fd3fa4baf..aced855bf669bdca7e839fe0bdebb45f939827cb 100644 (file)
@@ -4,11 +4,10 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d
 17 |     let b = Ref { data: y.data };
    |             ^^^
    |
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66...
-  --> $DIR/ex2d-push-inference-variable-2.rs:15:67
+note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
+  --> $DIR/ex2d-push-inference-variable-2.rs:15:1
    |
-15 |   fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-   |  ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
 16 | |     let a: &mut Vec<Ref<i32>> = x;
 17 | |     let b = Ref { data: y.data };
 18 | |     a.push(b);
@@ -19,11 +18,10 @@ note: ...so that reference does not outlive borrowed content
    |
 17 |     let b = Ref { data: y.data };
    |                         ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66...
-  --> $DIR/ex2d-push-inference-variable-2.rs:15:67
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
+  --> $DIR/ex2d-push-inference-variable-2.rs:15:1
    |
-15 |   fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-   |  ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
 16 | |     let a: &mut Vec<Ref<i32>> = x;
 17 | |     let b = Ref { data: y.data };
 18 | |     a.push(b);
index eff15bb794b76a8f602b3afdca71fffea5713f43..07e2316b63d8c61a8a1ed90b9cf59cbcd9cbe345 100644 (file)
@@ -4,11 +4,10 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d
 17 |     let b = Ref { data: y.data };
    |             ^^^
    |
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66...
-  --> $DIR/ex2e-push-inference-variable-3.rs:15:67
+note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
+  --> $DIR/ex2e-push-inference-variable-3.rs:15:1
    |
-15 |   fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-   |  ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
 16 | |     let a: &mut Vec<Ref<i32>> = x;
 17 | |     let b = Ref { data: y.data };
 18 | |     Vec::push(a, b);
@@ -19,11 +18,10 @@ note: ...so that reference does not outlive borrowed content
    |
 17 |     let b = Ref { data: y.data };
    |                         ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66...
-  --> $DIR/ex2e-push-inference-variable-3.rs:15:67
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
+  --> $DIR/ex2e-push-inference-variable-3.rs:15:1
    |
-15 |   fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-   |  ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
 16 | |     let a: &mut Vec<Ref<i32>> = x;
 17 | |     let b = Ref { data: y.data };
 18 | |     Vec::push(a, b);
diff --git a/src/test/ui/macros/trace-macro.rs b/src/test/ui/macros/trace-macro.rs
new file mode 100644 (file)
index 0000000..34f674a
--- /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.
+
+// compile-flags: -Z trace-macros
+
+fn main() {
+    println!("Hello, World!");
+}
diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr
new file mode 100644 (file)
index 0000000..09117a4
--- /dev/null
@@ -0,0 +1,9 @@
+note: trace_macro
+  --> $DIR/trace-macro.rs:14:5
+   |
+14 |     println!("Hello, World!");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expands to `println! { "Hello, World!" }`
+   = note: expands to `print! { concat ! ( "Hello, World!" , "/n" ) }`
+
index adc229aaacc54d77955283f760e5509e737aaf53..78e0f7e619b12791e7f52b917eb205959da36f9f 100644 (file)
@@ -4,7 +4,9 @@ error: no method named `count` found for type `std::iter::Filter<std::iter::Fuse
 17 |     once::<&str>("str").fuse().filter(|a: &str| true).count();
    |                                                       ^^^^^
    |
-   = note: the method `count` exists but the following trait bounds were not satisfied: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53] : std::ops::FnMut<(&_,)>`, `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator`
+   = note: the method `count` exists but the following trait bounds were not satisfied:
+           `[closure@$DIR/issue-36053-2.rs:17:39: 17:53] : std::ops::FnMut<(&_,)>`
+           `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator`
 
 error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` implements the trait `for<'r> std::ops::FnMut<(&'r str,)>`, but the trait `for<'r> std::ops::FnMut<(&'r &str,)>` is required
   --> $DIR/issue-36053-2.rs:17:32
diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs
new file mode 100644 (file)
index 0000000..a4eb445
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo;
+
+fn main() {
+    let a: Result<(), Foo> = Ok(());
+    a.unwrap();
+    //~^ ERROR no method named `unwrap` found for type `std::result::Result<(), Foo>`
+    //~| NOTE the method `unwrap` exists but the following trait bounds were not satisfied
+}
diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
new file mode 100644 (file)
index 0000000..2bd786c
--- /dev/null
@@ -0,0 +1,11 @@
+error: no method named `unwrap` found for type `std::result::Result<(), Foo>` in the current scope
+  --> $DIR/method-help-unsatisfied-bound.rs:15:7
+   |
+15 |     a.unwrap();
+   |       ^^^^^^
+   |
+   = note: the method `unwrap` exists but the following trait bounds were not satisfied:
+           `Foo : std::fmt::Debug`
+
+error: aborting due to previous error
+
index dd04c5ce356c626224f5eda92cbc93e69edc4d5c..17c5d5d15d40479415e0c5503c248ace94e25045 100644 (file)
@@ -4,8 +4,8 @@ error[E0425]: cannot find value `A` in module `namespaced_enums`
 15 |     let _ = namespaced_enums::A;
    |                               ^ not found in `namespaced_enums`
    |
-   = help: possible candidate is found in another module, you can import it into scope:
-             `use namespaced_enums::Foo::A;`
+help: possible candidate is found in another module, you can import it into scope
+   | use namespaced_enums::Foo::A;
 
 error[E0425]: cannot find function `B` in module `namespaced_enums`
   --> $DIR/enums-are-namespaced-xc.rs:18:31
@@ -13,8 +13,8 @@ error[E0425]: cannot find function `B` in module `namespaced_enums`
 18 |     let _ = namespaced_enums::B(10);
    |                               ^ not found in `namespaced_enums`
    |
-   = help: possible candidate is found in another module, you can import it into scope:
-             `use namespaced_enums::Foo::B;`
+help: possible candidate is found in another module, you can import it into scope
+   | use namespaced_enums::Foo::B;
 
 error[E0422]: cannot find struct, variant or union type `C` in module `namespaced_enums`
   --> $DIR/enums-are-namespaced-xc.rs:21:31
@@ -22,8 +22,8 @@ error[E0422]: cannot find struct, variant or union type `C` in module `namespace
 21 |     let _ = namespaced_enums::C { a: 10 };
    |                               ^ not found in `namespaced_enums`
    |
-   = help: possible candidate is found in another module, you can import it into scope:
-             `use namespaced_enums::Foo::C;`
+help: possible candidate is found in another module, you can import it into scope
+   | use namespaced_enums::Foo::C;
 
 error: aborting due to 3 previous errors
 
index 69c48cc1f3241b9bbd0658c0119eabdb0410014a..63d2ce109142c70116181304aad38511fcb51325 100644 (file)
@@ -4,10 +4,10 @@ error[E0574]: expected struct, variant or union type, found enum `Result`
 19 |         Result {
    |         ^^^^^^ not a struct, variant or union type
    |
-   = help: possible better candidates are found in other modules, you can import them into scope:
-             `use std::fmt::Result;`
-             `use std::io::Result;`
-             `use std::thread::Result;`
+help: possible better candidates are found in other modules, you can import them into scope
+   | use std::fmt::Result;
+   | use std::io::Result;
+   | use std::thread::Result;
 
 error: aborting due to previous error
 
index ea6841e600972e78c4f376da98d3b388f4cc56fb..c0438abfe43b45cd5458eb302868063ff96c15df 100644 (file)
@@ -4,8 +4,8 @@ error[E0422]: cannot find struct, variant or union type `E` in this scope
 16 |     E { name: "foobar" }; //~ ERROR unresolved struct, variant or union type `E`
    |     ^ not found in this scope
    |
-   = help: possible candidate is found in another module, you can import it into scope:
-             `use SomeEnum::E;`
+help: possible candidate is found in another module, you can import it into scope
+   | use SomeEnum::E;
 
 error: aborting due to previous error
 
index f38491d5362587200e7b7df5eca3ca0640604b79..7315d295f7b8427a9c84cafe3cfa3a37539d3d89 100644 (file)
@@ -4,10 +4,10 @@ error[E0405]: cannot find trait `Mul` in this scope
 53 | impl Mul for Foo {
    |      ^^^ not found in this scope
    |
-   = help: possible candidates are found in other modules, you can import them into scope:
-             `use mul1::Mul;`
-             `use mul2::Mul;`
-             `use std::ops::Mul;`
+help: possible candidates are found in other modules, you can import them into scope
+   | use mul1::Mul;
+   | use mul2::Mul;
+   | use std::ops::Mul;
 
 error[E0412]: cannot find type `Mul` in this scope
   --> $DIR/issue-21221-1.rs:72:16
@@ -15,12 +15,12 @@ error[E0412]: cannot find type `Mul` in this scope
 72 | fn getMul() -> Mul {
    |                ^^^ not found in this scope
    |
-   = help: possible candidates are found in other modules, you can import them into scope:
-             `use mul1::Mul;`
-             `use mul2::Mul;`
-             `use mul3::Mul;`
-             `use mul4::Mul;`
-           and 2 other candidates
+help: possible candidates are found in other modules, you can import them into scope
+   | use mul1::Mul;
+   | use mul2::Mul;
+   | use mul3::Mul;
+   | use mul4::Mul;
+and 2 other candidates
 
 error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope
   --> $DIR/issue-21221-1.rs:83:6
@@ -34,8 +34,8 @@ error[E0405]: cannot find trait `Div` in this scope
 88 | impl Div for Foo {
    |      ^^^ not found in this scope
    |
-   = help: possible candidate is found in another module, you can import it into scope:
-             `use std::ops::Div;`
+help: possible candidate is found in another module, you can import it into scope
+   | use std::ops::Div;
 
 error: cannot continue compilation due to previous error
 
index 14dac7de4b2e13af1aa4796bdcc75fa3830b189c..f0b22754e6444607af28f16310bbe92a490c5f7e 100644 (file)
@@ -4,8 +4,8 @@ error[E0405]: cannot find trait `T` in this scope
 28 | impl T for Foo { }
    |      ^ not found in this scope
    |
-   = help: possible candidate is found in another module, you can import it into scope:
-             `use foo::bar::T;`
+help: possible candidate is found in another module, you can import it into scope
+   | use foo::bar::T;
 
 error: main function not found
 
index e1e00571e5d4a1bb5d110828db316c98df5c828f..a4a2496b19ae4c0b85c070945fa4fff4d35e0f54 100644 (file)
@@ -4,8 +4,8 @@ error[E0405]: cannot find trait `OuterTrait` in this scope
 25 | impl OuterTrait for Foo {}
    |      ^^^^^^^^^^ not found in this scope
    |
-   = help: possible candidate is found in another module, you can import it into scope:
-             `use issue_21221_3::outer::OuterTrait;`
+help: possible candidate is found in another module, you can import it into scope
+   | use issue_21221_3::outer::OuterTrait;
 
 error: cannot continue compilation due to previous error
 
index 569315a59cf34c8d9d1a8e89f3840bd633f5d307..dc2f22717313320616be267464421c8f15841708 100644 (file)
@@ -4,8 +4,8 @@ error[E0405]: cannot find trait `T` in this scope
 20 | impl T for Foo {}
    |      ^ not found in this scope
    |
-   = help: possible candidate is found in another module, you can import it into scope:
-             `use issue_21221_4::T;`
+help: possible candidate is found in another module, you can import it into scope
+   | use issue_21221_4::T;
 
 error: cannot continue compilation due to previous error
 
index a7dd494d75b0df694304d8f1b2f3279e588a7f58..0bf39dc55cee76a5b30d073f3c532380d2b7c5af 100644 (file)
@@ -4,8 +4,8 @@ error[E0404]: expected trait, found type alias `Foo`
 20 | impl Foo for S { //~ ERROR expected trait, found type alias `Foo`
    |      ^^^ type aliases cannot be used for traits
    |
-   = help: possible better candidate is found in another module, you can import it into scope:
-             `use issue_3907::Foo;`
+help: possible better candidate is found in another module, you can import it into scope
+   | use issue_3907::Foo;
 
 error: cannot continue compilation due to previous error
 
index 940e4acabb2c16b8016f45733a08a724e6b033c9..19940ff4586d2e3baf028f71ebecec7ba96804f9 100644 (file)
@@ -8,8 +8,8 @@ error[E0423]: expected value, found struct `Z`
    |         did you mean `S`?
    |         constructor is not visible here due to private fields
    |
-   = help: possible better candidate is found in another module, you can import it into scope:
-             `use m::n::Z;`
+help: possible better candidate is found in another module, you can import it into scope
+   | use m::n::Z;
 
 error[E0423]: expected value, found struct `S`
   --> $DIR/privacy-struct-ctor.rs:36:5
@@ -20,8 +20,8 @@ error[E0423]: expected value, found struct `S`
    |     did you mean `S { /* fields */ }`?
    |     constructor is not visible here due to private fields
    |
-   = help: possible better candidate is found in another module, you can import it into scope:
-             `use m::S;`
+help: possible better candidate is found in another module, you can import it into scope
+   | use m::S;
 
 error[E0423]: expected value, found struct `xcrate::S`
   --> $DIR/privacy-struct-ctor.rs:42:5
@@ -32,8 +32,8 @@ error[E0423]: expected value, found struct `xcrate::S`
    |     did you mean `xcrate::S { /* fields */ }`?
    |     constructor is not visible here due to private fields
    |
-   = help: possible better candidate is found in another module, you can import it into scope:
-             `use m::S;`
+help: possible better candidate is found in another module, you can import it into scope
+   | use m::S;
 
 error: tuple struct `Z` is private
   --> $DIR/privacy-struct-ctor.rs:25:9
index 9dab2f77898153eea02c08e92d5ca9bc2089b71a..e53ea6a55afb5dc3a9b1028bba5f5d89312fe0e9 100644 (file)
@@ -4,8 +4,8 @@ error[E0404]: expected trait, found type parameter `Add`
 15 | impl<T: Clone, Add> Add for Foo<T> {
    |                     ^^^ not a trait
    |
-   = help: possible better candidate is found in another module, you can import it into scope:
-             `use std::ops::Add;`
+help: possible better candidate is found in another module, you can import it into scope
+   | use std::ops::Add;
 
 error: main function not found
 
diff --git a/src/test/ui/static-lifetime.rs b/src/test/ui/static-lifetime.rs
new file mode 100644 (file)
index 0000000..7b1887b
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+pub trait Arbitrary: Sized + 'static {}
+
+impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {}
+
+fn main() {
+}
\ No newline at end of file
diff --git a/src/test/ui/static-lifetime.stderr b/src/test/ui/static-lifetime.stderr
new file mode 100644 (file)
index 0000000..f73dff4
--- /dev/null
@@ -0,0 +1,10 @@
+error[E0477]: the type `std::borrow::Cow<'a, A>` does not fulfill the required lifetime
+  --> $DIR/static-lifetime.rs:13:20
+   |
+13 | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {}
+   |                    ^^^^^^^^^
+   |
+   = note: type must satisfy the static lifetime
+
+error: aborting due to previous error
+
index fa7584c1495c2d9c04a6416f8e7b546abfa88a52..397359840ecad02d5fe69b2a0cf328e98235ffea 160000 (submodule)
@@ -1 +1 @@
-Subproject commit fa7584c1495c2d9c04a6416f8e7b546abfa88a52
+Subproject commit 397359840ecad02d5fe69b2a0cf328e98235ffea
index a044282666da0a7ec100086b2927bdf097f3c3c9..911f3c51f5f6005f4181f023f67218ca72bd2111 100644 (file)
@@ -570,7 +570,7 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
                          format!("-command={}", debugger_script.to_str().unwrap())];
 
                 let mut gdb_path = tool_path;
-                gdb_path.push_str(&format!("/bin/{}-gdb", self.config.target));
+                gdb_path.push_str("/bin/gdb");
                 let procsrv::Result {
                     out,
                     err,
@@ -647,6 +647,11 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
                                              exe_file.to_str().unwrap()
                                              .replace(r"\", r"\\")));
 
+                // Force GDB to print values in the Rust format.
+                if self.config.gdb_native_rust {
+                    script_str.push_str("set language rust\n");
+                }
+
                 // Add line breakpoints
                 for line in &breakpoint_lines {
                     script_str.push_str(&format!("break '{}':{}\n",
index 3d9a4fba6cdeefc5be4d7e1e2dd427b4fe50f95a..1b55dc792c2e5d1ec77182504fc4454acb151ca2 100644 (file)
@@ -41,7 +41,7 @@ macro_rules! t {
 }
 
 fn main() {
-    let docs = env::args().nth(1).unwrap();
+    let docs = env::args_os().nth(1).unwrap();
     let docs = env::current_dir().unwrap().join(docs);
     let mut errors = false;
     walk(&mut HashMap::new(), &docs, &docs, &mut errors);
@@ -65,7 +65,6 @@ enum Redirect {
 struct FileEntry {
     source: String,
     ids: HashSet<String>,
-    names: HashSet<String>,
 }
 
 type Cache = HashMap<PathBuf, FileEntry>;
@@ -73,7 +72,7 @@ struct FileEntry {
 impl FileEntry {
     fn parse_ids(&mut self, file: &Path, contents: &str, errors: &mut bool) {
         if self.ids.is_empty() {
-            with_attrs_in_source(contents, " id", |fragment, i| {
+            with_attrs_in_source(contents, " id", |fragment, i, _| {
                 let frag = fragment.trim_left_matches("#").to_owned();
                 if !self.ids.insert(frag) {
                     *errors = true;
@@ -82,15 +81,6 @@ fn parse_ids(&mut self, file: &Path, contents: &str, errors: &mut bool) {
             });
         }
     }
-
-    fn parse_names(&mut self, contents: &str) {
-        if self.names.is_empty() {
-            with_attrs_in_source(contents, " name", |fragment, _| {
-                let frag = fragment.trim_left_matches("#").to_owned();
-                self.names.insert(frag);
-            });
-        }
-    }
 }
 
 fn walk(cache: &mut Cache, root: &Path, dir: &Path, errors: &mut bool) {
@@ -116,15 +106,8 @@ fn check(cache: &mut Cache,
          file: &Path,
          errors: &mut bool)
          -> Option<PathBuf> {
-    // ignore js files as they are not prone to errors as the rest of the
-    // documentation is and they otherwise bring up false positives.
-    if file.extension().and_then(|s| s.to_str()) == Some("js") {
-        return None;
-    }
-
-    // ignore handlebars files as they use {{}} to build links, we only
-    // want to test the generated files
-    if file.extension().and_then(|s| s.to_str()) == Some("hbs") {
+    // Ignore none HTML files.
+    if file.extension().and_then(|s| s.to_str()) != Some("html") {
         return None;
     }
 
@@ -147,13 +130,7 @@ fn check(cache: &mut Cache,
         return None;
     }
 
-    // mdbook uses the HTML <base> tag to handle links for subdirectories, which
-    // linkchecker doesn't support
-    if file.to_str().unwrap().contains("unstable-book") {
-        return None;
-    }
-
-    let res = load_file(cache, root, PathBuf::from(file), SkipRedirect);
+    let res = load_file(cache, root, file, SkipRedirect);
     let (pretty_file, contents) = match res {
         Ok(res) => res,
         Err(_) => return None,
@@ -162,13 +139,10 @@ fn check(cache: &mut Cache,
         cache.get_mut(&pretty_file)
              .unwrap()
              .parse_ids(&pretty_file, &contents, errors);
-        cache.get_mut(&pretty_file)
-             .unwrap()
-             .parse_names(&contents);
     }
 
     // Search for anything that's the regex 'href[ ]*=[ ]*".*?"'
-    with_attrs_in_source(&contents, " href", |url, i| {
+    with_attrs_in_source(&contents, " href", |url, i, base| {
         // Ignore external URLs
         if url.starts_with("http:") || url.starts_with("https:") ||
            url.starts_with("javascript:") || url.starts_with("ftp:") ||
@@ -184,9 +158,9 @@ fn check(cache: &mut Cache,
         // Once we've plucked out the URL, parse it using our base url and
         // then try to extract a file path.
         let mut path = file.to_path_buf();
-        if !url.is_empty() {
+        if !base.is_empty() || !url.is_empty() {
             path.pop();
-            for part in Path::new(url).components() {
+            for part in Path::new(base).join(url).components() {
                 match part {
                     Component::Prefix(_) |
                     Component::RootDir => panic!(),
@@ -197,13 +171,6 @@ fn check(cache: &mut Cache,
             }
         }
 
-        if let Some(extension) = path.extension() {
-            // don't check these files
-            if extension == "png" {
-                return;
-            }
-        }
-
         // Alright, if we've found a file name then this file had better
         // exist! If it doesn't then we register and print an error.
         if path.exists() {
@@ -218,11 +185,17 @@ fn check(cache: &mut Cache,
                          pretty_path.display());
                 return;
             }
-            let res = load_file(cache, root, path.clone(), FromRedirect(false));
+            if let Some(extension) = path.extension() {
+                // Ignore none HTML files.
+                if extension != "html" {
+                    return;
+                }
+            }
+            let res = load_file(cache, root, &path, FromRedirect(false));
             let (pretty_path, contents) = match res {
                 Ok(res) => res,
                 Err(LoadError::IOError(err)) => {
-                    panic!(format!("error loading {}: {}", path.display(), err));
+                    panic!("error loading {}: {}", path.display(), err);
                 }
                 Err(LoadError::BrokenRedirect(target, _)) => {
                     *errors = true;
@@ -245,11 +218,10 @@ fn check(cache: &mut Cache,
 
                 let entry = &mut cache.get_mut(&pretty_path).unwrap();
                 entry.parse_ids(&pretty_path, &contents, errors);
-                entry.parse_names(&contents);
 
-                if !(entry.ids.contains(*fragment) || entry.names.contains(*fragment)) {
+                if !entry.ids.contains(*fragment) {
                     *errors = true;
-                    print!("{}:{}: broken link fragment  ",
+                    print!("{}:{}: broken link fragment ",
                            pretty_file.display(),
                            i + 1);
                     println!("`#{}` pointing to `{}`", fragment, pretty_path.display());
@@ -267,7 +239,7 @@ fn check(cache: &mut Cache,
 
 fn load_file(cache: &mut Cache,
              root: &Path,
-             mut file: PathBuf,
+             file: &Path,
              redirect: Redirect)
              -> Result<(PathBuf, String), LoadError> {
     let mut contents = String::new();
@@ -279,9 +251,9 @@ fn load_file(cache: &mut Cache,
             None
         }
         Entry::Vacant(entry) => {
-            let mut fp = File::open(file.clone()).map_err(|err| {
+            let mut fp = File::open(file).map_err(|err| {
                 if let FromRedirect(true) = redirect {
-                    LoadError::BrokenRedirect(file.clone(), err)
+                    LoadError::BrokenRedirect(file.to_path_buf(), err)
                 } else {
                     LoadError::IOError(err)
                 }
@@ -297,17 +269,14 @@ fn load_file(cache: &mut Cache,
                 entry.insert(FileEntry {
                     source: contents.clone(),
                     ids: HashSet::new(),
-                    names: HashSet::new(),
                 });
             }
             maybe
         }
     };
-    file.pop();
-    match maybe_redirect.map(|url| file.join(url)) {
+    match maybe_redirect.map(|url| file.parent().unwrap().join(url)) {
         Some(redirect_file) => {
-            let path = PathBuf::from(redirect_file);
-            load_file(cache, root, path, FromRedirect(true))
+            load_file(cache, root, &redirect_file, FromRedirect(true))
         }
         None => Ok((pretty_file, contents)),
     }
@@ -329,10 +298,14 @@ fn maybe_redirect(source: &str) -> Option<String> {
     })
 }
 
-fn with_attrs_in_source<F: FnMut(&str, usize)>(contents: &str, attr: &str, mut f: F) {
+fn with_attrs_in_source<F: FnMut(&str, usize, &str)>(contents: &str, attr: &str, mut f: F) {
+    let mut base = "";
     for (i, mut line) in contents.lines().enumerate() {
         while let Some(j) = line.find(attr) {
             let rest = &line[j + attr.len()..];
+            // The base tag should always be the first link in the document so
+            // we can get away with using one pass.
+            let is_base = line[..j].ends_with("<base");
             line = rest;
             let pos_equals = match rest.find("=") {
                 Some(i) => i,
@@ -358,7 +331,11 @@ fn with_attrs_in_source<F: FnMut(&str, usize)>(contents: &str, attr: &str, mut f
                 Some(i) => &rest[..i],
                 None => continue,
             };
-            f(url, i)
+            if is_base {
+                base = url;
+                continue;
+            }
+            f(url, i, base)
         }
     }
 }
index 67babd2d63710444a3071dfd9184648fd85a6a3d..38ca9b702b73c03959e447f5dae56eff7497c986 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 67babd2d63710444a3071dfd9184648fd85a6a3d
+Subproject commit 38ca9b702b73c03959e447f5dae56eff7497c986
diff --git a/src/tools/rust-installer b/src/tools/rust-installer
new file mode 160000 (submodule)
index 0000000..daa2a05
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit daa2a05ebe7b8d07a309e8891ebc548652362954
index 3bf396db4d39da9fe845523b35bdf7993218749d..ba02ee0c6d73b7a39cfa9caf95695cec951b10f2 100644 (file)
     "Unlicense/MIT",
 ];
 
-/// These MPL licensed projects are acceptable, but only these.
+// These are exceptions to Rust's permissive licensing policy, and
+// should be considered bugs. Exceptions are only allowed in Rust
+// tooling. It is _crucial_ that no exception crates be dependencies
+// of the Rust runtime (std / test).
 static EXCEPTIONS: &'static [&'static str] = &[
-    "mdbook",
-    "openssl",
-    "pest",
-    "thread-id",
+    "mdbook", // MPL2, mdbook
+    "openssl", // BSD+advertising clause, cargo, mdbook
+    "pest", // MPL2, mdbook via handlebars
+    "thread-id", // Apache-2.0, mdbook
+    "strings", // this is actually MIT/Apache-2.0 but it's not in the manifest yet
 ];
 
 pub fn check(path: &Path, bad: &mut bool) {
index f14a6a03893b39cd1313b789febc938c42d83252..6b666fa809f7a8cbfeb1d099ff25289eaed5834f 100644 (file)
@@ -81,12 +81,12 @@ fn filter_dirs(path: &Path) -> bool {
         "src/libbacktrace",
         "src/compiler-rt",
         "src/rustllvm",
-        "src/rust-installer",
         "src/liblibc",
         "src/vendor",
         "src/rt/hoedown",
         "src/tools/cargo",
         "src/tools/rls",
+        "src/tools/rust-installer",
     ];
     skip.iter().any(|p| path.ends_with(p))
 }
index 28a55a8763c64e47c4720926bbadfcc9d5b1ad53..8bf683de8704aedde2b69566a9084e243d3e0c49 100644 (file)
@@ -107,6 +107,11 @@ pub fn check(path: &Path, bad: &mut bool) {
 
         contents.truncate(0);
         t!(t!(File::open(file), file).read_to_string(&mut contents));
+
+        if contents.is_empty() {
+            tidy_error!(bad, "{}: empty file", file.display());
+        }
+
         let skip_cr = contents.contains("ignore-tidy-cr");
         let skip_tab = contents.contains("ignore-tidy-tab");
         let skip_length = contents.contains("ignore-tidy-linelength");