]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #38635 - GuillaumeGomez:atomicptr_docs, r=frewsxcv
authorAlex Crichton <alex@alexcrichton.com>
Fri, 30 Dec 2016 01:26:28 +0000 (17:26 -0800)
committerGitHub <noreply@github.com>
Fri, 30 Dec 2016 01:26:28 +0000 (17:26 -0800)
Add missing urls for AtomicPtr

r? @frewsxcv

522 files changed:
.travis.yml
README.md
RELEASES.md
configure
mk/cfg/x86_64-unknown-redox.mk [new file with mode: 0644]
src/bootstrap/README.md
src/bootstrap/bin/rustc.rs
src/bootstrap/bin/rustdoc.rs
src/bootstrap/check.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/config.toml.example
src/bootstrap/doc.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/sanity.rs
src/bootstrap/step.rs
src/ci/docker/arm-android/Dockerfile
src/ci/docker/arm-android/start-emulator.sh
src/ci/docker/cross/Dockerfile
src/ci/docker/i686-gnu-nopt/Dockerfile
src/ci/docker/i686-gnu/Dockerfile
src/ci/docker/x86_64-freebsd/Dockerfile
src/ci/docker/x86_64-gnu-cargotest/Dockerfile
src/ci/docker/x86_64-gnu-debug/Dockerfile
src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile [new file with mode: 0644]
src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile
src/ci/docker/x86_64-gnu-make/Dockerfile
src/ci/docker/x86_64-gnu-nopt/Dockerfile
src/ci/docker/x86_64-gnu/Dockerfile
src/ci/docker/x86_64-musl/Dockerfile
src/doc/book/casting-between-types.md
src/doc/book/documentation.md
src/doc/book/ffi.md
src/doc/book/testing.md
src/doc/book/variable-bindings.md
src/doc/reference.md
src/etc/platform-intrinsics/nvptx/cuda.json [new file with mode: 0644]
src/etc/platform-intrinsics/nvptx/info.json [new file with mode: 0644]
src/etc/platform-intrinsics/nvptx/sreg.json [new file with mode: 0644]
src/liballoc/arc.rs
src/liballoc/heap.rs
src/liballoc_jemalloc/build.rs
src/liballoc_system/lib.rs
src/libcollections/Cargo.toml
src/libcollections/binary_heap.rs
src/libcollections/borrow.rs
src/libcollections/enum_set.rs
src/libcollections/linked_list.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcollections/vec_deque.rs
src/libcompiler_builtins/build.rs
src/libcore/Cargo.toml
src/libcore/sync/atomic.rs
src/liblibc
src/libproc_macro_tokens/Cargo.toml
src/librustc/cfg/construct.rs
src/librustc/dep_graph/graph.rs
src/librustc/dep_graph/visit.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/itemlikevisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/blocks.rs
src/librustc/hir/map/collector.rs
src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/definitions.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/infer/error_reporting.rs
src/librustc/lib.rs
src/librustc/lint/context.rs
src/librustc/lint/mod.rs
src/librustc/middle/const_qualif.rs [deleted file]
src/librustc/middle/cstore.rs
src/librustc/middle/dataflow.rs
src/librustc/middle/dead.rs
src/librustc/middle/dependency_format.rs
src/librustc/middle/effect.rs
src/librustc/middle/entry.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/intrinsicck.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/reachable.rs
src/librustc/middle/region.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/weak_lang_items.rs
src/librustc/mir/transform.rs
src/librustc/session/config.rs
src/librustc/ty/context.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/util/common.rs
src/librustc_back/target/apple_base.rs
src/librustc_back/target/asmjs_unknown_emscripten.rs
src/librustc_back/target/bitrig_base.rs
src/librustc_back/target/dragonfly_base.rs
src/librustc_back/target/freebsd_base.rs
src/librustc_back/target/fuchsia_base.rs
src/librustc_back/target/haiku_base.rs
src/librustc_back/target/linux_base.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/netbsd_base.rs
src/librustc_back/target/openbsd_base.rs
src/librustc_back/target/redox_base.rs [new file with mode: 0644]
src/librustc_back/target/solaris_base.rs
src/librustc_back/target/wasm32_unknown_emscripten.rs
src/librustc_back/target/windows_base.rs
src/librustc_back/target/windows_msvc_base.rs
src/librustc_back/target/x86_64_unknown_redox.rs [new file with mode: 0644]
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs
src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
src/librustc_borrowck/borrowck/mir/dataflow/mod.rs
src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs
src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
src/librustc_borrowck/borrowck/mir/gather_moves.rs
src/librustc_borrowck/borrowck/mir/mod.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/borrowck/move_data.rs
src/librustc_const_eval/_match.rs
src/librustc_const_eval/check_match.rs
src/librustc_const_eval/diagnostics.rs
src/librustc_const_eval/eval.rs
src/librustc_driver/derive_registrar.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_incremental/assert_dep_graph.rs
src/librustc_incremental/calculate_svh/mod.rs
src/librustc_incremental/calculate_svh/svh_visitor.rs
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_lint/bad_style.rs
src/librustc_lint/builtin.rs
src/librustc_lint/types.rs
src/librustc_lint/unused.rs
src/librustc_llvm/build.rs
src/librustc_llvm/ffi.rs
src/librustc_llvm/lib.rs
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/diagnostics.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/schema.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/lib.rs
src/librustc_mir/mir_map.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/consts.rs
src/librustc_passes/hir_stats.rs
src/librustc_passes/loops.rs
src/librustc_passes/rvalues.rs
src/librustc_passes/static_recursion.rs
src/librustc_platform_intrinsics/lib.rs
src/librustc_platform_intrinsics/nvptx.rs [new file with mode: 0644]
src/librustc_plugin/Cargo.toml
src/librustc_plugin/build.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/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_save_analysis/span_utils.rs
src/librustc_trans/README.md [new file with mode: 0644]
src/librustc_trans/README.txt [deleted file]
src/librustc_trans/abi.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/lto.rs
src/librustc_trans/back/symbol_export.rs
src/librustc_trans/back/write.rs
src/librustc_trans/base.rs
src/librustc_trans/cabi_nvptx.rs [new file with mode: 0644]
src/librustc_trans/cabi_nvptx64.rs [new file with mode: 0644]
src/librustc_trans/cabi_sparc.rs [new file with mode: 0644]
src/librustc_trans/cabi_x86.rs
src/librustc_trans/callee.rs
src/librustc_trans/cleanup.rs
src/librustc_trans/collector.rs
src/librustc_trans/context.rs
src/librustc_trans/glue.rs
src/librustc_trans/lib.rs
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/monomorphize.rs
src/librustc_trans/trans_item.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/upvar.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/check_unused.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/orphan.rs
src/librustc_typeck/coherence/overlap.rs
src/librustc_typeck/coherence/unsafety.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/impl_wf_check.rs
src/librustc_typeck/rscope.rs
src/librustc_typeck/variance/constraints.rs
src/librustc_typeck/variance/terms.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/doctree.rs
src/librustdoc/html/format.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/styles/main.css
src/librustdoc/lib.rs
src/librustdoc/markdown.rs
src/librustdoc/test.rs
src/librustdoc/visit_ast.rs
src/libstd/build.rs
src/libstd/fs.rs
src/libstd/io/buffered.rs
src/libstd/io/mod.rs
src/libstd/sys/redox/args.rs
src/libstd/sys/redox/ext/io.rs
src/libstd/sys/redox/fs.rs
src/libstd/sys/redox/mod.rs
src/libstd/sys/redox/net/mod.rs
src/libstd/sys/redox/net/netc.rs [new file with mode: 0644]
src/libstd/sys/redox/net/tcp.rs
src/libstd/sys/redox/net/udp.rs
src/libstd/sys/redox/rand.rs
src/libstd/sys/redox/syscall/arch/arm.rs [new file with mode: 0644]
src/libstd/sys/redox/syscall/arch/x86.rs [new file with mode: 0644]
src/libstd/sys/redox/syscall/arch/x86_64.rs [new file with mode: 0644]
src/libstd/sys/redox/syscall/call.rs [new file with mode: 0644]
src/libstd/sys/redox/syscall/data.rs [new file with mode: 0644]
src/libstd/sys/redox/syscall/error.rs [new file with mode: 0644]
src/libstd/sys/redox/syscall/flag.rs [new file with mode: 0644]
src/libstd/sys/redox/syscall/mod.rs [new file with mode: 0644]
src/libstd/sys/redox/syscall/number.rs [new file with mode: 0644]
src/libstd/sys/unix/fd.rs
src/libstd/sys/unix/process/magenta.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/handle.rs
src/libstd/sys/windows/stdio.rs
src/libstd/thread/mod.rs
src/libsyntax/abi.rs
src/libsyntax/ast.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/placeholders.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs
src/libsyntax/symbol.rs
src/libsyntax/test.rs
src/libsyntax_ext/concat_idents.rs
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_ext/deriving/mod.rs
src/libtest/lib.rs
src/rustllvm/RustWrapper.cpp
src/rustllvm/llvm-auto-clean-trigger
src/rustllvm/rustllvm.h
src/stage0.txt
src/test/codegen/fastcall-inreg.rs [new file with mode: 0644]
src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs
src/test/compile-fail-fulldeps/qquote.rs
src/test/compile-fail/E0033.rs
src/test/compile-fail/E0248.rs [deleted file]
src/test/compile-fail/E0423.rs
src/test/compile-fail/E0424.rs
src/test/compile-fail/E0425.rs
src/test/compile-fail/E0513.rs [deleted file]
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/associated-path-shl.rs
src/test/compile-fail/associated-types-eq-1.rs
src/test/compile-fail/auxiliary/issue-21221-3.rs [deleted file]
src/test/compile-fail/auxiliary/issue-21221-4.rs [deleted file]
src/test/compile-fail/auxiliary/issue_19452_aux.rs [deleted file]
src/test/compile-fail/auxiliary/issue_3907.rs [deleted file]
src/test/compile-fail/auxiliary/lint_stability.rs
src/test/compile-fail/auxiliary/rmeta_meta.rs
src/test/compile-fail/bad-expr-path.rs
src/test/compile-fail/bad-expr-path2.rs
src/test/compile-fail/class-missing-self.rs
src/test/compile-fail/coherence-error-suppression.rs
src/test/compile-fail/dep-graph-struct-signature.rs
src/test/compile-fail/dep-graph-type-alias.rs
src/test/compile-fail/derived-errors/issue-31997.rs
src/test/compile-fail/does-nothing.rs
src/test/compile-fail/empty-struct-braces-expr.rs
src/test/compile-fail/empty-struct-braces-pat-2.rs
src/test/compile-fail/enum-variant-type-2.rs
src/test/compile-fail/enums-are-namespaced-xc.rs [deleted file]
src/test/compile-fail/explicit-self-lifetime-mismatch.rs
src/test/compile-fail/export-fully-qualified.rs
src/test/compile-fail/export.rs
src/test/compile-fail/export2.rs
src/test/compile-fail/extern-with-type-bounds.rs
src/test/compile-fail/for-expn.rs
src/test/compile-fail/for-loop-hygiene.rs
src/test/compile-fail/glob-resolve1.rs
src/test/compile-fail/import-glob-0.rs
src/test/compile-fail/issue-14254.rs [deleted file]
src/test/compile-fail/issue-1476.rs
src/test/compile-fail/issue-15167.rs
src/test/compile-fail/issue-16058.rs [deleted file]
src/test/compile-fail/issue-17518.rs [deleted file]
src/test/compile-fail/issue-17546.rs
src/test/compile-fail/issue-18058.rs
src/test/compile-fail/issue-18119.rs
src/test/compile-fail/issue-18252.rs [deleted file]
src/test/compile-fail/issue-19452.rs [deleted file]
src/test/compile-fail/issue-19883.rs
src/test/compile-fail/issue-21221-1.rs [deleted file]
src/test/compile-fail/issue-21221-2.rs [deleted file]
src/test/compile-fail/issue-21221-3.rs [deleted file]
src/test/compile-fail/issue-21221-4.rs [deleted file]
src/test/compile-fail/issue-22037.rs
src/test/compile-fail/issue-22384.rs
src/test/compile-fail/issue-2281-part1.rs
src/test/compile-fail/issue-2330.rs
src/test/compile-fail/issue-23305.rs [deleted file]
src/test/compile-fail/issue-2356.rs [deleted file]
src/test/compile-fail/issue-24968.rs [deleted file]
src/test/compile-fail/issue-27008.rs
src/test/compile-fail/issue-28388-1.rs
src/test/compile-fail/issue-28388-3.rs
src/test/compile-fail/issue-30535.rs
src/test/compile-fail/issue-30589.rs
src/test/compile-fail/issue-31845.rs
src/test/compile-fail/issue-33876.rs [deleted file]
src/test/compile-fail/issue-34334.rs
src/test/compile-fail/issue-35075.rs
src/test/compile-fail/issue-37534.rs
src/test/compile-fail/issue-3907-2.rs [deleted file]
src/test/compile-fail/issue-3907.rs [deleted file]
src/test/compile-fail/issue-4366-2.rs
src/test/compile-fail/issue-4366.rs
src/test/compile-fail/issue-5035-2.rs [deleted file]
src/test/compile-fail/issue-5035.rs [deleted file]
src/test/compile-fail/issue-5099.rs
src/test/compile-fail/issue-5927.rs
src/test/compile-fail/issue-6702.rs [deleted file]
src/test/compile-fail/issue-7607-1.rs
src/test/compile-fail/issue-8767.rs
src/test/compile-fail/keyword-super-as-identifier.rs
src/test/compile-fail/keyword-super.rs
src/test/compile-fail/macro-outer-attributes.rs
src/test/compile-fail/macro-parameter-span.rs
src/test/compile-fail/match-join.rs
src/test/compile-fail/match-vec-mismatch.rs
src/test/compile-fail/mod_file_correct_spans.rs
src/test/compile-fail/name-clash-nullary.rs
src/test/compile-fail/namespace-mix.rs
src/test/compile-fail/namespaced-enum-glob-import-no-impls-xcrate.rs
src/test/compile-fail/namespaced-enum-glob-import-no-impls.rs
src/test/compile-fail/nested-cfg-attrs.rs
src/test/compile-fail/no-implicit-prelude-nested.rs
src/test/compile-fail/no-implicit-prelude.rs
src/test/compile-fail/no-link.rs
src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs
src/test/compile-fail/non-constant-expr-for-vec-repeat.rs
src/test/compile-fail/parser-recovery-1.rs
src/test/compile-fail/parser-recovery-2.rs
src/test/compile-fail/pattern-macro-hygiene.rs
src/test/compile-fail/privacy-ns1.rs
src/test/compile-fail/privacy-ns2.rs
src/test/compile-fail/privacy/restricted/test.rs
src/test/compile-fail/privacy/restricted/ty-params.rs
src/test/compile-fail/recursive-reexports.rs
src/test/compile-fail/repeat_count.rs
src/test/compile-fail/resolve-bad-import-prefix.rs [new file with mode: 0644]
src/test/compile-fail/resolve-bad-visibility.rs [new file with mode: 0644]
src/test/compile-fail/resolve-hint-macro.rs [deleted file]
src/test/compile-fail/resolve-primitive-fallback.rs
src/test/compile-fail/resolve-unknown-trait.rs
src/test/compile-fail/rmeta-lib-pass.rs
src/test/compile-fail/rmeta-pass.rs
src/test/compile-fail/rmeta-priv-warn.rs [new file with mode: 0644]
src/test/compile-fail/rmeta.rs
src/test/compile-fail/rmeta_meta_main.rs
src/test/compile-fail/struct-fields-shorthand-unresolved.rs
src/test/compile-fail/suggest-path-instead-of-mod-dot-item.rs [deleted file]
src/test/compile-fail/syntax-extension-minor.rs
src/test/compile-fail/test-cfg.rs
src/test/compile-fail/token-error-correct-2.rs [deleted file]
src/test/compile-fail/token-error-correct-3.rs [deleted file]
src/test/compile-fail/token-error-correct.rs [deleted file]
src/test/compile-fail/ufcs-partially-resolved.rs [new file with mode: 0644]
src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs [deleted file]
src/test/compile-fail/unresolved_static_type_field.rs [deleted file]
src/test/compile-fail/variant-used-as-type.rs
src/test/compile-fail/xcrate-unit-struct.rs
src/test/debuginfo/union-smoke.rs
src/test/incremental/hashes/consts.rs
src/test/incremental/hashes/enum_defs.rs
src/test/incremental/hashes/extern_mods.rs [new file with mode: 0644]
src/test/incremental/hashes/inherent_impls.rs
src/test/incremental/hashes/inline_asm.rs [new file with mode: 0644]
src/test/incremental/hashes/statics.rs
src/test/incremental/hashes/trait_defs.rs
src/test/incremental/string_constant.rs
src/test/parse-fail/where_with_bound.rs [new file with mode: 0644]
src/test/pretty/issue-4264.pp
src/test/run-make/graphviz-flowgraph/f18.dot-expected.dot
src/test/run-make/graphviz-flowgraph/f19.dot-expected.dot
src/test/run-make/issue-38237/Makefile [new file with mode: 0644]
src/test/run-make/issue-38237/bar.rs [new file with mode: 0644]
src/test/run-make/issue-38237/baz.rs [new file with mode: 0644]
src/test/run-make/issue-38237/foo.rs [new file with mode: 0644]
src/test/run-make/pretty-print-path-suffix/foo_method.pp
src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs
src/test/run-pass-fulldeps/issue-37290/auxiliary/lint.rs
src/test/run-pass/auxiliary/rmeta_rmeta.rs
src/test/run-pass/issue-38437.rs [new file with mode: 0644]
src/test/run-pass/issue-38556.rs [new file with mode: 0644]
src/test/run-pass/type-sizes.rs
src/test/rustdoc/search-index-summaries.rs [new file with mode: 0644]
src/test/ui/codemap_tests/tab.stderr
src/test/ui/codemap_tests/two_files.stderr
src/test/ui/codemap_tests/unicode.stderr
src/test/ui/macros/macro-backtrace-nested.stderr
src/test/ui/print_type_sizes/nullable.stdout
src/test/ui/print_type_sizes/packed.stdout
src/test/ui/print_type_sizes/padding.stdout
src/test/ui/resolve/auxiliary/issue-21221-3.rs [new file with mode: 0644]
src/test/ui/resolve/auxiliary/issue-21221-4.rs [new file with mode: 0644]
src/test/ui/resolve/auxiliary/issue_19452_aux.rs [new file with mode: 0644]
src/test/ui/resolve/auxiliary/issue_3907.rs [new file with mode: 0644]
src/test/ui/resolve/auxiliary/namespaced_enums.rs [new file with mode: 0644]
src/test/ui/resolve/enums-are-namespaced-xc.rs [new file with mode: 0644]
src/test/ui/resolve/enums-are-namespaced-xc.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-14254.rs [new file with mode: 0644]
src/test/ui/resolve/issue-14254.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-16058.rs [new file with mode: 0644]
src/test/ui/resolve/issue-16058.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-17518.rs [new file with mode: 0644]
src/test/ui/resolve/issue-17518.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-18252.rs [new file with mode: 0644]
src/test/ui/resolve/issue-18252.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-19452.rs [new file with mode: 0644]
src/test/ui/resolve/issue-19452.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-21221-1.rs [new file with mode: 0644]
src/test/ui/resolve/issue-21221-1.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-21221-2.rs [new file with mode: 0644]
src/test/ui/resolve/issue-21221-2.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-21221-3.rs [new file with mode: 0644]
src/test/ui/resolve/issue-21221-3.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-21221-4.rs [new file with mode: 0644]
src/test/ui/resolve/issue-21221-4.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-23305.rs [new file with mode: 0644]
src/test/ui/resolve/issue-23305.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-2356.rs [new file with mode: 0644]
src/test/ui/resolve/issue-2356.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-24968.rs [new file with mode: 0644]
src/test/ui/resolve/issue-24968.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-33876.rs [new file with mode: 0644]
src/test/ui/resolve/issue-33876.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-3907-2.rs [new file with mode: 0644]
src/test/ui/resolve/issue-3907-2.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-3907.rs [new file with mode: 0644]
src/test/ui/resolve/issue-3907.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-5035-2.rs [new file with mode: 0644]
src/test/ui/resolve/issue-5035-2.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-5035.rs [new file with mode: 0644]
src/test/ui/resolve/issue-5035.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-6702.rs [new file with mode: 0644]
src/test/ui/resolve/issue-6702.stderr [new file with mode: 0644]
src/test/ui/resolve/resolve-assoc-suggestions.rs [new file with mode: 0644]
src/test/ui/resolve/resolve-assoc-suggestions.stderr [new file with mode: 0644]
src/test/ui/resolve/resolve-hint-macro.rs [new file with mode: 0644]
src/test/ui/resolve/resolve-hint-macro.stderr [new file with mode: 0644]
src/test/ui/resolve/resolve-speculative-adjustment.rs [new file with mode: 0644]
src/test/ui/resolve/resolve-speculative-adjustment.stderr [new file with mode: 0644]
src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs [new file with mode: 0644]
src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr [new file with mode: 0644]
src/test/ui/resolve/token-error-correct-2.rs [new file with mode: 0644]
src/test/ui/resolve/token-error-correct-2.stderr [new file with mode: 0644]
src/test/ui/resolve/token-error-correct-3.rs [new file with mode: 0644]
src/test/ui/resolve/token-error-correct-3.stderr [new file with mode: 0644]
src/test/ui/resolve/token-error-correct.rs [new file with mode: 0644]
src/test/ui/resolve/token-error-correct.stderr [new file with mode: 0644]
src/test/ui/resolve/tuple-struct-alias.rs [new file with mode: 0644]
src/test/ui/resolve/tuple-struct-alias.stderr [new file with mode: 0644]
src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.rs [new file with mode: 0644]
src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr [new file with mode: 0644]
src/test/ui/resolve/unresolved_static_type_field.rs [new file with mode: 0644]
src/test/ui/resolve/unresolved_static_type_field.stderr [new file with mode: 0644]
src/test/ui/span/impl-wrong-item-for-trait.stderr
src/test/ui/span/issue-35987.stderr
src/test/ui/span/mut-arg-hint.stderr
src/test/ui/span/typo-suggestion.stderr
src/tools/cargotest/main.rs
src/tools/rustbook/Cargo.toml

index ea8c94af80b72337e40447c63076401a0dd8153a..915d0bb535b6d239a88f5a91f896810308372a18 100644 (file)
@@ -8,6 +8,8 @@ git:
   depth: 1
   submodules: false
 
+osx_image: xcode8.2
+
 matrix:
   include:
     # Linux builders, all docker images
@@ -17,6 +19,7 @@ matrix:
     - env: IMAGE=i686-gnu-nopt
     - env: IMAGE=x86_64-freebsd
     - env: IMAGE=x86_64-gnu
+    - env: IMAGE=x86_64-gnu-full-bootstrap
     - env: IMAGE=x86_64-gnu-cargotest
     - env: IMAGE=x86_64-gnu-debug
     - env: IMAGE=x86_64-gnu-nopt
@@ -76,7 +79,7 @@ before_cache:
   - docker history -q rust-ci |
     grep -v missing |
     xargs docker save |
-    gzip -9 > $HOME/docker/rust-ci.tar.gz
+    gzip > $HOME/docker/rust-ci.tar.gz
 before_install:
   - zcat $HOME/docker/rust-ci.tar.gz | docker load || true
 
index 2133b17de0fbbe214a26807b540b9804520afb56..c1218e9c600ce772e82b053083393e84ad44f47c 100644 (file)
--- a/README.md
+++ b/README.md
@@ -82,8 +82,9 @@ build.
    # Install build tools needed for Rust. If you're building a 32-bit compiler,
    # then replace "x86_64" below with "i686". If you've already got git, python,
    # or CMake installed and in PATH you can remove them from this list. Note
-   # that it is important that the `python2` and `cmake` packages **not** used.
-   # The build has historically been known to fail with these packages.
+   # that it is important that you do **not** use the 'python2' and 'cmake'
+   # packages from the 'msys2' subsystem. The build has historically been known
+   # to fail with these packages.
    $ pacman -S git \
                make \
                diffutils \
index e468a86e7acc32762b5853aabe42301fb882e702..e85c9d18db9807891e48ceb4f3d921c76062609c 100644 (file)
@@ -1,3 +1,222 @@
+Version 1.14.0 (2016-12-22)
+===========================
+
+Language
+--------
+
+* [`..` matches multiple tuple fields in enum variants, structs
+  and tuples][36843]. [RFC 1492].
+* [Safe `fn` items can be coerced to `unsafe fn` pointers][37389]
+* [`use *` and `use ::*` both glob-import from the crate root][37367]
+* [It's now possible to call a `Vec<Box<Fn()>>` without explicit
+  dereferencing][36822]
+
+Compiler
+--------
+
+* [Mark enums with non-zero discriminant as non-zero][37224]
+* [Lower-case `static mut` names are linted like other
+  statics and consts][37162]
+* [Fix ICE on some macros in const integer positions
+   (e.g. `[u8; m!()]`)][36819]
+* [Improve error message and snippet for "did you mean `x`"][36798]
+* [Add a panic-strategy field to the target specification][36794]
+* [Include LLVM version in `--version --verbose`][37200]
+
+Compile-time Optimizations
+--------------------------
+
+* [Improve macro expansion performance][37569]
+* [Shrink `Expr_::ExprInlineAsm`][37445]
+* [Replace all uses of SHA-256 with BLAKE2b][37439]
+* [Reduce the number of bytes hashed by `IchHasher`][37427]
+* [Avoid more allocations when compiling html5ever][37373]
+* [Use `SmallVector` in `CombineFields::instantiate`][37322]
+* [Avoid some allocations in the macro parser][37318]
+* [Use a faster deflate setting][37298]
+* [Add `ArrayVec` and `AccumulateVec` to reduce heap allocations
+  during interning of slices][37270]
+* [Optimize `write_metadata`][37267]
+* [Don't process obligation forest cycles when stalled][37231]
+* [Avoid many `CrateConfig` clones][37161]
+* [Optimize `Substs::super_fold_with`][37108]
+* [Optimize `ObligationForest`'s `NodeState` handling][36993]
+* [Speed up `plug_leaks`][36917]
+
+Libraries
+---------
+
+* [`println!()`, with no arguments, prints newline][36825].
+  Previously, an empty string was required to achieve the same.
+* [`Wrapping` impls standard binary and unary operators, as well as
+   the `Sum` and `Product` iterators][37356]
+* [Implement `From<Cow<str>> for String` and `From<Cow<[T]>> for
+  Vec<T>`][37326]
+* [Improve `fold` performance for `chain`, `cloned`, `map`, and
+  `VecDeque` iterators][37315]
+* [Improve `SipHasher` performance on small values][37312]
+* [Add Iterator trait TrustedLen to enable better FromIterator /
+  Extend][37306]
+* [Expand `.zip()` specialization to `.map()` and `.cloned()`][37230]
+* [`ReadDir` implements `Debug`][37221]
+* [Implement `RefUnwindSafe` for atomic types][37178]
+* [Specialize `Vec::extend` to `Vec::extend_from_slice`][37094]
+* [Avoid allocations in `Decoder::read_str`][37064]
+* [`io::Error` implements `From<io::ErrorKind>`][37037]
+* [Impl `Debug` for raw pointers to unsized data][36880]
+* [Don't reuse `HashMap` random seeds][37470]
+* [The internal memory layout of `HashMap` is more cache-friendly, for
+  significant improvements in some operations][36692]
+* [`HashMap` uses less memory on 32-bit architectures][36595]
+* [Impl `Add<{str, Cow<str>}>` for `Cow<str>`][36430]
+
+Cargo
+-----
+
+* [Expose rustc cfg values to build scripts][cargo/3243]
+* [Allow cargo to work with read-only `CARGO_HOME`][cargo/3259]
+* [Fix passing --features when testing multiple packages][cargo/3280]
+* [Use a single profile set per workspace][cargo/3249]
+* [Load `replace` sections from lock files][cargo/3220]
+* [Ignore `panic` configuration for test/bench profiles][cargo/3175]
+
+Tooling
+-------
+
+* [rustup is the recommended Rust installation method][1.14rustup]
+* This release includes host (rustc) builds for Linux on MIPS, PowerPC, and
+  S390x. These are [tier 2] platforms and may have major defects. Follow the
+  instructions on the website to install, or add the targets to an existing
+  installation with `rustup target add`. The new target triples are:
+  - `mips-unknown-linux-gnu`
+  - `mipsel-unknown-linux-gnu`
+  - `mips64-unknown-linux-gnuabi64`
+  - `mips64el-unknown-linux-gnuabi64 `
+  - `powerpc-unknown-linux-gnu`
+  - `powerpc64-unknown-linux-gnu`
+  - `powerpc64le-unknown-linux-gnu`
+  - `s390x-unknown-linux-gnu `
+* This release includes target (std) builds for ARM Linux running MUSL
+  libc. These are [tier 2] platforms and may have major defects. Add the
+  following triples to an existing rustup installation with `rustup target add`:
+  - `arm-unknown-linux-musleabi`
+  - `arm-unknown-linux-musleabihf`
+  - `armv7-unknown-linux-musleabihf`
+* This release includes [experimental support for WebAssembly][1.14wasm], via
+  the `wasm32-unknown-emscripten` target. This target is known to have major
+  defects. Please test, report, and fix.
+* rustup no longer installs documentation by default. Run `rustup
+  component add rust-docs` to install.
+* [Fix line stepping in debugger][37310]
+* [Enable line number debuginfo in releases][37280]
+
+Misc
+----
+
+* [Disable jemalloc on aarch64/powerpc/mips][37392]
+* [Add support for Fuchsia OS][37313]
+* [Detect local-rebuild by only MAJOR.MINOR version][37273]
+
+Compatibility Notes
+-------------------
+
+* [A number of forward-compatibility lints used by the compiler
+  to gradually introduce language changes have been converted
+  to deny by default][36894]:
+  - ["use of inaccessible extern crate erroneously allowed"][36886]
+  - ["type parameter default erroneously allowed in invalid location"][36887]
+  - ["detects super or self keywords at the beginning of global path"][36888]
+  - ["two overlapping inherent impls define an item with the same name
+    were erroneously allowed"][36889]
+  - ["floating-point constants cannot be used in patterns"][36890]
+  - ["constants of struct or enum type can only be used in a pattern if
+     the struct or enum has `#[derive(PartialEq, Eq)]`"][36891]
+  - ["lifetimes or labels named `'_` were erroneously allowed"][36892]
+* [Prohibit patterns in trait methods without bodies][37378]
+* [The atomic `Ordering` enum may not be matched exhaustively][37351]
+* [Future-proofing `#[no_link]` breaks some obscure cases][37247]
+* [The `$crate` macro variable is accepted in fewer locations][37213]
+* [Impls specifying extra region requirements beyond the trait
+  they implement are rejected][37167]
+* [Enums may not be unsized][37111]. Unsized enums are intended to
+  work but never have. For now they are forbidden.
+* [Enforce the shadowing restrictions from RFC 1560 for today's macros][36767]
+
+[tier 2]: https://forge.rust-lang.org/platform-support.html
+[1.14rustup]: https://internals.rust-lang.org/t/beta-testing-rustup-rs/3316/204
+[1.14wasm]: https://users.rust-lang.org/t/compiling-to-the-web-with-rust-and-emscripten/7627
+[36430]: https://github.com/rust-lang/rust/pull/36430
+[36595]: https://github.com/rust-lang/rust/pull/36595
+[36595]: https://github.com/rust-lang/rust/pull/36595
+[36692]: https://github.com/rust-lang/rust/pull/36692
+[36767]: https://github.com/rust-lang/rust/pull/36767
+[36794]: https://github.com/rust-lang/rust/pull/36794
+[36798]: https://github.com/rust-lang/rust/pull/36798
+[36819]: https://github.com/rust-lang/rust/pull/36819
+[36822]: https://github.com/rust-lang/rust/pull/36822
+[36825]: https://github.com/rust-lang/rust/pull/36825
+[36843]: https://github.com/rust-lang/rust/pull/36843
+[36880]: https://github.com/rust-lang/rust/pull/36880
+[36886]: https://github.com/rust-lang/rust/issues/36886
+[36887]: https://github.com/rust-lang/rust/issues/36887
+[36888]: https://github.com/rust-lang/rust/issues/36888
+[36889]: https://github.com/rust-lang/rust/issues/36889
+[36890]: https://github.com/rust-lang/rust/issues/36890
+[36891]: https://github.com/rust-lang/rust/issues/36891
+[36892]: https://github.com/rust-lang/rust/issues/36892
+[36894]: https://github.com/rust-lang/rust/pull/36894
+[36917]: https://github.com/rust-lang/rust/pull/36917
+[36993]: https://github.com/rust-lang/rust/pull/36993
+[37037]: https://github.com/rust-lang/rust/pull/37037
+[37064]: https://github.com/rust-lang/rust/pull/37064
+[37094]: https://github.com/rust-lang/rust/pull/37094
+[37108]: https://github.com/rust-lang/rust/pull/37108
+[37111]: https://github.com/rust-lang/rust/pull/37111
+[37161]: https://github.com/rust-lang/rust/pull/37161
+[37162]: https://github.com/rust-lang/rust/pull/37162
+[37167]: https://github.com/rust-lang/rust/pull/37167
+[37178]: https://github.com/rust-lang/rust/pull/37178
+[37200]: https://github.com/rust-lang/rust/pull/37200
+[37213]: https://github.com/rust-lang/rust/pull/37213
+[37221]: https://github.com/rust-lang/rust/pull/37221
+[37224]: https://github.com/rust-lang/rust/pull/37224
+[37230]: https://github.com/rust-lang/rust/pull/37230
+[37231]: https://github.com/rust-lang/rust/pull/37231
+[37247]: https://github.com/rust-lang/rust/pull/37247
+[37267]: https://github.com/rust-lang/rust/pull/37267
+[37270]: https://github.com/rust-lang/rust/pull/37270
+[37273]: https://github.com/rust-lang/rust/pull/37273
+[37280]: https://github.com/rust-lang/rust/pull/37280
+[37298]: https://github.com/rust-lang/rust/pull/37298
+[37306]: https://github.com/rust-lang/rust/pull/37306
+[37310]: https://github.com/rust-lang/rust/pull/37310
+[37312]: https://github.com/rust-lang/rust/pull/37312
+[37313]: https://github.com/rust-lang/rust/pull/37313
+[37315]: https://github.com/rust-lang/rust/pull/37315
+[37318]: https://github.com/rust-lang/rust/pull/37318
+[37322]: https://github.com/rust-lang/rust/pull/37322
+[37326]: https://github.com/rust-lang/rust/pull/37326
+[37351]: https://github.com/rust-lang/rust/pull/37351
+[37356]: https://github.com/rust-lang/rust/pull/37356
+[37367]: https://github.com/rust-lang/rust/pull/37367
+[37373]: https://github.com/rust-lang/rust/pull/37373
+[37378]: https://github.com/rust-lang/rust/pull/37378
+[37389]: https://github.com/rust-lang/rust/pull/37389
+[37392]: https://github.com/rust-lang/rust/pull/37392
+[37427]: https://github.com/rust-lang/rust/pull/37427
+[37439]: https://github.com/rust-lang/rust/pull/37439
+[37445]: https://github.com/rust-lang/rust/pull/37445
+[37470]: https://github.com/rust-lang/rust/pull/37470
+[37569]: https://github.com/rust-lang/rust/pull/37569
+[RFC 1492]: https://github.com/rust-lang/rfcs/blob/master/text/1492-dotdot-in-patterns.md
+[cargo/3175]: https://github.com/rust-lang/cargo/pull/3175
+[cargo/3220]: https://github.com/rust-lang/cargo/pull/3220
+[cargo/3243]: https://github.com/rust-lang/cargo/pull/3243
+[cargo/3249]: https://github.com/rust-lang/cargo/pull/3249
+[cargo/3259]: https://github.com/rust-lang/cargo/pull/3259
+[cargo/3280]: https://github.com/rust-lang/cargo/pull/3280
+
+
 Version 1.13.0 (2016-11-10)
 ===========================
 
index e495c0d3abdcaa3d550565c43fe1d652b3e2ec00..5094e5a764bdfcae3a1624e95a7a19d7ff1c564d 100755 (executable)
--- a/configure
+++ b/configure
@@ -693,6 +693,7 @@ opt_nosave manage-submodules 1 "let the build manage the git submodules"
 opt_nosave clang 0 "prefer clang to gcc for building the runtime"
 opt_nosave jemalloc 1 "build liballoc with jemalloc"
 opt elf-tls 1 "elf thread local storage on platforms where supported"
+opt full-bootstrap 0 "build three compilers instead of two"
 
 valopt_nosave prefix "/usr/local" "set installation prefix"
 valopt_nosave local-rust-root "/usr/local" "set prefix for local rust binary"
@@ -917,6 +918,18 @@ case $CFG_BUILD in
 esac
 putvar CFG_LLDB_PYTHON
 
+# Do some sanity checks if running on buildbot
+# (these env vars are set by rust-buildbot)
+if [ -n "$RUST_DIST_SERVER" -a -n "$ALLOW_NONZERO_RLIMIT_CORE" ]; then
+   # Frequently the llvm submodule directory is broken by the build
+   # being killed
+   llvm_lock="${CFG_SRC_DIR}/.git/modules/src/llvm/index.lock"
+   if [ -e "$llvm_lock" ]; then
+       step_msg "removing $llvm_lock"
+       rm -f "$llvm_lock"
+   fi
+fi
+
 step_msg "looking for target specific programs"
 
 probe CFG_ADB        adb
diff --git a/mk/cfg/x86_64-unknown-redox.mk b/mk/cfg/x86_64-unknown-redox.mk
new file mode 100644 (file)
index 0000000..34aee77
--- /dev/null
@@ -0,0 +1 @@
+# rustbuild-only target
index ade5bde07d2da50a7012747f120d2acbb37c826c..ac84edb4038470445bdc7e56b93ade654fa4c18b 100644 (file)
@@ -142,7 +142,7 @@ incremental builds:
 ```
 
 The `--incremental` flag will store incremental compilation artifacts
-in `build/stage0-incremental`. Note that we only use incremental
+in `build/<host>/stage0-incremental`. Note that we only use incremental
 compilation for the stage0 -> stage1 compilation -- this is because
 the stage1 compiler is changing, and we don't try to cache and reuse
 incremental artifacts across different versions of the compiler. For
index 9cab6c423f5f98d1df57071a9d2019ea72a0db43..129798836e03b7d1012f27de6866fe78020a0044 100644 (file)
@@ -67,6 +67,7 @@ fn main() {
         ("RUSTC_REAL", "RUSTC_LIBDIR")
     };
     let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
+    let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
 
     let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
     let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
@@ -83,7 +84,7 @@ fn main() {
     if let Some(target) = target {
         // The stage0 compiler has a special sysroot distinct from what we
         // actually downloaded, so we just always pass the `--sysroot` option.
-        cmd.arg("--sysroot").arg(env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set"));
+        cmd.arg("--sysroot").arg(sysroot);
 
         // When we build Rust dylibs they're all intended for intermediate
         // usage, so make sure we pass the -Cprefer-dynamic flag instead of
index a53bbe22eb94cbd9a2c5adfe2cdb20dec667d0dc..e9ca430f1582b4723529255bb17cfb7309fc4d36 100644 (file)
@@ -25,6 +25,7 @@ fn main() {
     let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set");
     let libdir = env::var_os("RUSTC_LIBDIR").expect("RUSTC_LIBDIR was not set");
     let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
+    let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
 
     let mut dylib_path = bootstrap::util::dylib_path();
     dylib_path.insert(0, PathBuf::from(libdir));
@@ -35,6 +36,8 @@ fn main() {
         .arg(format!("stage{}", stage))
         .arg("--cfg")
         .arg("dox")
+        .arg("--sysroot")
+        .arg(sysroot)
         .env(bootstrap::util::dylib_path_var(),
              env::join_paths(&dylib_path).unwrap());
     std::process::exit(match cmd.status() {
index e7b0afeb8ce630447d596704c771aa8656922cc9..ec0243908edab1bc1b4eb131ff6d04972eb02d83 100644 (file)
@@ -341,12 +341,22 @@ pub fn krate(build: &Build,
     println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage,
              compiler.host, target);
 
+    // If we're not doing a full bootstrap but we're testing a stage2 version of
+    // libstd, then what we're actually testing is the libstd produced in
+    // stage1. Reflect that here by updating the compiler that we're working
+    // with automatically.
+    let compiler = if build.force_use_stage1(compiler, target) {
+        Compiler::new(1, compiler.host)
+    } else {
+        compiler.clone()
+    };
+
     // Build up the base `cargo test` command.
     //
     // Pass in some standard flags then iterate over the graph we've discovered
     // in `cargo metadata` with the maps above and figure out what `-p`
     // arguments need to get passed.
-    let mut cargo = build.cargo(compiler, mode, target, test_kind.subcommand());
+    let mut cargo = build.cargo(&compiler, mode, target, test_kind.subcommand());
     cargo.arg("--manifest-path")
          .arg(build.src.join(path).join("Cargo.toml"))
          .arg("--features").arg(features);
@@ -380,7 +390,7 @@ pub fn krate(build: &Build,
     // Note that to run the compiler we need to run with the *host* libraries,
     // but our wrapper scripts arrange for that to be the case anyway.
     let mut dylib_path = dylib_path();
-    dylib_path.insert(0, build.sysroot_libdir(compiler, target));
+    dylib_path.insert(0, build.sysroot_libdir(&compiler, target));
     cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
 
     if target.contains("android") {
@@ -399,10 +409,10 @@ pub fn krate(build: &Build,
 
     if target.contains("android") {
         build.run(&mut cargo);
-        krate_android(build, compiler, target, mode);
+        krate_android(build, &compiler, target, mode);
     } else if target.contains("emscripten") {
         build.run(&mut cargo);
-        krate_emscripten(build, compiler, target, mode);
+        krate_emscripten(build, &compiler, target, mode);
     } else {
         cargo.args(&build.flags.cmd.test_args());
         build.run(&mut cargo);
index b268686ca6c3b15dcb7c52655263eb4c1728e123..24e29225c6e02d3708e557721990aa2d369ed662 100644 (file)
 /// This will build the standard library for a particular stage of the build
 /// using the `compiler` targeting the `target` architecture. The artifacts
 /// created will also be linked into the sysroot directory.
-pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
-    println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
-             compiler.host, target);
-
+pub fn std(build: &Build, target: &str, compiler: &Compiler) {
     let libdir = build.sysroot_libdir(compiler, target);
     let _ = fs::remove_dir_all(&libdir);
     t!(fs::create_dir_all(&libdir));
 
+    println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
+             compiler.host, target);
+
     // Some platforms have startup objects that may be required to produce the
     // libstd dynamic library, for example.
     build_startup_objects(build, target, &libdir);
@@ -65,29 +65,30 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
 
     build.run(&mut cargo);
     update_mtime(&libstd_stamp(build, &compiler, target));
-    std_link(build, target, compiler.stage, compiler.host);
 }
 
 /// Link all libstd rlibs/dylibs into the sysroot location.
 ///
-/// Links those artifacts generated in the given `stage` for `target` produced
-/// by `compiler` into `host`'s sysroot.
+/// Links those artifacts generated by `compiler` to a the `stage` compiler's
+/// sysroot for the specified `host` and `target`.
+///
+/// Note that this assumes that `compiler` has already generated the libstd
+/// libraries for `target`, and this method will find them in the relevant
+/// output directory.
 pub fn std_link(build: &Build,
-                target: &str,
-                stage: u32,
-                host: &str) {
-    let compiler = Compiler::new(stage, &build.config.build);
-    let target_compiler = Compiler::new(compiler.stage, host);
+                compiler: &Compiler,
+                target_compiler: &Compiler,
+                target: &str) {
+    println!("Copying stage{} std from stage{} ({} -> {} / {})",
+             target_compiler.stage,
+             compiler.stage,
+             compiler.host,
+             target_compiler.host,
+             target);
     let libdir = build.sysroot_libdir(&target_compiler, target);
     let out_dir = build.cargo_out(&compiler, Mode::Libstd, target);
 
-    // If we're linking one compiler host's output into another, then we weren't
-    // called from the `std` method above. In that case we clean out what's
-    // already there.
-    if host != compiler.host {
-        let _ = fs::remove_dir_all(&libdir);
-        t!(fs::create_dir_all(&libdir));
-    }
+    t!(fs::create_dir_all(&libdir));
     add_to_sysroot(&out_dir, &libdir);
 
     if target.contains("musl") && !target.contains("mips") {
@@ -137,7 +138,7 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) {
 /// This will build libtest and supporting libraries for a particular stage of
 /// the build using the `compiler` targeting the `target` architecture. The
 /// artifacts created will also be linked into the sysroot directory.
-pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
+pub fn test(build: &Build, target: &str, compiler: &Compiler) {
     println!("Building stage{} test artifacts ({} -> {})", compiler.stage,
              compiler.host, target);
     let out_dir = build.cargo_out(compiler, Mode::Libtest, target);
@@ -147,19 +148,13 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
          .arg(build.src.join("src/rustc/test_shim/Cargo.toml"));
     build.run(&mut cargo);
     update_mtime(&libtest_stamp(build, compiler, target));
-    test_link(build, target, compiler.stage, compiler.host);
 }
 
-/// Link all libtest rlibs/dylibs into the sysroot location.
-///
-/// Links those artifacts generated in the given `stage` for `target` produced
-/// by `compiler` into `host`'s sysroot.
+/// Same as `std_link`, only for libtest
 pub fn test_link(build: &Build,
-                 target: &str,
-                 stage: u32,
-                 host: &str) {
-    let compiler = Compiler::new(stage, &build.config.build);
-    let target_compiler = Compiler::new(compiler.stage, host);
+                 compiler: &Compiler,
+                 target_compiler: &Compiler,
+                 target: &str) {
     let libdir = build.sysroot_libdir(&target_compiler, target);
     let out_dir = build.cargo_out(&compiler, Mode::Libtest, target);
     add_to_sysroot(&out_dir, &libdir);
@@ -170,7 +165,7 @@ pub fn test_link(build: &Build,
 /// This will build the compiler for a particular stage of the build using
 /// the `compiler` targeting the `target` architecture. The artifacts
 /// created will also be linked into the sysroot directory.
-pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
+pub fn rustc(build: &Build, target: &str, compiler: &Compiler) {
     println!("Building stage{} compiler artifacts ({} -> {})",
              compiler.stage, compiler.host, target);
 
@@ -222,20 +217,13 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
         cargo.env("CFG_DEFAULT_AR", s);
     }
     build.run(&mut cargo);
-
-    rustc_link(build, target, compiler.stage, compiler.host);
 }
 
-/// Link all librustc rlibs/dylibs into the sysroot location.
-///
-/// Links those artifacts generated in the given `stage` for `target` produced
-/// by `compiler` into `host`'s sysroot.
+/// Same as `std_link`, only for librustc
 pub fn rustc_link(build: &Build,
-                  target: &str,
-                  stage: u32,
-                  host: &str) {
-    let compiler = Compiler::new(stage, &build.config.build);
-    let target_compiler = Compiler::new(compiler.stage, host);
+                  compiler: &Compiler,
+                  target_compiler: &Compiler,
+                  target: &str) {
     let libdir = build.sysroot_libdir(&target_compiler, target);
     let out_dir = build.cargo_out(&compiler, Mode::Librustc, target);
     add_to_sysroot(&out_dir, &libdir);
@@ -259,6 +247,17 @@ fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
     PathBuf::from(out.trim())
 }
 
+pub fn create_sysroot(build: &Build, compiler: &Compiler) {
+    // nothing to do in stage0
+    if compiler.stage == 0 {
+        return
+    }
+
+    let sysroot = build.sysroot(compiler);
+    let _ = fs::remove_dir_all(&sysroot);
+    t!(fs::create_dir_all(&sysroot));
+}
+
 /// Prepare a new compiler from the artifacts in `stage`
 ///
 /// This will assemble a compiler in `build/$host/stage$stage`. The compiler
@@ -269,18 +268,17 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) {
     if stage == 0 {
         return
     }
+
+    println!("Copying stage{} compiler ({})", stage, host);
+
     // The compiler that we're assembling
     let target_compiler = Compiler::new(stage, host);
 
     // The compiler that compiled the compiler we're assembling
     let build_compiler = Compiler::new(stage - 1, &build.config.build);
 
-    // Clear out old files
-    let sysroot = build.sysroot(&target_compiler);
-    let _ = fs::remove_dir_all(&sysroot);
-    t!(fs::create_dir_all(&sysroot));
-
     // Link in all dylibs to the libdir
+    let sysroot = build.sysroot(&target_compiler);
     let sysroot_libdir = sysroot.join(libdir(host));
     t!(fs::create_dir_all(&sysroot_libdir));
     let src_libdir = build.sysroot_libdir(&build_compiler, host);
index 6b86e537b7d22098e8e2b2e47e1a77e8a04acd2f..93fe39ab41b57aa43c5e1d3f1534462ffa227273 100644 (file)
@@ -46,6 +46,7 @@ pub struct Config {
     pub docs: bool,
     pub vendor: bool,
     pub target_config: HashMap<String, Target>,
+    pub full_bootstrap: bool,
 
     // llvm codegen options
     pub llvm_assertions: bool,
@@ -134,6 +135,7 @@ struct Build {
     vendor: Option<bool>,
     nodejs: Option<String>,
     python: Option<String>,
+    full_bootstrap: Option<bool>,
 }
 
 /// TOML representation of various global install decisions.
@@ -264,6 +266,7 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
         set(&mut config.docs, build.docs);
         set(&mut config.submodules, build.submodules);
         set(&mut config.vendor, build.vendor);
+        set(&mut config.full_bootstrap, build.full_bootstrap);
 
         if let Some(ref install) = toml.install {
             config.prefix = install.prefix.clone();
@@ -393,6 +396,7 @@ macro_rules! check {
                 ("NINJA", self.ninja),
                 ("CODEGEN_TESTS", self.codegen_tests),
                 ("VENDOR", self.vendor),
+                ("FULL_BOOTSTRAP", self.full_bootstrap),
             }
 
             match key {
index 5fc095137c793e0101d102ae64b22790ed3a29bd..7c8d3870e923b12c0147f0411216e45ff52e52b3 100644 (file)
 # Indicate whether the vendored sources are used for Rust dependencies or not
 #vendor = false
 
+# Typically the build system will build the rust compiler twice. The second
+# compiler, however, will simply use its own libraries to link against. If you
+# would rather to perform a full bootstrap, compiling the compiler three times,
+# then you can set this option to true. You shouldn't ever need to set this
+# option to true.
+#full-bootstrap = false
+
 # =============================================================================
 # General install configuration options
 # =============================================================================
index 30c7fefad87453bedfbfd4855aa50346c0e66a67..4c4462bf1220dd68261bd4a74f517e4b560699a5 100644 (file)
@@ -137,6 +137,11 @@ pub fn std(build: &Build, stage: u32, target: &str) {
     let out = build.doc_out(target);
     t!(fs::create_dir_all(&out));
     let compiler = Compiler::new(stage, &build.config.build);
+    let compiler = if build.force_use_stage1(&compiler, target) {
+        Compiler::new(1, compiler.host)
+    } else {
+        compiler
+    };
     let out_dir = build.stage_out(&compiler, Mode::Libstd)
                        .join(target).join("doc");
     let rustdoc = build.rustdoc(&compiler);
@@ -160,6 +165,11 @@ pub fn test(build: &Build, stage: u32, target: &str) {
     let out = build.doc_out(target);
     t!(fs::create_dir_all(&out));
     let compiler = Compiler::new(stage, &build.config.build);
+    let compiler = if build.force_use_stage1(&compiler, target) {
+        Compiler::new(1, compiler.host)
+    } else {
+        compiler
+    };
     let out_dir = build.stage_out(&compiler, Mode::Libtest)
                        .join(target).join("doc");
     let rustdoc = build.rustdoc(&compiler);
@@ -182,6 +192,11 @@ pub fn rustc(build: &Build, stage: u32, target: &str) {
     let out = build.doc_out(target);
     t!(fs::create_dir_all(&out));
     let compiler = Compiler::new(stage, &build.config.build);
+    let compiler = if build.force_use_stage1(&compiler, target) {
+        Compiler::new(1, compiler.host)
+    } else {
+        compiler
+    };
     let out_dir = build.stage_out(&compiler, Mode::Librustc)
                        .join(target).join("doc");
     let rustdoc = build.rustdoc(&compiler);
index 665e0c67b7f6c1153bb32104d799449d74a0ef04..49eaed4c67acd23658b3177a1126df13bf61db8c 100644 (file)
@@ -572,9 +572,7 @@ fn tool_cmd(&self, compiler: &Compiler, tool: &str) -> Command {
         let mut cmd = Command::new(self.tool(&compiler, tool));
         let host = compiler.host;
         let mut paths = vec![
-            self.cargo_out(compiler, Mode::Libstd, host).join("deps"),
-            self.cargo_out(compiler, Mode::Libtest, host).join("deps"),
-            self.cargo_out(compiler, Mode::Librustc, host).join("deps"),
+            self.sysroot_libdir(compiler, compiler.host),
             self.cargo_out(compiler, Mode::Tool, host).join("deps"),
         ];
 
@@ -880,6 +878,30 @@ fn musl_root(&self, target: &str) -> Option<&Path> {
     fn python(&self) -> &Path {
         self.config.python.as_ref().unwrap()
     }
+
+    /// Tests whether the `compiler` compiling for `target` should be forced to
+    /// use a stage1 compiler instead.
+    ///
+    /// Currently, by default, the build system does not perform a "full
+    /// bootstrap" by default where we compile the compiler three times.
+    /// Instead, we compile the compiler two times. The final stage (stage2)
+    /// just copies the libraries from the previous stage, which is what this
+    /// method detects.
+    ///
+    /// Here we return `true` if:
+    ///
+    /// * The build isn't performing a full bootstrap
+    /// * The `compiler` is in the final stage, 2
+    /// * We're not cross-compiling, so the artifacts are already available in
+    ///   stage1
+    ///
+    /// When all of these conditions are met the build will lift artifacts from
+    /// the previous stage forward.
+    fn force_use_stage1(&self, compiler: &Compiler, target: &str) -> bool {
+        !self.config.full_bootstrap &&
+            compiler.stage >= 2 &&
+            self.config.host.iter().any(|h| h == target)
+    }
 }
 
 impl<'a> Compiler<'a> {
index 6ba6b8e6c86205899d7213c89e291d1b000ba2bd..80f27a5ab673f5f464cf2f6ce4c2da1f3266ad0d 100644 (file)
@@ -81,7 +81,7 @@ pub fn llvm(build: &Build, target: &str) {
        .profile(profile)
        .define("LLVM_ENABLE_ASSERTIONS", assertions)
        .define("LLVM_TARGETS_TO_BUILD",
-               "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430")
+               "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX")
        .define("LLVM_INCLUDE_EXAMPLES", "OFF")
        .define("LLVM_INCLUDE_TESTS", "OFF")
        .define("LLVM_INCLUDE_DOCS", "OFF")
index 5d543419fc9b6a78b8331728caf46d2f02e31aa3..66bdd5e00f43da5f6776aa8662ca7e7589f9d0a8 100644 (file)
@@ -78,7 +78,11 @@ pub fn check(build: &mut Build) {
         }
         need_cmd("cmake".as_ref());
         if build.config.ninja {
-            need_cmd("ninja".as_ref())
+            // Some Linux distros rename `ninja` to `ninja-build`.
+            // CMake can work with either binary name.
+            if have_cmd("ninja-build".as_ref()).is_none() {
+                need_cmd("ninja".as_ref());
+            }
         }
         break
     }
index c5898c1119a670d31ae710f31afb78152aca780c..424a891f324e96494827d767d746df264aa9d146 100644 (file)
@@ -44,7 +44,7 @@ pub fn run(build: &Build) {
     rules.run(&steps);
 }
 
-pub fn build_rules(build: &Build) -> Rules {
+pub fn build_rules<'a>(build: &'a Build) -> Rules {
     let mut rules = Rules::new(build);
 
     // This is the first rule that we're going to define for rustbuild, which is
@@ -117,6 +117,7 @@ pub fn build_rules(build: &Build) -> Rules {
 
     // the compiler with no target libraries ready to go
     rules.build("rustc", "src/rustc")
+         .dep(|s| s.name("create-sysroot").target(s.host))
          .dep(move |s| {
              if s.stage == 0 {
                  Step::noop()
@@ -151,69 +152,131 @@ pub fn build_rules(build: &Build) -> Rules {
     // Crate compilations
     //
     // Tools used during the build system but not shipped
+    rules.build("create-sysroot", "path/to/nowhere")
+         .run(move |s| compile::create_sysroot(build, &s.compiler()));
+
+    // These rules are "pseudo rules" that don't actually do any work
+    // themselves, but represent a complete sysroot with the relevant compiler
+    // linked into place.
+    //
+    // That is, depending on "libstd" means that when the rule is completed then
+    // the `stage` sysroot for the compiler `host` will be available with a
+    // standard library built for `target` linked in place. Not all rules need
+    // the compiler itself to be available, just the standard library, so
+    // there's a distinction between the two.
     rules.build("libstd", "src/libstd")
-         .dep(|s| s.name("build-crate-std_shim"));
+         .dep(|s| s.name("rustc").target(s.host))
+         .dep(|s| s.name("libstd-link"));
     rules.build("libtest", "src/libtest")
-         .dep(|s| s.name("build-crate-test_shim"));
+         .dep(|s| s.name("libstd"))
+         .dep(|s| s.name("libtest-link"))
+         .default(true);
     rules.build("librustc", "src/librustc")
-         .dep(|s| s.name("build-crate-rustc-main"));
+         .dep(|s| s.name("libtest"))
+         .dep(|s| s.name("librustc-link"))
+         .host(true)
+         .default(true);
+
+    // Helper method to define the rules to link a crate into its place in the
+    // sysroot.
+    //
+    // The logic here is a little subtle as there's a few cases to consider.
+    // Not all combinations of (stage, host, target) actually require something
+    // to be compiled, but rather libraries could get propagated from a
+    // different location. For example:
+    //
+    // * Any crate with a `host` that's not the build triple will not actually
+    //   compile something. A different `host` means that the build triple will
+    //   actually compile the libraries, and then we'll copy them over from the
+    //   build triple to the `host` directory.
+    //
+    // * Some crates aren't even compiled by the build triple, but may be copied
+    //   from previous stages. For example if we're not doing a full bootstrap
+    //   then we may just depend on the stage1 versions of libraries to be
+    //   available to get linked forward.
+    //
+    // * Finally, there are some cases, however, which do indeed comiple crates
+    //   and link them into place afterwards.
+    //
+    // The rule definition below mirrors these three cases. The `dep` method
+    // calculates the correct dependency which either comes from stage1, a
+    // different compiler, or from actually building the crate itself (the `dep`
+    // rule). The `run` rule then mirrors these three cases and links the cases
+    // forward into the compiler sysroot specified from the correct location.
+    fn crate_rule<'a, 'b>(build: &'a Build,
+                          rules: &'b mut Rules<'a>,
+                          krate: &'a str,
+                          dep: &'a str,
+                          link: fn(&Build, &Compiler, &Compiler, &str))
+                          -> RuleBuilder<'a, 'b> {
+        let mut rule = rules.build(&krate, "path/to/nowhere");
+        rule.dep(move |s| {
+                if build.force_use_stage1(&s.compiler(), s.target) {
+                    s.host(&build.config.build).stage(1)
+                } else if s.host == build.config.build {
+                    s.name(dep)
+                } else {
+                    s.host(&build.config.build)
+                }
+            })
+            .run(move |s| {
+                if build.force_use_stage1(&s.compiler(), s.target) {
+                    link(build,
+                         &s.stage(1).host(&build.config.build).compiler(),
+                         &s.compiler(),
+                         s.target)
+                } else if s.host == build.config.build {
+                    link(build, &s.compiler(), &s.compiler(), s.target)
+                } else {
+                    link(build,
+                         &s.host(&build.config.build).compiler(),
+                         &s.compiler(),
+                         s.target)
+                }
+            });
+            return rule
+    }
+
+    // Similar to the `libstd`, `libtest`, and `librustc` rules above, except
+    // these rules only represent the libraries being available in the sysroot,
+    // not the compiler itself. This is done as not all rules need a compiler in
+    // the sysroot, but may just need the libraries.
+    //
+    // All of these rules use the helper definition above.
+    crate_rule(build,
+               &mut rules,
+               "libstd-link",
+               "build-crate-std_shim",
+               compile::std_link)
+        .dep(|s| s.name("create-sysroot").target(s.host));
+    crate_rule(build,
+               &mut rules,
+               "libtest-link",
+               "build-crate-test_shim",
+               compile::test_link)
+        .dep(|s| s.name("libstd-link"));
+    crate_rule(build,
+               &mut rules,
+               "librustc-link",
+               "build-crate-rustc-main",
+               compile::rustc_link)
+        .dep(|s| s.name("libtest-link"));
+
     for (krate, path, _default) in krates("std_shim") {
         rules.build(&krate.build_step, path)
              .dep(move |s| s.name("rustc").host(&build.config.build).target(s.host))
-             .dep(move |s| {
-                 if s.host == build.config.build {
-                     Step::noop()
-                 } else {
-                    s.host(&build.config.build)
-                 }
-             })
-             .run(move |s| {
-                 if s.host == build.config.build {
-                    compile::std(build, s.target, &s.compiler())
-                 } else {
-                    compile::std_link(build, s.target, s.stage, s.host)
-                 }
-             });
+             .run(move |s| compile::std(build, s.target, &s.compiler()));
     }
-    for (krate, path, default) in krates("test_shim") {
+    for (krate, path, _default) in krates("test_shim") {
         rules.build(&krate.build_step, path)
-             .dep(|s| s.name("libstd"))
-             .dep(move |s| {
-                 if s.host == build.config.build {
-                    Step::noop()
-                 } else {
-                    s.host(&build.config.build)
-                 }
-             })
-             .default(default)
-             .run(move |s| {
-                 if s.host == build.config.build {
-                    compile::test(build, s.target, &s.compiler())
-                 } else {
-                    compile::test_link(build, s.target, s.stage, s.host)
-                 }
-             });
+             .dep(|s| s.name("libstd-link"))
+             .run(move |s| compile::test(build, s.target, &s.compiler()));
     }
-    for (krate, path, default) in krates("rustc-main") {
+    for (krate, path, _default) in krates("rustc-main") {
         rules.build(&krate.build_step, path)
-             .dep(|s| s.name("libtest"))
+             .dep(|s| s.name("libtest-link"))
              .dep(move |s| s.name("llvm").host(&build.config.build).stage(0))
-             .dep(move |s| {
-                 if s.host == build.config.build {
-                    Step::noop()
-                 } else {
-                    s.host(&build.config.build)
-                 }
-             })
-             .host(true)
-             .default(default)
-             .run(move |s| {
-                 if s.host == build.config.build {
-                    compile::rustc(build, s.target, &s.compiler())
-                 } else {
-                    compile::rustc_link(build, s.target, s.stage, s.host)
-                 }
-             });
+             .run(move |s| compile::rustc(build, s.target, &s.compiler()));
     }
 
     // ========================================================================
@@ -444,25 +507,25 @@ pub fn build_rules(build: &Build) -> Rules {
          .run(move |s| doc::standalone(build, s.stage, s.target));
     rules.doc("doc-error-index", "src/tools/error_index_generator")
          .dep(move |s| s.name("tool-error-index").target(&build.config.build))
-         .dep(move |s| s.name("librustc"))
+         .dep(move |s| s.name("librustc-link"))
          .default(build.config.docs)
          .host(true)
          .run(move |s| doc::error_index(build, s.stage, s.target));
     for (krate, path, default) in krates("std_shim") {
         rules.doc(&krate.doc_step, path)
-             .dep(|s| s.name("libstd"))
+             .dep(|s| s.name("libstd-link"))
              .default(default && build.config.docs)
              .run(move |s| doc::std(build, s.stage, s.target));
     }
     for (krate, path, default) in krates("test_shim") {
         rules.doc(&krate.doc_step, path)
-             .dep(|s| s.name("libtest"))
+             .dep(|s| s.name("libtest-link"))
              .default(default && build.config.compiler_docs)
              .run(move |s| doc::test(build, s.stage, s.target));
     }
     for (krate, path, default) in krates("rustc-main") {
         rules.doc(&krate.doc_step, path)
-             .dep(|s| s.name("librustc"))
+             .dep(|s| s.name("librustc-link"))
              .host(true)
              .default(default && build.config.compiler_docs)
              .run(move |s| doc::rustc(build, s.stage, s.target));
@@ -481,9 +544,9 @@ pub fn build_rules(build: &Build) -> Rules {
              // for the `rust-std` package, so if this is a host target we
              // depend on librustc and otherwise we just depend on libtest.
              if build.config.host.iter().any(|t| t == s.target) {
-                 s.name("librustc")
+                 s.name("librustc-link")
              } else {
-                 s.name("libtest")
+                 s.name("libtest-link")
              }
          })
          .default(true)
@@ -838,14 +901,21 @@ fn plan(&self) -> Vec<Step<'a>> {
             } else {
                 &self.build.config.target
             };
-            // If --target was specified but --host wasn't specified, don't run
-            // any host-only tests
+            // Determine the actual targets participating in this rule.
+            // NOTE: We should keep the full projection from build triple to
+            // the hosts for the dist steps, now that the hosts array above is
+            // truncated to avoid duplication of work in that case. Therefore
+            // the original non-shadowed hosts array is used below.
             let arr = if rule.host {
-                if self.build.flags.target.len() > 0 &&
-                   self.build.flags.host.len() == 0 {
-                    &hosts[..0]
+                // If --target was specified but --host wasn't specified,
+                // don't run any host-only tests. Also, respect any `--host`
+                // overrides as done for `hosts`.
+                if self.build.flags.host.len() > 0 {
+                    &self.build.flags.host[..]
+                } else if self.build.flags.target.len() > 0 {
+                    &[]
                 } else {
-                    hosts
+                    &self.build.config.host[..]
                 }
             } else {
                 targets
index 8911b4ff0cb87e5353a818201f6a2853ee740b1c..a40e76839eccd8349938fe296bb3a67a0935f564 100644 (file)
@@ -11,7 +11,6 @@ RUN dpkg --add-architecture i386 && \
   python2.7 \
   git \
   cmake \
-  ccache \
   unzip \
   expect \
   openjdk-9-jre \
@@ -50,5 +49,3 @@ ENV RUST_CONFIGURE_ARGS \
       --i686-linux-android-ndk=/android/ndk-x86-9 \
       --aarch64-linux-android-ndk=/android/ndk-aarch64
 ENV XPY_CHECK test --target arm-linux-androideabi
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
index 93f20b28b8689e4d37ce95bc648f174f8558353d..fcf42c1819ee72bdf3fa332158cf42f769b7cc7a 100755 (executable)
@@ -11,5 +11,7 @@
 
 set -ex
 ANDROID_EMULATOR_FORCE_32BIT=true \
-  emulator @arm-18 -no-window -partition-size 2047 &
+  nohup nohup emulator @arm-18 -no-window -partition-size 2047 \
+  0<&- &>/dev/null &
+adb wait-for-device
 exec "$@"
index 08b436313f6378c60efa525e65e0f4323d613489..c5aa323f50cd281adbe462f1f8196f20a6b5cb1c 100644 (file)
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gcc-aarch64-linux-gnu libc6-dev-arm64-cross \
   gcc-arm-linux-gnueabi libc6-dev-armel-cross \
@@ -70,6 +69,3 @@ ENV AR_s390x_unknown_linux_gnu=s390x-linux-gnu-ar \
 
 # FIXME(rust-lang/rust#36150): powerpc unfortunately aborts right now
 ENV NO_LLVM_ASSERTIONS=1
-
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
index 1da33c94c7b18d6caece93cbfb0d638cc7c8ccfa..1ffb24981c59aaa55d501dd3703057f1d12d3a3b 100644 (file)
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gdb \
   xz-utils
@@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
 ENV RUST_CHECK_TARGET check
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
index 9e5b0e0435e8b88dcec18a96b50ba4932572cc69..e4310232d78cf48382fd7b80bdaca5fd4767e296 100644 (file)
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gdb \
   xz-utils
@@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu
 ENV RUST_CHECK_TARGET check
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
index 75f3174e2c0443458eaf592e52af065f0e29271b..86efa74ba3b6f16c6d216ca0b5f158c0c29307be 100644 (file)
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   bzip2 \
   xz-utils \
@@ -33,5 +32,3 @@ ENV \
 
 ENV RUST_CONFIGURE_ARGS --target=x86_64-unknown-freebsd
 ENV RUST_CHECK_TARGET ""
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
index 2c3db87d9fb1fdd716f22aa489483e44a983ea34..1be11cb24f2fbb0e21bf25b70f444b87ae330265 100644 (file)
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   libssl-dev \
   sudo \
   xz-utils \
@@ -27,5 +26,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
 ENV RUST_CHECK_TARGET check-cargotest
 ENV NO_VENDOR 1
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
index eec88442293a4c2bbdf62231db3e06be061688fb..9ec8c6059ec31b801319d35af804777af9b0682a 100644 (file)
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gdb \
   xz-utils
@@ -28,5 +27,3 @@ ENV RUST_CONFIGURE_ARGS \
       --enable-debug \
       --enable-optimize
 ENV RUST_CHECK_TARGET ""
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
diff --git a/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile
new file mode 100644 (file)
index 0000000..7c079e4
--- /dev/null
@@ -0,0 +1,28 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  g++ \
+  make \
+  file \
+  curl \
+  ca-certificates \
+  python2.7 \
+  git \
+  cmake \
+  sudo \
+  gdb \
+  xz-utils
+
+ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
+RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
+      tar xJf - -C /usr/local/bin --strip-components=1
+
+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", "--"]
+
+ENV RUST_CONFIGURE_ARGS \
+      --build=x86_64-unknown-linux-gnu \
+      --enable-full-bootstrap
+ENV RUST_CHECK_TARGET ""
index 4c9198d88eb2129fe53ac18924fb4c9eed95b375..aabfc0cd1bd8f2067f7b4ea13d18b56bc738a430 100644 (file)
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gdb \
   llvm-3.7-tools \
@@ -30,5 +29,3 @@ ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
       --llvm-root=/usr/lib/llvm-3.7
 ENV RUST_CHECK_TARGET check
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
index 1c503aea13d5087d803ef3a8304fb52de6a83b30..c6071d704f5f6b7cc66ae6ddded1622e2115690a 100644 (file)
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gdb \
   xz-utils
@@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-rustbuild
 ENV RUST_CHECK_TARGET check
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
index 66de6ea13ac67c830210516d9a9c45359992e7b3..d28dc3de1b494bdbfca54481019549f78cd82163 100644 (file)
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gdb \
   xz-utils
@@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-optimize-tests
 ENV RUST_CHECK_TARGET check
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
index 3d71b7ffb9a3a04a1554e1c6549e34c27bc45cd3..9d8b75c80c7f242d312b6404800fd968b314d923 100644 (file)
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gdb \
   xz-utils
@@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
 ENV RUST_CHECK_TARGET check
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
index 96b38067cbb1479be05ec81c5f144deac440d442..49954157ec023a539dbd87332180dc321741dcaf 100644 (file)
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   xz-utils \
   sudo \
   gdb
@@ -33,6 +32,3 @@ ENV RUST_CONFIGURE_ARGS \
 ENV RUST_CHECK_TARGET check-stage2-T-x86_64-unknown-linux-musl-H-x86_64-unknown-linux-gnu
 ENV PATH=$PATH:/musl-x86_64/bin
 ENV XPY_CHECK test --target x86_64-unknown-linux-musl
-
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
index 296384ab6efd9507921cfa06e0e6ddc660e3e84a..a8f8224c58b81e3ca43c6b83bccfb2aa8715e712 100644 (file)
@@ -16,18 +16,18 @@ function result.
 
 The most common case of coercion is removing mutability from a reference:
 
- * `&mut T` to `&T`
+* `&mut T` to `&T`
 
 An analogous conversion is to remove mutability from a
 [raw pointer](raw-pointers.md):
 
- * `*mut T` to `*const T`
+* `*mut T` to `*const T`
 
 References can also be coerced to raw pointers:
 
- * `&T` to `*const T`
+* `&T` to `*const T`
 
- * `&mut T` to `*mut T`
+* `&mut T` to `*mut T`
 
 Custom coercions may be defined using [`Deref`](deref-coercions.md).
 
@@ -59,11 +59,11 @@ A cast `e as U` is valid if `e` has type `T` and `T` *coerces* to `U`.
 
 A cast `e as U` is also valid in any of the following cases:
 
- * `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast*
- * `e` is a C-like enum (with no data attached to the variants),
-    and `U` is an integer type; *enum-cast*
- * `e` has type `bool` or `char` and `U` is an integer type; *prim-int-cast*
- * `e` has type `u8` and `U` is `char`; *u8-char-cast*
+* `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast*
+* `e` is a C-like enum (with no data attached to the variants),
+   and `U` is an integer type; *enum-cast*
+* `e` has type `bool` or `char` and `U` is an integer type; *prim-int-cast*
+* `e` has type `u8` and `U` is `char`; *u8-char-cast*
 
 For example
 
index f30a95b4e7890bd89e9e333408408eca52fe369e..dafcffc39c802b0ff992fb4be06d8b9e5f86fcf2 100644 (file)
@@ -460,8 +460,9 @@ not actually pass as a test.
 ```
 
 The `no_run` attribute will compile your code, but not run it. This is
-important for examples such as "Here's how to start up a network service,"
-which you would want to make sure compile, but might run in an infinite loop!
+important for examples such as "Here's how to retrieve a web page,"
+which you would want to ensure compiles, but might be run in a test
+environment that has no network access.
 
 ### Documenting modules
 
index b53af694428da2648c9d4c8be9aeaf3a2ff08b7b..41457ee67a5fdb2d1fe44c7780d1a4ef58c06fbd 100644 (file)
@@ -574,6 +574,31 @@ The [`libc` crate on crates.io][libc] includes type aliases and function
 definitions for the C standard library in the `libc` module, and Rust links
 against `libc` and `libm` by default.
 
+# Variadic functions
+
+In C, functions can be 'variadic', meaning they accept a variable number of arguments. This can
+be achieved in Rust by specifying `...` within the argument list of a foreign function declaration:
+
+```no_run
+extern {
+    fn foo(x: i32, ...);
+}
+
+fn main() {
+    unsafe {
+        foo(10, 20, 30, 40, 50);
+    }
+}
+```
+
+Normal Rust functions can *not* be variadic:
+
+```ignore
+// This will not compile
+
+fn foo(x: i32, ...) { }
+```
+
 # The "nullable pointer optimization"
 
 Certain Rust types are defined to never be `null`. This includes references (`&T`,
index ebeb9923197a9aca4a680f15670b47032f56b324..96cec7295aa9d11abfcd6d4598543137194da9ed 100644 (file)
@@ -589,11 +589,10 @@ please see the [Documentation chapter](documentation.html).
 
 # Testing and concurrency
 
-One thing that is important to note when writing tests is that they may be run
-concurrently using threads. For this reason you should take care that your tests
-are written in such a way as to not depend on each-other, or on any shared
-state. "Shared state" can also include the environment, such as the current
-working directory, or environment variables.
+It is important to note that tests are run concurrently using threads. For this
+reason, care should be taken to ensure your tests do not depend on each-other,
+or on any shared state. "Shared state" can also include the environment, such
+as the current working directory, or environment variables.
 
 If this is an issue it is possible to control this concurrency, either by
 setting the environment variable `RUST_TEST_THREADS`, or by passing the argument
index 37b6c0513fc9647feef5562e6e31158e66e4c6bd..e1947310a9a28de758bae61f0c35add5f8450dd9 100644 (file)
@@ -102,7 +102,7 @@ mutation, then the solution is quite easy: add `mut`.
 There are other good reasons to avoid mutable state when possible, but they’re
 out of the scope of this guide. In general, you can often avoid explicit
 mutation, and so it is preferable in Rust. That said, sometimes, mutation is
-what you need, so it’s not verboten.
+what you need, so it’s not forbidden.
 
 # Initializing bindings
 
index b5a91a170d8ed478b71b0bedf1a4cfde5d600a20..9898c31282c34949aa13db715c5b6b27ed12c907 100644 (file)
@@ -1657,6 +1657,15 @@ Functions within external blocks may be called by Rust code, just like
 functions defined in Rust. The Rust compiler automatically translates between
 the Rust ABI and the foreign ABI.
 
+Functions within external blocks may be variadic by specifying `...` after one
+or more named arguments in the argument list:
+
+```ignore
+extern {
+    fn foo(x: i32, ...);
+}
+```
+
 A number of [attributes](#ffi-attributes) control the behavior of external blocks.
 
 By default external blocks assume that the library they are calling uses the
diff --git a/src/etc/platform-intrinsics/nvptx/cuda.json b/src/etc/platform-intrinsics/nvptx/cuda.json
new file mode 100644 (file)
index 0000000..1beaaeb
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "intrinsic_prefix": "_",
+    "llvm_prefix": "llvm.cuda.",
+    "intrinsics": [
+        {
+            "intrinsic": "syncthreads",
+            "width": ["0"],
+            "llvm": "syncthreads",
+            "ret": "V",
+            "args": []
+        }
+    ]
+}
diff --git a/src/etc/platform-intrinsics/nvptx/info.json b/src/etc/platform-intrinsics/nvptx/info.json
new file mode 100644 (file)
index 0000000..80332c5
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "platform": "nvptx",
+  "number_info": {
+    "signed": {}
+  },
+  "width_info": {}
+}
diff --git a/src/etc/platform-intrinsics/nvptx/sreg.json b/src/etc/platform-intrinsics/nvptx/sreg.json
new file mode 100644 (file)
index 0000000..33d97f2
--- /dev/null
@@ -0,0 +1,90 @@
+{
+    "intrinsic_prefix": "_",
+    "llvm_prefix": "llvm.nvvm.read.ptx.sreg.",
+    "intrinsics": [
+        {
+            "intrinsic": "block_dim_x",
+            "width": ["0"],
+            "llvm": "ntid.x",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "block_dim_y",
+            "width": ["0"],
+            "llvm": "ntid.y",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "block_dim_z",
+            "width": ["0"],
+            "llvm": "ntid.z",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "block_idx_x",
+            "width": ["0"],
+            "llvm": "ctaid.x",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "block_idx_y",
+            "width": ["0"],
+            "llvm": "ctaid.y",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "block_idx_z",
+            "width": ["0"],
+            "llvm": "ctaid.z",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "grid_dim_x",
+            "width": ["0"],
+            "llvm": "nctaid.x",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "grid_dim_y",
+            "width": ["0"],
+            "llvm": "nctaid.y",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "grid_dim_z",
+            "width": ["0"],
+            "llvm": "nctaid.z",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "thread_idx_x",
+            "width": ["0"],
+            "llvm": "tid.x",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "thread_idx_y",
+            "width": ["0"],
+            "llvm": "tid.y",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "thread_idx_z",
+            "width": ["0"],
+            "llvm": "tid.z",
+            "ret": "S32",
+            "args": []
+        }
+    ]
+}
index 1cad8f7f40788dc07c78b18203f1e80890e008a1..e1a240a0d2ebad258669f4b17edc5614bca190b9 100644 (file)
 /// [`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`][send]
-/// as long as `T` implements `Send` and [`Sync`][sync]. The disadvantage is
+/// 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.
+/// using [`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
 /// more flexibility.
 ///
 /// The [`downgrade`][downgrade] method can be used to create a non-owning
-/// [`Weak`][weak] pointer. A `Weak` pointer can be [`upgrade`][upgrade]d
-/// to an `Arc`, but this will return [`None`][option] if the value has
-/// already been dropped.
+/// [`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
+/// dropped.
 ///
 /// A cycle between `Arc` pointers will never be deallocated. For this reason,
-/// `Weak` is used to break cycles. For example, a tree could have strong
-/// `Arc` pointers from parent nodes to children, and `Weak` pointers from
-/// children back to their parents.
+/// [`Weak`][weak] is used to break cycles. For example, a tree could have
+/// strong `Arc` pointers from parent nodes to children, and [`Weak`][weak]
+/// pointers from children back to their parents.
 ///
 /// `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
 /// Arc::downgrade(&my_arc);
 /// ```
 ///
-/// `Weak<T>` does not auto-dereference to `T`, because the value may have
+/// [`Weak<T>`][weak] does not auto-dereference to `T`, because the value may have
 /// already been destroyed.
 ///
 /// [arc]: struct.Arc.html
 /// [weak]: struct.Weak.html
-/// [rc]: ../../std/rc/struct.Rc.html
+/// [`Rc`]: ../../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
+/// [`Send`]: ../../std/marker/trait.Send.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
-/// [option]: ../../std/option/enum.Option.html
+/// [`None`]: ../../std/option/enum.Option.html#variant.None
 /// [assoc]: ../../book/method-syntax.html#associated-functions
 ///
 /// # Examples
 /// }
 /// ```
 ///
-/// Sharing a mutable `AtomicUsize`:
+/// Sharing a mutable [`AtomicUsize`]:
+///
+/// [`AtomicUsize`]: ../../std/sync/atomic/struct.AtomicUsize.html
 ///
 /// ```no_run
 /// use std::sync::Arc;
index a1e32636980812b8ba7cd802ee5936cd71d3e0eb..81ed4be7763e945d1c9338fb3f105696f98abe57 100644 (file)
@@ -144,6 +144,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
 }
 
 #[cfg(not(test))]
+#[cfg(stage0)]
 #[lang = "exchange_free"]
 #[inline]
 unsafe fn exchange_free(ptr: *mut u8, old_size: usize, align: usize) {
index 60b7875a97c84dd0cb01acadadda12371ce58abe..2bbec9e5fc2250aa222d754896487ddd6e949234 100644 (file)
@@ -36,7 +36,8 @@ fn main() {
     // targets, which means we have to build the alloc_jemalloc crate
     // for targets like emscripten, even if we don't use it.
     if target.contains("rumprun") || target.contains("bitrig") || target.contains("openbsd") ||
-       target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") {
+       target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") ||
+       target.contains("redox") {
         println!("cargo:rustc-cfg=dummy_jemalloc");
         return;
     }
index a4fabb5a2c96dbd69dc39340f1bdfb8ffea8250a..4daa6cbb8465e58e7d939ef68617c46e0fc0b122 100644 (file)
@@ -19,7 +19,7 @@
             issue = "27783")]
 #![feature(allocator)]
 #![feature(staged_api)]
-#![cfg_attr(unix, feature(libc))]
+#![cfg_attr(any(unix, target_os = "redox"), feature(libc))]
 
 // The minimum alignment guaranteed by the architecture. This value is used to
 // add fast paths for low alignment values. In practice, the alignment is a
@@ -71,7 +71,7 @@ pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize {
     imp::usable_size(size, align)
 }
 
-#[cfg(unix)]
+#[cfg(any(unix, target_os = "redox"))]
 mod imp {
     extern crate libc;
 
@@ -87,7 +87,7 @@ pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
         }
     }
 
-    #[cfg(target_os = "android")]
+    #[cfg(any(target_os = "android", target_os = "redox"))]
     unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 {
         // On android we currently target API level 9 which unfortunately
         // doesn't have the `posix_memalign` API used below. Instead we use
@@ -109,7 +109,7 @@ unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 {
         libc::memalign(align as libc::size_t, size as libc::size_t) as *mut u8
     }
 
-    #[cfg(not(target_os = "android"))]
+    #[cfg(not(any(target_os = "android", target_os = "redox")))]
     unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 {
         let mut out = ptr::null_mut();
         let ret = libc::posix_memalign(&mut out, align as libc::size_t, size as libc::size_t);
index ab882fde9c2775683f0b63f48f3cc843232a319e..186ba6e8f211243512c1814c6598a36f1b75dc48 100644 (file)
@@ -16,6 +16,7 @@ std_unicode = { path = "../libstd_unicode" }
 name = "collectionstest"
 path = "../libcollectionstest/lib.rs"
 
-[[bench]]
-name = "collectionstest"
-path = "../libcollectionstest/lib.rs"
+# FIXME: need to extract benchmarks to separate crate
+#[[bench]]
+#name = "collectionstest"
+#path = "../libcollectionstest/lib.rs"
index 8d0c76c36468c86028de4bfd0f772b7bbddc5206..c5d5ad27d2304923dc51aa9196933c78072475b6 100644 (file)
@@ -225,7 +225,7 @@ pub struct BinaryHeap<T> {
 /// [`peek_mut()`]: struct.BinaryHeap.html#method.peek_mut
 #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
 pub struct PeekMut<'a, T: 'a + Ord> {
-    heap: &'a mut BinaryHeap<T>
+    heap: &'a mut BinaryHeap<T>,
 }
 
 #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
@@ -385,9 +385,7 @@ pub fn peek_mut(&mut self) -> Option<PeekMut<T>> {
         if self.is_empty() {
             None
         } else {
-            Some(PeekMut {
-                heap: self
-            })
+            Some(PeekMut { heap: self })
         }
     }
 
@@ -1126,7 +1124,9 @@ fn into_iter(self) -> IntoIter<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> IntoIterator for &'a BinaryHeap<T> where T: Ord {
+impl<'a, T> IntoIterator for &'a BinaryHeap<T>
+    where T: Ord
+{
     type Item = &'a T;
     type IntoIter = Iter<'a, T>;
 
index 37618b7600a045d340869403f786709a0b0b235e..e5bcf0d8e81797d97d2cf134f9a04aa16ac21de2 100644 (file)
@@ -63,7 +63,9 @@ pub trait ToOwned {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> ToOwned for T where T: Clone {
+impl<T> ToOwned for T
+    where T: Clone
+{
     type Owned = T;
     fn to_owned(&self) -> T {
         self.clone()
@@ -117,17 +119,19 @@ pub enum Cow<'a, B: ?Sized + 'a>
 {
     /// Borrowed data.
     #[stable(feature = "rust1", since = "1.0.0")]
-    Borrowed(#[stable(feature = "rust1", since = "1.0.0")] &'a B),
+    Borrowed(#[stable(feature = "rust1", since = "1.0.0")]
+             &'a B),
 
     /// Owned data.
     #[stable(feature = "rust1", since = "1.0.0")]
-    Owned(
-        #[stable(feature = "rust1", since = "1.0.0")] <B as ToOwned>::Owned
-    ),
+    Owned(#[stable(feature = "rust1", since = "1.0.0")]
+          <B as ToOwned>::Owned),
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
+impl<'a, B: ?Sized> Clone for Cow<'a, B>
+    where B: ToOwned
+{
     fn clone(&self) -> Cow<'a, B> {
         match *self {
             Borrowed(b) => Borrowed(b),
@@ -139,7 +143,9 @@ fn clone(&self) -> Cow<'a, B> {
     }
 }
 
-impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
+impl<'a, B: ?Sized> Cow<'a, B>
+    where B: ToOwned
+{
     /// Acquires a mutable reference to the owned form of the data.
     ///
     /// Clones the data if it is not already owned.
@@ -194,7 +200,9 @@ pub fn into_owned(self) -> <B as ToOwned>::Owned {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned {
+impl<'a, B: ?Sized> Deref for Cow<'a, B>
+    where B: ToOwned
+{
     type Target = B;
 
     fn deref(&self) -> &B {
@@ -209,7 +217,9 @@ fn deref(&self) -> &B {
 impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned {
+impl<'a, B: ?Sized> Ord for Cow<'a, B>
+    where B: Ord + ToOwned
+{
     #[inline]
     fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
         Ord::cmp(&**self, &**other)
@@ -228,7 +238,9 @@ fn eq(&self, other: &Cow<'b, C>) -> bool {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned {
+impl<'a, B: ?Sized> PartialOrd for Cow<'a, B>
+    where B: PartialOrd + ToOwned
+{
     #[inline]
     fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
         PartialOrd::partial_cmp(&**self, &**other)
@@ -273,7 +285,9 @@ fn default() -> Cow<'a, B> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned {
+impl<'a, B: ?Sized> Hash for Cow<'a, B>
+    where B: Hash + ToOwned
+{
     #[inline]
     fn hash<H: Hasher>(&self, state: &mut H) {
         Hash::hash(&**self, state)
index 79e0021b148a049f34e9f06a493cbd400ad618ea..87bc5e59ef78c178cff569aa19dba980dd42ded5 100644 (file)
@@ -276,7 +276,8 @@ fn from_iter<I: IntoIterator<Item = E>>(iter: I) -> EnumSet<E> {
     }
 }
 
-impl<'a, E> IntoIterator for &'a EnumSet<E> where E: CLike
+impl<'a, E> IntoIterator for &'a EnumSet<E>
+    where E: CLike
 {
     type Item = E;
     type IntoIter = Iter<E>;
index 67f3708a62b91dbf50e83d6bf98fcb5842f967b0..310855090885caf3ecf48100cfe6490d36f39cd1 100644 (file)
 
 //! A doubly-linked list with owned nodes.
 //!
-//! The `LinkedList` allows pushing and popping elements at either end and is thus
-//! efficiently usable as a double-ended queue.
+//! The `LinkedList` allows pushing and popping elements at either end
+//! in constant time.
+//!
+//! Almost always it is better to use `Vec` or [`VecDeque`] instead of
+//! [`LinkedList`]. In general, array-based containers are faster,
+//! more memory efficient and make better use of CPU cache.
+//!
+//! [`LinkedList`]: ../linked_list/struct.LinkedList.html
+//! [`VecDeque`]: ../vec_deque/struct.VecDeque.html
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
 
 use super::SpecExtend;
 
-/// A doubly-linked list.
+/// A doubly-linked list with owned nodes.
+///
+/// The `LinkedList` allows pushing and popping elements at either end
+/// in constant time.
+///
+/// Almost always it is better to use `Vec` or `VecDeque` instead of
+/// `LinkedList`. In general, array-based containers are faster,
+/// more memory efficient and make better use of CPU cache.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct LinkedList<T> {
     head: Option<Shared<Node<T>>>,
@@ -225,15 +239,17 @@ pub fn new() -> Self {
     pub fn append(&mut self, other: &mut Self) {
         match self.tail {
             None => mem::swap(self, other),
-            Some(tail) => if let Some(other_head) = other.head.take() {
-                unsafe {
-                    (**tail).next = Some(other_head);
-                    (**other_head).prev = Some(tail);
-                }
+            Some(tail) => {
+                if let Some(other_head) = other.head.take() {
+                    unsafe {
+                        (**tail).next = Some(other_head);
+                        (**other_head).prev = Some(tail);
+                    }
 
-                self.tail = other.tail.take();
-                self.len += mem::replace(&mut other.len, 0);
-            },
+                    self.tail = other.tail.take();
+                    self.len += mem::replace(&mut other.len, 0);
+                }
+            }
         }
     }
 
@@ -674,7 +690,10 @@ pub fn split_off(&mut self, at: usize) -> LinkedList<T> {
                reason = "method name and placement protocol are subject to change",
                issue = "30172")]
     pub fn front_place(&mut self) -> FrontPlace<T> {
-        FrontPlace { list: self, node: IntermediateBox::make_place() }
+        FrontPlace {
+            list: self,
+            node: IntermediateBox::make_place(),
+        }
     }
 
     /// Returns a place for insertion at the back of the list.
@@ -699,7 +718,10 @@ pub fn front_place(&mut self) -> FrontPlace<T> {
                reason = "method name and placement protocol are subject to change",
                issue = "30172")]
     pub fn back_place(&mut self) -> BackPlace<T> {
-        BackPlace { list: self, node: IntermediateBox::make_place() }
+        BackPlace {
+            list: self,
+            node: IntermediateBox::make_place(),
+        }
     }
 }
 
@@ -852,7 +874,7 @@ pub fn insert_next(&mut self, element: T) {
                 (**head).prev = node;
 
                 self.list.len += 1;
-            }
+            },
         }
     }
 
@@ -1135,9 +1157,15 @@ unsafe fn finalize(self) {
 // Ensure that `LinkedList` and its read-only iterators are covariant in their type parameters.
 #[allow(dead_code)]
 fn assert_covariance() {
-    fn a<'a>(x: LinkedList<&'static str>) -> LinkedList<&'a str> { x }
-    fn b<'i, 'a>(x: Iter<'i, &'static str>) -> Iter<'i, &'a str> { x }
-    fn c<'a>(x: IntoIter<&'static str>) -> IntoIter<&'a str> { x }
+    fn a<'a>(x: LinkedList<&'static str>) -> LinkedList<&'a str> {
+        x
+    }
+    fn b<'i, 'a>(x: Iter<'i, &'static str>) -> Iter<'i, &'a str> {
+        x
+    }
+    fn c<'a>(x: IntoIter<&'static str>) -> IntoIter<&'a str> {
+        x
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1298,10 +1326,10 @@ fn test_insert_prev() {
     fn test_send() {
         let n = list_from(&[1, 2, 3]);
         thread::spawn(move || {
-            check_links(&n);
-            let a: &[_] = &[&1, &2, &3];
-            assert_eq!(a, &n.iter().collect::<Vec<_>>()[..]);
-        })
+                check_links(&n);
+                let a: &[_] = &[&1, &2, &3];
+                assert_eq!(a, &n.iter().collect::<Vec<_>>()[..]);
+            })
             .join()
             .ok()
             .unwrap();
index d4be0914f15c83598b7d79f7e87c1e7e2d868339..70cedce9a905e7bebaeb536b25eadae5f38c2af8 100644 (file)
@@ -1697,11 +1697,7 @@ fn map_uppercase_sigma(from: &str, i: usize, to: &mut String) {
             debug_assert!('Σ'.len_utf8() == 2);
             let is_word_final = case_ignoreable_then_cased(from[..i].chars().rev()) &&
                                 !case_ignoreable_then_cased(from[i + 2..].chars());
-            to.push_str(if is_word_final {
-                "ς"
-            } else {
-                "σ"
-            });
+            to.push_str(if is_word_final { "ς" } else { "σ" });
         }
 
         fn case_ignoreable_then_cased<I: Iterator<Item = char>>(iter: I) -> bool {
index b4c41a99a6b971715f679d2e62a560c23cb7b2f7..157c762b4a7ed3767cb223852dd5a4c67681fef1 100644 (file)
@@ -542,11 +542,7 @@ fn unsafe_get(xs: &[u8], i: usize) -> u8 {
             unsafe { *xs.get_unchecked(i) }
         }
         fn safe_get(xs: &[u8], i: usize, total: usize) -> u8 {
-            if i >= total {
-                0
-            } else {
-                unsafe_get(xs, i)
-            }
+            if i >= total { 0 } else { unsafe_get(xs, i) }
         }
 
         let mut res = String::with_capacity(total);
@@ -976,7 +972,7 @@ pub fn shrink_to_fit(&mut self) {
     pub fn push(&mut self, ch: char) {
         match ch.len_utf8() {
             1 => self.vec.push(ch as u8),
-            _ => self.vec.extend_from_slice(ch.encode_utf8(&mut [0;4]).as_bytes()),
+            _ => self.vec.extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()),
         }
     }
 
@@ -1935,7 +1931,7 @@ fn from_iter<I: IntoIterator<Item = String>>(it: I) -> Cow<'a, str> {
 
 #[stable(feature = "from_string_for_vec_u8", since = "1.14.0")]
 impl From<String> for Vec<u8> {
-    fn from(string : String) -> Vec<u8> {
+    fn from(string: String) -> Vec<u8> {
         string.into_bytes()
     }
 }
index dbe3fec205cb268ee7fa01e80b8194ef934bb131..67621b860bf391c5ad964a8e2b9f5bd23aecebc8 100644 (file)
@@ -206,11 +206,7 @@ unsafe fn copy_nonoverlapping(&self, dst: usize, src: usize, len: usize) {
     unsafe fn wrap_copy(&self, dst: usize, src: usize, len: usize) {
         #[allow(dead_code)]
         fn diff(a: usize, b: usize) -> usize {
-            if a <= b {
-                b - a
-            } else {
-                a - b
-            }
+            if a <= b { b - a } else { a - b }
         }
         debug_assert!(cmp::min(diff(dst, src), self.cap() - diff(dst, src)) + len <= self.cap(),
                       "wrc dst={} src={} len={} cap={}",
@@ -552,8 +548,8 @@ pub fn reserve(&mut self, additional: usize) {
         let old_cap = self.cap();
         let used_cap = self.len() + 1;
         let new_cap = used_cap.checked_add(additional)
-                              .and_then(|needed_cap| needed_cap.checked_next_power_of_two())
-                              .expect("capacity overflow");
+            .and_then(|needed_cap| needed_cap.checked_next_power_of_two())
+            .expect("capacity overflow");
 
         if new_cap > self.capacity() {
             self.buf.reserve_exact(used_cap, new_cap - used_cap);
@@ -1293,9 +1289,7 @@ pub fn insert(&mut self, index: usize, value: T) {
 
         let contiguous = self.is_contiguous();
 
-        match (contiguous,
-               distance_to_tail <= distance_to_head,
-               idx >= self.tail) {
+        match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) {
             (true, true, _) if index == 0 => {
                 // push_front
                 //
@@ -1513,9 +1507,7 @@ pub fn remove(&mut self, index: usize) -> Option<T> {
 
         let contiguous = self.is_contiguous();
 
-        match (contiguous,
-               distance_to_tail <= distance_to_head,
-               idx >= self.tail) {
+        match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) {
             (true, true, _) => {
                 unsafe {
                     // contiguous, remove closer to tail:
@@ -1812,7 +1804,7 @@ fn wrap_index(index: usize, size: usize) -> usize {
 }
 
 /// Returns the two slices that cover the VecDeque's valid range
-trait RingSlices : Sized {
+trait RingSlices: Sized {
     fn slice(self, from: usize, to: usize) -> Self;
     fn split_at(self, i: usize) -> (Self, Self);
 
@@ -1895,7 +1887,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
     }
 
     fn fold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
-        where F: FnMut(Acc, Self::Item) -> Acc,
+        where F: FnMut(Acc, Self::Item) -> Acc
     {
         let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
         accum = front.iter().fold(accum, &mut f);
@@ -1959,7 +1951,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
     }
 
     fn fold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
-        where F: FnMut(Acc, Self::Item) -> Acc,
+        where F: FnMut(Acc, Self::Item) -> Acc
     {
         let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
         accum = front.iter_mut().fold(accum, &mut f);
@@ -2082,17 +2074,15 @@ fn drop(&mut self) {
             (_, 0) => {
                 source_deque.head = drain_tail;
             }
-            _ => {
-                unsafe {
-                    if tail_len <= head_len {
-                        source_deque.tail = source_deque.wrap_sub(drain_head, tail_len);
-                        source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len);
-                    } else {
-                        source_deque.head = source_deque.wrap_add(drain_tail, head_len);
-                        source_deque.wrap_copy(drain_tail, drain_head, head_len);
-                    }
+            _ => unsafe {
+                if tail_len <= head_len {
+                    source_deque.tail = source_deque.wrap_sub(drain_head, tail_len);
+                    source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len);
+                } else {
+                    source_deque.head = source_deque.wrap_add(drain_tail, head_len);
+                    source_deque.wrap_copy(drain_tail, drain_head, head_len);
                 }
-            }
+            },
         }
     }
 }
@@ -2288,10 +2278,8 @@ fn from(mut other: Vec<T>) -> Self {
 
             // We need to extend the buf if it's not a power of two, too small
             // or doesn't have at least one free space
-            if !buf.cap().is_power_of_two()
-                || (buf.cap() < (MINIMUM_CAPACITY + 1))
-                || (buf.cap() == len)
-            {
+            if !buf.cap().is_power_of_two() || (buf.cap() < (MINIMUM_CAPACITY + 1)) ||
+               (buf.cap() == len) {
                 let cap = cmp::max(buf.cap() + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
                 buf.reserve_exact(len, cap - len);
             }
@@ -2299,7 +2287,7 @@ fn from(mut other: Vec<T>) -> Self {
             VecDeque {
                 tail: 0,
                 head: len,
-                buf: buf
+                buf: buf,
             }
         }
     }
@@ -2324,18 +2312,17 @@ fn from(other: VecDeque<T>) -> Self {
                     // do this in at most three copy moves.
                     if (cap - tail) > head {
                         // right hand block is the long one; move that enough for the left
-                        ptr::copy(
-                            buf.offset(tail as isize),
-                            buf.offset((tail - head) as isize),
-                            cap - tail);
+                        ptr::copy(buf.offset(tail as isize),
+                                  buf.offset((tail - head) as isize),
+                                  cap - tail);
                         // copy left in the end
                         ptr::copy(buf, buf.offset((cap - head) as isize), head);
                         // shift the new thing to the start
-                        ptr::copy(buf.offset((tail-head) as isize), buf, len);
+                        ptr::copy(buf.offset((tail - head) as isize), buf, len);
                     } else {
                         // left hand block is the long one, we can do it in two!
-                        ptr::copy(buf, buf.offset((cap-tail) as isize), head);
-                        ptr::copy(buf.offset(tail as isize), buf, cap-tail);
+                        ptr::copy(buf, buf.offset((cap - tail) as isize), head);
+                        ptr::copy(buf.offset(tail as isize), buf, cap - tail);
                     }
                 } else {
                     // Need to use N swaps to move the ring
@@ -2576,8 +2563,8 @@ fn test_drain() {
 
                         // We should see the correct values in the VecDeque
                         let expected: VecDeque<_> = (0..drain_start)
-                                                        .chain(drain_end..len)
-                                                        .collect();
+                            .chain(drain_end..len)
+                            .collect();
                         assert_eq!(expected, tester);
                     }
                 }
@@ -2693,19 +2680,19 @@ fn create_vec_and_test_convert(cap: usize, offset: usize, len: usize) {
             let cap = (2i32.pow(cap_pwr) - 1) as usize;
 
             // In these cases there is enough free space to solve it with copies
-            for len in 0..((cap+1)/2) {
+            for len in 0..((cap + 1) / 2) {
                 // Test contiguous cases
-                for offset in 0..(cap-len) {
+                for offset in 0..(cap - len) {
                     create_vec_and_test_convert(cap, offset, len)
                 }
 
                 // Test cases where block at end of buffer is bigger than block at start
-                for offset in (cap-len)..(cap-(len/2)) {
+                for offset in (cap - len)..(cap - (len / 2)) {
                     create_vec_and_test_convert(cap, offset, len)
                 }
 
                 // Test cases where block at start of buffer is bigger than block at end
-                for offset in (cap-(len/2))..cap {
+                for offset in (cap - (len / 2))..cap {
                     create_vec_and_test_convert(cap, offset, len)
                 }
             }
@@ -2714,19 +2701,19 @@ fn create_vec_and_test_convert(cap: usize, offset: usize, len: usize) {
             // the ring will use swapping when:
             // (cap + 1 - offset) > (cap + 1 - len) && (len - (cap + 1 - offset)) > (cap + 1 - len))
             //  right block size  >   free space    &&      left block size       >    free space
-            for len in ((cap+1)/2)..cap {
+            for len in ((cap + 1) / 2)..cap {
                 // Test contiguous cases
-                for offset in 0..(cap-len) {
+                for offset in 0..(cap - len) {
                     create_vec_and_test_convert(cap, offset, len)
                 }
 
                 // Test cases where block at end of buffer is bigger than block at start
-                for offset in (cap-len)..(cap-(len/2)) {
+                for offset in (cap - len)..(cap - (len / 2)) {
                     create_vec_and_test_convert(cap, offset, len)
                 }
 
                 // Test cases where block at start of buffer is bigger than block at end
-                for offset in (cap-(len/2))..cap {
+                for offset in (cap - (len / 2))..cap {
                     create_vec_and_test_convert(cap, offset, len)
                 }
             }
index f61e2281a5c3057b168fe29ba96bf5ce55ad1335..44aa08e245873511bcc1d86302df813d9f2a8374 100644 (file)
@@ -242,7 +242,7 @@ fn main() {
                          "atomic_thread_fence.c"]);
     }
 
-    if !target.contains("windows") {
+    if !target.contains("redox") && !target.contains("windows") {
         sources.extend(&["emutls.c"]);
     }
 
index a72c712ad1733c4d29ae1f5f688092acf69b5526..e0dbc096cd0d97f567da3f17d42b4f167dace0e0 100644 (file)
@@ -13,6 +13,7 @@ bench = false
 name = "coretest"
 path = "../libcoretest/lib.rs"
 
-[[bench]]
-name = "coretest"
-path = "../libcoretest/lib.rs"
+# FIXME: need to extract benchmarks to a separate crate
+#[[bench]]
+#name = "coretest"
+#path = "../libcoretest/lib.rs"
index f924c9278339b0336722a1dc07ac2502edba15e7..aebe624e13d3232adf7c1aacacb9a2aff7b9ded3 100644 (file)
@@ -237,11 +237,16 @@ pub fn into_inner(self) -> bool {
 
     /// Loads a value from the bool.
     ///
-    /// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
+    /// `load` takes an [`Ordering`] argument which describes the memory ordering
+    /// of this operation.
     ///
     /// # Panics
     ///
-    /// Panics if `order` is `Release` or `AcqRel`.
+    /// Panics if `order` is [`Release`] or [`AcqRel`].
+    ///
+    /// [`Ordering`]: enum.Ordering.html
+    /// [`Release`]: enum.Ordering.html#variant.Release
+    /// [`AcqRel`]: enum.Ordering.html#variant.Release
     ///
     /// # Examples
     ///
@@ -260,7 +265,10 @@ pub fn load(&self, order: Ordering) -> bool {
 
     /// Stores a value into the bool.
     ///
-    /// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
+    /// `store` takes an [`Ordering`] argument which describes the memory ordering
+    /// of this operation.
+    ///
+    /// [`Ordering`]: enum.Ordering.html
     ///
     /// # Examples
     ///
@@ -286,7 +294,10 @@ pub fn store(&self, val: bool, order: Ordering) {
 
     /// Stores a value into the bool, returning the old value.
     ///
-    /// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
+    /// `swap` takes an [`Ordering`] argument which describes the memory ordering
+    /// of this operation.
+    ///
+    /// [`Ordering`]: enum.Ordering.html
     ///
     /// # Examples
     ///
@@ -309,8 +320,10 @@ pub fn swap(&self, val: bool, order: Ordering) -> bool {
     /// The return value is always the previous value. If it is equal to `current`, then the value
     /// was updated.
     ///
-    /// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of
-    /// this operation.
+    /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
+    /// ordering of this operation.
+    ///
+    /// [`Ordering`]: enum.Ordering.html
     ///
     /// # Examples
     ///
@@ -339,10 +352,15 @@ pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> boo
     /// The return value is a result indicating whether the new value was written and containing
     /// the previous value. On success this value is guaranteed to be equal to `current`.
     ///
-    /// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this
-    /// operation. The first describes the required ordering if the operation succeeds while the
-    /// second describes the required ordering when the operation fails. The failure ordering can't
-    /// be `Release` or `AcqRel` and must be equivalent or weaker than the success ordering.
+    /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
+    /// ordering of this operation. The first describes the required ordering if the
+    /// operation succeeds while the second describes the required ordering when the
+    /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and must
+    /// be equivalent or weaker than the success ordering.
+    ///
+    /// [`Ordering`]: enum.Ordering.html
+    /// [`Release`]: enum.Ordering.html#variant.Release
+    /// [`AcqRel`]: enum.Ordering.html#variant.Release
     ///
     /// # Examples
     ///
@@ -387,11 +405,15 @@ pub fn compare_exchange(&self,
     /// return value is a result indicating whether the new value was written and containing the
     /// previous value.
     ///
-    /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory
+    /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
     /// ordering of this operation. The first describes the required ordering if the operation
     /// succeeds while the second describes the required ordering when the operation fails. The
-    /// failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker than the
-    /// success ordering.
+    /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or
+    /// weaker than the success ordering.
+    ///
+    /// [`Ordering`]: enum.Ordering.html
+    /// [`Release`]: enum.Ordering.html#variant.Release
+    /// [`AcqRel`]: enum.Ordering.html#variant.Release
     ///
     /// # Examples
     ///
index 0ac39c5ccf6a04395b7c40dd62321cb91f63f160..e49e9bb7c3d9c7f2fd893f0ee0db81617b8db21f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 0ac39c5ccf6a04395b7c40dd62321cb91f63f160
+Subproject commit e49e9bb7c3d9c7f2fd893f0ee0db81617b8db21f
index 2b66d56759f35b220debeab20ea604f5f51f07bb..b4365e4fb265a5bc159c244b960204c2f5ece639 100644 (file)
@@ -2,6 +2,7 @@
 authors = ["The Rust Project Developers"]
 name = "proc_macro_tokens"
 version = "0.0.0"
+build = false
 
 [lib]
 path = "lib.rs"
index f21d98a0fc7f97a5eedbb2f9fc3d6b353b375517..4d66bba9f07ee6b135b33b57e63f08ec59cb6aa3 100644 (file)
@@ -327,10 +327,6 @@ fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
                 self.opt_expr(base, field_cfg)
             }
 
-            hir::ExprRepeat(ref elem, ref count) => {
-                self.straightline(expr, pred, [elem, count].iter().map(|&e| &**e))
-            }
-
             hir::ExprAssign(ref l, ref r) |
             hir::ExprAssignOp(_, ref l, ref r) => {
                 self.straightline(expr, pred, [r, l].iter().map(|&e| &**e))
@@ -347,7 +343,8 @@ fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
             hir::ExprType(ref e, _) |
             hir::ExprUnary(_, ref e) |
             hir::ExprField(ref e, _) |
-            hir::ExprTupField(ref e, _) => {
+            hir::ExprTupField(ref e, _) |
+            hir::ExprRepeat(ref e, _) => {
                 self.straightline(expr, pred, Some(&**e).into_iter())
             }
 
index 2637d34c5c56e569d91a3e1bcff2ad47310efa50..26e1dc7e0490c21f826b4657e67d13c04c4c8e81 100644 (file)
@@ -51,6 +51,12 @@ pub fn new(enabled: bool) -> DepGraph {
         }
     }
 
+    /// True if we are actually building the full dep-graph.
+    #[inline]
+    pub fn is_fully_enabled(&self) -> bool {
+        self.data.thread.is_fully_enabled()
+    }
+
     pub fn query(&self) -> DepGraphQuery<DefId> {
         self.data.thread.query()
     }
index f6a22e47cf21278051fd3f11fc5ab474cab25303..1990574ca9a831d3232c95b282cb854e97333f59 100644 (file)
@@ -45,6 +45,16 @@ fn visit_item(&mut self, i: &'tcx hir::Item) {
             debug!("Ended task {:?}", task_id);
         }
 
+        fn visit_trait_item(&mut self, i: &'tcx hir::TraitItem) {
+            let trait_item_def_id = self.tcx.map.local_def_id(i.id);
+            let task_id = (self.dep_node_fn)(trait_item_def_id);
+            let _task = self.tcx.dep_graph.in_task(task_id.clone());
+            debug!("Started task {:?}", task_id);
+            self.tcx.dep_graph.read(DepNode::Hir(trait_item_def_id));
+            self.visitor.visit_trait_item(i);
+            debug!("Ended task {:?}", task_id);
+        }
+
         fn visit_impl_item(&mut self, i: &'tcx hir::ImplItem) {
             let impl_item_def_id = self.tcx.map.local_def_id(i.id);
             let task_id = (self.dep_node_fn)(impl_item_def_id);
index 186d6f626509fd0b0daf5f37ddeefa42d516ab1a..4b171193b4af17f54dddbd2807f06a561daf1175 100644 (file)
@@ -177,6 +177,17 @@ fn visit_nested_item(&mut self, id: ItemId) {
         }
     }
 
+    /// Like `visit_nested_item()`, but for trait items. See
+    /// `visit_nested_item()` for advice on when to override this
+    /// method.
+    #[allow(unused_variables)]
+    fn visit_nested_trait_item(&mut self, id: TraitItemId) {
+        let opt_item = self.nested_visit_map().inter().map(|map| map.trait_item(id));
+        if let Some(item) = opt_item {
+            self.visit_trait_item(item);
+        }
+    }
+
     /// Like `visit_nested_item()`, but for impl items. See
     /// `visit_nested_item()` for advice on when to override this
     /// method.
@@ -192,10 +203,10 @@ fn visit_nested_impl_item(&mut self, id: ImplItemId) {
     /// visit_nested_item, does nothing by default unless you override
     /// `nested_visit_map` to return `Some(_)`, in which case it will walk the
     /// body.
-    fn visit_body(&mut self, id: ExprId) {
-        let opt_expr = self.nested_visit_map().intra().map(|map| map.expr(id));
-        if let Some(expr) = opt_expr {
-            self.visit_expr(expr);
+    fn visit_nested_body(&mut self, id: BodyId) {
+        let opt_body = self.nested_visit_map().intra().map(|map| map.body(id));
+        if let Some(body) = opt_body {
+            self.visit_body(body);
         }
     }
 
@@ -205,6 +216,10 @@ fn visit_item(&mut self, i: &'v Item) {
         walk_item(self, i)
     }
 
+    fn visit_body(&mut self, b: &'v Body) {
+        walk_body(self, b);
+    }
+
     /// When invoking `visit_all_item_likes()`, you need to supply an
     /// item-like visitor.  This method converts a "intra-visit"
     /// visitor into an item-like visitor that walks the entire tree.
@@ -253,8 +268,6 @@ fn visit_decl(&mut self, d: &'v Decl) {
     fn visit_expr(&mut self, ex: &'v Expr) {
         walk_expr(self, ex)
     }
-    fn visit_expr_post(&mut self, _ex: &'v Expr) {
-    }
     fn visit_ty(&mut self, t: &'v Ty) {
         walk_ty(self, t)
     }
@@ -264,12 +277,18 @@ fn visit_generics(&mut self, g: &'v Generics) {
     fn visit_where_predicate(&mut self, predicate: &'v WherePredicate) {
         walk_where_predicate(self, predicate)
     }
-    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: ExprId, s: Span, id: NodeId) {
+    fn visit_fn_decl(&mut self, fd: &'v FnDecl) {
+        walk_fn_decl(self, fd)
+    }
+    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: BodyId, s: Span, id: NodeId) {
         walk_fn(self, fk, fd, b, s, id)
     }
     fn visit_trait_item(&mut self, ti: &'v TraitItem) {
         walk_trait_item(self, ti)
     }
+    fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) {
+        walk_trait_item_ref(self, ii)
+    }
     fn visit_impl_item(&mut self, ii: &'v ImplItem) {
         walk_impl_item(self, ii)
     }
@@ -375,6 +394,14 @@ pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod, mod_node_i
     }
 }
 
+pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) {
+    for argument in &body.arguments {
+        visitor.visit_id(argument.id);
+        visitor.visit_pat(&argument.pat);
+    }
+    visitor.visit_expr(&body.value);
+}
+
 pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
     visitor.visit_id(local.id);
     visitor.visit_pat(&local.pat);
@@ -420,11 +447,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_id(item.id);
             visitor.visit_path(path, item.id);
         }
-        ItemStatic(ref typ, _, ref expr) |
-        ItemConst(ref typ, ref expr) => {
+        ItemStatic(ref typ, _, body) |
+        ItemConst(ref typ, body) => {
             visitor.visit_id(item.id);
             visitor.visit_ty(typ);
-            visitor.visit_expr(expr);
+            visitor.visit_nested_body(body);
         }
         ItemFn(ref declaration, unsafety, constness, abi, ref generics, body_id) => {
             visitor.visit_fn(FnKind::ItemFn(item.name,
@@ -466,9 +493,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_generics(type_parameters);
             walk_list!(visitor, visit_trait_ref, opt_trait_reference);
             visitor.visit_ty(typ);
-            for impl_item_ref in impl_item_refs {
-                visitor.visit_impl_item_ref(impl_item_ref);
-            }
+            walk_list!(visitor, visit_impl_item_ref, impl_item_refs);
         }
         ItemStruct(ref struct_definition, ref generics) |
         ItemUnion(ref struct_definition, ref generics) => {
@@ -476,11 +501,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_id(item.id);
             visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span);
         }
-        ItemTrait(_, ref generics, ref bounds, ref methods) => {
+        ItemTrait(_, ref generics, ref bounds, ref trait_item_refs) => {
             visitor.visit_id(item.id);
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_ty_param_bound, bounds);
-            walk_list!(visitor, visit_trait_item, methods);
+            walk_list!(visitor, visit_trait_item_ref, trait_item_refs);
         }
     }
     walk_list!(visitor, visit_attribute, &item.attrs);
@@ -508,7 +533,7 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
                                generics,
                                parent_item_id,
                                variant.span);
-    walk_list!(visitor, visit_expr, &variant.node.disr_expr);
+    walk_list!(visitor, visit_nested_body, variant.node.disr_expr);
     walk_list!(visitor, visit_attribute, &variant.node.attrs);
 }
 
@@ -531,7 +556,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             walk_list!(visitor, visit_ty, tuple_element_types);
         }
         TyBareFn(ref function_declaration) => {
-            walk_fn_decl(visitor, &function_declaration.decl);
+            visitor.visit_fn_decl(&function_declaration.decl);
             walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes);
         }
         TyPath(ref qpath) => {
@@ -541,9 +566,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_ty_param_bound, bounds);
         }
-        TyArray(ref ty, ref expression) => {
+        TyArray(ref ty, length) => {
             visitor.visit_ty(ty);
-            visitor.visit_expr(expression)
+            visitor.visit_nested_body(length)
         }
         TyPolyTraitRef(ref bounds) => {
             walk_list!(visitor, visit_ty_param_bound, bounds);
@@ -551,8 +576,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
         TyImplTrait(ref bounds) => {
             walk_list!(visitor, visit_ty_param_bound, bounds);
         }
-        TyTypeof(ref expression) => {
-            visitor.visit_expr(expression)
+        TyTypeof(expression) => {
+            visitor.visit_nested_body(expression)
         }
         TyInfer => {}
     }
@@ -659,9 +684,12 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v
     visitor.visit_name(foreign_item.span, foreign_item.name);
 
     match foreign_item.node {
-        ForeignItemFn(ref function_declaration, ref generics) => {
-            walk_fn_decl(visitor, function_declaration);
-            visitor.visit_generics(generics)
+        ForeignItemFn(ref function_declaration, ref names, ref generics) => {
+            visitor.visit_generics(generics);
+            visitor.visit_fn_decl(function_declaration);
+            for name in names {
+                visitor.visit_name(name.span, name.node);
+            }
         }
         ForeignItemStatic(ref typ, _) => visitor.visit_ty(typ),
     }
@@ -729,18 +757,8 @@ pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionR
 }
 
 pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
-    for argument in &function_declaration.inputs {
-        visitor.visit_id(argument.id);
-        visitor.visit_pat(&argument.pat);
-        visitor.visit_ty(&argument.ty)
-    }
-    walk_fn_ret_ty(visitor, &function_declaration.output)
-}
-
-pub fn walk_fn_decl_nopat<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
-    for argument in &function_declaration.inputs {
-        visitor.visit_id(argument.id);
-        visitor.visit_ty(&argument.ty)
+    for ty in &function_declaration.inputs {
+        visitor.visit_ty(ty)
     }
     walk_fn_ret_ty(visitor, &function_declaration.output)
 }
@@ -760,42 +778,33 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'
 pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
                                    function_kind: FnKind<'v>,
                                    function_declaration: &'v FnDecl,
-                                   body_id: ExprId,
+                                   body_id: BodyId,
                                    _span: Span,
                                    id: NodeId) {
     visitor.visit_id(id);
-    walk_fn_decl(visitor, function_declaration);
-    walk_fn_kind(visitor, function_kind);
-    visitor.visit_body(body_id)
-}
-
-pub fn walk_fn_with_body<'v, V: Visitor<'v>>(visitor: &mut V,
-                                             function_kind: FnKind<'v>,
-                                             function_declaration: &'v FnDecl,
-                                             body: &'v Expr,
-                                             _span: Span,
-                                             id: NodeId) {
-    visitor.visit_id(id);
-    walk_fn_decl(visitor, function_declaration);
+    visitor.visit_fn_decl(function_declaration);
     walk_fn_kind(visitor, function_kind);
-    visitor.visit_expr(body)
+    visitor.visit_nested_body(body_id)
 }
 
 pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) {
     visitor.visit_name(trait_item.span, trait_item.name);
     walk_list!(visitor, visit_attribute, &trait_item.attrs);
     match trait_item.node {
-        ConstTraitItem(ref ty, ref default) => {
+        TraitItemKind::Const(ref ty, default) => {
             visitor.visit_id(trait_item.id);
             visitor.visit_ty(ty);
-            walk_list!(visitor, visit_expr, default);
+            walk_list!(visitor, visit_nested_body, default);
         }
-        MethodTraitItem(ref sig, None) => {
+        TraitItemKind::Method(ref sig, TraitMethod::Required(ref names)) => {
             visitor.visit_id(trait_item.id);
             visitor.visit_generics(&sig.generics);
-            walk_fn_decl(visitor, &sig.decl);
+            visitor.visit_fn_decl(&sig.decl);
+            for name in names {
+                visitor.visit_name(name.span, name.node);
+            }
         }
-        MethodTraitItem(ref sig, Some(body_id)) => {
+        TraitItemKind::Method(ref sig, TraitMethod::Provided(body_id)) => {
             visitor.visit_fn(FnKind::Method(trait_item.name,
                                             sig,
                                             None,
@@ -805,7 +814,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
                              trait_item.span,
                              trait_item.id);
         }
-        TypeTraitItem(ref bounds, ref default) => {
+        TraitItemKind::Type(ref bounds, ref default) => {
             visitor.visit_id(trait_item.id);
             walk_list!(visitor, visit_ty_param_bound, bounds);
             walk_list!(visitor, visit_ty, default);
@@ -813,6 +822,15 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
     }
 }
 
+pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: &'v TraitItemRef) {
+    // NB: Deliberately force a compilation error if/when new fields are added.
+    let TraitItemRef { id, name, ref kind, span, ref defaultness } = *trait_item_ref;
+    visitor.visit_nested_trait_item(id);
+    visitor.visit_name(span, name);
+    visitor.visit_associated_item_kind(kind);
+    visitor.visit_defaultness(defaultness);
+}
+
 pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
     // NB: Deliberately force a compilation error if/when new fields are added.
     let ImplItem { id: _, name, ref vis, ref defaultness, ref attrs, ref node, span } = *impl_item;
@@ -822,10 +840,10 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
     visitor.visit_defaultness(defaultness);
     walk_list!(visitor, visit_attribute, attrs);
     match *node {
-        ImplItemKind::Const(ref ty, ref expr) => {
+        ImplItemKind::Const(ref ty, body) => {
             visitor.visit_id(impl_item.id);
             visitor.visit_ty(ty);
-            visitor.visit_expr(expr);
+            visitor.visit_nested_body(body);
         }
         ImplItemKind::Method(ref sig, body_id) => {
             visitor.visit_fn(FnKind::Method(impl_item.name,
@@ -904,9 +922,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
         ExprArray(ref subexpressions) => {
             walk_list!(visitor, visit_expr, subexpressions);
         }
-        ExprRepeat(ref element, ref count) => {
+        ExprRepeat(ref element, count) => {
             visitor.visit_expr(element);
-            visitor.visit_expr(count)
+            visitor.visit_nested_body(count)
         }
         ExprStruct(ref qpath, ref fields, ref optional_base) => {
             visitor.visit_qpath(qpath, expression.id, expression.span);
@@ -1013,8 +1031,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             }
         }
     }
-
-    visitor.visit_expr_post(expression)
 }
 
 pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
@@ -1097,16 +1113,3 @@ fn visit_id(&mut self, id: NodeId) {
         self.result.add(id);
     }
 }
-
-/// Computes the id range for a single fn body, ignoring nested items.
-pub fn compute_id_range_for_fn_body<'v>(fk: FnKind<'v>,
-                                        decl: &'v FnDecl,
-                                        body: &'v Expr,
-                                        sp: Span,
-                                        id: NodeId,
-                                        map: &map::Map<'v>)
-                                        -> IdRange {
-    let mut visitor = IdRangeComputingVisitor::new(map);
-    walk_fn_with_body(&mut visitor, fk, decl, body, sp, id);
-    visitor.result()
-}
index 71ef7131440b80393fa90c3e3880437befd77909..f359ca2016359ef85cf04f58d9ee2c1e7d67f3b4 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::{Item, ImplItem};
+use super::{Item, ImplItem, TraitItem};
 use super::intravisit::Visitor;
 
 /// The "item-like visitor" visitor defines only the top-level methods
@@ -58,6 +58,7 @@
 /// needed.
 pub trait ItemLikeVisitor<'hir> {
     fn visit_item(&mut self, item: &'hir Item);
+    fn visit_trait_item(&mut self, trait_item: &'hir TraitItem);
     fn visit_impl_item(&mut self, impl_item: &'hir ImplItem);
 }
 
@@ -80,6 +81,10 @@ fn visit_item(&mut self, item: &'hir Item) {
         self.visitor.visit_item(item);
     }
 
+    fn visit_trait_item(&mut self, trait_item: &'hir TraitItem) {
+        self.visitor.visit_trait_item(trait_item);
+    }
+
     fn visit_impl_item(&mut self, impl_item: &'hir ImplItem) {
         self.visitor.visit_impl_item(impl_item);
     }
index e8c3492705a3f95da1e4886b661479e9748a27c6..9a2658f48f3d91f2cf7236120cd9b072c7febc3c 100644 (file)
 use hir::def_id::{DefIndex, DefId};
 use hir::def::{Def, PathResolution};
 use session::Session;
-use util::nodemap::NodeMap;
-use rustc_data_structures::fnv::FnvHashMap;
+use util::nodemap::{NodeMap, FxHashMap};
 
 use std::collections::BTreeMap;
 use std::iter;
-use std::mem;
 
 use syntax::ast::*;
 use syntax::errors;
@@ -71,17 +69,18 @@ pub struct LoweringContext<'a> {
     // the form of a DefIndex) so that if we create a new node which introduces
     // a definition, then we can properly create the def id.
     parent_def: Option<DefIndex>,
-    exprs: FnvHashMap<hir::ExprId, hir::Expr>,
     resolver: &'a mut Resolver,
 
     /// The items being lowered are collected here.
     items: BTreeMap<NodeId, hir::Item>,
 
+    trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem>,
     impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
+    bodies: FxHashMap<hir::BodyId, hir::Body>,
 }
 
 pub trait Resolver {
-    // Resolve a global hir path generated by the lowerer when expanding `for`, `if let`, etc.
+    // Resolve a hir path generated by the lowerer when expanding `for`, `if let`, etc.
     fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool);
 
     // Obtain the resolution for a node id
@@ -105,10 +104,11 @@ pub fn lower_crate(sess: &Session,
         crate_root: std_inject::injected_crate_name(krate),
         sess: sess,
         parent_def: None,
-        exprs: FnvHashMap(),
         resolver: resolver,
         items: BTreeMap::new(),
+        trait_items: BTreeMap::new(),
         impl_items: BTreeMap::new(),
+        bodies: FxHashMap(),
     }.lower_crate(krate)
 }
 
@@ -133,8 +133,9 @@ fn lower_crate(mut self, c: &Crate) -> hir::Crate {
             span: c.span,
             exported_macros: exported_macros,
             items: self.items,
+            trait_items: self.trait_items,
             impl_items: self.impl_items,
-            exprs: mem::replace(&mut self.exprs, FnvHashMap()),
+            bodies: self.bodies,
         }
     }
 
@@ -150,8 +151,15 @@ fn visit_item(&mut self, item: &'lcx Item) {
                 visit::walk_item(self, item);
             }
 
+            fn visit_trait_item(&mut self, item: &'lcx TraitItem) {
+                let id = hir::TraitItemId { node_id: item.id };
+                let hir_item = self.lctx.lower_trait_item(item);
+                self.lctx.trait_items.insert(id, hir_item);
+                visit::walk_trait_item(self, item);
+            }
+
             fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
-                let id = self.lctx.lower_impl_item_ref(item).id;
+                let id = hir::ImplItemId { node_id: item.id };
                 let hir_item = self.lctx.lower_impl_item(item);
                 self.lctx.impl_items.insert(id, hir_item);
                 visit::walk_impl_item(self, item);
@@ -162,9 +170,16 @@ fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
         visit::walk_crate(&mut item_lowerer, c);
     }
 
-    fn record_expr(&mut self, expr: hir::Expr) -> hir::ExprId {
-        let id = hir::ExprId(expr.id);
-        self.exprs.insert(id, expr);
+    fn record_body(&mut self, value: hir::Expr, decl: Option<&FnDecl>)
+                   -> hir::BodyId {
+        let body = hir::Body {
+            arguments: decl.map_or(hir_vec![], |decl| {
+                decl.inputs.iter().map(|x| self.lower_arg(x)).collect()
+            }),
+            value: value
+        };
+        let id = body.id();
+        self.bodies.insert(id, body);
         id
     }
 
@@ -259,7 +274,7 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
         P(hir::Ty {
             id: t.id,
             node: match t.node {
-                TyKind::Infer | TyKind::ImplicitSelf => hir::TyInfer,
+                TyKind::Infer => hir::TyInfer,
                 TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty)),
                 TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)),
                 TyKind::Rptr(ref region, ref mt) => {
@@ -283,14 +298,27 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
                 TyKind::Path(ref qself, ref path) => {
                     hir::TyPath(self.lower_qpath(t.id, qself, path, ParamMode::Explicit))
                 }
+                TyKind::ImplicitSelf => {
+                    hir::TyPath(hir::QPath::Resolved(None, P(hir::Path {
+                        def: self.expect_full_def(t.id),
+                        segments: hir_vec![hir::PathSegment {
+                            name: keywords::SelfType.name(),
+                            parameters: hir::PathParameters::none()
+                        }],
+                        span: t.span,
+                    })))
+                }
                 TyKind::ObjectSum(ref ty, ref bounds) => {
                     hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds))
                 }
-                TyKind::Array(ref ty, ref e) => {
-                    hir::TyArray(self.lower_ty(ty), P(self.lower_expr(e)))
+                TyKind::Array(ref ty, ref length) => {
+                    let length = self.lower_expr(length);
+                    hir::TyArray(self.lower_ty(ty),
+                                 self.record_body(length, None))
                 }
                 TyKind::Typeof(ref expr) => {
-                    hir::TyTypeof(P(self.lower_expr(expr)))
+                    let expr = self.lower_expr(expr);
+                    hir::TyTypeof(self.record_body(expr, None))
                 }
                 TyKind::PolyTraitRef(ref bounds) => {
                     hir::TyPolyTraitRef(self.lower_bounds(bounds))
@@ -317,7 +345,10 @@ fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
                 name: v.node.name.name,
                 attrs: self.lower_attrs(&v.node.attrs),
                 data: self.lower_variant_data(&v.node.data),
-                disr_expr: v.node.disr_expr.as_ref().map(|e| P(self.lower_expr(e))),
+                disr_expr: v.node.disr_expr.as_ref().map(|e| {
+                    let e = self.lower_expr(e);
+                    self.record_body(e, None)
+                }),
             },
             span: v.span,
         }
@@ -337,7 +368,6 @@ fn lower_qpath(&mut self,
 
         let proj_start = p.segments.len() - resolution.depth;
         let path = P(hir::Path {
-            global: p.global,
             def: resolution.base_def,
             segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| {
                 let param_mode = match (qself_position, param_mode) {
@@ -404,12 +434,17 @@ fn lower_path_extra(&mut self,
                         id: NodeId,
                         p: &Path,
                         name: Option<Name>,
-                        param_mode: ParamMode)
+                        param_mode: ParamMode,
+                        defaults_to_global: bool)
                         -> hir::Path {
+        let mut segments = p.segments.iter();
+        if defaults_to_global && p.is_global() {
+            segments.next();
+        }
+
         hir::Path {
-            global: p.global,
             def: self.expect_full_def(id),
-            segments: p.segments.iter().map(|segment| {
+            segments: segments.map(|segment| {
                 self.lower_path_segment(segment, param_mode)
             }).chain(name.map(|name| {
                 hir::PathSegment {
@@ -424,9 +459,10 @@ fn lower_path_extra(&mut self,
     fn lower_path(&mut self,
                   id: NodeId,
                   p: &Path,
-                  param_mode: ParamMode)
+                  param_mode: ParamMode,
+                  defaults_to_global: bool)
                   -> hir::Path {
-        self.lower_path_extra(id, p, None, param_mode)
+        self.lower_path_extra(id, p, None, param_mode, defaults_to_global)
     }
 
     fn lower_path_segment(&mut self,
@@ -500,13 +536,24 @@ fn lower_arg(&mut self, arg: &Arg) -> hir::Arg {
         hir::Arg {
             id: arg.id,
             pat: self.lower_pat(&arg.pat),
-            ty: self.lower_ty(&arg.ty),
         }
     }
 
+    fn lower_fn_args_to_names(&mut self, decl: &FnDecl)
+                              -> hir::HirVec<Spanned<Name>> {
+        decl.inputs.iter().map(|arg| {
+            match arg.pat.node {
+                PatKind::Ident(_, ident, None) => {
+                    respan(ident.span, ident.node.name)
+                }
+                _ => respan(arg.pat.span, keywords::Invalid.name()),
+            }
+        }).collect()
+    }
+
     fn lower_fn_decl(&mut self, decl: &FnDecl) -> P<hir::FnDecl> {
         P(hir::FnDecl {
-            inputs: decl.inputs.iter().map(|x| self.lower_arg(x)).collect(),
+            inputs: decl.inputs.iter().map(|arg| self.lower_ty(&arg.ty)).collect(),
             output: match decl.output {
                 FunctionRetTy::Ty(ref ty) => hir::Return(self.lower_ty(ty)),
                 FunctionRetTy::Default(span) => hir::DefaultReturn(span),
@@ -602,8 +649,8 @@ fn lower_generics(&mut self, g: &Generics) -> hir::Generics {
                         // Check if the where clause type is a plain type parameter.
                         match bound_pred.bounded_ty.node {
                             TyKind::Path(None, ref path)
-                                    if !path.global && path.segments.len() == 1 &&
-                                        bound_pred.bound_lifetimes.is_empty() => {
+                                    if path.segments.len() == 1 &&
+                                       bound_pred.bound_lifetimes.is_empty() => {
                                 if let Some(Def::TyParam(def_id)) =
                                         self.resolver.get_resolution(bound_pred.bounded_ty.id)
                                                      .map(|d| d.base_def) {
@@ -677,7 +724,7 @@ fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicat
                                                           span}) => {
                 hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
                     id: id,
-                    path: self.lower_path(id, path, ParamMode::Explicit),
+                    path: self.lower_path(id, path, ParamMode::Explicit, false),
                     ty: self.lower_ty(ty),
                     span: span,
                 })
@@ -707,7 +754,7 @@ fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
 
     fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
         hir::TraitRef {
-            path: self.lower_path(p.ref_id, &p.path, ParamMode::Explicit),
+            path: self.lower_path(p.ref_id, &p.path, ParamMode::Explicit, false),
             ref_id: p.ref_id,
         }
     }
@@ -800,7 +847,7 @@ fn lower_item_kind(&mut self,
                             };
 
                             let mut path = self.lower_path_extra(import.id, path, suffix,
-                                                                 ParamMode::Explicit);
+                                                                 ParamMode::Explicit, true);
                             path.span = span;
                             self.items.insert(import.id, hir::Item {
                                 id: import.id,
@@ -814,7 +861,7 @@ fn lower_item_kind(&mut self,
                         path
                     }
                 };
-                let path = P(self.lower_path(id, path, ParamMode::Explicit));
+                let path = P(self.lower_path(id, path, ParamMode::Explicit, true));
                 let kind = match view_path.node {
                     ViewPathSimple(ident, _) => {
                         *name = ident.name;
@@ -834,17 +881,20 @@ fn lower_item_kind(&mut self,
                 hir::ItemUse(path, kind)
             }
             ItemKind::Static(ref t, m, ref e) => {
+                let value = self.lower_expr(e);
                 hir::ItemStatic(self.lower_ty(t),
                                 self.lower_mutability(m),
-                                P(self.lower_expr(e)))
+                                self.record_body(value, None))
             }
             ItemKind::Const(ref t, ref e) => {
-                hir::ItemConst(self.lower_ty(t), P(self.lower_expr(e)))
+                let value = self.lower_expr(e);
+                hir::ItemConst(self.lower_ty(t),
+                               self.record_body(value, None))
             }
             ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
                 let body = self.lower_block(body);
                 let body = self.expr_block(body, ThinVec::new());
-                let body_id = self.record_expr(body);
+                let body_id = self.record_body(body, Some(decl));
                 hir::ItemFn(self.lower_fn_decl(decl),
                             self.lower_unsafety(unsafety),
                             self.lower_constness(constness),
@@ -892,7 +942,7 @@ fn lower_item_kind(&mut self,
             }
             ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => {
                 let bounds = self.lower_bounds(bounds);
-                let items = items.iter().map(|item| self.lower_trait_item(item)).collect();
+                let items = items.iter().map(|item| self.lower_trait_item_ref(item)).collect();
                 hir::ItemTrait(self.lower_unsafety(unsafety),
                                self.lower_generics(generics),
                                bounds,
@@ -910,20 +960,27 @@ fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
                 attrs: this.lower_attrs(&i.attrs),
                 node: match i.node {
                     TraitItemKind::Const(ref ty, ref default) => {
-                        hir::ConstTraitItem(this.lower_ty(ty),
-                                            default.as_ref().map(|x| P(this.lower_expr(x))))
-                    }
-                    TraitItemKind::Method(ref sig, ref body) => {
-                        hir::MethodTraitItem(this.lower_method_sig(sig),
-                                             body.as_ref().map(|x| {
-                            let body = this.lower_block(x);
-                            let expr = this.expr_block(body, ThinVec::new());
-                            this.record_expr(expr)
+                        hir::TraitItemKind::Const(this.lower_ty(ty),
+                                                  default.as_ref().map(|x| {
+                            let value = this.lower_expr(x);
+                            this.record_body(value, None)
                         }))
                     }
+                    TraitItemKind::Method(ref sig, None) => {
+                        let names = this.lower_fn_args_to_names(&sig.decl);
+                        hir::TraitItemKind::Method(this.lower_method_sig(sig),
+                                                   hir::TraitMethod::Required(names))
+                    }
+                    TraitItemKind::Method(ref sig, Some(ref body)) => {
+                        let body = this.lower_block(body);
+                        let expr = this.expr_block(body, ThinVec::new());
+                        let body_id = this.record_body(expr, Some(&sig.decl));
+                        hir::TraitItemKind::Method(this.lower_method_sig(sig),
+                                                   hir::TraitMethod::Provided(body_id))
+                    }
                     TraitItemKind::Type(ref bounds, ref default) => {
-                        hir::TypeTraitItem(this.lower_bounds(bounds),
-                                           default.as_ref().map(|x| this.lower_ty(x)))
+                        hir::TraitItemKind::Type(this.lower_bounds(bounds),
+                                                 default.as_ref().map(|x| this.lower_ty(x)))
                     }
                     TraitItemKind::Macro(..) => panic!("Shouldn't exist any more"),
                 },
@@ -932,6 +989,30 @@ fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
         })
     }
 
+    fn lower_trait_item_ref(&mut self, i: &TraitItem) -> hir::TraitItemRef {
+        let (kind, has_default) = match i.node {
+            TraitItemKind::Const(_, ref default) => {
+                (hir::AssociatedItemKind::Const, default.is_some())
+            }
+            TraitItemKind::Type(_, ref default) => {
+                (hir::AssociatedItemKind::Type, default.is_some())
+            }
+            TraitItemKind::Method(ref sig, ref default) => {
+                (hir::AssociatedItemKind::Method {
+                    has_self: sig.decl.has_self(),
+                 }, default.is_some())
+            }
+            TraitItemKind::Macro(..) => unimplemented!(),
+        };
+        hir::TraitItemRef {
+            id: hir::TraitItemId { node_id: i.id },
+            name: i.ident.name,
+            span: i.span,
+            defaultness: self.lower_defaultness(Defaultness::Default, has_default),
+            kind: kind,
+        }
+    }
+
     fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
         self.with_parent_def(i.id, |this| {
             hir::ImplItem {
@@ -942,13 +1023,15 @@ fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
                 defaultness: this.lower_defaultness(i.defaultness, true /* [1] */),
                 node: match i.node {
                     ImplItemKind::Const(ref ty, ref expr) => {
-                        hir::ImplItemKind::Const(this.lower_ty(ty), P(this.lower_expr(expr)))
+                        let value = this.lower_expr(expr);
+                        let body_id = this.record_body(value, None);
+                        hir::ImplItemKind::Const(this.lower_ty(ty), body_id)
                     }
                     ImplItemKind::Method(ref sig, ref body) => {
                         let body = this.lower_block(body);
                         let expr = this.expr_block(body, ThinVec::new());
-                        let expr_id = this.record_expr(expr);
-                        hir::ImplItemKind::Method(this.lower_method_sig(sig), expr_id)
+                        let body_id = this.record_body(expr, Some(&sig.decl));
+                        hir::ImplItemKind::Method(this.lower_method_sig(sig), body_id)
                     }
                     ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)),
                     ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
@@ -971,7 +1054,7 @@ fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
                 ImplItemKind::Const(..) => hir::AssociatedItemKind::Const,
                 ImplItemKind::Type(..) => hir::AssociatedItemKind::Type,
                 ImplItemKind::Method(ref sig, _) => hir::AssociatedItemKind::Method {
-                    has_self: sig.decl.get_self().is_some(),
+                    has_self: sig.decl.has_self(),
                 },
                 ImplItemKind::Macro(..) => unimplemented!(),
             },
@@ -1033,7 +1116,9 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
                 attrs: this.lower_attrs(&i.attrs),
                 node: match i.node {
                     ForeignItemKind::Fn(ref fdec, ref generics) => {
-                        hir::ForeignItemFn(this.lower_fn_decl(fdec), this.lower_generics(generics))
+                        hir::ForeignItemFn(this.lower_fn_decl(fdec),
+                                           this.lower_fn_args_to_names(fdec),
+                                           this.lower_generics(generics))
                     }
                     ForeignItemKind::Static(ref t, m) => {
                         hir::ForeignItemStatic(this.lower_ty(t), m)
@@ -1046,24 +1131,13 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
     }
 
     fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig {
-        let hir_sig = hir::MethodSig {
+        hir::MethodSig {
             generics: self.lower_generics(&sig.generics),
             abi: sig.abi,
             unsafety: self.lower_unsafety(sig.unsafety),
             constness: self.lower_constness(sig.constness),
             decl: self.lower_fn_decl(&sig.decl),
-        };
-        // Check for `self: _` and `self: &_`
-        if let Some(SelfKind::Explicit(..)) = sig.decl.get_self().map(|eself| eself.node) {
-            match hir_sig.decl.get_self().map(|eself| eself.node) {
-                Some(hir::SelfKind::Value(..)) | Some(hir::SelfKind::Region(..)) => {
-                    self.diagnostic().span_err(sig.decl.inputs[0].ty.span,
-                        "the type placeholder `_` is not allowed within types on item signatures");
-                }
-                _ => {}
-            }
         }
-        hir_sig
     }
 
     fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
@@ -1135,7 +1209,6 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                             Some(def) => {
                                 hir::PatKind::Path(hir::QPath::Resolved(None, P(hir::Path {
                                     span: pth1.span,
-                                    global: false,
                                     def: def,
                                     segments: hir_vec![
                                         hir::PathSegment::from_name(pth1.node.name)
@@ -1314,8 +1387,8 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 }
                 ExprKind::Repeat(ref expr, ref count) => {
                     let expr = P(self.lower_expr(expr));
-                    let count = P(self.lower_expr(count));
-                    hir::ExprRepeat(expr, count)
+                    let count = self.lower_expr(count);
+                    hir::ExprRepeat(expr, self.record_body(count, None))
                 }
                 ExprKind::Tup(ref elts) => {
                     hir::ExprTup(elts.iter().map(|x| self.lower_expr(x)).collect())
@@ -1398,7 +1471,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                         let expr = this.lower_expr(body);
                         hir::ExprClosure(this.lower_capture_clause(capture_clause),
                                          this.lower_fn_decl(decl),
-                                         this.record_expr(expr),
+                                         this.record_body(expr, Some(decl)),
                                          fn_decl_span)
                     })
                 }
@@ -1682,13 +1755,7 @@ fn make_struct(this: &mut LoweringContext,
                     // `::std::option::Option::Some(<pat>) => <body>`
                     let pat_arm = {
                         let body_block = self.lower_block(body);
-                        let body_span = body_block.span;
-                        let body_expr = P(hir::Expr {
-                            id: self.next_id(),
-                            node: hir::ExprBlock(body_block),
-                            span: body_span,
-                            attrs: ThinVec::new(),
-                        });
+                        let body_expr = P(self.expr_block(body_block, ThinVec::new()));
                         let pat = self.lower_pat(pat);
                         let some_pat = self.pat_some(e.span, pat);
 
@@ -1878,7 +1945,7 @@ fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility {
             Visibility::Crate(_) => hir::Visibility::Crate,
             Visibility::Restricted { ref path, id } => {
                 hir::Visibility::Restricted {
-                    path: P(self.lower_path(id, path, ParamMode::Explicit)),
+                    path: P(self.lower_path(id, path, ParamMode::Explicit, true)),
                     id: id
                 }
             }
@@ -1971,7 +2038,6 @@ fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> hir::Expr {
 
         let expr_path = hir::ExprPath(hir::QPath::Resolved(None, P(hir::Path {
             span: span,
-            global: false,
             def: def,
             segments: hir_vec![hir::PathSegment::from_name(id)],
         })));
@@ -2139,17 +2205,12 @@ fn pat(&mut self, span: Span, pat: hir::PatKind) -> P<hir::Pat> {
     /// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
     /// The path is also resolved according to `is_value`.
     fn std_path(&mut self, span: Span, components: &[&str], is_value: bool) -> hir::Path {
-        let idents = self.crate_root.iter().chain(components);
-
-        let segments: Vec<_> = idents.map(|name| {
-            hir::PathSegment::from_name(Symbol::intern(name))
-        }).collect();
-
         let mut path = hir::Path {
             span: span,
-            global: true,
             def: Def::Err,
-            segments: segments.into(),
+            segments: iter::once(keywords::CrateRoot.name()).chain({
+                self.crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern)
+            }).map(hir::PathSegment::from_name).collect(),
         };
 
         self.resolver.resolve_hir_path(&mut path, is_value);
index 068e7ed8624ed77300f10252a13fa392639634ee..6e08b52f9a2490bf1b8c0a8471723f8c9bc7f0cf 100644 (file)
@@ -48,7 +48,7 @@ pub struct FnLikeNode<'a> { node: map::Node<'a> }
 /// Components shared by fn-like things (fn items, methods, closures).
 pub struct FnParts<'a> {
     pub decl: &'a FnDecl,
-    pub body: ast::ExprId,
+    pub body: ast::BodyId,
     pub kind: FnKind<'a>,
     pub span: Span,
     pub id:   NodeId,
@@ -62,7 +62,10 @@ fn is_fn_like(&self) -> bool {
 
 impl MaybeFnLike for ast::TraitItem {
     fn is_fn_like(&self) -> bool {
-        match self.node { ast::MethodTraitItem(_, Some(_)) => true, _ => false, }
+        match self.node {
+            ast::TraitItemKind::Method(_, ast::TraitMethod::Provided(_)) => true,
+            _ => false,
+        }
     }
 }
 
@@ -115,7 +118,7 @@ struct ItemFnParts<'a> {
     abi:      abi::Abi,
     vis:      &'a ast::Visibility,
     generics: &'a ast::Generics,
-    body:     ast::ExprId,
+    body:     ast::BodyId,
     id:       NodeId,
     span:     Span,
     attrs:    &'a [Attribute],
@@ -125,14 +128,14 @@ struct ItemFnParts<'a> {
 /// for use when implementing FnLikeNode operations.
 struct ClosureParts<'a> {
     decl: &'a FnDecl,
-    body: ast::ExprId,
+    body: ast::BodyId,
     id: NodeId,
     span: Span,
     attrs: &'a [Attribute],
 }
 
 impl<'a> ClosureParts<'a> {
-    fn new(d: &'a FnDecl, b: ast::ExprId, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self {
+    fn new(d: &'a FnDecl, b: ast::BodyId, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self {
         ClosureParts {
             decl: d,
             body: b,
@@ -172,9 +175,9 @@ pub fn to_fn_parts(self) -> FnParts<'a> {
         }
     }
 
-    pub fn body(self) -> ast::ExprId {
+    pub fn body(self) -> ast::BodyId {
         self.handle(|i: ItemFnParts<'a>|  i.body,
-                    |_, _, _: &'a ast::MethodSig, _, body: ast::ExprId, _, _|  body,
+                    |_, _, _: &'a ast::MethodSig, _, body: ast::BodyId, _, _|  body,
                     |c: ClosureParts<'a>| c.body)
     }
 
@@ -227,7 +230,7 @@ fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
                   Name,
                   &'a ast::MethodSig,
                   Option<&'a ast::Visibility>,
-                  ast::ExprId,
+                  ast::BodyId,
                   Span,
                   &'a [Attribute])
                   -> A,
@@ -252,7 +255,7 @@ fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
                 _ => bug!("item FnLikeNode that is not fn-like"),
             },
             map::NodeTraitItem(ti) => match ti.node {
-                ast::MethodTraitItem(ref sig, Some(body)) => {
+                ast::TraitItemKind::Method(ref sig, ast::TraitMethod::Provided(body)) => {
                     method(ti.id, ti.name, sig, None, body, ti.span, &ti.attrs)
                 }
                 _ => bug!("trait method FnLikeNode that is not fn-like"),
index 45988886a608a30ff7ede1d35d39ca5096d63270..a6ffe7cea5592e752ce7b66b09a8c6e80b700c08 100644 (file)
@@ -11,7 +11,6 @@
 use super::*;
 
 use hir::intravisit::{Visitor, NestedVisitorMap};
-use middle::cstore::InlinedItem;
 use std::iter::repeat;
 use syntax::ast::{NodeId, CRATE_NODE_ID};
 use syntax_pos::Span;
@@ -21,7 +20,7 @@ pub struct NodeCollector<'ast> {
     /// The crate
     pub krate: &'ast Crate,
     /// The node map
-    pub map: Vec<MapEntry<'ast>>,
+    pub(super) map: Vec<MapEntry<'ast>>,
     /// The parent of this node
     pub parent_node: NodeId,
     /// If true, completely ignore nested items. We set this when loading
@@ -43,11 +42,11 @@ pub fn root(krate: &'ast Crate) -> NodeCollector<'ast> {
         collector
     }
 
-    pub fn extend(krate: &'ast Crate,
-                  parent: &'ast InlinedItem,
-                  parent_node: NodeId,
-                  map: Vec<MapEntry<'ast>>)
-                  -> NodeCollector<'ast> {
+    pub(super) fn extend(krate: &'ast Crate,
+                         parent: &'ast InlinedItem,
+                         parent_node: NodeId,
+                         map: Vec<MapEntry<'ast>>)
+                         -> NodeCollector<'ast> {
         let mut collector = NodeCollector {
             krate: krate,
             map: map,
@@ -98,12 +97,22 @@ fn visit_nested_item(&mut self, item: ItemId) {
         }
     }
 
+    fn visit_nested_trait_item(&mut self, item_id: TraitItemId) {
+        if !self.ignore_nested_items {
+            self.visit_trait_item(self.krate.trait_item(item_id))
+        }
+    }
+
     fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
-        self.visit_impl_item(self.krate.impl_item(item_id))
+        if !self.ignore_nested_items {
+            self.visit_impl_item(self.krate.impl_item(item_id))
+        }
     }
 
-    fn visit_body(&mut self, id: ExprId) {
-        self.visit_expr(self.krate.expr(id))
+    fn visit_nested_body(&mut self, id: BodyId) {
+        if !self.ignore_nested_items {
+            self.visit_body(self.krate.body(id))
+        }
     }
 
     fn visit_item(&mut self, i: &'ast Item) {
@@ -113,11 +122,6 @@ fn visit_item(&mut self, i: &'ast Item) {
 
         self.with_parent(i.id, |this| {
             match i.node {
-                ItemEnum(ref enum_definition, _) => {
-                    for v in &enum_definition.variants {
-                        this.insert(v.node.data.id(), NodeVariant(v));
-                    }
-                }
                 ItemStruct(ref struct_def, _) => {
                     // If this is a tuple-like struct, register the constructor.
                     if !struct_def.is_struct() {
@@ -209,7 +213,7 @@ fn visit_trait_ref(&mut self, tr: &'ast TraitRef) {
     }
 
     fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl,
-                b: ExprId, s: Span, id: NodeId) {
+                b: BodyId, s: Span, id: NodeId) {
         assert_eq!(self.parent_node, id);
         intravisit::walk_fn(self, fk, fd, b, s, id);
     }
@@ -243,6 +247,14 @@ fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
         self.insert_entry(macro_def.id, NotPresent);
     }
 
+    fn visit_variant(&mut self, v: &'ast Variant, g: &'ast Generics, item_id: NodeId) {
+        let id = v.node.data.id();
+        self.insert(id, NodeVariant(v));
+        self.with_parent(id, |this| {
+            intravisit::walk_variant(this, v, g, item_id);
+        });
+    }
+
     fn visit_struct_field(&mut self, field: &'ast StructField) {
         self.insert(field.id, NodeField(field));
         self.with_parent(field.id, |this| {
index 256aee342a3fc448f83637f02a78d7401df22c3f..be8780f39b10429d6aea31bbc28cc36c69e8cdc0 100644 (file)
@@ -16,7 +16,7 @@
 use syntax::visit;
 use syntax::symbol::{Symbol, keywords};
 
-/// Creates def ids for nodes in the HIR.
+/// Creates def ids for nodes in the AST.
 pub struct DefCollector<'a> {
     definitions: &'a mut Definitions,
     parent_def: Option<DefIndex>,
index 4f64670f482796bde55b37dda9a0d31df0bf0817..b28c5e80ea3c35bc4ddf41263ac89e4d272ce9fa 100644 (file)
@@ -220,7 +220,6 @@ pub fn deterministic_hash_to<H: Hasher>(&self, tcx: TyCtxt, state: &mut H) {
     }
 }
 
-
 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub enum DefPathData {
     // Root: these should only be used for the root nodes, because
@@ -339,7 +338,7 @@ pub fn create_def_with_parent(&mut self,
                 data,
                 self.table.def_key(self.node_to_def_index[&node_id]));
 
-        assert!(parent.is_some() ^ (data == DefPathData::CrateRoot));
+        assert_eq!(parent.is_some(), data != DefPathData::CrateRoot);
 
         // Find a unique DefKey. This basically means incrementing the disambiguator
         // until we get no match.
index 4546f6d8c27e6b64674c9fd166d8498de791c3db..27ebeea9ad91db21f18d477684a6288f5a699365 100644 (file)
@@ -17,7 +17,6 @@
 
 use dep_graph::{DepGraph, DepNode};
 
-use middle::cstore::InlinedItem;
 use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
 
 use syntax::abi::Abi;
@@ -26,7 +25,8 @@
 use syntax_pos::Span;
 
 use hir::*;
-use hir::print as pprust;
+use hir::intravisit::Visitor;
+use hir::print::Nested;
 
 use arena::TypedArena;
 use std::cell::RefCell;
 mod def_collector;
 pub mod definitions;
 
+/// The data we save and restore about an inlined item or method.  This is not
+/// part of the AST that we parse from a file, but it becomes part of the tree
+/// that we trans.
+#[derive(Debug)]
+struct InlinedItem {
+    def_id: DefId,
+    body: Body,
+}
+
 #[derive(Copy, Clone, Debug)]
 pub enum Node<'ast> {
     NodeItem(&'ast Item),
@@ -60,14 +69,12 @@ pub enum Node<'ast> {
     NodeLifetime(&'ast Lifetime),
     NodeTyParam(&'ast TyParam),
     NodeVisibility(&'ast Visibility),
-
-    NodeInlinedItem(&'ast InlinedItem),
 }
 
 /// Represents an entry and its parent NodeID.
 /// The odd layout is to bring down the total size.
 #[derive(Copy, Debug)]
-pub enum MapEntry<'ast> {
+enum MapEntry<'ast> {
     /// Placeholder for holes in the map.
     NotPresent,
 
@@ -121,8 +128,6 @@ fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
             NodeLifetime(n) => EntryLifetime(p, n),
             NodeTyParam(n) => EntryTyParam(p, n),
             NodeVisibility(n) => EntryVisibility(p, n),
-
-            NodeInlinedItem(n) => RootInlinedParent(n),
         }
     }
 
@@ -171,10 +176,49 @@ fn to_node(self) -> Option<Node<'ast>> {
             EntryLifetime(_, n) => NodeLifetime(n),
             EntryTyParam(_, n) => NodeTyParam(n),
             EntryVisibility(_, n) => NodeVisibility(n),
-            RootInlinedParent(n) => NodeInlinedItem(n),
             _ => return None
         })
     }
+
+    fn is_body_owner(self, node_id: NodeId) -> bool {
+        match self {
+            EntryItem(_, item) => {
+                match item.node {
+                    ItemConst(_, body) |
+                    ItemStatic(.., body) |
+                    ItemFn(_, _, _, _, _, body) => body.node_id == node_id,
+                    _ => false
+                }
+            }
+
+            EntryTraitItem(_, item) => {
+                match item.node {
+                    TraitItemKind::Const(_, Some(body)) |
+                    TraitItemKind::Method(_, TraitMethod::Provided(body)) => {
+                        body.node_id == node_id
+                    }
+                    _ => false
+                }
+            }
+
+            EntryImplItem(_, item) => {
+                match item.node {
+                    ImplItemKind::Const(_, body) |
+                    ImplItemKind::Method(_, body) => body.node_id == node_id,
+                    _ => false
+                }
+            }
+
+            EntryExpr(_, expr) => {
+                match expr.node {
+                    ExprClosure(.., body, _) => body.node_id == node_id,
+                    _ => false
+                }
+            }
+
+            _ => false
+        }
+    }
 }
 
 /// Stores a crate and any number of inlined items from other crates.
@@ -250,38 +294,34 @@ fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
         if !self.is_inlined_node_id(id) {
             let mut last_expr = None;
             loop {
-                match map[id.as_usize()] {
-                    EntryItem(_, item) => {
-                        assert_eq!(id, item.id);
-                        let def_id = self.local_def_id(id);
-
+                let entry = map[id.as_usize()];
+                match entry {
+                    EntryItem(..) |
+                    EntryTraitItem(..) |
+                    EntryImplItem(..) => {
                         if let Some(last_id) = last_expr {
-                            // The body of the item may have a separate dep node
-                            // (Note that trait items don't currently have
-                            // their own dep node, so there's also just one
-                            // HirBody node for all the items)
-                            if self.is_body(last_id, item) {
+                            // The body may have a separate dep node
+                            if entry.is_body_owner(last_id) {
+                                let def_id = self.local_def_id(id);
                                 return DepNode::HirBody(def_id);
                             }
                         }
-                        return DepNode::Hir(def_id);
+                        return DepNode::Hir(self.local_def_id(id));
                     }
 
-                    EntryImplItem(_, item) => {
-                        let def_id = self.local_def_id(id);
+                    EntryVariant(p, v) => {
+                        id = p;
 
-                        if let Some(last_id) = last_expr {
-                            // The body of the item may have a separate dep node
-                            if self.is_impl_item_body(last_id, item) {
+                        if last_expr.is_some() {
+                            if v.node.disr_expr.map(|e| e.node_id) == last_expr {
+                                // The enum parent holds both Hir and HirBody nodes.
+                                let def_id = self.local_def_id(id);
                                 return DepNode::HirBody(def_id);
                             }
                         }
-                        return DepNode::Hir(def_id);
                     }
 
                     EntryForeignItem(p, _) |
-                    EntryTraitItem(p, _) |
-                    EntryVariant(p, _) |
                     EntryField(p, _) |
                     EntryStmt(p, _) |
                     EntryTy(p, _) |
@@ -308,7 +348,7 @@ fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
                         bug!("node {} has inlined ancestor but is not inlined", id0),
 
                     NotPresent =>
-                        // Some nodes, notably struct fields, are not
+                        // Some nodes, notably macro definitions, are not
                         // present in the map for whatever reason, but
                         // they *do* have def-ids. So if we encounter an
                         // empty hole, check for that case.
@@ -358,29 +398,6 @@ fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
         }
     }
 
-    fn is_body(&self, node_id: NodeId, item: &Item) -> bool {
-        match item.node {
-            ItemFn(_, _, _, _, _, body) => body.node_id() == node_id,
-            // Since trait items currently don't get their own dep nodes,
-            // we check here whether node_id is the body of any of the items.
-            // If they get their own dep nodes, this can go away
-            ItemTrait(_, _, _, ref trait_items) => {
-                trait_items.iter().any(|trait_item| { match trait_item.node {
-                    MethodTraitItem(_, Some(body)) => body.node_id() == node_id,
-                    _ => false
-                }})
-            }
-            _ => false
-        }
-    }
-
-    fn is_impl_item_body(&self, node_id: NodeId, item: &ImplItem) -> bool {
-        match item.node {
-            ImplItemKind::Method(_, body) => body.node_id() == node_id,
-            _ => false
-        }
-    }
-
     pub fn num_local_def_ids(&self) -> usize {
         self.definitions.len()
     }
@@ -436,6 +453,14 @@ pub fn krate(&self) -> &'ast Crate {
         self.forest.krate()
     }
 
+    pub fn trait_item(&self, id: TraitItemId) -> &'ast TraitItem {
+        self.read(id.node_id);
+
+        // NB: intentionally bypass `self.forest.krate()` so that we
+        // do not trigger a read of the whole krate here
+        self.forest.krate.trait_item(id)
+    }
+
     pub fn impl_item(&self, id: ImplItemId) -> &'ast ImplItem {
         self.read(id.node_id);
 
@@ -444,6 +469,31 @@ pub fn impl_item(&self, id: ImplItemId) -> &'ast ImplItem {
         self.forest.krate.impl_item(id)
     }
 
+    pub fn body(&self, id: BodyId) -> &'ast Body {
+        self.read(id.node_id);
+
+        // NB: intentionally bypass `self.forest.krate()` so that we
+        // do not trigger a read of the whole krate here
+        self.forest.krate.body(id)
+    }
+
+    /// Returns the `NodeId` that corresponds to the definition of
+    /// which this is the body of, i.e. a `fn`, `const` or `static`
+    /// item (possibly associated), or a closure, or the body itself
+    /// for embedded constant expressions (e.g. `N` in `[T; N]`).
+    pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId {
+        let parent = self.get_parent_node(node_id);
+        if self.map.borrow()[parent.as_usize()].is_body_owner(node_id) {
+            parent
+        } else {
+            node_id
+        }
+    }
+
+    pub fn body_owner_def_id(&self, id: BodyId) -> DefId {
+        self.local_def_id(self.body_owner(id))
+    }
+
     /// Get the attributes on the krate. This is preferable to
     /// invoking `krate.attrs` because it registers a tighter
     /// dep-graph access.
@@ -687,17 +737,13 @@ pub fn expect_expr(&self, id: NodeId) -> &'ast Expr {
         }
     }
 
-    pub fn expect_inlined_item(&self, id: NodeId) -> &'ast InlinedItem {
+    pub fn expect_inlined_body(&self, id: NodeId) -> &'ast Body {
         match self.find_entry(id) {
-            Some(RootInlinedParent(inlined_item)) => inlined_item,
+            Some(RootInlinedParent(inlined_item)) => &inlined_item.body,
             _ => bug!("expected inlined item, found {}", self.node_to_string(id)),
         }
     }
 
-    pub fn expr(&self, id: ExprId) -> &'ast Expr {
-        self.expect_expr(id.node_id())
-    }
-
     /// Returns the name associated with the given NodeId's AST.
     pub fn name(&self, id: NodeId) -> Name {
         match self.get(id) {
@@ -778,7 +824,7 @@ pub fn span(&self, id: NodeId) -> Span {
             Some(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v),
 
             Some(RootCrate) => self.forest.krate.span,
-            Some(RootInlinedParent(parent)) => parent.body.span,
+            Some(RootInlinedParent(parent)) => parent.body.value.span,
             Some(NotPresent) | None => {
                 bug!("hir::map::Map::span: id not in map: {:?}", id)
             }
@@ -796,6 +842,10 @@ pub fn node_to_string(&self, id: NodeId) -> String {
     pub fn node_to_user_string(&self, id: NodeId) -> String {
         node_id_to_string(self, id, false)
     }
+
+    pub fn node_to_pretty_string(&self, id: NodeId) -> String {
+        print::to_string(self, |s| s.print_node(self.get(id)))
+    }
 }
 
 pub struct NodesMatchingSuffix<'a, 'ast:'a> {
@@ -934,33 +984,47 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest,
     }
 }
 
-/// Used for items loaded from external crate that are being inlined into this
+/// Used for bodies loaded from external crate that are being inlined into this
 /// crate.
-pub fn map_decoded_item<'ast>(map: &Map<'ast>,
-                              ii: InlinedItem,
-                              ii_parent_id: NodeId)
-                              -> &'ast InlinedItem {
+pub fn map_decoded_body<'ast>(map: &Map<'ast>,
+                              def_id: DefId,
+                              body: Body,
+                              parent_id: NodeId)
+                              -> &'ast Body {
     let _ignore = map.forest.dep_graph.in_ignore();
 
-    let ii = map.forest.inlined_items.alloc(ii);
+    let ii = map.forest.inlined_items.alloc(InlinedItem {
+        def_id: def_id,
+        body: body
+    });
 
     let mut collector = NodeCollector::extend(map.krate(),
                                               ii,
-                                              ii_parent_id,
+                                              parent_id,
                                               mem::replace(&mut *map.map.borrow_mut(), vec![]));
-    ii.visit(&mut collector);
+    collector.visit_body(&ii.body);
     *map.map.borrow_mut() = collector.map;
 
-    ii
+    &ii.body
 }
 
-pub trait NodePrinter {
-    fn print_node(&mut self, node: &Node) -> io::Result<()>;
+/// Identical to the `PpAnn` implementation for `hir::Crate`,
+/// except it avoids creating a dependency on the whole crate.
+impl<'ast> print::PpAnn for Map<'ast> {
+    fn nested(&self, state: &mut print::State, nested: print::Nested) -> io::Result<()> {
+        match nested {
+            Nested::Item(id) => state.print_item(self.expect_item(id.id)),
+            Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
+            Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
+            Nested::Body(id) => state.print_expr(&self.body(id).value),
+            Nested::BodyArgPat(id, i) => state.print_pat(&self.body(id).arguments[i].pat)
+        }
+    }
 }
 
-impl<'a> NodePrinter for pprust::State<'a> {
-    fn print_node(&mut self, node: &Node) -> io::Result<()> {
-        match *node {
+impl<'a> print::State<'a> {
+    pub fn print_node(&mut self, node: Node) -> io::Result<()> {
+        match node {
             NodeItem(a)        => self.print_item(&a),
             NodeForeignItem(a) => self.print_foreign_item(&a),
             NodeTraitItem(a)   => self.print_trait_item(a),
@@ -970,8 +1034,17 @@ fn print_node(&mut self, node: &Node) -> io::Result<()> {
             NodeStmt(a)        => self.print_stmt(&a),
             NodeTy(a)          => self.print_type(&a),
             NodeTraitRef(a)    => self.print_trait_ref(&a),
+            NodeLocal(a)       |
             NodePat(a)         => self.print_pat(&a),
-            NodeBlock(a)       => self.print_block(&a),
+            NodeBlock(a)       => {
+                use syntax::print::pprust::PrintState;
+
+                // containing cbox, will be closed by print-block at }
+                self.cbox(print::indent_unit)?;
+                // head-ibox, will be closed by print-block after {
+                self.ibox(0)?;
+                self.print_block(&a)
+            }
             NodeLifetime(a)    => self.print_lifetime(&a),
             NodeVisibility(a)  => self.print_visibility(&a),
             NodeTyParam(_)     => bug!("cannot print TyParam"),
@@ -979,10 +1052,7 @@ fn print_node(&mut self, node: &Node) -> io::Result<()> {
             // these cases do not carry enough information in the
             // ast_map to reconstruct their full structure for pretty
             // printing.
-            NodeLocal(_)       => bug!("cannot print isolated Local"),
             NodeStructCtor(_)  => bug!("cannot print isolated StructCtor"),
-
-            NodeInlinedItem(_) => bug!("cannot print inlined item"),
         }
     }
 }
@@ -1045,9 +1115,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
         }
         Some(NodeTraitItem(ti)) => {
             let kind = match ti.node {
-                ConstTraitItem(..) => "assoc constant",
-                MethodTraitItem(..) => "trait method",
-                TypeTraitItem(..) => "assoc type",
+                TraitItemKind::Const(..) => "assoc constant",
+                TraitItemKind::Method(..) => "trait method",
+                TraitItemKind::Type(..) => "assoc type",
             };
 
             format!("{} {} in {}{}", kind, ti.name, path_str(), id_str)
@@ -1062,33 +1132,32 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
                     field.name,
                     path_str(), id_str)
         }
-        Some(NodeExpr(ref expr)) => {
-            format!("expr {}{}", pprust::expr_to_string(&expr), id_str)
+        Some(NodeExpr(_)) => {
+            format!("expr {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeStmt(ref stmt)) => {
-            format!("stmt {}{}", pprust::stmt_to_string(&stmt), id_str)
+        Some(NodeStmt(_)) => {
+            format!("stmt {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeTy(ref ty)) => {
-            format!("type {}{}", pprust::ty_to_string(&ty), id_str)
+        Some(NodeTy(_)) => {
+            format!("type {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeTraitRef(ref tr)) => {
-            format!("trait_ref {}{}", pprust::path_to_string(&tr.path), id_str)
+        Some(NodeTraitRef(_)) => {
+            format!("trait_ref {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeLocal(ref pat)) => {
-            format!("local {}{}", pprust::pat_to_string(&pat), id_str)
+        Some(NodeLocal(_)) => {
+            format!("local {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodePat(ref pat)) => {
-            format!("pat {}{}", pprust::pat_to_string(&pat), id_str)
+        Some(NodePat(_)) => {
+            format!("pat {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeBlock(ref block)) => {
-            format!("block {}{}", pprust::block_to_string(&block), id_str)
+        Some(NodeBlock(_)) => {
+            format!("block {}{}", map.node_to_pretty_string(id), id_str)
         }
         Some(NodeStructCtor(_)) => {
             format!("struct_ctor {}{}", path_str(), id_str)
         }
-        Some(NodeLifetime(ref l)) => {
-            format!("lifetime {}{}",
-                    pprust::lifetime_to_string(&l), id_str)
+        Some(NodeLifetime(_)) => {
+            format!("lifetime {}{}", map.node_to_pretty_string(id), id_str)
         }
         Some(NodeTyParam(ref ty_param)) => {
             format!("typaram {:?}{}", ty_param, id_str)
@@ -1096,9 +1165,6 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
         Some(NodeVisibility(ref vis)) => {
             format!("visibility {:?}{}", vis, id_str)
         }
-        Some(NodeInlinedItem(_)) => {
-            format!("inlined item {}", id_str)
-        }
         None => {
             format!("unknown node{}", id_str)
         }
index f52ee35e1757306ae0605e1dd774db9d770398b4..9149da459c26e85127ca50ed0bca90877fd42d7b 100644 (file)
@@ -22,7 +22,6 @@
 pub use self::Mutability::*;
 pub use self::PrimTy::*;
 pub use self::Stmt_::*;
-pub use self::TraitItem_::*;
 pub use self::Ty_::*;
 pub use self::TyParamBound::*;
 pub use self::UnOp::*;
 
 use hir::def::Def;
 use hir::def_id::DefId;
-use util::nodemap::{NodeMap, FxHashSet};
-use rustc_data_structures::fnv::FnvHashMap;
+use util::nodemap::{NodeMap, FxHashMap, FxHashSet};
 
-use syntax_pos::{mk_sp, Span, ExpnId, DUMMY_SP};
-use syntax::codemap::{self, respan, Spanned};
+use syntax_pos::{Span, ExpnId, DUMMY_SP};
+use syntax::codemap::{self, Spanned};
 use syntax::abi::Abi;
 use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, AsmDialect};
 use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
@@ -87,7 +85,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f,
                "lifetime({}: {})",
                self.id,
-               print::lifetime_to_string(self))
+               print::to_string(print::NO_ANN, |s| s.print_lifetime(self)))
     }
 }
 
@@ -105,24 +103,22 @@ pub struct LifetimeDef {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
 pub struct Path {
     pub span: Span,
-    /// A `::foo` path, is relative to the crate root rather than current
-    /// module (like paths in an import).
-    pub global: bool,
     /// The definition that the path resolved to.
     pub def: Def,
     /// The segments in the path: the things separated by `::`.
     pub segments: HirVec<PathSegment>,
 }
 
-impl fmt::Debug for Path {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "path({})", print::path_to_string(self))
+impl Path {
+    pub fn is_global(&self) -> bool {
+        !self.segments.is_empty() && self.segments[0].name == keywords::CrateRoot.name()
     }
 }
 
-impl fmt::Display for Path {
+impl fmt::Debug for Path {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", print::path_to_string(self))
+        write!(f, "path({})",
+               print::to_string(print::NO_ANN, |s| s.print_path(self, false)))
     }
 }
 
@@ -428,8 +424,9 @@ pub struct Crate {
     // slightly different results.
     pub items: BTreeMap<NodeId, Item>,
 
+    pub trait_items: BTreeMap<TraitItemId, TraitItem>,
     pub impl_items: BTreeMap<ImplItemId, ImplItem>,
-    pub exprs: FnvHashMap<ExprId, Expr>,
+    pub bodies: FxHashMap<BodyId, Body>,
 }
 
 impl Crate {
@@ -437,6 +434,10 @@ pub fn item(&self, id: NodeId) -> &Item {
         &self.items[&id]
     }
 
+    pub fn trait_item(&self, id: TraitItemId) -> &TraitItem {
+        &self.trait_items[&id]
+    }
+
     pub fn impl_item(&self, id: ImplItemId) -> &ImplItem {
         &self.impl_items[&id]
     }
@@ -456,13 +457,17 @@ pub fn visit_all_item_likes<'hir, V>(&'hir self, visitor: &mut V)
             visitor.visit_item(item);
         }
 
+        for (_, trait_item) in &self.trait_items {
+            visitor.visit_trait_item(trait_item);
+        }
+
         for (_, impl_item) in &self.impl_items {
             visitor.visit_impl_item(impl_item);
         }
     }
 
-    pub fn expr(&self, id: ExprId) -> &Expr {
-        &self.exprs[&id]
+    pub fn body(&self, id: BodyId) -> &Body {
+        &self.bodies[&id]
     }
 }
 
@@ -500,7 +505,8 @@ pub struct Pat {
 
 impl fmt::Debug for Pat {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "pat({}: {})", self.id, print::pat_to_string(self))
+        write!(f, "pat({}: {})", self.id,
+               print::to_string(print::NO_ANN, |s| s.print_pat(self)))
     }
 }
 
@@ -752,7 +758,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f,
                "stmt({}: {})",
                spanned.node.id(),
-               print::stmt_to_string(&spanned))
+               print::to_string(print::NO_ANN, |s| s.print_stmt(&spanned)))
     }
 }
 
@@ -850,12 +856,23 @@ pub enum UnsafeSource {
     UserProvided,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct ExprId(NodeId);
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct BodyId {
+    pub node_id: NodeId,
+}
+
+/// The body of a function or constant value.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct Body {
+    pub arguments: HirVec<Arg>,
+    pub value: Expr
+}
 
-impl ExprId {
-    pub fn node_id(self) -> NodeId {
-        self.0
+impl Body {
+    pub fn id(&self) -> BodyId {
+        BodyId {
+            node_id: self.value.id
+        }
     }
 }
 
@@ -868,15 +885,10 @@ pub struct Expr {
     pub attrs: ThinVec<Attribute>,
 }
 
-impl Expr {
-    pub fn expr_id(&self) -> ExprId {
-        ExprId(self.id)
-    }
-}
-
 impl fmt::Debug for Expr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "expr({}: {})", self.id, print::expr_to_string(self))
+        write!(f, "expr({}: {})", self.id,
+               print::to_string(print::NO_ANN, |s| s.print_expr(self)))
     }
 }
 
@@ -933,7 +945,7 @@ pub enum Expr_ {
     /// A closure (for example, `move |a, b, c| {a + b + c}`).
     ///
     /// The final span is the span of the argument block `|...|`
-    ExprClosure(CaptureClause, P<FnDecl>, ExprId, Span),
+    ExprClosure(CaptureClause, P<FnDecl>, BodyId, Span),
     /// A block (`{ ... }`)
     ExprBlock(P<Block>),
 
@@ -977,7 +989,7 @@ pub enum Expr_ {
     ///
     /// For example, `[1; 5]`. The first expression is the element
     /// to be repeated; the second is the number of times to repeat it.
-    ExprRepeat(P<Expr>, P<Expr>),
+    ExprRepeat(P<Expr>, BodyId),
 }
 
 /// Optionally `Self`-qualified value/type path or associated extension.
@@ -1000,12 +1012,6 @@ pub enum QPath {
     TypeRelative(P<Ty>, P<PathSegment>)
 }
 
-impl fmt::Display for QPath {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", print::qpath_to_string(self))
-    }
-}
-
 /// Hints at the original code for a `match _ { .. }`
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum MatchSource {
@@ -1067,6 +1073,14 @@ pub struct MethodSig {
     pub generics: Generics,
 }
 
+// The bodies for items are stored "out of line", in a separate
+// hashmap in the `Crate`. Here we just record the node-id of the item
+// so it can fetched later.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct TraitItemId {
+    pub node_id: NodeId,
+}
+
 /// Represents an item declaration within a trait declaration,
 /// possibly including a default implementation. A trait item is
 /// either required (meaning it doesn't have an implementation, just a
@@ -1076,21 +1090,31 @@ pub struct TraitItem {
     pub id: NodeId,
     pub name: Name,
     pub attrs: HirVec<Attribute>,
-    pub node: TraitItem_,
+    pub node: TraitItemKind,
     pub span: Span,
 }
 
+/// A trait method's body (or just argument names).
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum TraitMethod {
+    /// No default body in the trait, just a signature.
+    Required(HirVec<Spanned<Name>>),
+
+    /// Both signature and body are provided in the trait.
+    Provided(BodyId),
+}
+
 /// Represents a trait method or associated constant or type
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum TraitItem_ {
+pub enum TraitItemKind {
     /// An associated constant with an optional value (otherwise `impl`s
     /// must contain a value)
-    ConstTraitItem(P<Ty>, Option<P<Expr>>),
+    Const(P<Ty>, Option<BodyId>),
     /// A method with an optional body
-    MethodTraitItem(MethodSig, Option<ExprId>),
+    Method(MethodSig, TraitMethod),
     /// An associated type with (possibly empty) bounds and optional concrete
     /// type
-    TypeTraitItem(TyParamBounds, Option<P<Ty>>),
+    Type(TyParamBounds, Option<P<Ty>>),
 }
 
 // The bodies for items are stored "out of line", in a separate
@@ -1118,9 +1142,9 @@ pub struct ImplItem {
 pub enum ImplItemKind {
     /// An associated constant of the given type, set to the constant result
     /// of the expression
-    Const(P<Ty>, P<Expr>),
+    Const(P<Ty>, BodyId),
     /// A method implementation with the given signature and body
-    Method(MethodSig, ExprId),
+    Method(MethodSig, BodyId),
     /// An associated type
     Type(P<Ty>),
 }
@@ -1144,7 +1168,8 @@ pub struct Ty {
 
 impl fmt::Debug for Ty {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "type({})", print::ty_to_string(self))
+        write!(f, "type({})",
+               print::to_string(print::NO_ANN, |s| s.print_type(self)))
     }
 }
 
@@ -1173,7 +1198,7 @@ pub enum Ty_ {
     /// A variable length slice (`[T]`)
     TySlice(P<Ty>),
     /// A fixed length array (`[T; n]`)
-    TyArray(P<Ty>, P<Expr>),
+    TyArray(P<Ty>, BodyId),
     /// A raw pointer (`*const T` or `*mut T`)
     TyPtr(MutTy),
     /// A reference (`&'a T` or `&'a mut T`)
@@ -1197,7 +1222,7 @@ pub enum Ty_ {
     /// An `impl TraitA+TraitB` type.
     TyImplTrait(TyParamBounds),
     /// Unused for now
-    TyTypeof(P<Expr>),
+    TyTypeof(BodyId),
     /// TyInfer means the type should be inferred instead of it having been
     /// specified. This can appear anywhere in a type.
     TyInfer,
@@ -1226,67 +1251,18 @@ pub struct InlineAsm {
 /// represents an argument in a function header
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct Arg {
-    pub ty: P<Ty>,
     pub pat: P<Pat>,
     pub id: NodeId,
 }
 
-/// Alternative representation for `Arg`s describing `self` parameter of methods.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum SelfKind {
-    /// `self`, `mut self`
-    Value(Mutability),
-    /// `&'lt self`, `&'lt mut self`
-    Region(Option<Lifetime>, Mutability),
-    /// `self: TYPE`, `mut self: TYPE`
-    Explicit(P<Ty>, Mutability),
-}
-
-pub type ExplicitSelf = Spanned<SelfKind>;
-
-impl Arg {
-    pub fn to_self(&self) -> Option<ExplicitSelf> {
-        if let PatKind::Binding(BindByValue(mutbl), _, name, _) = self.pat.node {
-            if name.node == keywords::SelfValue.name() {
-                return match self.ty.node {
-                    TyInfer => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
-                    TyRptr(lt, MutTy{ref ty, mutbl}) if ty.node == TyInfer => {
-                        Some(respan(self.pat.span, SelfKind::Region(lt, mutbl)))
-                    }
-                    _ => Some(respan(mk_sp(self.pat.span.lo, self.ty.span.hi),
-                                     SelfKind::Explicit(self.ty.clone(), mutbl)))
-                }
-            }
-        }
-        None
-    }
-
-    pub fn is_self(&self) -> bool {
-        if let PatKind::Binding(_, _, name, _) = self.pat.node {
-            name.node == keywords::SelfValue.name()
-        } else {
-            false
-        }
-    }
-}
-
 /// Represents the header (not the body) of a function declaration
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct FnDecl {
-    pub inputs: HirVec<Arg>,
+    pub inputs: HirVec<P<Ty>>,
     pub output: FunctionRetTy,
     pub variadic: bool,
 }
 
-impl FnDecl {
-    pub fn get_self(&self) -> Option<ExplicitSelf> {
-        self.inputs.get(0).and_then(Arg::to_self)
-    }
-    pub fn has_self(&self) -> bool {
-        self.inputs.get(0).map(Arg::is_self).unwrap_or(false)
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Unsafety {
     Unsafe,
@@ -1400,7 +1376,7 @@ pub struct Variant_ {
     pub attrs: HirVec<Attribute>,
     pub data: VariantData,
     /// Explicit discriminant, eg `Foo = 1`
-    pub disr_expr: Option<P<Expr>>,
+    pub disr_expr: Option<BodyId>,
 }
 
 pub type Variant = Spanned<Variant_>;
@@ -1531,8 +1507,6 @@ pub struct ItemId {
     pub id: NodeId,
 }
 
-//  FIXME (#3300): Should allow items to be anonymous. Right now
-//  we just use dummy names for anon items.
 /// An item
 ///
 /// The name might be a dummy name in case of anonymous items
@@ -1561,11 +1535,11 @@ pub enum Item_ {
     ItemUse(P<Path>, UseKind),
 
     /// A `static` item
-    ItemStatic(P<Ty>, Mutability, P<Expr>),
+    ItemStatic(P<Ty>, Mutability, BodyId),
     /// A `const` item
-    ItemConst(P<Ty>, P<Expr>),
+    ItemConst(P<Ty>, BodyId),
     /// A function declaration
-    ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, ExprId),
+    ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, BodyId),
     /// A module
     ItemMod(Mod),
     /// An external module
@@ -1579,7 +1553,7 @@ pub enum Item_ {
     /// A union definition, e.g. `union Foo<A, B> {x: A, y: B}`
     ItemUnion(VariantData, Generics),
     /// Represents a Trait Declaration
-    ItemTrait(Unsafety, Generics, TyParamBounds, HirVec<TraitItem>),
+    ItemTrait(Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>),
 
     // Default trait implementations
     ///
@@ -1615,6 +1589,21 @@ pub fn descriptive_variant(&self) -> &str {
     }
 }
 
+/// A reference from an trait to one of its associated items. This
+/// contains the item's id, naturally, but also the item's name and
+/// some other high-level details (like whether it is an associated
+/// type or method, and whether it is public). This allows other
+/// passes to find the impl they want without loading the id (which
+/// means fewer edges in the incremental compilation graph).
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct TraitItemRef {
+    pub id: TraitItemId,
+    pub name: Name,
+    pub kind: AssociatedItemKind,
+    pub span: Span,
+    pub defaultness: Defaultness,
+}
+
 /// A reference from an impl to one of its associated items. This
 /// contains the item's id, naturally, but also the item's name and
 /// some other high-level details (like whether it is an associated
@@ -1652,7 +1641,7 @@ pub struct ForeignItem {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum ForeignItem_ {
     /// A foreign function
-    ForeignItemFn(P<FnDecl>, Generics),
+    ForeignItemFn(P<FnDecl>, HirVec<Spanned<Name>>, Generics),
     /// A foreign static item (`static ext: u8`), with optional mutability
     /// (the boolean is true when mutable)
     ForeignItemStatic(P<Ty>, bool),
index 74920b1328076d392dd9212fe903cd8ea0e80993..18fa6836b510827bfeb4e1c43d5e949bd09af7d7 100644 (file)
@@ -13,7 +13,6 @@
 use syntax::abi::Abi;
 use syntax::ast;
 use syntax::codemap::{CodeMap, Spanned};
-use syntax::parse::token::{self, BinOpToken};
 use syntax::parse::lexer::comments;
 use syntax::print::pp::{self, break_offset, word, space, hardbreak};
 use syntax::print::pp::{Breaks, eof};
@@ -25,7 +24,7 @@
 use errors;
 
 use hir;
-use hir::{Crate, PatKind, RegionTyParamBound, SelfKind, TraitTyParamBound, TraitBoundModifier};
+use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 
 use std::io::{self, Write, Read};
 
@@ -38,7 +37,18 @@ pub enum AnnNode<'a> {
     NodePat(&'a hir::Pat),
 }
 
+pub enum Nested {
+    Item(hir::ItemId),
+    TraitItem(hir::TraitItemId),
+    ImplItem(hir::ImplItemId),
+    Body(hir::BodyId),
+    BodyArgPat(hir::BodyId, usize)
+}
+
 pub trait PpAnn {
+    fn nested(&self, _state: &mut State, _nested: Nested) -> io::Result<()> {
+        Ok(())
+    }
     fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> {
         Ok(())
     }
@@ -47,14 +57,23 @@ fn post(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> {
     }
 }
 
-#[derive(Copy, Clone)]
 pub struct NoAnn;
-
 impl PpAnn for NoAnn {}
+pub const NO_ANN: &'static PpAnn = &NoAnn;
 
+impl PpAnn for hir::Crate {
+    fn nested(&self, state: &mut State, nested: Nested) -> io::Result<()> {
+        match nested {
+            Nested::Item(id) => state.print_item(self.item(id.id)),
+            Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
+            Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
+            Nested::Body(id) => state.print_expr(&self.body(id).value),
+            Nested::BodyArgPat(id, i) => state.print_pat(&self.body(id).arguments[i].pat)
+        }
+    }
+}
 
 pub struct State<'a> {
-    krate: Option<&'a Crate>,
     pub s: pp::Printer<'a>,
     cm: Option<&'a CodeMap>,
     comments: Option<Vec<comments::Comment>>,
@@ -86,30 +105,6 @@ fn literals(&self) -> &Option<Vec<comments::Literal>> {
     }
 }
 
-pub fn rust_printer<'a>(writer: Box<Write + 'a>, krate: Option<&'a Crate>) -> State<'a> {
-    static NO_ANN: NoAnn = NoAnn;
-    rust_printer_annotated(writer, &NO_ANN, krate)
-}
-
-pub fn rust_printer_annotated<'a>(writer: Box<Write + 'a>,
-                                  ann: &'a PpAnn,
-                                  krate: Option<&'a Crate>)
-                                  -> State<'a> {
-    State {
-        krate: krate,
-        s: pp::mk_printer(writer, default_columns),
-        cm: None,
-        comments: None,
-        literals: None,
-        cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral {
-            cur_cmnt: 0,
-            cur_lit: 0,
-        },
-        boxes: Vec::new(),
-        ann: ann,
-    }
-}
-
 #[allow(non_upper_case_globals)]
 pub const indent_unit: usize = 4;
 
@@ -130,7 +125,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
                        is_expanded: bool)
                        -> io::Result<()> {
     let mut s = State::new_from_input(cm, span_diagnostic, filename, input,
-                                      out, ann, is_expanded, Some(krate));
+                                      out, ann, is_expanded);
 
     // When printing the AST, we sometimes need to inject `#[no_std]` here.
     // Since you can't compile the HIR, it's not necessary.
@@ -147,8 +142,7 @@ pub fn new_from_input(cm: &'a CodeMap,
                           input: &mut Read,
                           out: Box<Write + 'a>,
                           ann: &'a PpAnn,
-                          is_expanded: bool,
-                          krate: Option<&'a Crate>)
+                          is_expanded: bool)
                           -> State<'a> {
         let (cmnts, lits) = comments::gather_comments_and_literals(span_diagnostic,
                                                                    filename,
@@ -165,19 +159,16 @@ pub fn new_from_input(cm: &'a CodeMap,
                        None
                    } else {
                        Some(lits)
-                   },
-                   krate)
+                   })
     }
 
     pub fn new(cm: &'a CodeMap,
                out: Box<Write + 'a>,
                ann: &'a PpAnn,
                comments: Option<Vec<comments::Comment>>,
-               literals: Option<Vec<comments::Literal>>,
-               krate: Option<&'a Crate>)
+               literals: Option<Vec<comments::Literal>>)
                -> State<'a> {
         State {
-            krate: krate,
             s: pp::mk_printer(out, default_columns),
             cm: Some(cm),
             comments: comments.clone(),
@@ -192,144 +183,36 @@ pub fn new(cm: &'a CodeMap,
     }
 }
 
-pub fn to_string<F>(f: F) -> String
+pub fn to_string<F>(ann: &PpAnn, f: F) -> String
     where F: FnOnce(&mut State) -> io::Result<()>
 {
     let mut wr = Vec::new();
     {
-        let mut printer = rust_printer(Box::new(&mut wr), None);
+        let mut printer = State {
+            s: pp::mk_printer(Box::new(&mut wr), default_columns),
+            cm: None,
+            comments: None,
+            literals: None,
+            cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral {
+                cur_cmnt: 0,
+                cur_lit: 0,
+            },
+            boxes: Vec::new(),
+            ann: ann,
+        };
         f(&mut printer).unwrap();
         eof(&mut printer.s).unwrap();
     }
     String::from_utf8(wr).unwrap()
 }
 
-pub fn binop_to_string(op: BinOpToken) -> &'static str {
-    match op {
-        token::Plus => "+",
-        token::Minus => "-",
-        token::Star => "*",
-        token::Slash => "/",
-        token::Percent => "%",
-        token::Caret => "^",
-        token::And => "&",
-        token::Or => "|",
-        token::Shl => "<<",
-        token::Shr => ">>",
-    }
-}
-
-pub fn ty_to_string(ty: &hir::Ty) -> String {
-    to_string(|s| s.print_type(ty))
-}
-
-pub fn bounds_to_string(bounds: &[hir::TyParamBound]) -> String {
-    to_string(|s| s.print_bounds("", bounds))
-}
-
-pub fn pat_to_string(pat: &hir::Pat) -> String {
-    to_string(|s| s.print_pat(pat))
-}
-
-pub fn arm_to_string(arm: &hir::Arm) -> String {
-    to_string(|s| s.print_arm(arm))
-}
-
-pub fn expr_to_string(e: &hir::Expr) -> String {
-    to_string(|s| s.print_expr(e))
-}
-
-pub fn lifetime_to_string(e: &hir::Lifetime) -> String {
-    to_string(|s| s.print_lifetime(e))
-}
-
-pub fn stmt_to_string(stmt: &hir::Stmt) -> String {
-    to_string(|s| s.print_stmt(stmt))
-}
-
-pub fn item_to_string(i: &hir::Item) -> String {
-    to_string(|s| s.print_item(i))
-}
-
-pub fn impl_item_to_string(i: &hir::ImplItem) -> String {
-    to_string(|s| s.print_impl_item(i))
-}
-
-pub fn trait_item_to_string(i: &hir::TraitItem) -> String {
-    to_string(|s| s.print_trait_item(i))
-}
-
-pub fn generics_to_string(generics: &hir::Generics) -> String {
-    to_string(|s| s.print_generics(generics))
-}
-
-pub fn where_clause_to_string(i: &hir::WhereClause) -> String {
-    to_string(|s| s.print_where_clause(i))
-}
-
-pub fn fn_block_to_string(p: &hir::FnDecl) -> String {
-    to_string(|s| s.print_fn_block_args(p))
-}
-
-pub fn path_to_string(p: &hir::Path) -> String {
-    to_string(|s| s.print_path(p, false))
-}
-
-pub fn qpath_to_string(p: &hir::QPath) -> String {
-    to_string(|s| s.print_qpath(p, false))
-}
-
-pub fn name_to_string(name: ast::Name) -> String {
-    to_string(|s| s.print_name(name))
-}
-
-pub fn fun_to_string(decl: &hir::FnDecl,
-                     unsafety: hir::Unsafety,
-                     constness: hir::Constness,
-                     name: ast::Name,
-                     generics: &hir::Generics)
-                     -> String {
-    to_string(|s| {
-        s.head("")?;
-        s.print_fn(decl,
-                   unsafety,
-                   constness,
-                   Abi::Rust,
-                   Some(name),
-                   generics,
-                   &hir::Inherited)?;
-        s.end()?; // Close the head box
-        s.end() // Close the outer box
+pub fn visibility_qualified(vis: &hir::Visibility, w: &str) -> String {
+    to_string(NO_ANN, |s| {
+        s.print_visibility(vis)?;
+        word(&mut s.s, w)
     })
 }
 
-pub fn block_to_string(blk: &hir::Block) -> String {
-    to_string(|s| {
-        // containing cbox, will be closed by print-block at }
-        s.cbox(indent_unit)?;
-        // head-ibox, will be closed by print-block after {
-        s.ibox(0)?;
-        s.print_block(blk)
-    })
-}
-
-pub fn variant_to_string(var: &hir::Variant) -> String {
-    to_string(|s| s.print_variant(var))
-}
-
-pub fn arg_to_string(arg: &hir::Arg) -> String {
-    to_string(|s| s.print_arg(arg, false))
-}
-
-pub fn visibility_qualified(vis: &hir::Visibility, s: &str) -> String {
-    match *vis {
-        hir::Public => format!("pub {}", s),
-        hir::Visibility::Crate => format!("pub(crate) {}", s),
-        hir::Visibility::Restricted { ref path, .. } => format!("pub({}) {}", path, s),
-        hir::Inherited => s.to_string(),
-    }
-}
-
 fn needs_parentheses(expr: &hir::Expr) -> bool {
     match expr.node {
         hir::ExprAssign(..) |
@@ -462,8 +345,8 @@ pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[hir::Expr]) -> io::Result<(
 
     pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) -> io::Result<()> {
         self.print_inner_attributes(attrs)?;
-        for item_id in &_mod.item_ids {
-            self.print_item_id(item_id)?;
+        for &item_id in &_mod.item_ids {
+            self.ann.nested(self, Nested::Item(item_id))?;
         }
         Ok(())
     }
@@ -545,16 +428,16 @@ pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> {
             hir::TyImplTrait(ref bounds) => {
                 self.print_bounds("impl ", &bounds[..])?;
             }
-            hir::TyArray(ref ty, ref v) => {
+            hir::TyArray(ref ty, v) => {
                 word(&mut self.s, "[")?;
                 self.print_type(&ty)?;
                 word(&mut self.s, "; ")?;
-                self.print_expr(&v)?;
+                self.ann.nested(self, Nested::Body(v))?;
                 word(&mut self.s, "]")?;
             }
-            hir::TyTypeof(ref e) => {
+            hir::TyTypeof(e) => {
                 word(&mut self.s, "typeof(")?;
-                self.print_expr(&e)?;
+                self.ann.nested(self, Nested::Body(e))?;
                 word(&mut self.s, ")")?;
             }
             hir::TyInfer => {
@@ -569,7 +452,7 @@ pub fn print_foreign_item(&mut self, item: &hir::ForeignItem) -> io::Result<()>
         self.maybe_print_comment(item.span.lo)?;
         self.print_outer_attributes(&item.attrs)?;
         match item.node {
-            hir::ForeignItemFn(ref decl, ref generics) => {
+            hir::ForeignItemFn(ref decl, ref arg_names, ref generics) => {
                 self.head("")?;
                 self.print_fn(decl,
                               hir::Unsafety::Normal,
@@ -577,7 +460,9 @@ pub fn print_foreign_item(&mut self, item: &hir::ForeignItem) -> io::Result<()>
                               Abi::Rust,
                               Some(item.name),
                               generics,
-                              &item.vis)?;
+                              &item.vis,
+                              arg_names,
+                              None)?;
                 self.end()?; // end head-ibox
                 word(&mut self.s, ";")?;
                 self.end() // end the outer fn box
@@ -600,7 +485,7 @@ pub fn print_foreign_item(&mut self, item: &hir::ForeignItem) -> io::Result<()>
     fn print_associated_const(&mut self,
                               name: ast::Name,
                               ty: &hir::Ty,
-                              default: Option<&hir::Expr>,
+                              default: Option<hir::BodyId>,
                               vis: &hir::Visibility)
                               -> io::Result<()> {
         word(&mut self.s, &visibility_qualified(vis, ""))?;
@@ -611,7 +496,7 @@ fn print_associated_const(&mut self,
         if let Some(expr) = default {
             space(&mut self.s)?;
             self.word_space("=")?;
-            self.print_expr(expr)?;
+            self.ann.nested(self, Nested::Body(expr))?;
         }
         word(&mut self.s, ";")
     }
@@ -634,25 +519,6 @@ fn print_associated_type(&mut self,
         word(&mut self.s, ";")
     }
 
-    pub fn print_item_id(&mut self, item_id: &hir::ItemId) -> io::Result<()> {
-        if let Some(krate) = self.krate {
-            // skip nested items if krate context was not provided
-            let item = &krate.items[&item_id.id];
-            self.print_item(item)
-        } else {
-            Ok(())
-        }
-    }
-
-    pub fn print_expr_id(&mut self, expr_id: &hir::ExprId) -> io::Result<()> {
-        if let Some(krate) = self.krate {
-            let expr = &krate.exprs[expr_id];
-            self.print_expr(expr)
-        } else {
-            Ok(())
-        }
-    }
-
     /// Pretty-print an item
     pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
         self.hardbreak_if_not_bol()?;
@@ -697,7 +563,7 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 self.end()?; // end inner head-block
                 self.end()?; // end outer head-block
             }
-            hir::ItemStatic(ref ty, m, ref expr) => {
+            hir::ItemStatic(ref ty, m, expr) => {
                 self.head(&visibility_qualified(&item.vis, "static"))?;
                 if m == hir::MutMutable {
                     self.word_space("mut")?;
@@ -709,11 +575,11 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 self.end()?; // end the head-ibox
 
                 self.word_space("=")?;
-                self.print_expr(&expr)?;
+                self.ann.nested(self, Nested::Body(expr))?;
                 word(&mut self.s, ";")?;
                 self.end()?; // end the outer cbox
             }
-            hir::ItemConst(ref ty, ref expr) => {
+            hir::ItemConst(ref ty, expr) => {
                 self.head(&visibility_qualified(&item.vis, "const"))?;
                 self.print_name(item.name)?;
                 self.word_space(":")?;
@@ -722,11 +588,11 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 self.end()?; // end the head-ibox
 
                 self.word_space("=")?;
-                self.print_expr(&expr)?;
+                self.ann.nested(self, Nested::Body(expr))?;
                 word(&mut self.s, ";")?;
                 self.end()?; // end the outer cbox
             }
-            hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, ref body) => {
+            hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, body) => {
                 self.head("")?;
                 self.print_fn(decl,
                               unsafety,
@@ -734,11 +600,13 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                               abi,
                               Some(item.name),
                               typarams,
-                              &item.vis)?;
+                              &item.vis,
+                              &[],
+                              Some(body))?;
                 word(&mut self.s, " ")?;
                 self.end()?; // need to close a box
                 self.end()?; // need to close a box
-                self.print_expr_id(body)?;
+                self.ann.nested(self, Nested::Body(body))?;
             }
             hir::ItemMod(ref _mod) => {
                 self.head(&visibility_qualified(&item.vis, "mod"))?;
@@ -832,7 +700,7 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 self.bopen()?;
                 self.print_inner_attributes(&item.attrs)?;
                 for impl_item in impl_items {
-                    self.print_impl_item_ref(impl_item)?;
+                    self.ann.nested(self, Nested::ImplItem(impl_item.id))?;
                 }
                 self.bclose(item.span)?;
             }
@@ -858,7 +726,7 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 word(&mut self.s, " ")?;
                 self.bopen()?;
                 for trait_item in trait_items {
-                    self.print_trait_item(trait_item)?;
+                    self.ann.nested(self, Nested::TraitItem(trait_item.id))?;
                 }
                 self.bclose(item.span)?;
             }
@@ -928,8 +796,11 @@ pub fn print_visibility(&mut self, vis: &hir::Visibility) -> io::Result<()> {
         match *vis {
             hir::Public => self.word_nbsp("pub"),
             hir::Visibility::Crate => self.word_nbsp("pub(crate)"),
-            hir::Visibility::Restricted { ref path, .. } =>
-                self.word_nbsp(&format!("pub({})", path)),
+            hir::Visibility::Restricted { ref path, .. } => {
+                word(&mut self.s, "pub(")?;
+                self.print_path(path, false)?;
+                self.word_nbsp(")")
+            }
             hir::Inherited => Ok(()),
         }
     }
@@ -985,19 +856,19 @@ pub fn print_variant(&mut self, v: &hir::Variant) -> io::Result<()> {
         self.head("")?;
         let generics = hir::Generics::empty();
         self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?;
-        match v.node.disr_expr {
-            Some(ref d) => {
-                space(&mut self.s)?;
-                self.word_space("=")?;
-                self.print_expr(&d)
-            }
-            _ => Ok(()),
+        if let Some(d) = v.node.disr_expr {
+            space(&mut self.s)?;
+            self.word_space("=")?;
+            self.ann.nested(self, Nested::Body(d))?;
         }
+        Ok(())
     }
     pub fn print_method_sig(&mut self,
                             name: ast::Name,
                             m: &hir::MethodSig,
-                            vis: &hir::Visibility)
+                            vis: &hir::Visibility,
+                            arg_names: &[Spanned<ast::Name>],
+                            body_id: Option<hir::BodyId>)
                             -> io::Result<()> {
         self.print_fn(&m.decl,
                       m.unsafety,
@@ -1005,7 +876,9 @@ pub fn print_method_sig(&mut self,
                       m.abi,
                       Some(name),
                       &m.generics,
-                      vis)
+                      vis,
+                      arg_names,
+                      body_id)
     }
 
     pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
@@ -1014,27 +887,22 @@ pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
         self.maybe_print_comment(ti.span.lo)?;
         self.print_outer_attributes(&ti.attrs)?;
         match ti.node {
-            hir::ConstTraitItem(ref ty, ref default) => {
-                self.print_associated_const(ti.name,
-                                            &ty,
-                                            default.as_ref().map(|expr| &**expr),
-                                            &hir::Inherited)?;
-            }
-            hir::MethodTraitItem(ref sig, ref body) => {
-                if body.is_some() {
-                    self.head("")?;
-                }
-                self.print_method_sig(ti.name, sig, &hir::Inherited)?;
-                if let Some(ref body) = *body {
-                    self.nbsp()?;
-                    self.end()?; // need to close a box
-                    self.end()?; // need to close a box
-                    self.print_expr_id(body)?;
-                } else {
-                    word(&mut self.s, ";")?;
-                }
+            hir::TraitItemKind::Const(ref ty, default) => {
+                self.print_associated_const(ti.name, &ty, default, &hir::Inherited)?;
             }
-            hir::TypeTraitItem(ref bounds, ref default) => {
+            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref arg_names)) => {
+                self.print_method_sig(ti.name, sig, &hir::Inherited, arg_names, None)?;
+                word(&mut self.s, ";")?;
+            }
+            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
+                self.head("")?;
+                self.print_method_sig(ti.name, sig, &hir::Inherited, &[], Some(body))?;
+                self.nbsp()?;
+                self.end()?; // need to close a box
+                self.end()?; // need to close a box
+                self.ann.nested(self, Nested::Body(body))?;
+            }
+            hir::TraitItemKind::Type(ref bounds, ref default) => {
                 self.print_associated_type(ti.name,
                                            Some(bounds),
                                            default.as_ref().map(|ty| &**ty))?;
@@ -1043,16 +911,6 @@ pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
         self.ann.post(self, NodeSubItem(ti.id))
     }
 
-    pub fn print_impl_item_ref(&mut self, item_ref: &hir::ImplItemRef) -> io::Result<()> {
-        if let Some(krate) = self.krate {
-            // skip nested items if krate context was not provided
-            let item = &krate.impl_item(item_ref.id);
-            self.print_impl_item(item)
-        } else {
-            Ok(())
-        }
-    }
-
     pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
         self.ann.pre(self, NodeSubItem(ii.id))?;
         self.hardbreak_if_not_bol()?;
@@ -1065,16 +923,16 @@ pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
         }
 
         match ii.node {
-            hir::ImplItemKind::Const(ref ty, ref expr) => {
-                self.print_associated_const(ii.name, &ty, Some(&expr), &ii.vis)?;
+            hir::ImplItemKind::Const(ref ty, expr) => {
+                self.print_associated_const(ii.name, &ty, Some(expr), &ii.vis)?;
             }
-            hir::ImplItemKind::Method(ref sig, ref body) => {
+            hir::ImplItemKind::Method(ref sig, body) => {
                 self.head("")?;
-                self.print_method_sig(ii.name, sig, &ii.vis)?;
+                self.print_method_sig(ii.name, sig, &ii.vis, &[], Some(body))?;
                 self.nbsp()?;
                 self.end()?; // need to close a box
                 self.end()?; // need to close a box
-                self.print_expr_id(body)?;
+                self.ann.nested(self, Nested::Body(body))?;
             }
             hir::ImplItemKind::Type(ref ty) => {
                 self.print_associated_type(ii.name, None, Some(ty))?;
@@ -1246,12 +1104,12 @@ fn print_expr_vec(&mut self, exprs: &[hir::Expr]) -> io::Result<()> {
         self.end()
     }
 
-    fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::Expr) -> io::Result<()> {
+    fn print_expr_repeat(&mut self, element: &hir::Expr, count: hir::BodyId) -> io::Result<()> {
         self.ibox(indent_unit)?;
         word(&mut self.s, "[")?;
         self.print_expr(element)?;
         self.word_space(";")?;
-        self.print_expr(count)?;
+        self.ann.nested(self, Nested::Body(count))?;
         word(&mut self.s, "]")?;
         self.end()
     }
@@ -1362,8 +1220,8 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
             hir::ExprArray(ref exprs) => {
                 self.print_expr_vec(exprs)?;
             }
-            hir::ExprRepeat(ref element, ref count) => {
-                self.print_expr_repeat(&element, &count)?;
+            hir::ExprRepeat(ref element, count) => {
+                self.print_expr_repeat(&element, count)?;
             }
             hir::ExprStruct(ref qpath, ref fields, ref wth) => {
                 self.print_expr_struct(qpath, &fields[..], wth)?;
@@ -1434,14 +1292,14 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
                 }
                 self.bclose_(expr.span, indent_unit)?;
             }
-            hir::ExprClosure(capture_clause, ref decl, ref body, _fn_decl_span) => {
+            hir::ExprClosure(capture_clause, ref decl, body, _fn_decl_span) => {
                 self.print_capture_clause(capture_clause)?;
 
-                self.print_fn_block_args(&decl)?;
+                self.print_closure_args(&decl, body)?;
                 space(&mut self.s)?;
 
                 // this is a bare expression
-                self.print_expr_id(body)?;
+                self.ann.nested(self, Nested::Body(body))?;
                 self.end()?; // need to close a box
 
                 // a box will be closed by print_expr, but we didn't want an overall
@@ -1615,8 +1473,8 @@ pub fn print_decl(&mut self, decl: &hir::Decl) -> io::Result<()> {
                 }
                 self.end()
             }
-            hir::DeclItem(ref item) => {
-                self.print_item_id(item)
+            hir::DeclItem(item) => {
+                self.ann.nested(self, Nested::Item(item))
             }
         }
     }
@@ -1637,32 +1495,29 @@ pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) -> io::Resu
         self.print_expr(coll)
     }
 
-    fn print_path(&mut self,
-                  path: &hir::Path,
-                  colons_before_params: bool)
-                  -> io::Result<()> {
+    pub fn print_path(&mut self,
+                      path: &hir::Path,
+                      colons_before_params: bool)
+                      -> io::Result<()> {
         self.maybe_print_comment(path.span.lo)?;
 
-        let mut first = !path.global;
-        for segment in &path.segments {
-            if first {
-                first = false
-            } else {
+        for (i, segment) in path.segments.iter().enumerate() {
+            if i > 0 {
                 word(&mut self.s, "::")?
             }
-
-            self.print_name(segment.name)?;
-
-            self.print_path_parameters(&segment.parameters, colons_before_params)?;
+            if segment.name != keywords::CrateRoot.name() && segment.name != "$crate" {
+                self.print_name(segment.name)?;
+                self.print_path_parameters(&segment.parameters, colons_before_params)?;
+            }
         }
 
         Ok(())
     }
 
-    fn print_qpath(&mut self,
-                   qpath: &hir::QPath,
-                   colons_before_params: bool)
-                   -> io::Result<()> {
+    pub fn print_qpath(&mut self,
+                       qpath: &hir::QPath,
+                       colons_before_params: bool)
+                       -> io::Result<()> {
         match *qpath {
             hir::QPath::Resolved(None, ref path) => {
                 self.print_path(path, colons_before_params)
@@ -1673,15 +1528,14 @@ fn print_qpath(&mut self,
                 space(&mut self.s)?;
                 self.word_space("as")?;
 
-                let mut first = !path.global;
-                for segment in &path.segments[..path.segments.len() - 1] {
-                    if first {
-                        first = false
-                    } else {
+                for (i, segment) in path.segments[..path.segments.len() - 1].iter().enumerate() {
+                    if i > 0 {
                         word(&mut self.s, "::")?
                     }
-                    self.print_name(segment.name)?;
-                    self.print_path_parameters(&segment.parameters, colons_before_params)?;
+                    if segment.name != keywords::CrateRoot.name() && segment.name != "$crate" {
+                        self.print_name(segment.name)?;
+                        self.print_path_parameters(&segment.parameters, colons_before_params)?;
+                    }
                 }
 
                 word(&mut self.s, ">")?;
@@ -1958,27 +1812,6 @@ fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> {
         self.end() // close enclosing cbox
     }
 
-    fn print_explicit_self(&mut self, explicit_self: &hir::ExplicitSelf) -> io::Result<()> {
-        match explicit_self.node {
-            SelfKind::Value(m) => {
-                self.print_mutability(m)?;
-                word(&mut self.s, "self")
-            }
-            SelfKind::Region(ref lt, m) => {
-                word(&mut self.s, "&")?;
-                self.print_opt_lifetime(lt)?;
-                self.print_mutability(m)?;
-                word(&mut self.s, "self")
-            }
-            SelfKind::Explicit(ref typ, m) => {
-                self.print_mutability(m)?;
-                word(&mut self.s, "self")?;
-                self.word_space(":")?;
-                self.print_type(&typ)
-            }
-        }
-    }
-
     pub fn print_fn(&mut self,
                     decl: &hir::FnDecl,
                     unsafety: hir::Unsafety,
@@ -1986,7 +1819,9 @@ pub fn print_fn(&mut self,
                     abi: Abi,
                     name: Option<ast::Name>,
                     generics: &hir::Generics,
-                    vis: &hir::Visibility)
+                    vis: &hir::Visibility,
+                    arg_names: &[Spanned<ast::Name>],
+                    body_id: Option<hir::BodyId>)
                     -> io::Result<()> {
         self.print_fn_header_info(unsafety, constness, abi, vis)?;
 
@@ -1995,24 +1830,51 @@ pub fn print_fn(&mut self,
             self.print_name(name)?;
         }
         self.print_generics(generics)?;
-        self.print_fn_args_and_ret(decl)?;
-        self.print_where_clause(&generics.where_clause)
-    }
 
-    pub fn print_fn_args_and_ret(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
         self.popen()?;
-        self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))?;
+        let mut i = 0;
+        // Make sure we aren't supplied *both* `arg_names` and `body_id`.
+        assert!(arg_names.is_empty() || body_id.is_none());
+        self.commasep(Inconsistent, &decl.inputs, |s, ty| {
+            s.ibox(indent_unit)?;
+            if let Some(name) = arg_names.get(i) {
+                word(&mut s.s, &name.node.as_str())?;
+                word(&mut s.s, ":")?;
+                space(&mut s.s)?;
+            } else if let Some(body_id) = body_id {
+                s.ann.nested(s, Nested::BodyArgPat(body_id, i))?;
+                word(&mut s.s, ":")?;
+                space(&mut s.s)?;
+            }
+            i += 1;
+            s.print_type(ty)?;
+            s.end()
+        })?;
         if decl.variadic {
             word(&mut self.s, ", ...")?;
         }
         self.pclose()?;
 
-        self.print_fn_output(decl)
+        self.print_fn_output(decl)?;
+        self.print_where_clause(&generics.where_clause)
     }
 
-    pub fn print_fn_block_args(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
+    fn print_closure_args(&mut self, decl: &hir::FnDecl, body_id: hir::BodyId) -> io::Result<()> {
         word(&mut self.s, "|")?;
-        self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true))?;
+        let mut i = 0;
+        self.commasep(Inconsistent, &decl.inputs, |s, ty| {
+            s.ibox(indent_unit)?;
+
+            s.ann.nested(s, Nested::BodyArgPat(body_id, i))?;
+            i += 1;
+
+            if ty.node != hir::TyInfer {
+                word(&mut s.s, ":")?;
+                space(&mut s.s)?;
+                s.print_type(ty)?;
+            }
+            s.end()
+        })?;
         word(&mut self.s, "|")?;
 
         if let hir::DefaultReturn(..) = decl.output {
@@ -2184,31 +2046,6 @@ pub fn print_mt(&mut self, mt: &hir::MutTy) -> io::Result<()> {
         self.print_type(&mt.ty)
     }
 
-    pub fn print_arg(&mut self, input: &hir::Arg, is_closure: bool) -> io::Result<()> {
-        self.ibox(indent_unit)?;
-        match input.ty.node {
-            hir::TyInfer if is_closure => self.print_pat(&input.pat)?,
-            _ => {
-                if let Some(eself) = input.to_self() {
-                    self.print_explicit_self(&eself)?;
-                } else {
-                    let invalid = if let PatKind::Binding(_, _, name, _) = input.pat.node {
-                        name.node == keywords::Invalid.name()
-                    } else {
-                        false
-                    };
-                    if !invalid {
-                        self.print_pat(&input.pat)?;
-                        word(&mut self.s, ":")?;
-                        space(&mut self.s)?;
-                    }
-                    self.print_type(&input.ty)?;
-                }
-            }
-        }
-        self.end()
-    }
-
     pub fn print_fn_output(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
         if let hir::DefaultReturn(..) = decl.output {
             return Ok(());
@@ -2256,7 +2093,9 @@ pub fn print_ty_fn(&mut self,
                       abi,
                       name,
                       &generics,
-                      &hir::Inherited)?;
+                      &hir::Inherited,
+                      &[],
+                      None)?;
         self.end()
     }
 
index 90d752ae6ee297db8100658c6e236c59739d0b4c..9ff7dcc7d58835beaface33b9cf59205fda0a0b6 100644 (file)
@@ -75,7 +75,6 @@
 
 use hir::map as ast_map;
 use hir;
-use hir::print as pprust;
 
 use lint;
 use hir::def::Def;
@@ -1051,8 +1050,8 @@ fn give_suggestion(&self, err: &mut DiagnosticBuilder, same_regions: &[SameRegio
             Some(ref node) => match *node {
                 ast_map::NodeItem(ref item) => {
                     match item.node {
-                        hir::ItemFn(ref fn_decl, unsafety, constness, _, ref gen, _) => {
-                            Some((fn_decl, gen, unsafety, constness, item.name, item.span))
+                        hir::ItemFn(ref fn_decl, unsafety, constness, _, ref gen, body) => {
+                            Some((fn_decl, gen, unsafety, constness, item.name, item.span, body))
                         }
                         _ => None,
                     }
@@ -1066,26 +1065,28 @@ fn give_suggestion(&self, err: &mut DiagnosticBuilder, same_regions: &[SameRegio
                             return;
                         }
                     }
-                    if let hir::ImplItemKind::Method(ref sig, _) = item.node {
+                    if let hir::ImplItemKind::Method(ref sig, body) = item.node {
                         Some((&sig.decl,
                               &sig.generics,
                               sig.unsafety,
                               sig.constness,
                               item.name,
-                              item.span))
+                              item.span,
+                              body))
                     } else {
                         None
                     }
                 },
                 ast_map::NodeTraitItem(item) => {
                     match item.node {
-                        hir::MethodTraitItem(ref sig, Some(_)) => {
+                        hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
                             Some((&sig.decl,
                                   &sig.generics,
                                   sig.unsafety,
                                   sig.constness,
                                   item.name,
-                                  item.span))
+                                  item.span,
+                                  body))
                         }
                         _ => None,
                     }
@@ -1094,12 +1095,12 @@ fn give_suggestion(&self, err: &mut DiagnosticBuilder, same_regions: &[SameRegio
             },
             None => None,
         };
-        let (fn_decl, generics, unsafety, constness, name, span)
+        let (fn_decl, generics, unsafety, constness, name, span, body)
                                     = node_inner.expect("expect item fn");
         let rebuilder = Rebuilder::new(self.tcx, fn_decl, generics, same_regions, &life_giver);
         let (fn_decl, generics) = rebuilder.rebuild();
         self.give_expl_lifetime_param(
-            err, &fn_decl, unsafety, constness, name, &generics, span);
+            err, &fn_decl, unsafety, constness, name, &generics, span, body);
     }
 
     pub fn issue_32330_warnings(&self, span: Span, issue32330s: &[ty::Issue32330]) {
@@ -1375,23 +1376,14 @@ fn rebuild_generics(&self,
     }
 
     fn rebuild_args_ty(&self,
-                       inputs: &[hir::Arg],
+                       inputs: &[P<hir::Ty>],
                        lifetime: hir::Lifetime,
                        anon_nums: &HashSet<u32>,
                        region_names: &HashSet<ast::Name>)
-                       -> hir::HirVec<hir::Arg> {
-        let mut new_inputs = Vec::new();
-        for arg in inputs {
-            let new_ty = self.rebuild_arg_ty_or_output(&arg.ty, lifetime,
-                                                       anon_nums, region_names);
-            let possibly_new_arg = hir::Arg {
-                ty: new_ty,
-                pat: arg.pat.clone(),
-                id: arg.id
-            };
-            new_inputs.push(possibly_new_arg);
-        }
-        new_inputs.into()
+                       -> hir::HirVec<P<hir::Ty>> {
+        inputs.iter().map(|arg_ty| {
+            self.rebuild_arg_ty_or_output(arg_ty, lifetime, anon_nums, region_names)
+        }).collect()
     }
 
     fn rebuild_output(&self, ty: &hir::FunctionRetTy,
@@ -1620,7 +1612,6 @@ fn rebuild_path(&self,
         new_segs.push(new_seg);
         hir::Path {
             span: path.span,
-            global: path.global,
             def: path.def,
             segments: new_segs.into()
         }
@@ -1635,10 +1626,26 @@ fn give_expl_lifetime_param(&self,
                                 constness: hir::Constness,
                                 name: ast::Name,
                                 generics: &hir::Generics,
-                                span: Span) {
-        let suggested_fn = pprust::fun_to_string(decl, unsafety, constness, name, generics);
-        let msg = format!("consider using an explicit lifetime \
-                           parameter as shown: {}", suggested_fn);
+                                span: Span,
+                                body: hir::BodyId) {
+        let s = hir::print::to_string(&self.tcx.map, |s| {
+            use syntax::abi::Abi;
+            use syntax::print::pprust::PrintState;
+
+            s.head("")?;
+            s.print_fn(decl,
+                       unsafety,
+                       constness,
+                       Abi::Rust,
+                       Some(name),
+                       generics,
+                       &hir::Inherited,
+                       &[],
+                       Some(body))?;
+            s.end()?; // Close the head box
+            s.end()   // Close the outer box
+        });
+        let msg = format!("consider using an explicit lifetime parameter as shown: {}", s);
         err.span_help(span, &msg[..]);
     }
 
index 17cc34fcd839414b36e8445bbf91d2dac34515c1..efe855f0a39e9c84af006a7ed2e4a7b7115abf0f 100644 (file)
@@ -30,9 +30,9 @@
 #![feature(conservative_impl_trait)]
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
-#![cfg_attr(stage0, feature(item_like_imports))]
 #![feature(libc)]
 #![feature(nonzero)]
+#![feature(pub_restricted)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
@@ -80,9 +80,8 @@
 
 pub mod middle {
     pub mod astconv_util;
-    pub mod expr_use_visitor; // STAGE0: increase glitch immunity
+    pub mod expr_use_visitor;
     pub mod const_val;
-    pub mod const_qualif;
     pub mod cstore;
     pub mod dataflow;
     pub mod dead;
index 3ff2abac277b580fc14e66990ff1338a6fc45d53..cce79820ca8da5bea21811b57aca1cb4e50004e7 100644 (file)
@@ -821,6 +821,7 @@ fn visit_expr(&mut self, e: &'tcx hir::Expr) {
         self.with_lint_attrs(&e.attrs, |cx| {
             run_lints!(cx, check_expr, late_passes, e);
             hir_visit::walk_expr(cx, e);
+            run_lints!(cx, check_expr_post, late_passes, e);
         })
     }
 
@@ -835,8 +836,8 @@ fn visit_stmt(&mut self, s: &'tcx hir::Stmt) {
     }
 
     fn visit_fn(&mut self, fk: hir_visit::FnKind<'tcx>, decl: &'tcx hir::FnDecl,
-                body_id: hir::ExprId, span: Span, id: ast::NodeId) {
-        let body = self.tcx.map.expr(body_id);
+                body_id: hir::BodyId, span: Span, id: ast::NodeId) {
+        let body = self.tcx.map.body(body_id);
         run_lints!(self, check_fn, late_passes, fk, decl, body, span, id);
         hir_visit::walk_fn(self, fk, decl, body_id, span, id);
         run_lints!(self, check_fn_post, late_passes, fk, decl, body, span, id);
@@ -909,10 +910,6 @@ fn visit_decl(&mut self, d: &'tcx hir::Decl) {
         hir_visit::walk_decl(self, d);
     }
 
-    fn visit_expr_post(&mut self, e: &'tcx hir::Expr) {
-        run_lints!(self, check_expr_post, late_passes, e);
-    }
-
     fn visit_generics(&mut self, g: &'tcx hir::Generics) {
         run_lints!(self, check_generics, late_passes, g);
         hir_visit::walk_generics(self, g);
index ccf53f01cd5323112bfe2b3e9d21bde83ef65e58..7e0da00694c4a4280aa5722d0122f6f9fe8286ea 100644 (file)
@@ -162,14 +162,14 @@ fn check_fn(&mut self,
                 _: &LateContext<'a, 'tcx>,
                 _: FnKind<'tcx>,
                 _: &'tcx hir::FnDecl,
-                _: &'tcx hir::Expr,
+                _: &'tcx hir::Body,
                 _: Span,
                 _: ast::NodeId) { }
     fn check_fn_post(&mut self,
                      _: &LateContext<'a, 'tcx>,
                      _: FnKind<'tcx>,
                      _: &'tcx hir::FnDecl,
-                     _: &'tcx hir::Expr,
+                     _: &'tcx hir::Body,
                      _: Span,
                      _: ast::NodeId) { }
     fn check_trait_item(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::TraitItem) { }
diff --git a/src/librustc/middle/const_qualif.rs b/src/librustc/middle/const_qualif.rs
deleted file mode 100644 (file)
index ec98637..0000000
+++ /dev/null
@@ -1,44 +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.
-
-// Const qualification, from partial to completely promotable.
-bitflags! {
-    #[derive(RustcEncodable, RustcDecodable)]
-    flags ConstQualif: u8 {
-        // Inner mutability (can not be placed behind a reference) or behind
-        // &mut in a non-global expression. Can be copied from static memory.
-        const MUTABLE_MEM        = 1 << 0,
-        // Constant value with a type that implements Drop. Can be copied
-        // from static memory, similar to MUTABLE_MEM.
-        const NEEDS_DROP         = 1 << 1,
-        // Even if the value can be placed in static memory, copying it from
-        // there is more expensive than in-place instantiation, and/or it may
-        // be too large. This applies to [T; N] and everything containing it.
-        // N.B.: references need to clear this flag to not end up on the stack.
-        const PREFER_IN_PLACE    = 1 << 2,
-        // May use more than 0 bytes of memory, doesn't impact the constness
-        // directly, but is not allowed to be borrowed mutably in a constant.
-        const NON_ZERO_SIZED     = 1 << 3,
-        // Actually borrowed, has to always be in static memory. Does not
-        // propagate, and requires the expression to behave like a 'static
-        // lvalue. The set of expressions with this flag is the minimum
-        // that have to be promoted.
-        const HAS_STATIC_BORROWS = 1 << 4,
-        // Invalid const for miscellaneous reasons (e.g. not implemented).
-        const NOT_CONST          = 1 << 5,
-
-        // Borrowing the expression won't produce &'static T if any of these
-        // bits are set, though the value could be copied from static memory
-        // if `NOT_CONST` isn't set.
-        const NON_STATIC_BORROWS = ConstQualif::MUTABLE_MEM.bits |
-                                   ConstQualif::NEEDS_DROP.bits |
-                                   ConstQualif::NOT_CONST.bits
-    }
-}
index 9f9c6fd87aa856f590c83daa3d5c46a0198be2e9..7151e5226cab0cb3f365d3b8a63d07af06706403 100644 (file)
 use session::Session;
 use session::search_paths::PathKind;
 use util::nodemap::{NodeSet, DefIdMap};
+
+use std::collections::BTreeMap;
 use std::path::PathBuf;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::attr;
 use syntax::ext::base::SyntaxExtension;
-use syntax::ptr::P;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
 use rustc_back::target::Target;
 use hir;
-use hir::intravisit::Visitor;
 use rustc_back::PanicStrategy;
 
 pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown};
@@ -134,102 +134,6 @@ pub struct NativeLibrary {
     pub foreign_items: Vec<DefIndex>,
 }
 
-/// The data we save and restore about an inlined item or method.  This is not
-/// part of the AST that we parse from a file, but it becomes part of the tree
-/// that we trans.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct InlinedItem {
-    pub def_id: DefId,
-    pub body: P<hir::Expr>,
-    pub const_fn_args: Vec<Option<DefId>>,
-}
-
-/// A borrowed version of `hir::InlinedItem`. This is what's encoded when saving
-/// a crate; it then gets read as an InlinedItem.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, Hash, Debug)]
-pub struct InlinedItemRef<'a> {
-    pub def_id: DefId,
-    pub body: &'a hir::Expr,
-    pub const_fn_args: Vec<Option<DefId>>,
-}
-
-fn get_fn_args(decl: &hir::FnDecl) -> Vec<Option<DefId>> {
-    decl.inputs.iter().map(|arg| match arg.pat.node {
-        hir::PatKind::Binding(_, def_id, _, _) => Some(def_id),
-        _ => None
-    }).collect()
-}
-
-impl<'a> InlinedItemRef<'a> {
-    pub fn from_item<'b, 'tcx>(def_id: DefId,
-                               item: &'a hir::Item,
-                               tcx: TyCtxt<'b, 'a, 'tcx>)
-                               -> InlinedItemRef<'a> {
-        let (body, args) = match item.node {
-            hir::ItemFn(ref decl, _, _, _, _, body_id) =>
-                (tcx.map.expr(body_id), get_fn_args(decl)),
-            hir::ItemConst(_, ref body) => (&**body, Vec::new()),
-            _ => bug!("InlinedItemRef::from_item wrong kind")
-        };
-        InlinedItemRef {
-            def_id: def_id,
-            body: body,
-            const_fn_args: args
-        }
-    }
-
-    pub fn from_trait_item(def_id: DefId,
-                           item: &'a hir::TraitItem,
-                           _tcx: TyCtxt)
-                           -> InlinedItemRef<'a> {
-        let (body, args) = match item.node {
-            hir::ConstTraitItem(_, Some(ref body)) =>
-                (&**body, Vec::new()),
-            hir::ConstTraitItem(_, None) => {
-                bug!("InlinedItemRef::from_trait_item called for const without body")
-            },
-            _ => bug!("InlinedItemRef::from_trait_item wrong kind")
-        };
-        InlinedItemRef {
-            def_id: def_id,
-            body: body,
-            const_fn_args: args
-        }
-    }
-
-    pub fn from_impl_item<'b, 'tcx>(def_id: DefId,
-                                    item: &'a hir::ImplItem,
-                                    tcx: TyCtxt<'b, 'a, 'tcx>)
-                                    -> InlinedItemRef<'a> {
-        let (body, args) = match item.node {
-            hir::ImplItemKind::Method(ref sig, body_id) =>
-                (tcx.map.expr(body_id), get_fn_args(&sig.decl)),
-            hir::ImplItemKind::Const(_, ref body) =>
-                (&**body, Vec::new()),
-            _ => bug!("InlinedItemRef::from_impl_item wrong kind")
-        };
-        InlinedItemRef {
-            def_id: def_id,
-            body: body,
-            const_fn_args: args
-        }
-    }
-
-    pub fn visit<V>(&self, visitor: &mut V)
-        where V: Visitor<'a>
-    {
-        visitor.visit_expr(&self.body);
-    }
-}
-
-impl InlinedItem {
-    pub fn visit<'ast,V>(&'ast self, visitor: &mut V)
-        where V: Visitor<'ast>
-    {
-        visitor.visit_expr(&self.body);
-    }
-}
-
 pub enum LoadedMacro {
     MacroRules(ast::MacroDef),
     ProcMacro(Rc<SyntaxExtension>),
@@ -298,8 +202,7 @@ fn custom_coerce_unsized_kind(&self, def: DefId)
 
     // trait/impl-item info
     fn trait_of_item(&self, def_id: DefId) -> Option<DefId>;
-    fn associated_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                           -> Option<ty::AssociatedItem>;
+    fn associated_item(&self, def: DefId) -> Option<ty::AssociatedItem>;
 
     // flags
     fn is_const_fn(&self, did: DefId) -> bool;
@@ -347,10 +250,10 @@ fn retrace_path(&self,
     fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro;
 
     // misc. metadata
-    fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                              -> Option<(&'tcx InlinedItem, ast::NodeId)>;
-    fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId>;
-    fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId>;
+    fn maybe_get_item_body<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
+                               -> Option<&'tcx hir::Body>;
+    fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap<hir::BodyId, hir::Body>;
+    fn const_is_rvalue_promotable_to_static(&self, def: DefId) -> bool;
 
     fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Mir<'tcx>;
     fn is_item_mir_available(&self, def: DefId) -> bool;
@@ -456,8 +359,7 @@ 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<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                           -> Option<ty::AssociatedItem> { bug!("associated_item") }
+    fn associated_item(&self, def: DefId) -> Option<ty::AssociatedItem> { bug!("associated_item") }
 
     // flags
     fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") }
@@ -518,15 +420,15 @@ fn item_children(&self, did: DefId) -> Vec<def::Export> { bug!("item_children")
     fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") }
 
     // misc. metadata
-    fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                              -> Option<(&'tcx InlinedItem, ast::NodeId)> {
-        bug!("maybe_get_item_ast")
+    fn maybe_get_item_body<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
+                               -> Option<&'tcx hir::Body> {
+        bug!("maybe_get_item_body")
     }
-    fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId> {
-        bug!("local_node_for_inlined_defid")
+    fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap<hir::BodyId, hir::Body> {
+        bug!("item_body_nested_bodies")
     }
-    fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId> {
-        bug!("defid_for_inlined_node")
+    fn const_is_rvalue_promotable_to_static(&self, def: DefId) -> bool {
+        bug!("const_is_rvalue_promotable_to_static")
     }
 
     fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
index f7a34c43cccbd8335afcbd0dfd85a655e16cd5f4..dfcb5cb7b79fee81b4c21224ba1c0ed9c77f7c8d 100644 (file)
@@ -108,6 +108,9 @@ fn has_bitset_for_nodeid(&self, n: ast::NodeId) -> bool {
 }
 
 impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O> {
+    fn nested(&self, state: &mut pprust::State, nested: pprust::Nested) -> io::Result<()> {
+        pprust::PpAnn::nested(&self.tcx.map, state, nested)
+    }
     fn pre(&self,
            ps: &mut pprust::State,
            node: pprust::AnnNode) -> io::Result<()> {
@@ -160,7 +163,7 @@ fn pre(&self,
     }
 }
 
-fn build_nodeid_to_index(decl: Option<&hir::FnDecl>,
+fn build_nodeid_to_index(body: Option<&hir::Body>,
                          cfg: &cfg::CFG) -> NodeMap<Vec<CFGIndex>> {
     let mut index = NodeMap();
 
@@ -168,8 +171,8 @@ fn build_nodeid_to_index(decl: Option<&hir::FnDecl>,
     // into cfg itself?  i.e. introduce a fn-based flow-graph in
     // addition to the current block-based flow-graph, rather than
     // have to put traversals like this here?
-    if let Some(decl) = decl {
-        add_entries_from_fn_decl(&mut index, decl, cfg.entry);
+    if let Some(body) = body {
+        add_entries_from_fn_body(&mut index, body, cfg.entry);
     }
 
     cfg.graph.each_node(|node_idx, node| {
@@ -181,20 +184,24 @@ fn build_nodeid_to_index(decl: Option<&hir::FnDecl>,
 
     return index;
 
-    fn add_entries_from_fn_decl(index: &mut NodeMap<Vec<CFGIndex>>,
-                                decl: &hir::FnDecl,
+    /// Add mappings from the ast nodes for the formal bindings to
+    /// the entry-node in the graph.
+    fn add_entries_from_fn_body(index: &mut NodeMap<Vec<CFGIndex>>,
+                                body: &hir::Body,
                                 entry: CFGIndex) {
-        //! add mappings from the ast nodes for the formal bindings to
-        //! the entry-node in the graph.
+        use hir::intravisit::Visitor;
+
         struct Formals<'a> {
             entry: CFGIndex,
             index: &'a mut NodeMap<Vec<CFGIndex>>,
         }
         let mut formals = Formals { entry: entry, index: index };
-        intravisit::walk_fn_decl(&mut formals, decl);
-        impl<'a, 'v> intravisit::Visitor<'v> for Formals<'a> {
+        for arg in &body.arguments {
+            formals.visit_pat(&arg.pat);
+        }
+        impl<'a, 'v> Visitor<'v> for Formals<'a> {
             fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'v> {
-                panic!("should not encounter fn bodies or items")
+                intravisit::NestedVisitorMap::None
             }
 
             fn visit_pat(&mut self, p: &hir::Pat) {
@@ -227,7 +234,7 @@ pub enum KillFrom {
 impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
     pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                analysis_name: &'static str,
-               decl: Option<&hir::FnDecl>,
+               body: Option<&hir::Body>,
                cfg: &cfg::CFG,
                oper: O,
                id_range: IdRange,
@@ -250,7 +257,7 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let kills2 = zeroes;
         let on_entry = vec![entry; num_nodes * words_per_id];
 
-        let nodeid_to_index = build_nodeid_to_index(decl, cfg);
+        let nodeid_to_index = build_nodeid_to_index(body, cfg);
 
         DataFlowContext {
             tcx: tcx,
@@ -502,7 +509,7 @@ pub fn add_kills_from_flow_exits(&mut self, cfg: &cfg::CFG) {
 
 impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> {
 //                                ^^^^^^^^^^^^^ only needed for pretty printing
-    pub fn propagate(&mut self, cfg: &cfg::CFG, body: &hir::Expr) {
+    pub fn propagate(&mut self, cfg: &cfg::CFG, body: &hir::Body) {
         //! Performs the data flow analysis.
 
         if self.bits_per_id == 0 {
@@ -526,20 +533,11 @@ pub fn propagate(&mut self, cfg: &cfg::CFG, body: &hir::Expr) {
         }
 
         debug!("Dataflow result for {}:", self.analysis_name);
-        debug!("{}", {
-            let mut v = Vec::new();
-            self.pretty_print_to(box &mut v, body).unwrap();
-            String::from_utf8(v).unwrap()
-        });
-    }
-
-    fn pretty_print_to<'b>(&self, wr: Box<io::Write + 'b>,
-                           body: &hir::Expr) -> io::Result<()> {
-        let mut ps = pprust::rust_printer_annotated(wr, self, None);
-        ps.cbox(pprust::indent_unit)?;
-        ps.ibox(0)?;
-        ps.print_expr(body)?;
-        pp::eof(&mut ps.s)
+        debug!("{}", pprust::to_string(self, |s| {
+            s.cbox(pprust::indent_unit)?;
+            s.ibox(0)?;
+            s.print_expr(&body.value)
+        }));
     }
 }
 
index 1c5dd97b74bd332c2b5854116df34f5910c34649..76adee4e00c15684ec411deddddf5daa2232cb45 100644 (file)
@@ -328,11 +328,12 @@ fn visit_item(&mut self, item: &hir::Item) {
                 self.worklist.extend(enum_def.variants.iter()
                                                       .map(|variant| variant.node.data.id()));
             }
-            hir::ItemTrait(.., ref trait_items) => {
-                for trait_item in trait_items {
+            hir::ItemTrait(.., ref trait_item_refs) => {
+                for trait_item_ref in trait_item_refs {
+                    let trait_item = self.krate.trait_item(trait_item_ref.id);
                     match trait_item.node {
-                        hir::ConstTraitItem(_, Some(_)) |
-                        hir::MethodTraitItem(_, Some(_)) => {
+                        hir::TraitItemKind::Const(_, Some(_)) |
+                        hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => {
                             if has_allow_dead_code_or_lang_attr(&trait_item.attrs) {
                                 self.worklist.push(trait_item.id);
                             }
@@ -354,6 +355,10 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _item: &hir::TraitItem) {
+        // ignore: we are handling this in `visit_item` above
+    }
+
     fn visit_impl_item(&mut self, _item: &hir::ImplItem) {
         // ignore: we are handling this in `visit_item` above
     }
@@ -546,19 +551,19 @@ fn visit_struct_field(&mut self, field: &'tcx hir::StructField) {
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
         match impl_item.node {
-            hir::ImplItemKind::Const(_, ref expr) => {
+            hir::ImplItemKind::Const(_, body_id) => {
                 if !self.symbol_is_live(impl_item.id, None) {
                     self.warn_dead_code(impl_item.id, impl_item.span,
                                         impl_item.name, "associated const");
                 }
-                intravisit::walk_expr(self, expr)
+                self.visit_nested_body(body_id)
             }
             hir::ImplItemKind::Method(_, body_id) => {
                 if !self.symbol_is_live(impl_item.id, None) {
                     self.warn_dead_code(impl_item.id, impl_item.span,
                                         impl_item.name, "method");
                 }
-                self.visit_body(body_id)
+                self.visit_nested_body(body_id)
             }
             hir::ImplItemKind::Type(..) => {}
         }
@@ -567,15 +572,13 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
     // Overwrite so that we don't warn the trait item itself.
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
         match trait_item.node {
-            hir::ConstTraitItem(_, Some(ref body)) => {
-                intravisit::walk_expr(self, body)
-            }
-            hir::MethodTraitItem(_, Some(body_id)) => {
-                self.visit_body(body_id)
+            hir::TraitItemKind::Const(_, Some(body_id)) |
+            hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => {
+                self.visit_nested_body(body_id)
             }
-            hir::ConstTraitItem(_, None) |
-            hir::MethodTraitItem(_, None) |
-            hir::TypeTraitItem(..) => {}
+            hir::TraitItemKind::Const(_, None) |
+            hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) |
+            hir::TraitItemKind::Type(..) => {}
         }
     }
 }
index 075b3d7a8e90c9e2588bac8f87a5d7dc0f175e75..e60d0533c9f8166be71f6991e22e84c36a43ab71 100644 (file)
@@ -103,6 +103,10 @@ pub fn calculate(sess: &session::Session) {
 
 fn calculate_type(sess: &session::Session,
                   ty: config::CrateType) -> DependencyList {
+    if !sess.opts.output_types.should_trans() {
+        return Vec::new();
+    }
+
     match ty {
         // If the global prefer_dynamic switch is turned off, first attempt
         // static linkage (this can fail).
@@ -114,7 +118,7 @@ fn calculate_type(sess: &session::Session,
 
         // No linkage happens with rlibs, we just needed the metadata (which we
         // got long ago), so don't bother with anything.
-        config::CrateTypeRlib | config::CrateTypeMetadata => return Vec::new(),
+        config::CrateTypeRlib => return Vec::new(),
 
         // Staticlibs and cdylibs must have all static dependencies. If any fail
         // to be found, we generate some nice pretty errors.
index 2ec7aa4c4d9031c316c0ac37d3557008203de98f..38b0b18b0129af7b7c6263505c85740c9d131eb3 100644 (file)
@@ -98,7 +98,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     }
 
     fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, fn_decl: &'tcx hir::FnDecl,
-                body_id: hir::ExprId, span: Span, id: ast::NodeId) {
+                body_id: hir::BodyId, span: Span, id: ast::NodeId) {
 
         let (is_item_fn, is_unsafe_fn) = match fn_kind {
             FnKind::ItemFn(_, _, unsafety, ..) =>
index e927843a984b8c351a307ca2e625d4ba69f831bf..f2e46d4cbc96ba6c0831179db41b23e66e51fd29 100644 (file)
@@ -17,7 +17,7 @@
 use syntax::attr;
 use syntax::entry::EntryPointType;
 use syntax_pos::Span;
-use hir::{Item, ItemFn, ImplItem};
+use hir::{Item, ItemFn, ImplItem, TraitItem};
 use hir::itemlikevisit::ItemLikeVisitor;
 
 struct EntryContext<'a, 'tcx: 'a> {
@@ -47,6 +47,9 @@ fn visit_item(&mut self, item: &'tcx Item) {
         find_item(item, self, at_root);
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &'tcx TraitItem) {
+        // entry fn is never a trait item
+    }
 
     fn visit_impl_item(&mut self, _impl_item: &'tcx ImplItem) {
         // entry fn is never an impl item
index b3e61f1e5706772c1eeffc77f0c19c3d9fa6c399..a3a49c916338e544a047bcd6b14f5fb819e2d066 100644 (file)
@@ -287,20 +287,11 @@ pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a),
         }
     }
 
-    pub fn walk_fn(&mut self,
-                   decl: &hir::FnDecl,
-                   body: &hir::Expr) {
-        self.walk_arg_patterns(decl, body);
-        self.consume_expr(body);
-    }
-
-    fn walk_arg_patterns(&mut self,
-                         decl: &hir::FnDecl,
-                         body: &hir::Expr) {
-        for arg in &decl.inputs {
+    pub fn consume_body(&mut self, body: &hir::Body) {
+        for arg in &body.arguments {
             let arg_ty = return_if_err!(self.mc.infcx.node_ty(arg.pat.id));
 
-            let fn_body_scope_r = self.tcx().node_scope_region(body.id);
+            let fn_body_scope_r = self.tcx().node_scope_region(body.value.id);
             let arg_cmt = self.mc.cat_rvalue(
                 arg.id,
                 arg.pat.span,
@@ -309,6 +300,8 @@ fn walk_arg_patterns(&mut self,
 
             self.walk_irrefutable_pat(arg_cmt, &arg.pat);
         }
+
+        self.consume_expr(&body.value);
     }
 
     fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
@@ -537,9 +530,8 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) {
                 }
             }
 
-            hir::ExprRepeat(ref base, ref count) => {
+            hir::ExprRepeat(ref base, _) => {
                 self.consume_expr(&base);
-                self.consume_expr(&count);
             }
 
             hir::ExprClosure(.., fn_decl_span) => {
index 2357549c82e081fedfaea3737221985ebe01a904..d932061d42d3db4984f56ee62c9373873398416d 100644 (file)
@@ -34,13 +34,13 @@ struct ItemVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> ItemVisitor<'a, 'tcx> {
-    fn visit_const(&mut self, item_id: ast::NodeId, expr: &'tcx hir::Expr) {
+    fn visit_const(&mut self, item_id: ast::NodeId, body: hir::BodyId) {
         let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id);
         self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| {
             let mut visitor = ExprVisitor {
                 infcx: &infcx
             };
-            visitor.visit_expr(expr);
+            visitor.visit_nested_body(body);
         });
     }
 }
@@ -122,33 +122,33 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     }
 
     // const, static and N in [T; N].
-    fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
+    fn visit_body(&mut self, body: &'tcx hir::Body) {
         self.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
             let mut visitor = ExprVisitor {
                 infcx: &infcx
             };
-            visitor.visit_expr(expr);
+            visitor.visit_body(body);
         });
     }
 
     fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
-        if let hir::ConstTraitItem(_, Some(ref expr)) = item.node {
-            self.visit_const(item.id, expr);
+        if let hir::TraitItemKind::Const(_, Some(body)) = item.node {
+            self.visit_const(item.id, body);
         } else {
             intravisit::walk_trait_item(self, item);
         }
     }
 
     fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
-        if let hir::ImplItemKind::Const(_, ref expr) = item.node {
-            self.visit_const(item.id, expr);
+        if let hir::ImplItemKind::Const(_, body) = item.node {
+            self.visit_const(item.id, body);
         } else {
             intravisit::walk_impl_item(self, item);
         }
     }
 
     fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
-                b: hir::ExprId, s: Span, id: ast::NodeId) {
+                b: hir::BodyId, s: Span, id: ast::NodeId) {
         if let FnKind::Closure(..) = fk {
             span_bug!(s, "intrinsicck: closure outside of function")
         }
index 1efc211b8c35be608b29cfd05cf2b103c67607bc..4cae5b370eb7eb77ee603a62c373ccf456dafe60 100644 (file)
@@ -140,6 +140,10 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+        // at present, lang items are always items, not trait items
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
         // at present, lang items are always items, not impl items
     }
@@ -328,7 +332,6 @@ pub fn collect_language_items(session: &Session,
     PanicFmtLangItem,                "panic_fmt",               panic_fmt;
 
     ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
-    ExchangeFreeFnLangItem,          "exchange_free",           exchange_free_fn;
     BoxFreeFnLangItem,               "box_free",                box_free_fn;
     StrDupUniqFnLangItem,            "strdup_uniq",             strdup_uniq_fn;
 
index 445aed8f97d600fe3eeb547b24d2ca96e008d3ee..745a94a5ddba31cd6cafc49f1d240872ef5d9511 100644 (file)
 
 use hir::Expr;
 use hir;
-use hir::print::{expr_to_string, block_to_string};
 use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
 
 /// For use with `propagate_through_loop`.
@@ -188,7 +187,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     }
 
     fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
-                b: hir::ExprId, s: Span, id: NodeId) {
+                b: hir::BodyId, s: Span, id: NodeId) {
         visit_fn(self, fk, fd, b, s, id);
     }
     fn visit_local(&mut self, l: &'tcx hir::Local) { visit_local(self, l); }
@@ -354,13 +353,9 @@ fn lnk(&self, ln: LiveNode) -> LiveNodeKind {
 
 impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::OnlyBodies(&self.ir.tcx.map)
+        NestedVisitorMap::None
     }
 
-    fn visit_fn(&mut self, _: FnKind<'tcx>, _: &'tcx hir::FnDecl,
-                _: hir::ExprId, _: Span, _: NodeId) {
-        // do not check contents of nested fns
-    }
     fn visit_local(&mut self, l: &'tcx hir::Local) {
         check_local(self, l);
     }
@@ -375,7 +370,7 @@ fn visit_arm(&mut self, a: &'tcx hir::Arm) {
 fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
                           fk: FnKind<'tcx>,
                           decl: &'tcx hir::FnDecl,
-                          body_id: hir::ExprId,
+                          body_id: hir::BodyId,
                           sp: Span,
                           id: ast::NodeId) {
     debug!("visit_fn");
@@ -385,7 +380,9 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
 
     debug!("creating fn_maps: {:?}", &fn_maps as *const IrMaps);
 
-    for arg in &decl.inputs {
+    let body = ir.tcx.map.body(body_id);
+
+    for arg in &body.arguments {
         arg.pat.each_binding(|_bm, arg_id, _x, path1| {
             debug!("adding argument {}", arg_id);
             let name = path1.node;
@@ -408,16 +405,14 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
         clean_exit_var: fn_maps.add_variable(CleanExit)
     };
 
-    let body = ir.tcx.map.expr(body_id);
-
     // compute liveness
     let mut lsets = Liveness::new(&mut fn_maps, specials);
-    let entry_ln = lsets.compute(body);
+    let entry_ln = lsets.compute(&body.value);
 
     // check for various error conditions
-    lsets.visit_expr(body);
+    lsets.visit_body(body);
     lsets.check_ret(id, sp, fk, entry_ln, body);
-    lsets.warn_about_unused_args(decl, entry_ln);
+    lsets.warn_about_unused_args(body, entry_ln);
 }
 
 fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) {
@@ -823,7 +818,7 @@ fn compute(&mut self, body: &hir::Expr) -> LiveNode {
         // effectively a return---this only occurs in `for` loops,
         // where the body is really a closure.
 
-        debug!("compute: using id for body, {}", expr_to_string(body));
+        debug!("compute: using id for body, {}", self.ir.tcx.map.node_to_pretty_string(body.id));
 
         let exit_ln = self.s.exit_ln;
         let entry_ln: LiveNode = self.with_loop_nodes(body.id, exit_ln, exit_ln, |this| {
@@ -916,7 +911,7 @@ fn propagate_through_opt_expr(&mut self,
 
     fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
                               -> LiveNode {
-        debug!("propagate_through_expr: {}", expr_to_string(expr));
+        debug!("propagate_through_expr: {}", self.ir.tcx.map.node_to_pretty_string(expr.id));
 
         match expr.node {
           // Interesting cases with control flow or which gen/kill
@@ -935,14 +930,14 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
 
           hir::ExprClosure(.., blk_id, _) => {
               debug!("{} is an ExprClosure",
-                     expr_to_string(expr));
+                     self.ir.tcx.map.node_to_pretty_string(expr.id));
 
               /*
               The next-node for a break is the successor of the entire
               loop. The next-node for a continue is the top of this loop.
               */
               let node = self.live_node(expr.id, expr.span);
-              self.with_loop_nodes(blk_id.node_id(), succ, node, |this| {
+              self.with_loop_nodes(blk_id.node_id, succ, node, |this| {
 
                  // the construction of a closure itself is not important,
                  // but we have to consider the closed over variables.
@@ -1088,11 +1083,6 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
             self.propagate_through_exprs(exprs, succ)
           }
 
-          hir::ExprRepeat(ref element, ref count) => {
-            let succ = self.propagate_through_expr(&count, succ);
-            self.propagate_through_expr(&element, succ)
-          }
-
           hir::ExprStruct(_, ref fields, ref with_expr) => {
             let succ = self.propagate_through_opt_expr(with_expr.as_ref().map(|e| &**e), succ);
             fields.iter().rev().fold(succ, |succ, field| {
@@ -1149,7 +1139,8 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
           hir::ExprAddrOf(_, ref e) |
           hir::ExprCast(ref e, _) |
           hir::ExprType(ref e, _) |
-          hir::ExprUnary(_, ref e) => {
+          hir::ExprUnary(_, ref e) |
+          hir::ExprRepeat(ref e, _) => {
             self.propagate_through_expr(&e, succ)
           }
 
@@ -1315,7 +1306,7 @@ fn propagate_through_loop(&mut self,
             }
         }
         debug!("propagate_through_loop: using id for loop body {} {}",
-               expr.id, block_to_string(body));
+               expr.id, self.ir.tcx.map.node_to_pretty_string(body.id));
 
         let cond_ln = match kind {
             LoopLoop => ln,
@@ -1443,7 +1434,7 @@ fn check_ret(&self,
                  sp: Span,
                  fk: FnKind,
                  entry_ln: LiveNode,
-                 body: &hir::Expr)
+                 body: &hir::Body)
     {
         let fn_ty = if let FnKind::Closure(_) = fk {
             self.ir.tcx.tables().node_id_to_type(id)
@@ -1460,7 +1451,7 @@ fn check_ret(&self,
         // and must outlive the *call-site* of the function.
         let fn_ret =
             self.ir.tcx.liberate_late_bound_regions(
-                self.ir.tcx.region_maps.call_site_extent(id, body.id),
+                self.ir.tcx.region_maps.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() {
@@ -1510,8 +1501,8 @@ fn should_warn(&self, var: Variable) -> Option<String> {
         }
     }
 
-    fn warn_about_unused_args(&self, decl: &hir::FnDecl, entry_ln: LiveNode) {
-        for arg in &decl.inputs {
+    fn warn_about_unused_args(&self, body: &hir::Body, entry_ln: LiveNode) {
+        for arg in &body.arguments {
             arg.pat.each_binding(|_bm, p_id, sp, path1| {
                 let var = self.variable(p_id, sp);
                 // Ignore unused self.
index 4c3b102e540399f1c38d2f3b1b5841617a541ecd..2d88567b8b873228d292229d057aa087a6ff872f 100644 (file)
@@ -73,7 +73,6 @@
 use hir::def_id::DefId;
 use hir::map as ast_map;
 use infer::InferCtxt;
-use middle::const_qualif::ConstQualif;
 use hir::def::{Def, CtorKind};
 use ty::adjustment;
 use ty::{self, Ty, TyCtxt};
@@ -705,7 +704,7 @@ fn env_deref(&self,
             };
 
             match fn_expr.node {
-                hir::ExprClosure(.., body_id, _) => body_id.node_id(),
+                hir::ExprClosure(.., body_id, _) => body_id.node_id,
                 _ => bug!()
             }
         };
@@ -773,23 +772,23 @@ pub fn cat_rvalue_node(&self,
                            span: Span,
                            expr_ty: Ty<'tcx>)
                            -> cmt<'tcx> {
-        let qualif = self.tcx().const_qualif_map.borrow().get(&id).cloned()
-                               .unwrap_or(ConstQualif::NOT_CONST);
+        let promotable = self.tcx().rvalue_promotable_to_static.borrow().get(&id).cloned()
+                                   .unwrap_or(false);
 
         // Only promote `[T; 0]` before an RFC for rvalue promotions
         // is accepted.
-        let qualif = match expr_ty.sty {
-            ty::TyArray(_, 0) => qualif,
-            _ => ConstQualif::NOT_CONST
+        let promotable = match expr_ty.sty {
+            ty::TyArray(_, 0) => true,
+            _ => promotable & false
         };
 
         // Compute maximum lifetime of this rvalue. This is 'static if
         // we can promote to a constant, otherwise equal to enclosing temp
         // lifetime.
-        let re = if qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
-            self.temporary_scope(id)
-        } else {
+        let re = if promotable {
             self.tcx().mk_region(ty::ReStatic)
+        } else {
+            self.temporary_scope(id)
         };
         let ret = self.cat_rvalue(id, span, re, expr_ty);
         debug!("cat_rvalue_node ret {:?}", ret);
index 2c4710f1e452b6559c2709bfc55df0eb538b928e..765d93742d8fbc4f521b629bfb5f29094bd8b2cb 100644 (file)
@@ -139,7 +139,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
     fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ReachableContext<'a, 'tcx> {
         let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| {
             *ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib ||
-            *ty == config::CrateTypeProcMacro || *ty == config::CrateTypeMetadata
+            *ty == config::CrateTypeProcMacro
         });
         ReachableContext {
             tcx: tcx,
@@ -166,9 +166,10 @@ fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
             }
             Some(ast_map::NodeTraitItem(trait_method)) => {
                 match trait_method.node {
-                    hir::ConstTraitItem(_, ref default) => default.is_some(),
-                    hir::MethodTraitItem(_, ref body) => body.is_some(),
-                    hir::TypeTraitItem(..) => false,
+                    hir::TraitItemKind::Const(_, ref default) => default.is_some(),
+                    hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => true,
+                    hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) |
+                    hir::TraitItemKind::Type(..) => false,
                 }
             }
             Some(ast_map::NodeImplItem(impl_item)) => {
@@ -250,15 +251,15 @@ fn propagate_node(&mut self, node: &ast_map::Node<'tcx>,
                 match item.node {
                     hir::ItemFn(.., body) => {
                         if item_might_be_inlined(&item) {
-                            self.visit_body(body);
+                            self.visit_nested_body(body);
                         }
                     }
 
                     // Reachable constants will be inlined into other crates
                     // unconditionally, so we need to make sure that their
                     // contents are also reachable.
-                    hir::ItemConst(_, ref init) => {
-                        self.visit_expr(&init);
+                    hir::ItemConst(_, init) => {
+                        self.visit_nested_body(init);
                     }
 
                     // These are normal, nothing reachable about these
@@ -274,28 +275,26 @@ fn propagate_node(&mut self, node: &ast_map::Node<'tcx>,
             }
             ast_map::NodeTraitItem(trait_method) => {
                 match trait_method.node {
-                    hir::ConstTraitItem(_, None) |
-                    hir::MethodTraitItem(_, None) => {
+                    hir::TraitItemKind::Const(_, None) |
+                    hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => {
                         // Keep going, nothing to get exported
                     }
-                    hir::ConstTraitItem(_, Some(ref body)) => {
-                        self.visit_expr(body);
+                    hir::TraitItemKind::Const(_, Some(body_id)) |
+                    hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => {
+                        self.visit_nested_body(body_id);
                     }
-                    hir::MethodTraitItem(_, Some(body_id)) => {
-                        self.visit_body(body_id);
-                    }
-                    hir::TypeTraitItem(..) => {}
+                    hir::TraitItemKind::Type(..) => {}
                 }
             }
             ast_map::NodeImplItem(impl_item) => {
                 match impl_item.node {
-                    hir::ImplItemKind::Const(_, ref expr) => {
-                        self.visit_expr(&expr);
+                    hir::ImplItemKind::Const(_, body) => {
+                        self.visit_nested_body(body);
                     }
                     hir::ImplItemKind::Method(ref sig, body) => {
                         let did = self.tcx.map.get_parent_did(search_item);
                         if method_might_be_inlined(self.tcx, sig, impl_item, did) {
-                            self.visit_body(body)
+                            self.visit_nested_body(body)
                         }
                     }
                     hir::ImplItemKind::Type(_) => {}
@@ -358,6 +357,8 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {}
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
         // processed in visit_item above
     }
index b1e35e54eb9bb8c89a8c9a8e6bab0d257f74d0d8..faf4a448b7a84e5b20ea8d0ba53384044bc74a78 100644 (file)
@@ -1088,7 +1088,7 @@ fn resolve_item_like<'a, 'tcx, F>(visitor: &mut RegionResolutionVisitor<'tcx, 'a
 fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
                         kind: FnKind<'tcx>,
                         decl: &'tcx hir::FnDecl,
-                        body_id: hir::ExprId,
+                        body_id: hir::BodyId,
                         sp: Span,
                         id: ast::NodeId) {
     debug!("region::resolve_fn(id={:?}, \
@@ -1101,22 +1101,22 @@ fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
            visitor.cx.parent);
 
     visitor.cx.parent = visitor.new_code_extent(
-        CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id() });
+        CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id });
 
     let fn_decl_scope = visitor.new_code_extent(
-        CodeExtentData::ParameterScope { fn_id: id, body_id: body_id.node_id() });
+        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);
+        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());
+    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()),
+        root_id: Some(body_id.node_id),
         parent: ROOT_CODE_EXTENT,
         var_parent: fn_decl_scope,
     };
@@ -1126,11 +1126,11 @@ fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
 
     // The body of the every fn is a root scope.
     visitor.cx = Context {
-        root_id: Some(body_id.node_id()),
+        root_id: Some(body_id.node_id),
         parent: fn_decl_scope,
         var_parent: fn_decl_scope
     };
-    visitor.visit_body(body_id);
+    visitor.visit_nested_body(body_id);
 
     // Restore context we had at the start.
     visitor.cx = outer_cx;
@@ -1195,7 +1195,7 @@ fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
     }
 
     fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl,
-                b: hir::ExprId, s: Span, n: NodeId) {
+                b: hir::BodyId, s: Span, n: NodeId) {
         resolve_fn(self, fk, fd, b, s, n);
     }
     fn visit_arm(&mut self, a: &'ast Arm) {
index c5b03a4a32add5b64a3a0309b6d3979cf39e4edb..c491af972acbce6120f926b2f66b13166d06fd69 100644 (file)
@@ -33,7 +33,6 @@
 
 use rustc_data_structures::fx::FxHashSet;
 use hir;
-use hir::print::lifetime_to_string;
 use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
@@ -190,7 +189,7 @@ fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem) {
         // Items always introduce a new root scope
         self.with(RootScope, |_, this| {
             match item.node {
-                hir::ForeignItemFn(ref decl, ref generics) => {
+                hir::ForeignItemFn(ref decl, _, ref generics) => {
                     this.visit_early_late(item.id, decl, generics, |this| {
                         intravisit::walk_foreign_item(this, item);
                     })
@@ -206,7 +205,7 @@ fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem) {
     }
 
     fn visit_fn(&mut self, fk: FnKind<'tcx>, decl: &'tcx hir::FnDecl,
-                b: hir::ExprId, s: Span, fn_id: ast::NodeId) {
+                b: hir::BodyId, s: Span, fn_id: ast::NodeId) {
         match fk {
             FnKind::ItemFn(_, generics, ..) => {
                 self.visit_early_late(fn_id,decl, generics, |this| {
@@ -266,7 +265,8 @@ fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
         // methods in an impl can reuse label names.
         let saved = replace(&mut self.labels_in_fn, vec![]);
 
-        if let hir::MethodTraitItem(ref sig, None) = trait_item.node {
+        if let hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(_)) =
+                trait_item.node {
             self.visit_early_late(
                 trait_item.id,
                 &sig.decl, &sig.generics,
@@ -407,7 +407,7 @@ fn signal_shadowing_problem(sess: &Session, name: ast::Name, orig: Original, sha
 
 // Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning
 // if one of the label shadows a lifetime or another label.
-fn extract_labels(ctxt: &mut LifetimeContext, b: hir::ExprId) {
+fn extract_labels(ctxt: &mut LifetimeContext, b: hir::BodyId) {
     struct GatherLabels<'a> {
         sess: &'a Session,
         scope: Scope<'a>,
@@ -419,7 +419,7 @@ struct GatherLabels<'a> {
         scope: ctxt.scope,
         labels_in_fn: &mut ctxt.labels_in_fn,
     };
-    gather.visit_expr(ctxt.hir_map.expr(b));
+    gather.visit_body(ctxt.hir_map.body(b));
     return;
 
     impl<'v, 'a> Visitor<'v> for GatherLabels<'a> {
@@ -501,7 +501,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
     fn add_scope_and_walk_fn(&mut self,
                              fk: FnKind<'tcx>,
                              fd: &'tcx hir::FnDecl,
-                             fb: hir::ExprId,
+                             fb: hir::BodyId,
                              _span: Span,
                              fn_id: ast::NodeId) {
         match fk {
@@ -522,8 +522,8 @@ fn add_scope_and_walk_fn(&mut self,
         // `self.labels_in_fn`.
         extract_labels(self, fb);
 
-        self.with(FnScope { fn_id: fn_id, body_id: fb.node_id(), s: self.scope },
-                  |_old_scope, this| this.visit_body(fb))
+        self.with(FnScope { fn_id: fn_id, body_id: fb.node_id, s: self.scope },
+                  |_old_scope, this| this.visit_nested_body(fb))
     }
 
     // FIXME(#37666) this works around a limitation in the region inferencer
@@ -821,9 +821,8 @@ fn insert_lifetime(&mut self,
                        probably a bug in syntax::fold");
         }
 
-        debug!("lifetime_ref={:?} id={:?} resolved to {:?} span={:?}",
-               lifetime_to_string(lifetime_ref),
-               lifetime_ref.id,
+        debug!("{} resolved to {:?} span={:?}",
+               self.hir_map.node_to_string(lifetime_ref.id),
                def,
                self.sess.codemap().span_to_string(lifetime_ref.span));
         self.map.defs.insert(lifetime_ref.id, def);
@@ -860,8 +859,8 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
     debug!("insert_late_bound_lifetimes(decl={:?}, generics={:?})", decl, generics);
 
     let mut constrained_by_input = ConstrainedCollector { regions: FxHashSet() };
-    for arg in &decl.inputs {
-        constrained_by_input.visit_ty(&arg.ty);
+    for arg_ty in &decl.inputs {
+        constrained_by_input.visit_ty(arg_ty);
     }
 
     let mut appears_in_output = AllCollector {
index c6df1497e681dd3ac3c4587d0c7d45e772ff3c29..acb506878e6b65eb94f45d772dab26fe388ec647 100644 (file)
@@ -75,8 +75,7 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) {
             config::CrateTypeCdylib |
             config::CrateTypeExecutable |
             config::CrateTypeStaticlib => true,
-            config::CrateTypeRlib |
-            config::CrateTypeMetadata => false,
+            config::CrateTypeRlib => false,
         }
     });
     if !needs_check {
index 3576ae662a005033e1a5f200327b9d03228dfa75..3c5a91f4ff04c8dae35599a94bbf7d9964032d2e 100644 (file)
@@ -48,7 +48,7 @@ pub fn from_node(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId) -> MirSource {
 
         match tcx.map.get(id) {
             map::NodeItem(&Item { node: ItemConst(..), .. }) |
-            map::NodeTraitItem(&TraitItem { node: ConstTraitItem(..), .. }) |
+            map::NodeTraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) |
             map::NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) => {
                 MirSource::Const(id)
             }
index a415d1f991fcd18a59817d98b9a8b06334769347..b3cb5ace45bc04e702d8b16a506f48f1b9277cea 100644 (file)
@@ -73,6 +73,7 @@ pub enum OutputType {
     Bitcode,
     Assembly,
     LlvmAssembly,
+    Metadata,
     Object,
     Exe,
     DepInfo,
@@ -86,7 +87,8 @@ fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool {
             OutputType::Bitcode |
             OutputType::Assembly |
             OutputType::LlvmAssembly |
-            OutputType::Object => false,
+            OutputType::Object |
+            OutputType::Metadata => false,
         }
     }
 
@@ -96,6 +98,7 @@ fn shorthand(&self) -> &'static str {
             OutputType::Assembly => "asm",
             OutputType::LlvmAssembly => "llvm-ir",
             OutputType::Object => "obj",
+            OutputType::Metadata => "metadata",
             OutputType::Exe => "link",
             OutputType::DepInfo => "dep-info",
         }
@@ -107,6 +110,7 @@ pub fn extension(&self) -> &'static str {
             OutputType::Assembly => "s",
             OutputType::LlvmAssembly => "ll",
             OutputType::Object => "o",
+            OutputType::Metadata => "rmeta",
             OutputType::DepInfo => "d",
             OutputType::Exe => "",
         }
@@ -152,6 +156,19 @@ pub fn keys<'a>(&'a self) -> BTreeMapKeysIter<'a, OutputType, Option<PathBuf>> {
     pub fn values<'a>(&'a self) -> BTreeMapValuesIter<'a, OutputType, Option<PathBuf>> {
         self.0.values()
     }
+
+    // True if any of the output types require codegen or linking.
+    pub fn should_trans(&self) -> bool {
+        self.0.keys().any(|k| match *k {
+            OutputType::Bitcode |
+            OutputType::Assembly |
+            OutputType::LlvmAssembly |
+            OutputType::Object |
+            OutputType::Exe => true,
+            OutputType::Metadata |
+            OutputType::DepInfo => false,
+        })
+    }
 }
 
 
@@ -482,7 +499,6 @@ pub enum CrateType {
     CrateTypeStaticlib,
     CrateTypeCdylib,
     CrateTypeProcMacro,
-    CrateTypeMetadata,
 }
 
 #[derive(Clone, Hash)]
@@ -943,33 +959,28 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
     let os = &sess.target.target.target_os;
     let env = &sess.target.target.target_env;
     let vendor = &sess.target.target.target_vendor;
+    let min_atomic_width = sess.target.target.min_atomic_width();
     let max_atomic_width = sess.target.target.max_atomic_width();
 
-    let fam = if let Some(ref fam) = sess.target.target.options.target_family {
-        Symbol::intern(fam)
-    } else if sess.target.target.options.is_like_windows {
-        Symbol::intern("windows")
-    } else {
-        Symbol::intern("unix")
-    };
-
     let mut ret = HashSet::new();
     // Target bindings.
     ret.insert((Symbol::intern("target_os"), Some(Symbol::intern(os))));
-    ret.insert((Symbol::intern("target_family"), Some(fam)));
+    if let Some(ref fam) = sess.target.target.options.target_family {
+        ret.insert((Symbol::intern("target_family"), Some(Symbol::intern(fam))));
+        if fam == "windows" || fam == "unix" {
+            ret.insert((Symbol::intern(fam), None));
+        }
+    }
     ret.insert((Symbol::intern("target_arch"), Some(Symbol::intern(arch))));
     ret.insert((Symbol::intern("target_endian"), Some(Symbol::intern(end))));
     ret.insert((Symbol::intern("target_pointer_width"), Some(Symbol::intern(wordsz))));
     ret.insert((Symbol::intern("target_env"), Some(Symbol::intern(env))));
     ret.insert((Symbol::intern("target_vendor"), Some(Symbol::intern(vendor))));
-    if fam == "windows" || fam == "unix" {
-        ret.insert((fam, None));
-    }
     if sess.target.target.options.has_elf_tls {
         ret.insert((Symbol::intern("target_thread_local"), None));
     }
     for &i in &[8, 16, 32, 64, 128] {
-        if i <= max_atomic_width {
+        if i >= min_atomic_width && i <= max_atomic_width {
             let s = i.to_string();
             ret.insert((Symbol::intern("target_has_atomic"), Some(Symbol::intern(&s))));
             if &s == wordsz {
@@ -1164,12 +1175,12 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
                              assumed.", "[KIND=]NAME"),
         opt::multi_s("", "crate-type", "Comma separated list of types of crates
                                     for the compiler to emit",
-                   "[bin|lib|rlib|dylib|cdylib|staticlib|metadata]"),
+                   "[bin|lib|rlib|dylib|cdylib|staticlib]"),
         opt::opt_s("", "crate-name", "Specify the name of the crate being built",
                "NAME"),
         opt::multi_s("", "emit", "Comma separated list of types of output for \
                               the compiler to emit",
-                 "[asm|llvm-bc|llvm-ir|obj|link|dep-info]"),
+                 "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info]"),
         opt::multi_s("", "print", "Comma separated list of compiler information to \
                                print on stdout", &print_opts.join("|")),
         opt::flagmulti_s("g",  "",  "Equivalent to -C debuginfo=2"),
@@ -1298,7 +1309,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
     };
 
     let unparsed_crate_types = matches.opt_strs("crate-type");
-    let crate_types = parse_crate_types_from_list(unparsed_crate_types)
+    let (crate_types, emit_metadata) = parse_crate_types_from_list(unparsed_crate_types)
         .unwrap_or_else(|e| early_error(error_format, &e[..]));
 
     let mut lint_opts = vec![];
@@ -1332,6 +1343,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
                     "llvm-ir" => OutputType::LlvmAssembly,
                     "llvm-bc" => OutputType::Bitcode,
                     "obj" => OutputType::Object,
+                    "metadata" => OutputType::Metadata,
                     "link" => OutputType::Exe,
                     "dep-info" => OutputType::DepInfo,
                     part => {
@@ -1344,7 +1356,9 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
             }
         }
     };
-    if output_types.is_empty() {
+    if emit_metadata {
+        output_types.insert(OutputType::Metadata, None);
+    } else if output_types.is_empty() {
         output_types.insert(OutputType::Exe, None);
     }
 
@@ -1546,8 +1560,10 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
     cfg)
 }
 
-pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateType>, String> {
+pub fn parse_crate_types_from_list(list_list: Vec<String>)
+                                   -> Result<(Vec<CrateType>, bool), String> {
     let mut crate_types: Vec<CrateType> = Vec::new();
+    let mut emit_metadata = false;
     for unparsed_crate_type in &list_list {
         for part in unparsed_crate_type.split(',') {
             let new_part = match part {
@@ -1558,7 +1574,13 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
                 "cdylib"    => CrateTypeCdylib,
                 "bin"       => CrateTypeExecutable,
                 "proc-macro" => CrateTypeProcMacro,
-                "metadata"  => CrateTypeMetadata,
+                // FIXME(#38640) remove this when Cargo is fixed.
+                "metadata"  => {
+                    early_warn(ErrorOutputType::default(), "--crate-type=metadata is deprecated, \
+                                                            prefer --emit=metadata");
+                    emit_metadata = true;
+                    CrateTypeRlib
+                }
                 _ => {
                     return Err(format!("unknown crate type: `{}`",
                                        part));
@@ -1570,7 +1592,7 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
         }
     }
 
-    return Ok(crate_types);
+    return Ok((crate_types, emit_metadata));
 }
 
 pub mod nightly_options {
@@ -1643,7 +1665,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             CrateTypeStaticlib => "staticlib".fmt(f),
             CrateTypeCdylib => "cdylib".fmt(f),
             CrateTypeProcMacro => "proc-macro".fmt(f),
-            CrateTypeMetadata => "metadata".fmt(f),
         }
     }
 }
index f24ff98035532222905e7e32733d8f3d1f5b498a..cb1fc15c5f68210c704352863b87a7f6a73229ad 100644 (file)
@@ -508,14 +508,6 @@ pub struct GlobalCtxt<'tcx> {
     /// FIXME(arielb1): why is this separate from populated_external_types?
     pub populated_external_primitive_impls: RefCell<DefIdSet>,
 
-    /// Cache used by const_eval when decoding external constants.
-    /// Contains `None` when the constant has been fetched but doesn't exist.
-    /// Constains `Some(expr_id, type)` otherwise.
-    /// `type` is `None` in case it's not a primitive type
-    pub extern_const_statics: RefCell<DefIdMap<Option<(NodeId, Option<Ty<'tcx>>)>>>,
-    /// Cache used by const_eval when decoding extern const fns
-    pub extern_const_fns: RefCell<DefIdMap<NodeId>>,
-
     /// Maps any item's def-id to its stability index.
     pub stability: RefCell<stability::Index<'tcx>>,
 
@@ -537,8 +529,8 @@ pub struct GlobalCtxt<'tcx> {
     /// Caches the representation hints for struct definitions.
     repr_hint_cache: RefCell<DepTrackingMap<maps::ReprHints<'tcx>>>,
 
-    /// Maps Expr NodeId's to their constant qualification.
-    pub const_qualif_map: RefCell<NodeMap<middle::const_qualif::ConstQualif>>,
+    /// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime.
+    pub rvalue_promotable_to_static: RefCell<NodeMap<bool>>,
 
     /// Caches CoerceUnsized kinds for impls on custom types.
     pub custom_coerce_unsized_kinds: RefCell<DefIdMap<ty::adjustment::CustomCoerceUnsized>>,
@@ -787,13 +779,11 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             used_trait_imports: RefCell::new(NodeSet()),
             populated_external_types: RefCell::new(DefIdSet()),
             populated_external_primitive_impls: RefCell::new(DefIdSet()),
-            extern_const_statics: RefCell::new(DefIdMap()),
-            extern_const_fns: RefCell::new(DefIdMap()),
             stability: RefCell::new(stability),
             selection_cache: traits::SelectionCache::new(),
             evaluation_cache: traits::EvaluationCache::new(),
             repr_hint_cache: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
-            const_qualif_map: RefCell::new(NodeMap()),
+            rvalue_promotable_to_static: RefCell::new(NodeMap()),
             custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
             cast_kinds: RefCell::new(NodeMap()),
             fragment_infos: RefCell::new(DefIdMap()),
index 53ed103ad914106c27847f2277b867c7d2bb91c8..ebac30c8e506edf57fbca9e28c1bca2bdd55b711 100644 (file)
@@ -575,6 +575,10 @@ fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
             });
         }
 
+        // Disable field reordering until we can decide what to do.
+        // The odd pattern here avoids a warning about the value never being read.
+        if can_optimize { can_optimize = false }
+
         let (optimize, sort_ascending) = match kind {
             StructKind::AlwaysSizedUnivariant => (can_optimize, false),
             StructKind::MaybeUnsizedUnivariant => (can_optimize, false),
index 4e175e50194c332d446d80c66e195570a6bdc541..b03a432de413107a4c4a25f69c552ba3a1db7679 100644 (file)
@@ -219,26 +219,18 @@ pub enum Visibility {
     /// Visible everywhere (including in other crates).
     Public,
     /// Visible only in the given crate-local module.
-    Restricted(NodeId),
+    Restricted(DefId),
     /// Not visible anywhere in the local crate. This is the visibility of private external items.
-    PrivateExternal,
+    Invisible,
 }
 
-pub trait NodeIdTree {
-    fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool;
+pub trait DefIdTree: Copy {
+    fn parent(self, id: DefId) -> Option<DefId>;
 }
 
-impl<'a> NodeIdTree for ast_map::Map<'a> {
-    fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool {
-        let mut node_ancestor = node;
-        while node_ancestor != ancestor {
-            let node_ancestor_parent = self.get_module_parent(node_ancestor);
-            if node_ancestor_parent == node_ancestor {
-                return false;
-            }
-            node_ancestor = node_ancestor_parent;
-        }
-        true
+impl<'a, 'gcx, 'tcx> DefIdTree for TyCtxt<'a, 'gcx, 'tcx> {
+    fn parent(self, id: DefId) -> Option<DefId> {
+        self.def_key(id).parent.map(|index| DefId { index: index, ..id })
     }
 }
 
@@ -246,36 +238,46 @@ impl Visibility {
     pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: TyCtxt) -> Self {
         match *visibility {
             hir::Public => Visibility::Public,
-            hir::Visibility::Crate => Visibility::Restricted(ast::CRATE_NODE_ID),
+            hir::Visibility::Crate => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
             hir::Visibility::Restricted { ref path, .. } => match path.def {
                 // If there is no resolution, `resolve` will have already reported an error, so
                 // assume that the visibility is public to avoid reporting more privacy errors.
                 Def::Err => Visibility::Public,
-                def => Visibility::Restricted(tcx.map.as_local_node_id(def.def_id()).unwrap()),
+                def => Visibility::Restricted(def.def_id()),
             },
-            hir::Inherited => Visibility::Restricted(tcx.map.get_module_parent(id)),
+            hir::Inherited => {
+                Visibility::Restricted(tcx.map.local_def_id(tcx.map.get_module_parent(id)))
+            }
         }
     }
 
     /// Returns true if an item with this visibility is accessible from the given block.
-    pub fn is_accessible_from<T: NodeIdTree>(self, block: NodeId, tree: &T) -> bool {
+    pub fn is_accessible_from<T: DefIdTree>(self, mut module: DefId, tree: T) -> bool {
         let restriction = match self {
             // Public items are visible everywhere.
             Visibility::Public => return true,
             // Private items from other crates are visible nowhere.
-            Visibility::PrivateExternal => return false,
+            Visibility::Invisible => return false,
             // Restricted items are visible in an arbitrary local module.
+            Visibility::Restricted(other) if other.krate != module.krate => return false,
             Visibility::Restricted(module) => module,
         };
 
-        tree.is_descendant_of(block, restriction)
+        while module != restriction {
+            match tree.parent(module) {
+                Some(parent) => module = parent,
+                None => return false,
+            }
+        }
+
+        true
     }
 
     /// Returns true if this visibility is at least as accessible as the given visibility
-    pub fn is_at_least<T: NodeIdTree>(self, vis: Visibility, tree: &T) -> bool {
+    pub fn is_at_least<T: DefIdTree>(self, vis: Visibility, tree: T) -> bool {
         let vis_restriction = match vis {
             Visibility::Public => return self == Visibility::Public,
-            Visibility::PrivateExternal => return true,
+            Visibility::Invisible => return true,
             Visibility::Restricted(module) => module,
         };
 
@@ -1204,13 +1206,13 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                         tcx.construct_parameter_environment(
                             impl_item.span,
                             tcx.map.local_def_id(id),
-                            tcx.region_maps.call_site_extent(id, body.node_id()))
+                            tcx.region_maps.call_site_extent(id, body.node_id))
                     }
                 }
             }
             Some(ast_map::NodeTraitItem(trait_item)) => {
                 match trait_item.node {
-                    hir::TypeTraitItem(..) | hir::ConstTraitItem(..) => {
+                    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.map.get_parent(id);
@@ -1219,13 +1221,13 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                                                             trait_def_id,
                                                             tcx.region_maps.item_extent(id))
                     }
-                    hir::MethodTraitItem(_, ref body) => {
+                    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 Some(body_id) = *body {
+                        let extent = if let hir::TraitMethod::Provided(body_id) = *body {
                             // default impl: use call_site extent as free_id_outlive bound.
-                            tcx.region_maps.call_site_extent(id, body_id.node_id())
+                            tcx.region_maps.call_site_extent(id, body_id.node_id)
                         } else {
                             // no default impl: use item extent as free_id_outlive bound.
                             tcx.region_maps.item_extent(id)
@@ -1246,7 +1248,7 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                         tcx.construct_parameter_environment(
                             item.span,
                             fn_def_id,
-                            tcx.region_maps.call_site_extent(id, body_id.node_id()))
+                            tcx.region_maps.call_site_extent(id, body_id.node_id))
                     }
                     hir::ItemEnum(..) |
                     hir::ItemStruct(..) |
@@ -1282,7 +1284,7 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                     tcx.construct_parameter_environment(
                         expr.span,
                         base_def_id,
-                        tcx.region_maps.call_site_extent(id, body.node_id()))
+                        tcx.region_maps.call_site_extent(id, body.node_id))
                 } else {
                     tcx.empty_parameter_environment()
                 }
@@ -1779,7 +1781,7 @@ pub fn is_uninhabited_recurse(&self,
                                   block: Option<NodeId>,
                                   tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                   substs: &'tcx Substs<'tcx>) -> bool {
-        block.map_or(true, |b| self.vis.is_accessible_from(b, &tcx.map)) &&
+        block.map_or(true, |b| tcx.vis_is_accessible_from(self.vis, b)) &&
         self.ty(tcx, substs).is_uninhabited_recurse(visited, block, tcx)
     }
 }
@@ -2069,7 +2071,7 @@ pub fn custom_coerce_unsized_kind(self, did: DefId) -> adjustment::CustomCoerceU
     pub fn associated_item(self, def_id: DefId) -> AssociatedItem {
         self.associated_items.memoize(def_id, || {
             if !def_id.is_local() {
-                return self.sess.cstore.associated_item(self.global_tcx(), def_id)
+                return self.sess.cstore.associated_item(def_id)
                            .expect("missing AssociatedItem in metadata");
             }
 
@@ -2098,10 +2100,10 @@ pub fn associated_item(self, def_id: DefId) -> AssociatedItem {
                     }
                 }
 
-                hir::ItemTrait(.., ref trait_items) => {
-                    for trait_item in trait_items {
+                hir::ItemTrait(.., ref trait_item_refs) => {
+                    for trait_item_ref in trait_item_refs {
                         let assoc_item =
-                            self.associated_item_from_trait_item_ref(parent_def_id, trait_item);
+                            self.associated_item_from_trait_item_ref(parent_def_id, trait_item_ref);
                         self.associated_items.borrow_mut().insert(assoc_item.def_id, assoc_item);
                     }
                 }
@@ -2119,28 +2121,22 @@ pub fn associated_item(self, def_id: DefId) -> AssociatedItem {
 
     fn associated_item_from_trait_item_ref(self,
                                            parent_def_id: DefId,
-                                           trait_item: &hir::TraitItem)
+                                           trait_item_ref: &hir::TraitItemRef)
                                            -> AssociatedItem {
-        let def_id = self.map.local_def_id(trait_item.id);
-
-        let (kind, has_self, has_value) = match trait_item.node {
-            hir::MethodTraitItem(ref sig, ref body) => {
-                (AssociatedKind::Method, sig.decl.get_self().is_some(),
-                 body.is_some())
-            }
-            hir::ConstTraitItem(_, ref value) => {
-                (AssociatedKind::Const, false, value.is_some())
-            }
-            hir::TypeTraitItem(_, ref ty) => {
-                (AssociatedKind::Type, false, ty.is_some())
+        let def_id = self.map.local_def_id(trait_item_ref.id.node_id);
+        let (kind, has_self) = match trait_item_ref.kind {
+            hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false),
+            hir::AssociatedItemKind::Method { has_self } => {
+                (ty::AssociatedKind::Method, has_self)
             }
+            hir::AssociatedItemKind::Type => (ty::AssociatedKind::Type, false),
         };
 
         AssociatedItem {
-            name: trait_item.name,
+            name: trait_item_ref.name,
             kind: kind,
-            vis: Visibility::from_hir(&hir::Inherited, trait_item.id, self),
-            defaultness: hir::Defaultness::Default { has_value: has_value },
+            vis: Visibility::from_hir(&hir::Inherited, trait_item_ref.id.node_id, self),
+            defaultness: trait_item_ref.defaultness,
             def_id: def_id,
             container: TraitContainer(parent_def_id),
             method_has_self_argument: has_self
@@ -2185,11 +2181,11 @@ pub fn associated_item_def_ids(self, def_id: DefId) -> Rc<Vec<DefId>> {
             let id = self.map.as_local_node_id(def_id).unwrap();
             let item = self.map.expect_item(id);
             let vec: Vec<_> = match item.node {
-                hir::ItemTrait(.., ref trait_items) => {
-                    trait_items.iter()
-                               .map(|trait_item| trait_item.id)
-                               .map(|id| self.map.local_def_id(id))
-                               .collect()
+                hir::ItemTrait(.., ref trait_item_refs) => {
+                    trait_item_refs.iter()
+                                   .map(|trait_item_ref| trait_item_ref.id)
+                                   .map(|id| self.map.local_def_id(id.node_id))
+                                   .collect()
                 }
                 hir::ItemImpl(.., ref impl_item_refs) => {
                     impl_item_refs.iter()
@@ -2266,6 +2262,10 @@ pub fn def_span(self, def_id: DefId) -> Span {
         }
     }
 
+    pub fn vis_is_accessible_from(self, vis: Visibility, block: NodeId) -> bool {
+        vis.is_accessible_from(self.map.local_def_id(self.map.get_module_parent(block)), self)
+    }
+
     pub fn item_name(self, id: DefId) -> ast::Name {
         if let Some(id) = self.map.as_local_node_id(id) {
             self.map.name(id)
@@ -2520,8 +2520,7 @@ pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> {
     /// ID of the impl that the method belongs to. Otherwise, return `None`.
     pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
         if def_id.krate != LOCAL_CRATE {
-            return self.sess.cstore.associated_item(self.global_tcx(), def_id)
-                       .and_then(|item| {
+            return self.sess.cstore.associated_item(def_id).and_then(|item| {
                 match item.container {
                     TraitContainer(_) => None,
                     ImplContainer(def_id) => Some(def_id),
index e01856b2a476265b161671e78b5760d249e545ae..4ddccbfd4c597ff59d5df2df0ec937b3d2acd821 100644 (file)
 #[derive(Clone, Copy, Debug)]
 pub struct ErrorReported;
 
+thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0));
+
+/// Read the current depth of `time()` calls. This is used to
+/// encourage indentation across threads.
+pub fn time_depth() -> usize {
+    TIME_DEPTH.with(|slot| slot.get())
+}
+
+/// Set the current depth of `time()` calls. The idea is to call
+/// `set_time_depth()` with the result from `time_depth()` in the
+/// parent thread.
+pub fn set_time_depth(depth: usize) {
+    TIME_DEPTH.with(|slot| slot.set(depth));
+}
+
 pub fn time<T, F>(do_it: bool, what: &str, f: F) -> T where
     F: FnOnce() -> T,
 {
-    thread_local!(static DEPTH: Cell<usize> = Cell::new(0));
     if !do_it { return f(); }
 
-    let old = DEPTH.with(|slot| {
+    let old = TIME_DEPTH.with(|slot| {
         let r = slot.get();
         slot.set(r + 1);
         r
@@ -56,7 +70,7 @@ pub fn time<T, F>(do_it: bool, what: &str, f: F) -> T where
              mem_string,
              what);
 
-    DEPTH.with(|slot| slot.set(old));
+    TIME_DEPTH.with(|slot| slot.set(old));
 
     rv
 }
index 70c7ea99e13d1fef12deadc4a3811756df0c8079..21a2d4293df77025700e162354fa90aeadb954b2 100644 (file)
@@ -37,6 +37,7 @@ pub fn opts() -> TargetOptions {
         function_sections: false,
         dynamic_linking: true,
         executables: true,
+        target_family: Some("unix".to_string()),
         is_like_osx: true,
         has_rpath: true,
         dll_prefix: "lib".to_string(),
index d86a9b093272e9b78b93e7b976f7fb4a84d483fe..98a9e343d004426f732233ae3b55e7133cf3ef94 100644 (file)
@@ -23,6 +23,7 @@ pub fn target() -> Result<Target, String> {
         obj_is_bitcode: true,
         max_atomic_width: Some(32),
         post_link_args: vec!["-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()],
+        target_family: Some("unix".to_string()),
         .. Default::default()
     };
     Ok(Target {
index 7baf80066b27456d442829891ba31d13f5523c83..62418e68d43415fe020671e30759bcf075d076ac 100644 (file)
@@ -15,6 +15,7 @@ pub fn opts() -> TargetOptions {
     TargetOptions {
         dynamic_linking: true,
         executables: true,
+        target_family: Some("unix".to_string()),
         linker_is_gnu: true,
         has_rpath: true,
         position_independent_executables: true,
index 7555181a15cf20d5a5d3856401b10df91a5bfe10..dca33e45af7c7ffc656b02609dedf9dc537b4fa5 100644 (file)
@@ -15,6 +15,7 @@ pub fn opts() -> TargetOptions {
     TargetOptions {
         dynamic_linking: true,
         executables: true,
+        target_family: Some("unix".to_string()),
         linker_is_gnu: true,
         has_rpath: true,
         pre_link_args: vec![
index 7555181a15cf20d5a5d3856401b10df91a5bfe10..dca33e45af7c7ffc656b02609dedf9dc537b4fa5 100644 (file)
@@ -15,6 +15,7 @@ pub fn opts() -> TargetOptions {
     TargetOptions {
         dynamic_linking: true,
         executables: true,
+        target_family: Some("unix".to_string()),
         linker_is_gnu: true,
         has_rpath: true,
         pre_link_args: vec![
index 69546684cb70bda5c5626811199f0b72c56c8bc0..8c517224201b2fe7b2e44b5a7812055c9a5cbfb0 100644 (file)
@@ -15,6 +15,7 @@ pub fn opts() -> TargetOptions {
     TargetOptions {
         dynamic_linking: true,
         executables: true,
+        target_family: Some("unix".to_string()),
         linker_is_gnu: true,
         has_rpath: true,
         pre_link_args: vec![
index 5e319ba1838a0a9558e4d31fe65092da0b5dd7b5..bfdc9faaa8a736b37addb6b2c67868ca5cf37c63 100644 (file)
@@ -17,6 +17,7 @@ pub fn opts() -> TargetOptions {
         dynamic_linking: true,
         executables: true,
         has_rpath: true,
+        target_family: Some("unix".to_string()),
         linker_is_gnu: true,
         .. Default::default()
     }
index d1ab71e41404ef46b4fb6ef749feca43b7c13855..4b2ae9c8e699c1e23ca0f056afff69d02faf1ea1 100644 (file)
@@ -15,6 +15,7 @@ pub fn opts() -> TargetOptions {
     TargetOptions {
         dynamic_linking: true,
         executables: true,
+        target_family: Some("unix".to_string()),
         linker_is_gnu: true,
         has_rpath: true,
         pre_link_args: vec![
index 13333be66f5701a0dbb4c7123e1da9ab05d20cdd..6a409edf0feccbf564f38d91cfbbf24888e29765 100644 (file)
@@ -69,6 +69,7 @@
 mod windows_msvc_base;
 mod thumb_base;
 mod fuchsia_base;
+mod redox_base;
 
 pub type TargetResult = Result<Target, String>;
 
@@ -184,6 +185,8 @@ fn $module() {
     ("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia),
     ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
 
+    ("x86_64-unknown-redox", x86_64_unknown_redox),
+
     ("i386-apple-ios", i386_apple_ios),
     ("x86_64-apple-ios", x86_64_apple_ios),
     ("aarch64-apple-ios", aarch64_apple_ios),
@@ -373,6 +376,9 @@ pub struct TargetOptions {
     // file
     pub no_integrated_as: bool,
 
+    /// Don't use this field; instead use the `.min_atomic_width()` method.
+    pub min_atomic_width: Option<u64>,
+
     /// Don't use this field; instead use the `.max_atomic_width()` method.
     pub max_atomic_width: Option<u64>,
 
@@ -436,6 +442,7 @@ fn default() -> TargetOptions {
             has_elf_tls: false,
             obj_is_bitcode: false,
             no_integrated_as: false,
+            min_atomic_width: None,
             max_atomic_width: None,
             panic_strategy: PanicStrategy::Unwind,
             abi_blacklist: vec![],
@@ -459,6 +466,12 @@ pub fn adjust_abi(&self, abi: Abi) -> Abi {
         }
     }
 
+    /// Minimum integer size in bits that this target can perform atomic
+    /// operations on.
+    pub fn min_atomic_width(&self) -> u64 {
+        self.options.min_atomic_width.unwrap_or(8)
+    }
+
     /// Maximum integer size in bits that this target can perform atomic
     /// operations on.
     pub fn max_atomic_width(&self) -> u64 {
@@ -601,6 +614,7 @@ macro_rules! key {
         key!(obj_is_bitcode, bool);
         key!(no_integrated_as, bool);
         key!(max_atomic_width, Option<u64>);
+        key!(min_atomic_width, Option<u64>);
         try!(key!(panic_strategy, PanicStrategy));
         key!(crt_static_default, bool);
 
@@ -763,6 +777,7 @@ macro_rules! target_option_val {
         target_option_val!(has_elf_tls);
         target_option_val!(obj_is_bitcode);
         target_option_val!(no_integrated_as);
+        target_option_val!(min_atomic_width);
         target_option_val!(max_atomic_width);
         target_option_val!(panic_strategy);
         target_option_val!(crt_static_default);
index 6e038a7ed56ee2b9fae85974e934a5fda7c4b6ac..57179a68afd8e9ccdc79bb1f459296277bca6339 100644 (file)
@@ -15,6 +15,7 @@ pub fn opts() -> TargetOptions {
     TargetOptions {
         dynamic_linking: true,
         executables: true,
+        target_family: Some("unix".to_string()),
         linker_is_gnu: true,
         has_rpath: true,
         pre_link_args: vec![
index 1f74170e399893da9efba1030b1f731a000cb2fc..12b8e8bdc88fd931e776664af40136cacf0afd81 100644 (file)
@@ -15,6 +15,7 @@ pub fn opts() -> TargetOptions {
     TargetOptions {
         dynamic_linking: true,
         executables: true,
+        target_family: Some("unix".to_string()),
         linker_is_gnu: true,
         has_rpath: true,
         is_like_openbsd: true,
diff --git a/src/librustc_back/target/redox_base.rs b/src/librustc_back/target/redox_base.rs
new file mode 100644 (file)
index 0000000..1dffff5
--- /dev/null
@@ -0,0 +1,50 @@
+// 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.
+
+use PanicStrategy;
+use target::TargetOptions;
+use std::default::Default;
+
+pub fn opts() -> TargetOptions {
+    TargetOptions {
+        pre_link_args: vec![
+            // We want to be able to strip as much executable code as possible
+            // from the linker command line, and this flag indicates to the
+            // linker that it can avoid linking in dynamic libraries that don't
+            // actually satisfy any symbols up to that point (as with many other
+            // resolutions the linker does). This option only applies to all
+            // following libraries so we're sure to pass it as one of the first
+            // arguments.
+            "-Wl,--as-needed".to_string(),
+
+            // Always enable NX protection when it is available
+            "-Wl,-z,noexecstack".to_string(),
+
+            // Static link
+            "-static".to_string()
+        ],
+        late_link_args: vec![
+            "-lc".to_string(),
+            "-lm".to_string()
+        ],
+        executables: true,
+        relocation_model: "static".to_string(),
+        disable_redzone: true,
+        eliminate_frame_pointer: false,
+        target_family: None,
+        linker_is_gnu: true,
+        no_default_libraries: true,
+        lib_allocation_crate: "alloc_system".to_string(),
+        exe_allocation_crate: "alloc_system".to_string(),
+        has_elf_tls: true,
+        panic_strategy: PanicStrategy::Abort,
+        .. Default::default()
+    }
+}
index a7af0462e570fb1d131f4982cad16a72892e09a5..41323c9c26ba7290fc0b7216d68a477e17a3d7f5 100644 (file)
@@ -16,6 +16,7 @@ pub fn opts() -> TargetOptions {
         dynamic_linking: true,
         executables: true,
         has_rpath: true,
+        target_family: Some("unix".to_string()),
         is_like_solaris: true,
         exe_allocation_crate: super::maybe_jemalloc(),
 
index 77ab4fcae70087dfc95ceb9e883d2f8931c5d896..fec269074da8bed879f94e795c9be087db0ae019 100644 (file)
@@ -26,6 +26,7 @@ pub fn target() -> Result<Target, String> {
         max_atomic_width: Some(32),
         post_link_args: vec!["-s".to_string(), "BINARYEN=1".to_string(),
                              "-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()],
+        target_family: Some("unix".to_string()),
         .. Default::default()
     };
     Ok(Target {
index 19ca0df51b9dc331d36077ce481641078115d08f..db02e142fcc8efac34aca9480845a87696be1cdf 100644 (file)
@@ -24,6 +24,7 @@ pub fn opts() -> TargetOptions {
         staticlib_prefix: "".to_string(),
         staticlib_suffix: ".lib".to_string(),
         no_default_libraries: true,
+        target_family: Some("windows".to_string()),
         is_like_windows: true,
         allows_weak_linkage: false,
         pre_link_args: vec![
index 84e22e84fdb58438b4732558a31d8632ec2bbb6f..efa215b419d7044fed385b8b176d2f664a6e3bc1 100644 (file)
@@ -53,6 +53,7 @@ pub fn opts() -> TargetOptions {
         exe_suffix: ".exe".to_string(),
         staticlib_prefix: "".to_string(),
         staticlib_suffix: ".lib".to_string(),
+        target_family: Some("windows".to_string()),
         is_like_windows: true,
         is_like_msvc: true,
         pre_link_args: vec![
diff --git a/src/librustc_back/target/x86_64_unknown_redox.rs b/src/librustc_back/target/x86_64_unknown_redox.rs
new file mode 100644 (file)
index 0000000..cecac06
--- /dev/null
@@ -0,0 +1,30 @@
+// 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.
+
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::redox_base::opts();
+    base.cpu = "x86-64".to_string();
+    base.max_atomic_width = Some(64);
+    base.pre_link_args.push("-m64".to_string());
+
+    Ok(Target {
+        llvm_target: "x86_64-unknown-redox".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        arch: "x86_64".to_string(),
+        target_os: "redox".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
+        options: base,
+    })
+}
index 5ed628d7dcae5f8be847efa4e5c71043bfd67c3f..dc2214dd34e72141ae4f6a02d59599fcaef22afb 100644 (file)
@@ -189,9 +189,8 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                      move_data: &move_data::FlowedMoveData<'c, 'tcx>,
                                      all_loans: &[Loan<'tcx>],
                                      fn_id: ast::NodeId,
-                                     decl: &hir::FnDecl,
-                                     body: &hir::Expr) {
-    debug!("check_loans(body id={})", body.id);
+                                     body: &hir::Body) {
+    debug!("check_loans(body id={})", body.value.id);
 
     let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
     let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env);
@@ -202,7 +201,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         all_loans: all_loans,
         param_env: &infcx.parameter_environment
     };
-    euv::ExprUseVisitor::new(&mut clcx, &infcx).walk_fn(decl, body);
+    euv::ExprUseVisitor::new(&mut clcx, &infcx).consume_body(body);
 }
 
 #[derive(PartialEq)]
index 5d59b58b847d9e0eabc99315c5352f0dd67c60d2..34f1ad57c6211e8317a21fa15365030f8db23e1f 100644 (file)
 
 pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                     fn_id: NodeId,
-                                    decl: &hir::FnDecl,
-                                    body: &hir::Expr)
+                                    body: &hir::Body)
                                     -> (Vec<Loan<'tcx>>,
                                         move_data::MoveData<'tcx>) {
     let mut glcx = GatherLoanCtxt {
         bccx: bccx,
         all_loans: Vec::new(),
-        item_ub: bccx.tcx.region_maps.node_extent(body.id),
+        item_ub: bccx.tcx.region_maps.node_extent(body.value.id),
         move_data: MoveData::new(),
         move_error_collector: move_error::MoveErrorCollector::new(),
     };
 
     let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
     let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env);
-    euv::ExprUseVisitor::new(&mut glcx, &infcx).walk_fn(decl, body);
+    euv::ExprUseVisitor::new(&mut glcx, &infcx).consume_body(body);
 
     glcx.report_potential_errors();
     let GatherLoanCtxt { all_loans, move_data, .. } = glcx;
@@ -548,14 +547,14 @@ fn visit_expr(&mut self, ex: &'tcx Expr) {
 
 pub fn gather_loans_in_static_initializer<'a, 'tcx>(bccx: &mut BorrowckCtxt<'a, 'tcx>,
                                                     item_id: ast::NodeId,
-                                                    expr: &'tcx hir::Expr) {
+                                                    body: hir::BodyId) {
 
-    debug!("gather_loans_in_static_initializer(expr={:?})", expr);
+    debug!("gather_loans_in_static_initializer(expr={:?})", body);
 
     let mut sicx = StaticInitializerCtxt {
         bccx: bccx,
         item_id: item_id
     };
 
-    sicx.visit_expr(expr);
+    sicx.visit_nested_body(body);
 }
index 8461f6d061a5577f7505369459cbc7f16b5aa754..b15c1873f9bd84506dbe3cd7b3f5946bf83dad59 100644 (file)
 use std::mem;
 use std::path::Path;
 
-use super::super::MoveDataParamEnv;
 use super::super::MirBorrowckCtxtPreDataflow;
 use super::{BitDenotation, DataflowState};
 
 impl<O: BitDenotation> DataflowState<O> {
-    fn each_bit<F>(&self, ctxt: &O::Ctxt, words: &IdxSet<O::Idx>, mut f: F)
+    fn each_bit<F>(&self, words: &IdxSet<O::Idx>, mut f: F)
         where F: FnMut(O::Idx) {
         //! Helper for iterating over the bits in a bitvector.
 
-        let bits_per_block = self.operator.bits_per_block(ctxt);
+        let bits_per_block = self.operator.bits_per_block();
         let usize_bits: usize = mem::size_of::<usize>() * 8;
 
         for (word_index, &word) in words.words().iter().enumerate() {
@@ -65,35 +64,33 @@ fn each_bit<F>(&self, ctxt: &O::Ctxt, words: &IdxSet<O::Idx>, mut f: F)
     }
 
     pub fn interpret_set<'c, P>(&self,
-                                ctxt: &'c O::Ctxt,
+                                o: &'c O,
                                 words: &IdxSet<O::Idx>,
                                 render_idx: &P)
                                 -> Vec<&'c Debug>
-        where P: for <'b> Fn(&'b O::Ctxt, O::Idx) -> &'b Debug
+        where P: Fn(&O, O::Idx) -> &Debug
     {
         let mut v = Vec::new();
-        self.each_bit(ctxt, words, |i| {
-            v.push(render_idx(ctxt, i));
+        self.each_bit(words, |i| {
+            v.push(render_idx(o, i));
         });
         v
     }
 }
 
 pub trait MirWithFlowState<'tcx> {
-    type BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>;
+    type BD: BitDenotation;
     fn node_id(&self) -> NodeId;
     fn mir(&self) -> &Mir<'tcx>;
-    fn analysis_ctxt(&self) -> &<Self::BD as BitDenotation>::Ctxt;
     fn flow_state(&self) -> &DataflowState<Self::BD>;
 }
 
 impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
-    where 'tcx: 'a, BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>
+    where 'tcx: 'a, BD: BitDenotation
 {
     type BD = BD;
     fn node_id(&self) -> NodeId { self.node_id }
     fn mir(&self) -> &Mir<'tcx> { self.flow_state.mir() }
-    fn analysis_ctxt(&self) -> &BD::Ctxt { &self.flow_state.ctxt }
     fn flow_state(&self) -> &DataflowState<Self::BD> { &self.flow_state.flow_state }
 }
 
@@ -110,8 +107,8 @@ pub fn print_borrowck_graph_to<'a, 'tcx, BD, P>(
     path: &Path,
     render_idx: P)
     -> io::Result<()>
-    where BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>,
-          P: for <'b> Fn(&'b BD::Ctxt, BD::Idx) -> &'b Debug
+    where BD: BitDenotation,
+          P: Fn(&BD, BD::Idx) -> &Debug
 {
     let g = Graph { mbcx: mbcx, phantom: PhantomData, render_idx: render_idx };
     let mut v = Vec::new();
@@ -133,9 +130,7 @@ fn outgoing(mir: &Mir, bb: BasicBlock) -> Vec<Edge> {
 
 impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
     where MWF: MirWithFlowState<'tcx>,
-          P: for <'b> Fn(&'b <MWF::BD as BitDenotation>::Ctxt,
-                         <MWF::BD as BitDenotation>::Idx)
-                         -> &'b Debug,
+          P: for <'b> Fn(&'b MWF::BD, <MWF::BD as BitDenotation>::Idx) -> &'b Debug,
 {
     type Node = Node;
     type Edge = Edge;
@@ -227,9 +222,8 @@ fn chunked_present_left<W:io::Write>(w: &mut W,
         ::rustc_mir::graphviz::write_node_label(
             *n, self.mbcx.mir(), &mut v, 4,
             |w| {
-                let ctxt = self.mbcx.analysis_ctxt();
                 let flow = self.mbcx.flow_state();
-                let entry_interp = flow.interpret_set(ctxt,
+                let entry_interp = flow.interpret_set(&flow.operator,
                                                       flow.sets.on_entry_set_for(i),
                                                       &self.render_idx);
                 chunked_present_left(w, &entry_interp[..], chunk_size)?;
@@ -244,12 +238,11 @@ fn chunked_present_left<W:io::Write>(w: &mut W,
                        entrybits=bits_to_string(entry.words(), bits_per_block))
             },
             |w| {
-                let ctxt = self.mbcx.analysis_ctxt();
                 let flow = self.mbcx.flow_state();
                 let gen_interp =
-                    flow.interpret_set(ctxt, flow.sets.gen_set_for(i), &self.render_idx);
+                    flow.interpret_set(&flow.operator, flow.sets.gen_set_for(i), &self.render_idx);
                 let kill_interp =
-                    flow.interpret_set(ctxt, flow.sets.kill_set_for(i), &self.render_idx);
+                    flow.interpret_set(&flow.operator, flow.sets.kill_set_for(i), &self.render_idx);
                 chunked_present_left(w, &gen_interp[..], chunk_size)?;
                 let bits_per_block = flow.sets.bits_per_block();
                 {
index fcb453d81aa770c98a9fefca31bfddcc7280b42c..1fa4da94dd6bfae51f1052e820e0945ac66cdcf1 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_data_structures::indexed_set::{IdxSet};
 use rustc_data_structures::indexed_vec::Idx;
 
-use super::super::gather_moves::{MoveOutIndex, MovePathIndex};
+use super::super::gather_moves::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex};
 use super::super::MoveDataParamEnv;
 use super::super::DropFlagState;
 use super::super::drop_flag_effects_for_function_entry;
 pub struct MaybeInitializedLvals<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &'a Mir<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'tcx>,
 }
 
 impl<'a, 'tcx: 'a> MaybeInitializedLvals<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
-        MaybeInitializedLvals { tcx: tcx, mir: mir }
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+               mir: &'a Mir<'tcx>,
+               mdpe: &'a MoveDataParamEnv<'tcx>)
+               -> Self
+    {
+        MaybeInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe }
     }
 }
 
+impl<'a, 'tcx: 'a> HasMoveData<'tcx> for MaybeInitializedLvals<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
+}
+
 /// `MaybeUninitializedLvals` tracks all l-values that might be
 /// uninitialized upon reaching a particular point in the control flow
 /// for a function.
@@ -112,14 +121,23 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
 pub struct MaybeUninitializedLvals<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &'a Mir<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'tcx>,
 }
 
 impl<'a, 'tcx: 'a> MaybeUninitializedLvals<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
-        MaybeUninitializedLvals { tcx: tcx, mir: mir }
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+               mir: &'a Mir<'tcx>,
+               mdpe: &'a MoveDataParamEnv<'tcx>)
+               -> Self
+    {
+        MaybeUninitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe }
     }
 }
 
+impl<'a, 'tcx: 'a> HasMoveData<'tcx> for MaybeUninitializedLvals<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
+}
+
 /// `DefinitelyInitializedLvals` tracks all l-values that are definitely
 /// initialized upon reaching a particular point in the control flow
 /// for a function.
@@ -164,14 +182,23 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
 pub struct DefinitelyInitializedLvals<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &'a Mir<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'tcx>,
 }
 
 impl<'a, 'tcx: 'a> DefinitelyInitializedLvals<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
-        DefinitelyInitializedLvals { tcx: tcx, mir: mir }
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+               mir: &'a Mir<'tcx>,
+               mdpe: &'a MoveDataParamEnv<'tcx>)
+               -> Self
+    {
+        DefinitelyInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe }
     }
 }
 
+impl<'a, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedLvals<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
+}
+
 /// `MovingOutStatements` tracks the statements that perform moves out
 /// of particular l-values. More precisely, it tracks whether the
 /// *effect* of such moves (namely, the uninitialization of the
@@ -189,6 +216,11 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
 pub struct MovingOutStatements<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &'a Mir<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'tcx>,
+}
+
+impl<'a, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
 }
 
 impl<'a, 'tcx> MaybeInitializedLvals<'a, 'tcx> {
@@ -226,16 +258,15 @@ fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
 
 impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> {
     type Idx = MovePathIndex;
-    type Ctxt = MoveDataParamEnv<'tcx>;
     fn name() -> &'static str { "maybe_init" }
-    fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.move_data.move_paths.len()
+    fn bits_per_block(&self) -> usize {
+        self.move_data().move_paths.len()
     }
 
-    fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathIndex>)
+    fn start_block_effect(&self, sets: &mut BlockSets<MovePathIndex>)
     {
         drop_flag_effects_for_function_entry(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             |path, s| {
                 assert!(s == DropFlagState::Present);
                 sets.on_entry.add(&path);
@@ -243,60 +274,56 @@ fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathInd
     }
 
     fn statement_effect(&self,
-                        ctxt: &Self::Ctxt,
                         sets: &mut BlockSets<MovePathIndex>,
                         bb: mir::BasicBlock,
                         idx: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: idx },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn terminator_effect(&self,
-                         ctxt: &Self::Ctxt,
                          sets: &mut BlockSets<MovePathIndex>,
                          bb: mir::BasicBlock,
                          statements_len: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: statements_len },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn propagate_call_return(&self,
-                             ctxt: &Self::Ctxt,
                              in_out: &mut IdxSet<MovePathIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              dest_lval: &mir::Lvalue) {
         // when a call returns successfully, that means we need to set
         // the bits for that dest_lval to 1 (initialized).
-        on_lookup_result_bits(self.tcx, self.mir, &ctxt.move_data,
-                              ctxt.move_data.rev_lookup.find(dest_lval),
+        on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
+                              self.move_data().rev_lookup.find(dest_lval),
                               |mpi| { in_out.add(&mpi); });
     }
 }
 
 impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> {
     type Idx = MovePathIndex;
-    type Ctxt = MoveDataParamEnv<'tcx>;
     fn name() -> &'static str { "maybe_uninit" }
-    fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.move_data.move_paths.len()
+    fn bits_per_block(&self) -> usize {
+        self.move_data().move_paths.len()
     }
 
     // sets on_entry bits for Arg lvalues
-    fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathIndex>) {
+    fn start_block_effect(&self, sets: &mut BlockSets<MovePathIndex>) {
         // set all bits to 1 (uninit) before gathering counterevidence
         for e in sets.on_entry.words_mut() { *e = !0; }
 
         drop_flag_effects_for_function_entry(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             |path, s| {
                 assert!(s == DropFlagState::Present);
                 sets.on_entry.remove(&path);
@@ -304,59 +331,55 @@ fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathInd
     }
 
     fn statement_effect(&self,
-                        ctxt: &Self::Ctxt,
                         sets: &mut BlockSets<MovePathIndex>,
                         bb: mir::BasicBlock,
                         idx: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: idx },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn terminator_effect(&self,
-                         ctxt: &Self::Ctxt,
                          sets: &mut BlockSets<MovePathIndex>,
                          bb: mir::BasicBlock,
                          statements_len: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: statements_len },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn propagate_call_return(&self,
-                             ctxt: &Self::Ctxt,
                              in_out: &mut IdxSet<MovePathIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              dest_lval: &mir::Lvalue) {
         // when a call returns successfully, that means we need to set
         // the bits for that dest_lval to 0 (initialized).
-        on_lookup_result_bits(self.tcx, self.mir, &ctxt.move_data,
-                              ctxt.move_data.rev_lookup.find(dest_lval),
+        on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
+                              self.move_data().rev_lookup.find(dest_lval),
                               |mpi| { in_out.remove(&mpi); });
     }
 }
 
 impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
     type Idx = MovePathIndex;
-    type Ctxt = MoveDataParamEnv<'tcx>;
     fn name() -> &'static str { "definite_init" }
-    fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.move_data.move_paths.len()
+    fn bits_per_block(&self) -> usize {
+        self.move_data().move_paths.len()
     }
 
     // sets on_entry bits for Arg lvalues
-    fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathIndex>) {
+    fn start_block_effect(&self, sets: &mut BlockSets<MovePathIndex>) {
         for e in sets.on_entry.words_mut() { *e = 0; }
 
         drop_flag_effects_for_function_entry(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             |path, s| {
                 assert!(s == DropFlagState::Present);
                 sets.on_entry.add(&path);
@@ -364,63 +387,58 @@ fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathInd
     }
 
     fn statement_effect(&self,
-                        ctxt: &Self::Ctxt,
                         sets: &mut BlockSets<MovePathIndex>,
                         bb: mir::BasicBlock,
                         idx: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: idx },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn terminator_effect(&self,
-                         ctxt: &Self::Ctxt,
                          sets: &mut BlockSets<MovePathIndex>,
                          bb: mir::BasicBlock,
                          statements_len: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: statements_len },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn propagate_call_return(&self,
-                             ctxt: &Self::Ctxt,
                              in_out: &mut IdxSet<MovePathIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              dest_lval: &mir::Lvalue) {
         // when a call returns successfully, that means we need to set
         // the bits for that dest_lval to 1 (initialized).
-        on_lookup_result_bits(self.tcx, self.mir, &ctxt.move_data,
-                              ctxt.move_data.rev_lookup.find(dest_lval),
+        on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
+                              self.move_data().rev_lookup.find(dest_lval),
                               |mpi| { in_out.add(&mpi); });
     }
 }
 
 impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
     type Idx = MoveOutIndex;
-    type Ctxt = MoveDataParamEnv<'tcx>;
     fn name() -> &'static str { "moving_out" }
-    fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.move_data.moves.len()
+    fn bits_per_block(&self) -> usize {
+        self.move_data().moves.len()
     }
 
-    fn start_block_effect(&self,_move_data: &Self::Ctxt, _sets: &mut BlockSets<MoveOutIndex>) {
+    fn start_block_effect(&self, _sets: &mut BlockSets<MoveOutIndex>) {
         // no move-statements have been executed prior to function
         // execution, so this method has no effect on `_sets`.
     }
     fn statement_effect(&self,
-                        ctxt: &Self::Ctxt,
                         sets: &mut BlockSets<MoveOutIndex>,
                         bb: mir::BasicBlock,
                         idx: usize) {
-        let (tcx, mir, move_data) = (self.tcx, self.mir, &ctxt.move_data);
+        let (tcx, mir, move_data) = (self.tcx, self.mir, self.move_data());
         let stmt = &mir[bb].statements[idx];
         let loc_map = &move_data.loc_map;
         let path_map = &move_data.path_map;
@@ -435,7 +453,7 @@ fn statement_effect(&self,
             // here, in dataflow vector
             zero_to_one(sets.gen_set.words_mut(), *move_index);
         }
-        let bits_per_block = self.bits_per_block(ctxt);
+        let bits_per_block = self.bits_per_block();
         match stmt.kind {
             mir::StatementKind::SetDiscriminant { .. } => {
                 span_bug!(stmt.source_info.span, "SetDiscriminant should not exist in borrowck");
@@ -460,18 +478,17 @@ fn statement_effect(&self,
     }
 
     fn terminator_effect(&self,
-                         ctxt: &Self::Ctxt,
                          sets: &mut BlockSets<MoveOutIndex>,
                          bb: mir::BasicBlock,
                          statements_len: usize)
     {
-        let (mir, move_data) = (self.mir, &ctxt.move_data);
+        let (mir, move_data) = (self.mir, self.move_data());
         let term = mir[bb].terminator();
         let loc_map = &move_data.loc_map;
         let loc = Location { block: bb, statement_index: statements_len };
         debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}",
                term, loc, &loc_map[loc]);
-        let bits_per_block = self.bits_per_block(ctxt);
+        let bits_per_block = self.bits_per_block();
         for move_index in &loc_map[loc] {
             assert!(move_index.index() < bits_per_block);
             zero_to_one(sets.gen_set.words_mut(), *move_index);
@@ -479,13 +496,12 @@ fn terminator_effect(&self,
     }
 
     fn propagate_call_return(&self,
-                             ctxt: &Self::Ctxt,
                              in_out: &mut IdxSet<MoveOutIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              dest_lval: &mir::Lvalue) {
-        let move_data = &ctxt.move_data;
-        let bits_per_block = self.bits_per_block(ctxt);
+        let move_data = self.move_data();
+        let bits_per_block = self.bits_per_block();
 
         let path_map = &move_data.path_map;
         on_lookup_result_bits(self.tcx,
index 51817afbfeafdd53a7b24bc15f08a1d8dbc801ba..f11cf90834dd900f565c5f420f371b1fe34f6fee 100644 (file)
@@ -22,7 +22,6 @@
 use std::usize;
 
 use super::MirBorrowckCtxtPreDataflow;
-use super::MoveDataParamEnv;
 
 pub use self::sanity_check::sanity_check_via_rustc_peek;
 pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals};
 mod impls;
 
 pub trait Dataflow<BD: BitDenotation> {
-    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug;
+    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug;
 }
 
 impl<'a, 'tcx: 'a, BD> Dataflow<BD> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
-    where BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>> + DataflowOperator
+    where BD: BitDenotation + DataflowOperator
 {
-    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug {
+    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug {
         self.flow_state.build_sets();
         self.pre_dataflow_instrumentation(|c,i| p(c,i)).unwrap();
         self.flow_state.propagate();
@@ -48,7 +47,7 @@ fn dataflow<P>(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug {
 }
 
 struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O>
-    where O: 'b + BitDenotation, O::Ctxt: 'a
+    where O: 'b + BitDenotation
 {
     builder: &'b mut DataflowAnalysis<'a, 'tcx, O>,
     changed: bool,
@@ -79,7 +78,7 @@ fn build_sets(&mut self) {
 
         {
             let sets = &mut self.flow_state.sets.for_block(mir::START_BLOCK.index());
-            self.flow_state.operator.start_block_effect(&self.ctxt, sets);
+            self.flow_state.operator.start_block_effect(sets);
         }
 
         for (bb, data) in self.mir.basic_blocks().iter_enumerated() {
@@ -87,12 +86,12 @@ fn build_sets(&mut self) {
 
             let sets = &mut self.flow_state.sets.for_block(bb.index());
             for j_stmt in 0..statements.len() {
-                self.flow_state.operator.statement_effect(&self.ctxt, sets, bb, j_stmt);
+                self.flow_state.operator.statement_effect(sets, bb, j_stmt);
             }
 
             if terminator.is_some() {
                 let stmts_len = statements.len();
-                self.flow_state.operator.terminator_effect(&self.ctxt, sets, bb, stmts_len);
+                self.flow_state.operator.terminator_effect(sets, bb, stmts_len);
             }
         }
     }
@@ -137,10 +136,10 @@ fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf {
 }
 
 impl<'a, 'tcx: 'a, BD> MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
-    where BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>
+    where BD: BitDenotation
 {
     fn pre_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
-        where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug
+        where P: Fn(&BD, BD::Idx) -> &Debug
     {
         if let Some(ref path_str) = self.print_preflow_to {
             let path = dataflow_path(BD::name(), "preflow", path_str);
@@ -151,7 +150,7 @@ fn pre_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
     }
 
     fn post_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
-        where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug
+        where P: Fn(&BD, BD::Idx) -> &Debug
     {
         if let Some(ref path_str) = self.print_postflow_to {
             let path = dataflow_path(BD::name(), "postflow", path_str);
@@ -179,11 +178,10 @@ fn new(bits: IdxSetBuf<E>) -> Self {
 }
 
 pub struct DataflowAnalysis<'a, 'tcx: 'a, O>
-    where O: BitDenotation, O::Ctxt: 'a
+    where O: BitDenotation
 {
     flow_state: DataflowState<O>,
     mir: &'a Mir<'tcx>,
-    ctxt: &'a O::Ctxt,
 }
 
 impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O>
@@ -295,9 +293,6 @@ pub trait BitDenotation {
     /// Specifies what index type is used to access the bitvector.
     type Idx: Idx;
 
-    /// Specifies what, if any, separate context needs to be supplied for methods below.
-    type Ctxt;
-
     /// A name describing the dataflow analysis that this
     /// BitDenotation is supporting.  The name should be something
     /// suitable for plugging in as part of a filename e.g. avoid
@@ -308,7 +303,7 @@ pub trait BitDenotation {
     fn name() -> &'static str;
 
     /// Size of each bitvector allocated for each block in the analysis.
-    fn bits_per_block(&self, &Self::Ctxt) -> usize;
+    fn bits_per_block(&self) -> usize;
 
     /// Mutates the block-sets (the flow sets for the given
     /// basic block) according to the effects that have been
@@ -319,7 +314,7 @@ pub trait BitDenotation {
     /// (Typically this should only modify `sets.on_entry`, since the
     /// gen and kill sets should reflect the effects of *executing*
     /// the start block itself.)
-    fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<Self::Idx>);
+    fn start_block_effect(&self, sets: &mut BlockSets<Self::Idx>);
 
     /// Mutates the block-sets (the flow sets for the given
     /// basic block) according to the effects of evaluating statement.
@@ -332,7 +327,6 @@ pub trait BitDenotation {
     /// `bb_data` is the sequence of statements identifed by `bb` in
     /// the MIR.
     fn statement_effect(&self,
-                        ctxt: &Self::Ctxt,
                         sets: &mut BlockSets<Self::Idx>,
                         bb: mir::BasicBlock,
                         idx_stmt: usize);
@@ -348,7 +342,6 @@ fn statement_effect(&self,
     /// The effects applied here cannot depend on which branch the
     /// terminator took.
     fn terminator_effect(&self,
-                         ctxt: &Self::Ctxt,
                          sets: &mut BlockSets<Self::Idx>,
                          bb: mir::BasicBlock,
                          idx_term: usize);
@@ -373,7 +366,6 @@ fn terminator_effect(&self,
     /// kill-sets associated with each edge coming out of the basic
     /// block.
     fn propagate_call_return(&self,
-                             ctxt: &Self::Ctxt,
                              in_out: &mut IdxSet<Self::Idx>,
                              call_bb: mir::BasicBlock,
                              dest_bb: mir::BasicBlock,
@@ -385,9 +377,8 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
 {
     pub fn new(_tcx: TyCtxt<'a, 'tcx, 'tcx>,
                mir: &'a Mir<'tcx>,
-               ctxt: &'a D::Ctxt,
                denotation: D) -> Self {
-        let bits_per_block = denotation.bits_per_block(&ctxt);
+        let bits_per_block = denotation.bits_per_block();
         let usize_bits = mem::size_of::<usize>() * 8;
         let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits;
 
@@ -405,7 +396,6 @@ pub fn new(_tcx: TyCtxt<'a, 'tcx, 'tcx>,
         });
 
         DataflowAnalysis {
-            ctxt: ctxt,
             mir: mir,
             flow_state: DataflowState {
                 sets: AllSets {
@@ -482,7 +472,7 @@ fn propagate_bits_into_graph_successors_of(
                     // N.B.: This must be done *last*, after all other
                     // propagation, as documented in comment above.
                     self.flow_state.operator.propagate_call_return(
-                        &self.ctxt, in_out, bb, *dest_bb, dest_lval);
+                        in_out, bb, *dest_bb, dest_lval);
                     self.propagate_bits_into_entry_set_for(in_out, changed, dest_bb);
                 }
             }
index 916d17dcc91deff5b598dd9d7f5f7dab7a3c915b..ea6ef423c92cebb89f577a6d8055111bc5d83f20 100644 (file)
@@ -17,9 +17,9 @@
 use rustc_data_structures::indexed_vec::Idx;
 
 use super::super::gather_moves::{MovePathIndex, LookupResult};
-use super::super::MoveDataParamEnv;
 use super::BitDenotation;
 use super::DataflowResults;
+use super::super::gather_moves::HasMoveData;
 
 /// This function scans `mir` for all calls to the intrinsic
 /// `rustc_peek` that have the expression form `rustc_peek(&expr)`.
@@ -41,9 +41,8 @@ pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 mir: &Mir<'tcx>,
                                                 id: ast::NodeId,
                                                 _attributes: &[ast::Attribute],
-                                                flow_ctxt: &O::Ctxt,
                                                 results: &DataflowResults<O>)
-    where O: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>, Idx=MovePathIndex>
+    where O: BitDenotation<Idx=MovePathIndex> + HasMoveData<'tcx>
 {
     debug!("sanity_check_via_rustc_peek id: {:?}", id);
     // FIXME: this is not DRY. Figure out way to abstract this and
@@ -51,18 +50,17 @@ pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // stuff, so such generalization may not be realistic.)
 
     for bb in mir.basic_blocks().indices() {
-        each_block(tcx, mir, flow_ctxt, results, bb);
+        each_block(tcx, mir, results, bb);
     }
 }
 
 fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            mir: &Mir<'tcx>,
-                           ctxt: &O::Ctxt,
                            results: &DataflowResults<O>,
                            bb: mir::BasicBlock) where
-    O: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>, Idx=MovePathIndex>
+    O: BitDenotation<Idx=MovePathIndex> + HasMoveData<'tcx>
 {
-    let move_data = &ctxt.move_data;
+    let move_data = results.0.operator.move_data();
     let mir::BasicBlockData { ref statements, ref terminator, is_cleanup: _ } = mir[bb];
 
     let (args, span) = match is_rustc_peek(tcx, terminator) {
@@ -146,7 +144,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // reset GEN and KILL sets before emulating their effect.
         for e in sets.gen_set.words_mut() { *e = 0; }
         for e in sets.kill_set.words_mut() { *e = 0; }
-        results.0.operator.statement_effect(ctxt, &mut sets, bb, j);
+        results.0.operator.statement_effect(&mut sets, bb, j);
         sets.on_entry.union(sets.gen_set);
         sets.on_entry.subtract(sets.kill_set);
     }
index 4f49bfc9725b345078da7699fe1b680b9a5cfd31..8e0d9c147824d81642d2d16ba76e88292be141eb 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::gather_moves::{MoveData, MovePathIndex, LookupResult};
+use super::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult};
 use super::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
 use super::dataflow::{DataflowResults};
 use super::{drop_flag_effects_for_location, on_all_children_bits};
@@ -51,11 +51,13 @@ fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 param_env: param_env
             };
             let flow_inits =
-                super::do_dataflow(tcx, mir, id, &[], &env,
-                                   MaybeInitializedLvals::new(tcx, mir));
+                super::do_dataflow(tcx, mir, id, &[],
+                                   MaybeInitializedLvals::new(tcx, mir, &env),
+                                   |bd, p| &bd.move_data().move_paths[p]);
             let flow_uninits =
-                super::do_dataflow(tcx, mir, id, &[], &env,
-                                   MaybeUninitializedLvals::new(tcx, mir));
+                super::do_dataflow(tcx, mir, id, &[],
+                                   MaybeUninitializedLvals::new(tcx, mir, &env),
+                                   |bd, p| &bd.move_data().move_paths[p]);
 
             ElaborateDropsCtxt {
                 tcx: tcx,
@@ -481,54 +483,55 @@ fn drop_halfladder<'a>(&mut self,
                            is_cleanup: bool)
                            -> Vec<BasicBlock>
     {
-        let mut succ = succ;
         let mut unwind_succ = if is_cleanup {
             None
         } else {
             c.unwind
         };
-        let mut update_drop_flag = true;
+
+        let mut succ = self.new_block(
+            c, c.is_cleanup, TerminatorKind::Goto { target: succ }
+        );
+
+        // Always clear the "master" drop flag at the bottom of the
+        // ladder. This is needed because the "master" drop flag
+        // protects the ADT's discriminant, which is invalidated
+        // after the ADT is dropped.
+        self.set_drop_flag(
+            Location { block: succ, statement_index: 0 },
+            c.path,
+            DropFlagState::Absent
+        );
 
         fields.iter().rev().enumerate().map(|(i, &(ref lv, path))| {
-            let drop_block = match path {
-                Some(path) => {
-                    debug!("drop_ladder: for std field {} ({:?})", i, lv);
-
-                    self.elaborated_drop_block(&DropCtxt {
-                        source_info: c.source_info,
-                        is_cleanup: is_cleanup,
-                        init_data: c.init_data,
-                        lvalue: lv,
-                        path: path,
-                        succ: succ,
-                        unwind: unwind_succ,
-                    })
-                }
-                None => {
-                    debug!("drop_ladder: for rest field {} ({:?})", i, lv);
-
-                    let blk = self.complete_drop(&DropCtxt {
-                        source_info: c.source_info,
-                        is_cleanup: is_cleanup,
-                        init_data: c.init_data,
-                        lvalue: lv,
-                        path: c.path,
-                        succ: succ,
-                        unwind: unwind_succ,
-                    }, update_drop_flag);
-
-                    // the drop flag has been updated - updating
-                    // it again would clobber it.
-                    update_drop_flag = false;
-
-                    blk
-                }
+            succ = if let Some(path) = path {
+                debug!("drop_ladder: for std field {} ({:?})", i, lv);
+
+                self.elaborated_drop_block(&DropCtxt {
+                    source_info: c.source_info,
+                    is_cleanup: is_cleanup,
+                    init_data: c.init_data,
+                    lvalue: lv,
+                    path: path,
+                    succ: succ,
+                    unwind: unwind_succ,
+                })
+            } else {
+                debug!("drop_ladder: for rest field {} ({:?})", i, lv);
+
+                self.complete_drop(&DropCtxt {
+                    source_info: c.source_info,
+                    is_cleanup: is_cleanup,
+                    init_data: c.init_data,
+                    lvalue: lv,
+                    path: c.path,
+                    succ: succ,
+                    unwind: unwind_succ,
+                }, false)
             };
 
-            succ = drop_block;
             unwind_succ = unwind_ladder.as_ref().map(|p| p[i]);
-
-            drop_block
+            succ
         }).collect()
     }
 
index 02064b52cb1fb2c24b264f621bc879294d29e021..2a9acaf58b8f2bf091ccce29eb8aede48a6abb88 100644 (file)
@@ -120,6 +120,10 @@ pub struct MoveData<'tcx> {
     pub rev_lookup: MovePathLookup<'tcx>,
 }
 
+pub trait HasMoveData<'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx>;
+}
+
 #[derive(Debug)]
 pub struct LocationMap<T> {
     /// Location-indexed (BasicBlock for outer index, index within BB
index 9035c2ab3c236e05cf85fb26813a69dab174bbee..c7bd5b7ed0461c2c7bd0ef3340a4b7304ee5ba96 100644 (file)
 use borrowck::BorrowckCtxt;
 
 use syntax::ast::{self, MetaItem};
-use syntax_pos::{Span, DUMMY_SP};
-
-use rustc::hir;
-use rustc::hir::intravisit::{FnKind};
+use syntax_pos::DUMMY_SP;
 
 use rustc::mir::{self, BasicBlock, BasicBlockData, Mir, Statement, Terminator, Location};
 use rustc::session::Session;
@@ -32,7 +29,9 @@
 use self::dataflow::{Dataflow, DataflowAnalysis, DataflowResults};
 use self::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
 use self::dataflow::{DefinitelyInitializedLvals};
-use self::gather_moves::{MoveData, MovePathIndex, LookupResult};
+use self::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult};
+
+use std::fmt;
 
 fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<MetaItem> {
     for attr in attrs {
@@ -55,44 +54,34 @@ pub struct MoveDataParamEnv<'tcx> {
 }
 
 pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
-                    fk: FnKind,
-                    _decl: &hir::FnDecl,
-                    body: &hir::Expr,
-                    _sp: Span,
                     id: ast::NodeId,
                     attributes: &[ast::Attribute]) {
-    match fk {
-        FnKind::ItemFn(name, ..) |
-        FnKind::Method(name, ..) => {
-            debug!("borrowck_mir({}) UNIMPLEMENTED", name);
-        }
-        FnKind::Closure(_) => {
-            debug!("borrowck_mir closure (body.id={}) UNIMPLEMENTED", body.id);
-        }
-    }
-
     let tcx = bcx.tcx;
-    let param_env = ty::ParameterEnvironment::for_item(tcx, id);
-
-    let mir = &tcx.item_mir(tcx.map.local_def_id(id));
+    let def_id = tcx.map.local_def_id(id);
+    debug!("borrowck_mir({}) UNIMPLEMENTED", tcx.item_path_str(def_id));
 
+    let mir = &tcx.item_mir(def_id);
+    let param_env = ty::ParameterEnvironment::for_item(tcx, id);
     let move_data = MoveData::gather_moves(mir, tcx, &param_env);
     let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
     let flow_inits =
-        do_dataflow(tcx, mir, id, attributes, &mdpe, MaybeInitializedLvals::new(tcx, mir));
+        do_dataflow(tcx, mir, id, attributes, MaybeInitializedLvals::new(tcx, mir, &mdpe),
+                    |bd, i| &bd.move_data().move_paths[i]);
     let flow_uninits =
-        do_dataflow(tcx, mir, id, attributes, &mdpe, MaybeUninitializedLvals::new(tcx, mir));
+        do_dataflow(tcx, mir, id, attributes, MaybeUninitializedLvals::new(tcx, mir, &mdpe),
+                    |bd, i| &bd.move_data().move_paths[i]);
     let flow_def_inits =
-        do_dataflow(tcx, mir, id, attributes, &mdpe, DefinitelyInitializedLvals::new(tcx, mir));
+        do_dataflow(tcx, mir, id, attributes, DefinitelyInitializedLvals::new(tcx, mir, &mdpe),
+                    |bd, i| &bd.move_data().move_paths[i]);
 
     if has_rustc_mir_with(attributes, "rustc_peek_maybe_init").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &flow_inits);
+        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_inits);
     }
     if has_rustc_mir_with(attributes, "rustc_peek_maybe_uninit").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &flow_uninits);
+        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_uninits);
     }
     if has_rustc_mir_with(attributes, "rustc_peek_definite_init").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &flow_def_inits);
+        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_def_inits);
     }
 
     if has_rustc_mir_with(attributes, "stop_after_dataflow").is_some() {
@@ -103,7 +92,7 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
         bcx: bcx,
         mir: mir,
         node_id: id,
-        move_data: mdpe.move_data,
+        move_data: &mdpe.move_data,
         flow_inits: flow_inits,
         flow_uninits: flow_uninits,
     };
@@ -115,13 +104,15 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
     debug!("borrowck_mir done");
 }
 
-fn do_dataflow<'a, 'tcx, BD>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             mir: &Mir<'tcx>,
-                             node_id: ast::NodeId,
-                             attributes: &[ast::Attribute],
-                             ctxt: &BD::Ctxt,
-                             bd: BD) -> DataflowResults<BD>
-    where BD: BitDenotation<Idx=MovePathIndex, Ctxt=MoveDataParamEnv<'tcx>> + DataflowOperator
+fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                mir: &Mir<'tcx>,
+                                node_id: ast::NodeId,
+                                attributes: &[ast::Attribute],
+                                bd: BD,
+                                p: P)
+                                -> DataflowResults<BD>
+    where BD: BitDenotation<Idx=MovePathIndex> + DataflowOperator,
+          P: Fn(&BD, BD::Idx) -> &fmt::Debug
 {
     let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option<String> {
         if let Some(item) = has_rustc_mir_with(attrs, name) {
@@ -146,16 +137,15 @@ fn do_dataflow<'a, 'tcx, BD>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         node_id: node_id,
         print_preflow_to: print_preflow_to,
         print_postflow_to: print_postflow_to,
-        flow_state: DataflowAnalysis::new(tcx, mir, ctxt, bd),
+        flow_state: DataflowAnalysis::new(tcx, mir, bd),
     };
 
-    mbcx.dataflow(|ctxt, i| &ctxt.move_data.move_paths[i]);
+    mbcx.dataflow(p);
     mbcx.flow_state.results()
 }
 
 
-pub struct MirBorrowckCtxtPreDataflow<'a, 'tcx: 'a, BD>
-    where BD: BitDenotation, BD::Ctxt: 'a
+pub struct MirBorrowckCtxtPreDataflow<'a, 'tcx: 'a, BD> where BD: BitDenotation
 {
     node_id: ast::NodeId,
     flow_state: DataflowAnalysis<'a, 'tcx, BD>,
@@ -168,7 +158,7 @@ pub struct MirBorrowckCtxt<'b, 'a: 'b, 'tcx: 'a> {
     bcx: &'b mut BorrowckCtxt<'a, 'tcx>,
     mir: &'b Mir<'tcx>,
     node_id: ast::NodeId,
-    move_data: MoveData<'tcx>,
+    move_data: &'b MoveData<'tcx>,
     flow_inits: DataflowResults<MaybeInitializedLvals<'b, 'tcx>>,
     flow_uninits: DataflowResults<MaybeUninitializedLvals<'b, 'tcx>>
 }
index ecf5c3ef176e566f59003cbf943eaa0cdd98cca5..1ba313015d59685c82af9830cd77a9923b20352d 100644 (file)
@@ -68,7 +68,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     }
 
     fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
-                b: hir::ExprId, s: Span, id: ast::NodeId) {
+                b: hir::BodyId, s: Span, id: ast::NodeId) {
         match fk {
             FnKind::ItemFn(..) |
             FnKind::Method(..) => {
@@ -88,15 +88,15 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
     }
 
     fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
-        if let hir::ConstTraitItem(_, Some(ref expr)) = ti.node {
-            gather_loans::gather_loans_in_static_initializer(self, ti.id, &expr);
+        if let hir::TraitItemKind::Const(_, Some(expr)) = ti.node {
+            gather_loans::gather_loans_in_static_initializer(self, ti.id, expr);
         }
         intravisit::walk_trait_item(self, ti);
     }
 
     fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
-        if let hir::ImplItemKind::Const(_, ref expr) = ii.node {
-            gather_loans::gather_loans_in_static_initializer(self, ii.id, &expr);
+        if let hir::ImplItemKind::Const(_, expr) = ii.node {
+            gather_loans::gather_loans_in_static_initializer(self, ii.id, expr);
         }
         intravisit::walk_impl_item(self, ii);
     }
@@ -141,9 +141,9 @@ fn borrowck_item<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, item: &'tcx hir::I
     // loan step is intended for things that have a data
     // flow dependent conditions.
     match item.node {
-        hir::ItemStatic(.., ref ex) |
-        hir::ItemConst(_, ref ex) => {
-            gather_loans::gather_loans_in_static_initializer(this, item.id, &ex);
+        hir::ItemStatic(.., ex) |
+        hir::ItemConst(_, ex) => {
+            gather_loans::gather_loans_in_static_initializer(this, item.id, ex);
         }
         _ => { }
     }
@@ -161,25 +161,25 @@ pub struct AnalysisData<'a, 'tcx: 'a> {
 fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
                          fk: FnKind<'tcx>,
                          decl: &'tcx hir::FnDecl,
-                         body_id: hir::ExprId,
+                         body_id: hir::BodyId,
                          sp: Span,
                          id: ast::NodeId,
                          attributes: &[ast::Attribute]) {
     debug!("borrowck_fn(id={})", id);
 
-    let body = this.tcx.map.expr(body_id);
+    let body = this.tcx.map.body(body_id);
 
     if attributes.iter().any(|item| item.check_name("rustc_mir_borrowck")) {
         this.with_temp_region_map(id, |this| {
-            mir::borrowck_mir(this, fk, decl, body, sp, id, attributes)
+            mir::borrowck_mir(this, id, attributes)
         });
     }
 
-    let cfg = cfg::CFG::new(this.tcx, body);
+    let cfg = cfg::CFG::new(this.tcx, &body.value);
     let AnalysisData { all_loans,
                        loans: loan_dfcx,
                        move_data: flowed_moves } =
-        build_borrowck_dataflow_data(this, fk, decl, &cfg, body, sp, id);
+        build_borrowck_dataflow_data(this, &cfg, body, id);
 
     move_data::fragments::instrument_move_fragments(&flowed_moves.move_data,
                                                     this.tcx,
@@ -194,31 +194,31 @@ fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
                              &flowed_moves,
                              &all_loans[..],
                              id,
-                             decl,
                              body);
 
     intravisit::walk_fn(this, fk, decl, body_id, sp, id);
 }
 
 fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
-                                          fk: FnKind<'tcx>,
-                                          decl: &'tcx hir::FnDecl,
                                           cfg: &cfg::CFG,
-                                          body: &'tcx hir::Expr,
-                                          sp: Span,
+                                          body: &'tcx hir::Body,
                                           id: ast::NodeId)
                                           -> AnalysisData<'a, 'tcx>
 {
     // Check the body of fn items.
     let tcx = this.tcx;
-    let id_range = intravisit::compute_id_range_for_fn_body(fk, decl, body, sp, id, &tcx.map);
+    let id_range = {
+        let mut visitor = intravisit::IdRangeComputingVisitor::new(&tcx.map);
+        visitor.visit_body(body);
+        visitor.result()
+    };
     let (all_loans, move_data) =
-        gather_loans::gather_loans_in_fn(this, id, decl, body);
+        gather_loans::gather_loans_in_fn(this, id, body);
 
     let mut loan_dfcx =
         DataFlowContext::new(this.tcx,
                              "borrowck",
-                             Some(decl),
+                             Some(body),
                              cfg,
                              LoanDataFlowOperator,
                              id_range,
@@ -235,7 +235,6 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
                                                       this.tcx,
                                                       cfg,
                                                       id_range,
-                                                      decl,
                                                       body);
 
     AnalysisData { all_loans: all_loans,
@@ -263,14 +262,11 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
         }
     };
 
-    let body = tcx.map.expr(fn_parts.body);
+    let body = tcx.map.body(fn_parts.body);
 
     let dataflow_data = build_borrowck_dataflow_data(&mut bccx,
-                                                     fn_parts.kind,
-                                                     &fn_parts.decl,
                                                      cfg,
                                                      body,
-                                                     fn_parts.span,
                                                      fn_parts.id);
 
     (bccx, dataflow_data)
@@ -416,7 +412,7 @@ pub fn closure_to_block(closure_id: ast::NodeId,
     match tcx.map.get(closure_id) {
         hir_map::NodeExpr(expr) => match expr.node {
             hir::ExprClosure(.., body_id, _) => {
-                body_id.node_id()
+                body_id.node_id
             }
             _ => {
                 bug!("encountered non-closure id: {}", closure_id)
@@ -1121,22 +1117,21 @@ fn note_and_explain_mutbl_error(&self, db: &mut DiagnosticBuilder, err: &BckErro
                 if let Categorization::Deref(ref inner_cmt, ..) = err.cmt.cat {
                     if let Categorization::Local(local_id) = inner_cmt.cat {
                         let parent = self.tcx.map.get_parent_node(local_id);
-                        let opt_fn_decl = FnLikeNode::from_node(self.tcx.map.get(parent))
-                            .map(|fn_like| fn_like.decl());
 
-                        if let Some(fn_decl) = opt_fn_decl {
-                            if let Some(ref arg) = fn_decl.inputs.iter()
-                                .find(|ref arg| arg.pat.id == local_id) {
+                        if let Some(fn_like) = FnLikeNode::from_node(self.tcx.map.get(parent)) {
+                            if let Some(i) = self.tcx.map.body(fn_like.body()).arguments.iter()
+                                                     .position(|arg| arg.pat.id == local_id) {
+                                let arg_ty = &fn_like.decl().inputs[i];
                                 if let hir::TyRptr(
                                     opt_lifetime,
                                     hir::MutTy{mutbl: hir::Mutability::MutImmutable, ref ty}) =
-                                    arg.ty.node {
+                                    arg_ty.node {
                                     if let Some(lifetime) = opt_lifetime {
                                         if let Ok(snippet) = self.tcx.sess.codemap()
                                             .span_to_snippet(ty.span) {
                                             if let Ok(lifetime_snippet) = self.tcx.sess.codemap()
                                                 .span_to_snippet(lifetime.span) {
-                                                    db.span_label(arg.ty.span,
+                                                    db.span_label(arg_ty.span,
                                                                   &format!("use `&{} mut {}` \
                                                                             here to make mutable",
                                                                             lifetime_snippet,
@@ -1145,9 +1140,9 @@ fn note_and_explain_mutbl_error(&self, db: &mut DiagnosticBuilder, err: &BckErro
                                         }
                                     }
                                     else if let Ok(snippet) = self.tcx.sess.codemap()
-                                        .span_to_snippet(arg.ty.span) {
+                                        .span_to_snippet(arg_ty.span) {
                                         if snippet.starts_with("&") {
-                                            db.span_label(arg.ty.span,
+                                            db.span_label(arg_ty.span,
                                                           &format!("use `{}` here to make mutable",
                                                                    snippet.replace("&", "&mut ")));
                                         }
index 32bda5e11620ac2429a3dd22be4257b4dc18adf4..a02aba7208c7fe4be3c6975eb1ac8d24a266e4d6 100644 (file)
@@ -655,13 +655,12 @@ pub fn new(move_data: MoveData<'tcx>,
                tcx: TyCtxt<'a, 'tcx, 'tcx>,
                cfg: &cfg::CFG,
                id_range: IdRange,
-               decl: &hir::FnDecl,
-               body: &hir::Expr)
+               body: &hir::Body)
                -> FlowedMoveData<'a, 'tcx> {
         let mut dfcx_moves =
             DataFlowContext::new(tcx,
                                  "flowed_move_data_moves",
-                                 Some(decl),
+                                 Some(body),
                                  cfg,
                                  MoveDataFlowOperator,
                                  id_range,
@@ -669,7 +668,7 @@ pub fn new(move_data: MoveData<'tcx>,
         let mut dfcx_assign =
             DataFlowContext::new(tcx,
                                  "flowed_move_data_assigns",
-                                 Some(decl),
+                                 Some(body),
                                  cfg,
                                  AssignDataFlowOperator,
                                  id_range,
index 23771f4bae3dc109cb81e6b0383443c421f344ba..ebe103490110436e6712fbf3b86b52805cf655c8 100644 (file)
@@ -324,7 +324,6 @@ fn apply_constructor<'a, 'tcx>(
                     let v = ctor.variant_for_adt(adt);
                     let qpath = hir::QPath::Resolved(None, P(hir::Path {
                         span: DUMMY_SP,
-                        global: false,
                         def: Def::Err,
                         segments: vec![hir::PathSegment::from_name(v.name)].into(),
                     }));
index 786b59e818da2052de8fc7f4e7e3c65523698cfe..01b19e1f53979d8dd563a9ed60873b47983fe98b 100644 (file)
@@ -30,7 +30,6 @@
 
 use rustc::hir::def::*;
 use rustc::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
-use rustc::hir::print::pat_to_string;
 use rustc::hir::{self, Pat, PatKind};
 
 use rustc_back::slice;
@@ -43,39 +42,17 @@ struct OuterVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> }
 
 impl<'a, 'tcx> Visitor<'tcx> for OuterVisitor<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::None
-    }
-
-    fn visit_expr(&mut self, _expr: &'tcx hir::Expr) {
-        return // const, static and N in [T; N] - shouldn't contain anything
-    }
-
-    fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
-        if let hir::ConstTraitItem(..) = item.node {
-            return // nothing worth match checking in a constant
-        } else {
-            intravisit::walk_trait_item(self, item);
-        }
-    }
-
-    fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
-        if let hir::ImplItemKind::Const(..) = item.node {
-            return // nothing worth match checking in a constant
-        } else {
-            intravisit::walk_impl_item(self, item);
-        }
+        NestedVisitorMap::OnlyBodies(&self.tcx.map)
     }
 
     fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
-                b: hir::ExprId, s: Span, id: ast::NodeId) {
-        if let FnKind::Closure(..) = fk {
-            span_bug!(s, "check_match: closure outside of function")
-        }
+                b: hir::BodyId, s: Span, id: ast::NodeId) {
+        intravisit::walk_fn(self, fk, fd, b, s, id);
 
         MatchVisitor {
             tcx: self.tcx,
             param_env: &ty::ParameterEnvironment::for_item(self.tcx, id)
-        }.visit_fn(fk, fd, b, s, id);
+        }.visit_body(self.tcx.map.body(b));
     }
 }
 
@@ -96,7 +73,7 @@ struct MatchVisitor<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.map)
+        NestedVisitorMap::None
     }
 
     fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
@@ -119,13 +96,12 @@ fn visit_local(&mut self, loc: &'tcx hir::Local) {
         self.check_patterns(false, slice::ref_slice(&loc.pat));
     }
 
-    fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
-                b: hir::ExprId, s: Span, n: ast::NodeId) {
-        intravisit::walk_fn(self, fk, fd, b, s, n);
+    fn visit_body(&mut self, body: &'tcx hir::Body) {
+        intravisit::walk_body(self, body);
 
-        for input in &fd.inputs {
-            self.check_irrefutable(&input.pat, true);
-            self.check_patterns(false, slice::ref_slice(&input.pat));
+        for arg in &body.arguments {
+            self.check_irrefutable(&arg.pat, true);
+            self.check_patterns(false, slice::ref_slice(&arg.pat));
         }
     }
 }
@@ -254,7 +230,9 @@ fn check_irrefutable(&self, pat: &Pat, is_fn_arg: bool) {
                 Useful => bug!()
             };
 
-            let pattern_string = pat_to_string(witness[0].single_pattern());
+            let pattern_string = hir::print::to_string(&self.tcx.map, |s| {
+                s.print_pat(witness[0].single_pattern())
+            });
             let mut diag = struct_span_err!(
                 self.tcx.sess, pat.span, E0005,
                 "refutable pattern in {}: `{}` not covered",
@@ -405,7 +383,9 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                         },
                         _ => bug!(),
                     };
-                    let pattern_string = pat_to_string(witness);
+                    let pattern_string = hir::print::to_string(&cx.tcx.map, |s| {
+                        s.print_pat(witness)
+                    });
                     struct_span_err!(cx.tcx.sess, sp, E0297,
                         "refutable pattern in `for` loop binding: \
                                 `{}` not covered",
@@ -415,7 +395,7 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                 },
                 _ => {
                     let pattern_strings: Vec<_> = witnesses.iter().map(|w| {
-                        pat_to_string(w)
+                        hir::print::to_string(&cx.tcx.map, |s| s.print_pat(w))
                     }).collect();
                     const LIMIT: usize = 3;
                     let joined_patterns = match pattern_strings.len() {
index 83b0d9dec6d904c087a7f16ec18404a6006b267d..b24cd261dd58474730ee98fc242ef15f222e803f 100644 (file)
@@ -576,18 +576,18 @@ enum Enum {
 
 
 E0306: r##"
-In an array literal `[x; N]`, `N` is the number of elements in the array. This
+In an array type `[T; N]`, `N` is the number of elements in the array. This
 must be an unsigned integer. Erroneous code example:
 
 ```compile_fail,E0306
-let x = [0i32; true]; // error: expected positive integer for repeat count,
-                      //        found boolean
+const X: [i32; true] = [0]; // error: expected `usize` for array length,
+                            //        found boolean
 ```
 
 Working example:
 
 ```
-let x = [0i32; 2];
+const X: [i32; 1] = [0];
 ```
 "##,
 }
index 9fcab1239899fed2b44055026b324cb5f3ee3c80..e8e7a2eb7ede0919fb3c167aa0416312ee0350e5 100644 (file)
@@ -17,7 +17,6 @@
 
 use rustc::hir::map as ast_map;
 use rustc::hir::map::blocks::FnLikeNode;
-use rustc::middle::cstore::InlinedItem;
 use rustc::traits;
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::DefId;
@@ -56,15 +55,17 @@ macro_rules! math {
 fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   variant_def: DefId)
                                   -> Option<&'tcx Expr> {
-    fn variant_expr<'a>(variants: &'a [hir::Variant], id: ast::NodeId)
-                        -> Option<&'a Expr> {
+    let variant_expr = |variants: &'tcx [hir::Variant], id: ast::NodeId |
+                        -> Option<&'tcx Expr> {
         for variant in variants {
             if variant.node.data.id() == id {
-                return variant.node.disr_expr.as_ref().map(|e| &**e);
+                return variant.node.disr_expr.map(|e| {
+                    &tcx.map.body(e).value
+                });
             }
         }
         None
-    }
+    };
 
     if let Some(variant_node_id) = tcx.map.as_local_node_id(variant_def) {
         let enum_node_id = tcx.map.get_parent(variant_node_id);
@@ -96,21 +97,24 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         match tcx.map.find(node_id) {
             None => None,
             Some(ast_map::NodeItem(it)) => match it.node {
-                hir::ItemConst(ref ty, ref const_expr) => {
-                    Some((&const_expr, tcx.ast_ty_to_prim_ty(ty)))
+                hir::ItemConst(ref ty, body) => {
+                    Some((&tcx.map.body(body).value,
+                          tcx.ast_ty_to_prim_ty(ty)))
                 }
                 _ => None
             },
             Some(ast_map::NodeTraitItem(ti)) => match ti.node {
-                hir::ConstTraitItem(ref ty, ref expr_option) => {
+                hir::TraitItemKind::Const(ref ty, default) => {
                     if let Some(substs) = substs {
                         // If we have a trait item and the substitutions for it,
                         // `resolve_trait_associated_const` will select an impl
                         // or the default.
                         let trait_id = tcx.map.get_parent(node_id);
                         let trait_id = tcx.map.local_def_id(trait_id);
-                        let default_value = expr_option.as_ref()
-                            .map(|expr| (&**expr, tcx.ast_ty_to_prim_ty(ty)));
+                        let default_value = default.map(|body| {
+                            (&tcx.map.body(body).value,
+                             tcx.ast_ty_to_prim_ty(ty))
+                        });
                         resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs)
                     } else {
                         // Technically, without knowing anything about the
@@ -125,29 +129,19 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 _ => None
             },
             Some(ast_map::NodeImplItem(ii)) => match ii.node {
-                hir::ImplItemKind::Const(ref ty, ref expr) => {
-                    Some((&expr, tcx.ast_ty_to_prim_ty(ty)))
+                hir::ImplItemKind::Const(ref ty, body) => {
+                    Some((&tcx.map.body(body).value,
+                          tcx.ast_ty_to_prim_ty(ty)))
                 }
                 _ => None
             },
             Some(_) => None
         }
     } else {
-        match tcx.extern_const_statics.borrow().get(&def_id) {
-            Some(&None) => return None,
-            Some(&Some((expr_id, ty))) => {
-                return Some((tcx.map.expect_expr(expr_id), ty));
-            }
-            None => {}
-        }
-        let mut used_substs = false;
-        let expr_ty = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
-            Some((&InlinedItem { body: ref const_expr, .. }, _)) => {
-                Some((&**const_expr, Some(tcx.sess.cstore.item_type(tcx, def_id))))
-            }
-            _ => None
-        };
-        let expr_ty = match tcx.sess.cstore.describe_def(def_id) {
+        let expr_ty = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| {
+            (&body.value, Some(tcx.sess.cstore.item_type(tcx, def_id)))
+        });
+        match tcx.sess.cstore.describe_def(def_id) {
             Some(Def::AssociatedConst(_)) => {
                 let trait_id = tcx.sess.cstore.trait_of_item(def_id);
                 // As mentioned in the comments above for in-crate
@@ -155,8 +149,6 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 // trait-associated const if the caller gives us the
                 // substitutions for the reference to it.
                 if let Some(trait_id) = trait_id {
-                    used_substs = true;
-
                     if let Some(substs) = substs {
                         resolve_trait_associated_const(tcx, def_id, expr_ty, trait_id, substs)
                     } else {
@@ -168,70 +160,27 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             },
             Some(Def::Const(..)) => expr_ty,
             _ => None
-        };
-        // If we used the substitutions, particularly to choose an impl
-        // of a trait-associated const, don't cache that, because the next
-        // lookup with the same def_id may yield a different result.
-        if !used_substs {
-            tcx.extern_const_statics
-               .borrow_mut()
-               .insert(def_id, expr_ty.map(|(e, t)| (e.id, t)));
         }
-        expr_ty
     }
 }
 
-fn inline_const_fn_from_external_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                                 def_id: DefId)
-                                                 -> Option<ast::NodeId> {
-    match tcx.extern_const_fns.borrow().get(&def_id) {
-        Some(&ast::DUMMY_NODE_ID) => return None,
-        Some(&fn_id) => return Some(fn_id),
-        None => {}
-    }
-
-    if !tcx.sess.cstore.is_const_fn(def_id) {
-        tcx.extern_const_fns.borrow_mut().insert(def_id, ast::DUMMY_NODE_ID);
-        return None;
-    }
-
-    let fn_id = tcx.sess.cstore.maybe_get_item_ast(tcx, def_id).map(|t| t.1);
-    tcx.extern_const_fns.borrow_mut().insert(def_id,
-                                             fn_id.unwrap_or(ast::DUMMY_NODE_ID));
-    fn_id
-}
-
-pub enum ConstFnNode<'tcx> {
-    Local(FnLikeNode<'tcx>),
-    Inlined(&'tcx InlinedItem)
-}
-
-pub fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-                                       -> Option<ConstFnNode<'tcx>>
+fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+                                   -> Option<&'tcx hir::Body>
 {
-    let fn_id = if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
-        node_id
-    } else {
-        if let Some(fn_id) = inline_const_fn_from_external_crate(tcx, def_id) {
-            if let ast_map::NodeInlinedItem(ii) = tcx.map.get(fn_id) {
-                return Some(ConstFnNode::Inlined(ii));
+    if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
+        FnLikeNode::from_node(tcx.map.get(node_id)).and_then(|fn_like| {
+            if fn_like.constness() == hir::Constness::Const {
+                Some(tcx.map.body(fn_like.body()))
             } else {
-                bug!("Got const fn from external crate, but it's not inlined")
+                None
             }
+        })
+    } else {
+        if tcx.sess.cstore.is_const_fn(def_id) {
+            tcx.sess.cstore.maybe_get_item_body(tcx, def_id)
         } else {
-            return None;
+            None
         }
-    };
-
-    let fn_like = match FnLikeNode::from_node(tcx.map.get(fn_id)) {
-        Some(fn_like) => fn_like,
-        None => return None
-    };
-
-    if fn_like.constness() == hir::Constness::Const {
-        Some(ConstFnNode::Local(fn_like))
-    } else {
-        None
     }
 }
 
@@ -864,18 +813,15 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
               Struct(_) => signal!(e, UnimplementedConstVal("tuple struct constructors")),
               callee => signal!(e, CallOn(callee)),
           };
-          let (arg_defs, body_id) = match lookup_const_fn_by_id(tcx, did) {
-              Some(ConstFnNode::Inlined(ii)) => (ii.const_fn_args.clone(), ii.body.expr_id()),
-              Some(ConstFnNode::Local(fn_like)) =>
-                  (fn_like.decl().inputs.iter()
-                   .map(|arg| match arg.pat.node {
-                       hir::PatKind::Binding(_, def_id, _, _) => Some(def_id),
-                       _ => None
-                   }).collect(),
-                   fn_like.body()),
+          let body = match lookup_const_fn_by_id(tcx, did) {
+              Some(body) => body,
               None => signal!(e, NonConstPath),
           };
-          let result = tcx.map.expr(body_id);
+
+          let arg_defs = body.arguments.iter().map(|arg| match arg.pat.node {
+               hir::PatKind::Binding(_, def_id, _, _) => Some(def_id),
+               _ => None
+           }).collect::<Vec<_>>();
           assert_eq!(arg_defs.len(), args.len());
 
           let mut call_args = DefIdMap();
@@ -893,7 +839,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
               }
           }
           debug!("const call({:?})", call_args);
-          eval_const_expr_partial(tcx, &result, ty_hint, Some(&call_args))?
+          eval_const_expr_partial(tcx, &body.value, ty_hint, Some(&call_args))?
       },
       hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ety) {
           Ok(val) => val,
@@ -953,11 +899,12 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
       }
       hir::ExprArray(ref v) => Array(e.id, v.len() as u64),
-      hir::ExprRepeat(_, ref n) => {
+      hir::ExprRepeat(_, n) => {
           let len_hint = ty_hint.checked_or(tcx.types.usize);
+          let n = &tcx.map.body(n).value;
           Repeat(
               e.id,
-              match eval_const_expr_partial(tcx, &n, len_hint, fn_args)? {
+              match eval_const_expr_partial(tcx, n, len_hint, fn_args)? {
                   Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type),
                   Integral(_) => signal!(e, RepeatCountNotNatural),
                   _ => signal!(e, RepeatCountNotInt),
@@ -1373,7 +1320,8 @@ pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
             if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = count_expr.node {
                 if let Def::Local(..) = path.def {
-                    diag.note(&format!("`{}` is a variable", path));
+                    diag.note(&format!("`{}` is a variable",
+                                       tcx.map.node_to_pretty_string(count_expr.id)));
                 }
             }
 
index 4db620b2bec3b1ec507be9519bcf13e70ae1a09f..6a884bafce752dcc0060cfc68247830c2800459c 100644 (file)
@@ -35,6 +35,9 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index 360933c6b669532457f61cf647dccf7a96813bee..291f0e0d50d8fa4ea83421224d030e2ff741ad36 100644 (file)
@@ -592,6 +592,7 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         }
     });
 
+    let whitelisted_legacy_custom_derives = registry.take_whitelisted_custom_derives();
     let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups,
                    llvm_passes, attributes, mir_passes, .. } = registry;
 
@@ -631,6 +632,7 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
     let resolver_arenas = Resolver::arenas();
     let mut resolver =
         Resolver::new(sess, &krate, make_glob_map, &mut crate_loader, &resolver_arenas);
+    resolver.whitelisted_legacy_custom_derives = whitelisted_legacy_custom_derives;
     syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features.borrow().quote);
 
     krate = time(time_passes, "expansion", || {
@@ -1180,9 +1182,6 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
                          Some(ref n) if *n == "rlib" => {
                              Some(config::CrateTypeRlib)
                          }
-                         Some(ref n) if *n == "metadata" => {
-                             Some(config::CrateTypeMetadata)
-                         }
                          Some(ref n) if *n == "dylib" => {
                              Some(config::CrateTypeDylib)
                          }
index f84622c2f028553a547113d7f0b2ef6a40c499b0..5ceec9edda3d07a5aaef494ac70e3b864b7018e1 100644 (file)
@@ -493,7 +493,8 @@ fn build_controller(&mut self,
             control.after_hir_lowering.stop = Compilation::Stop;
         }
 
-        if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe) {
+        if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe ||
+                                                   i == OutputType::Metadata) {
             control.after_llvm.stop = Compilation::Stop;
         }
 
index 74df1e52bde43143a7dab39a42aee28611022fc9..5103a55fd71e1bd673df5b4e5b3533bbd89db23e 100644 (file)
@@ -47,7 +47,7 @@
 use std::str::FromStr;
 
 use rustc::hir::map as hir_map;
-use rustc::hir::map::{blocks, NodePrinter};
+use rustc::hir::map::blocks;
 use rustc::hir;
 use rustc::hir::print as pprust_hir;
 
@@ -320,7 +320,16 @@ fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn {
 }
 
 impl<'ast> pprust::PpAnn for NoAnn<'ast> {}
-impl<'ast> pprust_hir::PpAnn for NoAnn<'ast> {}
+impl<'ast> pprust_hir::PpAnn for NoAnn<'ast> {
+    fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested)
+              -> io::Result<()> {
+        if let Some(ref map) = self.ast_map {
+            pprust_hir::PpAnn::nested(map, state, nested)
+        } else {
+            Ok(())
+        }
+    }
+}
 
 struct IdentifiedAnnotation<'ast> {
     sess: &'ast Session,
@@ -393,6 +402,14 @@ fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn {
 }
 
 impl<'ast> pprust_hir::PpAnn for IdentifiedAnnotation<'ast> {
+    fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested)
+              -> io::Result<()> {
+        if let Some(ref map) = self.ast_map {
+            pprust_hir::PpAnn::nested(map, state, nested)
+        } else {
+            Ok(())
+        }
+    }
     fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
         match node {
             pprust_hir::NodeExpr(_) => s.popen(),
@@ -488,6 +505,10 @@ fn node_path(&self, id: ast::NodeId) -> Option<String> {
 }
 
 impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> {
+    fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested)
+              -> io::Result<()> {
+        pprust_hir::PpAnn::nested(&self.tcx.map, state, nested)
+    }
     fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
         match node {
             pprust_hir::NodeExpr(_) => s.popen(),
@@ -702,8 +723,8 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
     let cfg = match code {
         blocks::Code::Expr(expr) => cfg::CFG::new(tcx, expr),
         blocks::Code::FnLike(fn_like) => {
-            let body = tcx.map.expr(fn_like.body());
-            cfg::CFG::new(tcx, body)
+            let body = tcx.map.body(fn_like.body());
+            cfg::CFG::new(tcx, &body.value)
         },
     };
     let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges;
@@ -909,11 +930,10 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                                                                          &mut rdr,
                                                                          box out,
                                                                          annotation.pp_ann(),
-                                                                         true,
-                                                                         Some(ast_map.krate()));
+                                                                         true);
                     for node_id in uii.all_matching_node_ids(ast_map) {
                         let node = ast_map.get(node_id);
-                        pp_state.print_node(&node)?;
+                        pp_state.print_node(node)?;
                         pp::space(&mut pp_state.s)?;
                         let path = annotation.node_path(node_id)
                             .expect("--unpretty missing node paths");
index 87e6b2befdc3281fcbbb9359c11bf499d4eaccfd..b5fe158f158cac7aead2d5fe5d8144a75243b3fa 100644 (file)
@@ -171,6 +171,10 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         self.process_attrs(item.id, &item.attrs);
     }
 
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+        self.process_attrs(trait_item.id, &trait_item.attrs);
+    }
+
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
         self.process_attrs(impl_item.id, &impl_item.attrs);
     }
index eb31be4a8ade289d58edc0c3c1eff942cee0fb74..49609fbc7984f937c84ea3ab51b227db64a7f45f 100644 (file)
@@ -234,13 +234,13 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         visit::walk_item(self, item);
     }
 
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+        self.calculate_node_id(trait_item.id, |v| v.visit_trait_item(trait_item));
+        visit::walk_trait_item(self, trait_item);
+    }
+
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
         self.calculate_node_id(impl_item.id, |v| v.visit_impl_item(impl_item));
         visit::walk_impl_item(self, impl_item);
     }
-
-    fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem) {
-        self.calculate_node_id(item.id, |v| v.visit_foreign_item(item));
-        visit::walk_foreign_item(self, item);
-    }
 }
index ec44e19df10c999518d873199520d035632cfab3..4bb12667bbc147f861ed2583909c9758c89fcef0 100644 (file)
@@ -28,7 +28,7 @@
 use rustc::hir::intravisit as visit;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fnv;
-use std::hash::Hash;
+use std::hash::{Hash, Hasher};
 
 use super::def_path_hash::DefPathHashes;
 use super::caching_codemap_view::CachingCodemapView;
@@ -180,16 +180,16 @@ enum SawAbiComponent<'a> {
     SawLifetimeDef(usize),
 
     SawMod,
-    SawForeignItem,
+    SawForeignItem(SawForeignItemComponent),
     SawItem(SawItemComponent),
     SawTy(SawTyComponent),
+    SawFnDecl(bool),
     SawGenerics,
     SawTraitItem(SawTraitOrImplItemComponent),
     SawImplItem(SawTraitOrImplItemComponent),
     SawStructField,
-    SawVariant,
+    SawVariant(bool),
     SawQPath,
-    SawPath(bool),
     SawPathSegment,
     SawPathParameters,
     SawBlock,
@@ -265,7 +265,7 @@ enum SawExprComponent<'a> {
     SawExprPath,
     SawExprAddrOf(hir::Mutability),
     SawExprRet,
-    SawExprInlineAsm(&'a hir::InlineAsm),
+    SawExprInlineAsm(StableInlineAsm<'a>),
     SawExprStruct,
     SawExprRepeat,
 }
@@ -341,7 +341,7 @@ fn saw_expr<'a>(node: &'a Expr_,
         ExprBreak(label, _)      => (SawExprBreak(label.map(|l| l.name.as_str())), false),
         ExprAgain(label)         => (SawExprAgain(label.map(|l| l.name.as_str())), false),
         ExprRet(..)              => (SawExprRet, false),
-        ExprInlineAsm(ref a,..)  => (SawExprInlineAsm(a), false),
+        ExprInlineAsm(ref a,..)  => (SawExprInlineAsm(StableInlineAsm(a)), false),
         ExprStruct(..)           => (SawExprStruct, false),
         ExprRepeat(..)           => (SawExprRepeat, false),
     }
@@ -364,7 +364,7 @@ enum SawItemComponent {
     SawItemConst,
     SawItemFn(Unsafety, Constness, Abi),
     SawItemMod,
-    SawItemForeignMod,
+    SawItemForeignMod(Abi),
     SawItemTy,
     SawItemEnum,
     SawItemStruct,
@@ -382,7 +382,7 @@ fn saw_item(node: &Item_) -> SawItemComponent {
         ItemConst(..) =>SawItemConst,
         ItemFn(_, unsafety, constness, abi, _, _) => SawItemFn(unsafety, constness, abi),
         ItemMod(..) => SawItemMod,
-        ItemForeignMod(..) => SawItemForeignMod,
+        ItemForeignMod(ref fm) => SawItemForeignMod(fm.abi),
         ItemTy(..) => SawItemTy,
         ItemEnum(..) => SawItemEnum,
         ItemStruct(..) => SawItemStruct,
@@ -393,6 +393,12 @@ fn saw_item(node: &Item_) -> SawItemComponent {
     }
 }
 
+#[derive(Hash)]
+enum SawForeignItemComponent {
+    Static { mutable: bool },
+    Fn,
+}
+
 #[derive(Hash)]
 enum SawPatComponent {
     SawPatWild,
@@ -467,12 +473,14 @@ enum SawTraitOrImplItemComponent {
     SawTraitOrImplItemType
 }
 
-fn saw_trait_item(ti: &TraitItem_) -> SawTraitOrImplItemComponent {
+fn saw_trait_item(ti: &TraitItemKind) -> SawTraitOrImplItemComponent {
     match *ti {
-        ConstTraitItem(..) => SawTraitOrImplItemConst,
-        MethodTraitItem(ref sig, ref body) =>
-            SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, body.is_some()),
-        TypeTraitItem(..) => SawTraitOrImplItemType
+        TraitItemKind::Const(..) => SawTraitOrImplItemConst,
+        TraitItemKind::Method(ref sig, TraitMethod::Required(_)) =>
+            SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, false),
+        TraitItemKind::Method(ref sig, TraitMethod::Provided(_)) =>
+            SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, true),
+        TraitItemKind::Type(..) => SawTraitOrImplItemType
     }
 }
 
@@ -492,6 +500,46 @@ enum SawSpanExpnKind {
     SomeExpansion,
 }
 
+/// A wrapper that provides a stable Hash implementation.
+struct StableInlineAsm<'a>(&'a InlineAsm);
+
+impl<'a> Hash for StableInlineAsm<'a> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let InlineAsm {
+            asm,
+            asm_str_style,
+            ref outputs,
+            ref inputs,
+            ref clobbers,
+            volatile,
+            alignstack,
+            dialect,
+            expn_id: _, // This is used for error reporting
+        } = *self.0;
+
+        asm.as_str().hash(state);
+        asm_str_style.hash(state);
+        outputs.len().hash(state);
+        for output in outputs {
+            let InlineAsmOutput { constraint, is_rw, is_indirect } = *output;
+            constraint.as_str().hash(state);
+            is_rw.hash(state);
+            is_indirect.hash(state);
+        }
+        inputs.len().hash(state);
+        for input in inputs {
+            input.as_str().hash(state);
+        }
+        clobbers.len().hash(state);
+        for clobber in clobbers {
+            clobber.as_str().hash(state);
+        }
+        volatile.hash(state);
+        alignstack.hash(state);
+        dialect.hash(state);
+    }
+}
+
 macro_rules! hash_attrs {
     ($visitor:expr, $attrs:expr) => ({
         let attrs = $attrs;
@@ -538,7 +586,7 @@ fn visit_variant(&mut self,
                      g: &'tcx Generics,
                      item_id: NodeId) {
         debug!("visit_variant: st={:?}", self.st);
-        SawVariant.hash(self.st);
+        SawVariant(v.node.disr_expr.is_some()).hash(self.st);
         hash_attrs!(self, &v.node.attrs);
         visit::walk_variant(self, v, g, item_id)
     }
@@ -570,7 +618,12 @@ fn visit_expr(&mut self, ex: &'tcx Expr) {
         // implicitly hashing the discriminant of SawExprComponent.
         hash_span!(self, ex.span, force_span);
         hash_attrs!(self, &ex.attrs);
-        visit::walk_expr(self, ex)
+
+        // Always hash nested constant bodies (e.g. n in `[x; n]`).
+        let hash_bodies = self.hash_bodies;
+        self.hash_bodies = true;
+        visit::walk_expr(self, ex);
+        self.hash_bodies = hash_bodies;
     }
 
     fn visit_stmt(&mut self, s: &'tcx Stmt) {
@@ -602,7 +655,17 @@ fn visit_stmt(&mut self, s: &'tcx Stmt) {
     fn visit_foreign_item(&mut self, i: &'tcx ForeignItem) {
         debug!("visit_foreign_item: st={:?}", self.st);
 
-        SawForeignItem.hash(self.st);
+        match i.node {
+            ForeignItemFn(..) => {
+                SawForeignItem(SawForeignItemComponent::Fn)
+            }
+            ForeignItemStatic(_, mutable) => {
+                SawForeignItem(SawForeignItemComponent::Static {
+                    mutable: mutable
+                })
+            }
+        }.hash(self.st);
+
         hash_span!(self, i.span);
         hash_attrs!(self, &i.attrs);
         visit::walk_foreign_item(self, i)
@@ -630,7 +693,12 @@ fn visit_ty(&mut self, t: &'tcx Ty) {
         debug!("visit_ty: st={:?}", self.st);
         SawTy(saw_ty(&t.node)).hash(self.st);
         hash_span!(self, t.span);
-        visit::walk_ty(self, t)
+
+        // Always hash nested constant bodies (e.g. N in `[T; N]`).
+        let hash_bodies = self.hash_bodies;
+        self.hash_bodies = true;
+        visit::walk_ty(self, t);
+        self.hash_bodies = hash_bodies;
     }
 
     fn visit_generics(&mut self, g: &'tcx Generics) {
@@ -639,6 +707,12 @@ fn visit_generics(&mut self, g: &'tcx Generics) {
         visit::walk_generics(self, g)
     }
 
+    fn visit_fn_decl(&mut self, fd: &'tcx FnDecl) {
+        debug!("visit_fn_decl: st={:?}", self.st);
+        SawFnDecl(fd.variadic).hash(self.st);
+        visit::walk_fn_decl(self, fd)
+    }
+
     fn visit_trait_item(&mut self, ti: &'tcx TraitItem) {
         debug!("visit_trait_item: st={:?}", self.st);
 
@@ -678,7 +752,6 @@ fn visit_qpath(&mut self, qpath: &'tcx QPath, id: NodeId, span: Span) {
 
     fn visit_path(&mut self, path: &'tcx Path, _: ast::NodeId) {
         debug!("visit_path: st={:?}", self.st);
-        SawPath(path.global).hash(self.st);
         hash_span!(self, path.span);
         visit::walk_path(self, path)
     }
@@ -1096,8 +1169,9 @@ pub fn hash_crate_root_module(&mut self, krate: &'tcx Crate) {
             // These fields are handled separately:
             exported_macros: _,
             items: _,
+            trait_items: _,
             impl_items: _,
-            exprs: _,
+            bodies: _,
         } = *krate;
 
         visit::Visitor::visit_mod(self, module, span, ast::CRATE_NODE_ID);
index 40873011a7b8d7fc73aaa76fa17fc9c75b91a8ac..481462dff86e479289e36f363defdd3598877cd2 100644 (file)
@@ -185,6 +185,9 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
@@ -229,6 +232,9 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index 2aa74407afc5b087fe64c4804f1e0b279b4e3e1d..2baef47c214c28ae54b17906a0be338afc8e2253 100644 (file)
@@ -243,7 +243,7 @@ fn check_fn(&mut self,
                 cx: &LateContext,
                 fk: FnKind,
                 _: &hir::FnDecl,
-                _: &hir::Expr,
+                _: &hir::Body,
                 span: Span,
                 id: ast::NodeId) {
         match fk {
@@ -271,12 +271,15 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         }
     }
 
-    fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
-        if let hir::MethodTraitItem(_, None) = trait_item.node {
+    fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
+        if let hir::TraitItemKind::Method(_, hir::TraitMethod::Required(ref names)) = item.node {
             self.check_snake_case(cx,
                                   "trait method",
-                                  &trait_item.name.as_str(),
-                                  Some(trait_item.span));
+                                  &item.name.as_str(),
+                                  Some(item.span));
+            for name in names {
+                self.check_snake_case(cx, "variable", &name.node.as_str(), Some(name.span));
+            }
         }
     }
 
@@ -288,14 +291,6 @@ fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) {
     }
 
     fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
-        // Exclude parameter names from foreign functions
-        let parent_node = cx.tcx.map.get_parent_node(p.id);
-        if let hir::map::NodeForeignItem(item) = cx.tcx.map.get(parent_node) {
-            if let hir::ForeignItemFn(..) = item.node {
-                return;
-            }
-        }
-
         if let &PatKind::Binding(_, _, ref path1, _) = &p.node {
             self.check_snake_case(cx, "variable", &path1.node.as_str(), Some(p.span));
         }
@@ -363,7 +358,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
 
     fn check_trait_item(&mut self, cx: &LateContext, ti: &hir::TraitItem) {
         match ti.node {
-            hir::ConstTraitItem(..) => {
+            hir::TraitItemKind::Const(..) => {
                 NonUpperCaseGlobals::check_upper_case(cx, "associated constant", ti.name, ti.span);
             }
             _ => {}
@@ -382,7 +377,7 @@ fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) {
     fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
         // Lint for constants that look like binding identifiers (#7526)
         if let PatKind::Path(hir::QPath::Resolved(None, ref path)) = p.node {
-            if !path.global && path.segments.len() == 1 && path.segments[0].parameters.is_empty() {
+            if path.segments.len() == 1 && path.segments[0].parameters.is_empty() {
                 if let Def::Const(..) = path.def {
                     NonUpperCaseGlobals::check_upper_case(cx,
                                                           "constant in pattern",
index cd414846af4fb610f0f9dc56157218542daed3d6..c021ffee81899002c9c6a4273fdec2c97df20d34 100644 (file)
@@ -222,7 +222,7 @@ fn check_fn(&mut self,
                 cx: &LateContext,
                 fk: FnKind<'tcx>,
                 _: &hir::FnDecl,
-                _: &hir::Expr,
+                _: &hir::Body,
                 span: Span,
                 _: ast::NodeId) {
         match fk {
@@ -240,11 +240,11 @@ fn check_fn(&mut self,
         }
     }
 
-    fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
-        if let hir::MethodTraitItem(ref sig, None) = trait_item.node {
+    fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
+        if let hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(_)) = item.node {
             if sig.unsafety == hir::Unsafety::Unsafe {
                 cx.span_lint(UNSAFE_CODE,
-                             trait_item.span,
+                             item.span,
                              "declaration of an `unsafe` method")
             }
         }
@@ -374,12 +374,12 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
             hir::ItemEnum(..) => "an enum",
             hir::ItemStruct(..) => "a struct",
             hir::ItemUnion(..) => "a union",
-            hir::ItemTrait(.., ref items) => {
+            hir::ItemTrait(.., ref trait_item_refs) => {
                 // Issue #11592, traits are always considered exported, even when private.
                 if it.vis == hir::Visibility::Inherited {
                     self.private_traits.insert(it.id);
-                    for itm in items {
-                        self.private_traits.insert(itm.id);
+                    for trait_item_ref in trait_item_refs {
+                        self.private_traits.insert(trait_item_ref.id.node_id);
                     }
                     return;
                 }
@@ -418,9 +418,9 @@ fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
         }
 
         let desc = match trait_item.node {
-            hir::ConstTraitItem(..) => "an associated constant",
-            hir::MethodTraitItem(..) => "a trait method",
-            hir::TypeTraitItem(..) => "an associated type",
+            hir::TraitItemKind::Const(..) => "an associated constant",
+            hir::TraitItemKind::Method(..) => "a trait method",
+            hir::TraitItemKind::Type(..) => "an associated type",
         };
 
         self.check_missing_docs_attrs(cx,
@@ -674,7 +674,7 @@ fn check_fn(&mut self,
                 cx: &LateContext,
                 fn_kind: FnKind,
                 _: &hir::FnDecl,
-                blk: &hir::Expr,
+                body: &hir::Body,
                 sp: Span,
                 id: ast::NodeId) {
         let method = match fn_kind {
@@ -712,7 +712,7 @@ fn check_fn(&mut self,
         // to have behaviour like the above, rather than
         // e.g. accidentally recurring after an assert.
 
-        let cfg = cfg::CFG::new(cx.tcx, blk);
+        let cfg = cfg::CFG::new(cx.tcx, &body.value);
 
         let mut work_queue = vec![cfg.entry];
         let mut reached_exit_without_self_call = false;
index 751c9c3440f66326a06454204416c9cf237f388f..a3aa4af493aaf72bb1ffa2fc613980f2490f5d70 100644 (file)
@@ -679,7 +679,7 @@ fn check_foreign_fn(&mut self, id: ast::NodeId, decl: &hir::FnDecl) {
         let sig = self.cx.tcx.erase_late_bound_regions(&sig);
 
         for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) {
-            self.check_type_for_ffi_and_report_errors(input_hir.ty.span, input_ty);
+            self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty);
         }
 
         if let hir::Return(ref ret_hir) = decl.output {
@@ -713,7 +713,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
             if nmod.abi != Abi::RustIntrinsic && nmod.abi != Abi::PlatformIntrinsic {
                 for ni in &nmod.items {
                     match ni.node {
-                        hir::ForeignItemFn(ref decl, _) => {
+                        hir::ForeignItemFn(ref decl, _, _) => {
                             vis.check_foreign_fn(ni.id, decl);
                         }
                         hir::ForeignItemStatic(ref ty, _) => {
index 429bfb8e3d60667bc683ee829c17d5ce76fb7b59..b7ee688117d93a07149632464d4eafcb6d1d2e9d 100644 (file)
@@ -97,11 +97,11 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
     fn check_fn(&mut self,
                 cx: &LateContext,
                 _: FnKind,
-                decl: &hir::FnDecl,
-                _: &hir::Expr,
+                _: &hir::FnDecl,
+                body: &hir::Body,
                 _: Span,
                 _: ast::NodeId) {
-        for a in &decl.inputs {
+        for a in &body.arguments {
             self.check_unused_mut_pat(cx, slice::ref_slice(&a.pat));
         }
     }
index 86c40a0208ad340755cb3630c38378d93a177f7d..2ee4cc49435611316e1a7e1d3b717dae609c8574 100644 (file)
@@ -95,7 +95,8 @@ fn main() {
     let is_crossed = target != host;
 
     let optional_components =
-        ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", "systemz", "jsbackend", "msp430"];
+        ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", "systemz", "jsbackend", "msp430",
+         "sparc", "nvptx"];
 
     // FIXME: surely we don't need all these components, right? Stuff like mcjit
     //        or interpreter the compiler itself never uses.
index d2b86ade7a2ab26fb283d5396321453224b5d1db..c1705815165939b505ed948ab23434f655a145bd 100644 (file)
@@ -42,6 +42,7 @@ pub enum CallConv {
     X86StdcallCallConv = 64,
     X86FastcallCallConv = 65,
     ArmAapcsCallConv = 67,
+    PtxKernel = 71,
     X86_64_SysV = 78,
     X86_64_Win64 = 79,
     X86_VectorCall = 80,
@@ -117,6 +118,7 @@ pub enum Attribute {
     StructRet       = 16,
     UWTable         = 17,
     ZExt            = 18,
+    InReg           = 19,
 }
 
 /// LLVMIntPredicate
@@ -471,9 +473,7 @@ pub enum DIBuilder_opaque {}
 // generates an llvmdeps.rs file next to this one which will be
 // automatically updated whenever LLVM is updated to include an up-to-date
 // set of the libraries we need to link to LLVM for.
-#[cfg_attr(not(all(stage0,cargobuild)),
-           link(name = "rustllvm", kind = "static"))] // not quite true but good enough
-#[cfg_attr(stage0, linked_from = "rustllvm")]
+#[link(name = "rustllvm", kind = "static")] // not quite true but good enough
 extern "C" {
     // Create and destroy contexts.
     pub fn LLVMContextCreate() -> ContextRef;
index a15edcd44be2a21083d98dd3d46de94f1fea0d5a..1e45ea083c9e011046d33475e8e0df4852d48161 100644 (file)
@@ -27,9 +27,8 @@
 #![feature(concat_idents)]
 #![feature(libc)]
 #![feature(link_args)]
-#![cfg_attr(stage0, feature(linked_from))]
 #![feature(staged_api)]
-#![cfg_attr(not(stage0), feature(rustc_private))]
+#![feature(rustc_private)]
 
 extern crate libc;
 #[macro_use]
@@ -270,7 +269,8 @@ pub fn mk_section_iter(llof: ObjectFileRef) -> SectionIter {
 /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
 pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef {
     unsafe {
-        assert!(index < LLVMCountParams(llfn));
+        assert!(index < LLVMCountParams(llfn),
+            "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn));
         LLVMGetParam(llfn, index)
     }
 }
@@ -370,6 +370,17 @@ fn init() { }
                  LLVMInitializeMSP430Target,
                  LLVMInitializeMSP430TargetMC,
                  LLVMInitializeMSP430AsmPrinter);
+    init_target!(llvm_component = "sparc",
+                 LLVMInitializeSparcTargetInfo,
+                 LLVMInitializeSparcTarget,
+                 LLVMInitializeSparcTargetMC,
+                 LLVMInitializeSparcAsmPrinter,
+                 LLVMInitializeSparcAsmParser);
+    init_target!(llvm_component = "nvptx",
+                 LLVMInitializeNVPTXTargetInfo,
+                 LLVMInitializeNVPTXTarget,
+                 LLVMInitializeNVPTXTargetMC,
+                 LLVMInitializeNVPTXAsmPrinter);
 }
 
 pub fn last_error() -> Option<String> {
index 926c44824ce482393083697b4569d9a8dbbeee16..b27b164bd47aaffec7910ac2f3ca775b22f0f119 100644 (file)
@@ -16,8 +16,7 @@
 use encoder::EncodeContext;
 use schema::*;
 
-use rustc::middle::cstore::{InlinedItem, InlinedItemRef};
-use rustc::middle::const_qualif::ConstQualif;
+use rustc::hir;
 use rustc::hir::def::Def;
 use rustc::hir::def_id::DefId;
 use rustc::ty::{self, TyCtxt, Ty};
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct Ast<'tcx> {
     id_range: IdRange,
-    item: Lazy<InlinedItem>,
+    body: Lazy<hir::Body>,
     side_tables: LazySeq<(ast::NodeId, TableEntry<'tcx>)>,
+    pub nested_bodies: LazySeq<hir::Body>,
+    pub rvalue_promotable_to_static: bool,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
@@ -39,16 +40,17 @@ enum TableEntry<'tcx> {
     NodeType(Ty<'tcx>),
     ItemSubsts(ty::ItemSubsts<'tcx>),
     Adjustment(ty::adjustment::Adjustment<'tcx>),
-    ConstQualif(ConstQualif),
 }
 
 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
-    pub fn encode_inlined_item(&mut self, ii: InlinedItemRef<'tcx>) -> Lazy<Ast<'tcx>> {
+    pub fn encode_body(&mut self, body: hir::BodyId) -> Lazy<Ast<'tcx>> {
+        let body = self.tcx.map.body(body);
+
         let mut id_visitor = IdRangeComputingVisitor::new(&self.tcx.map);
-        ii.visit(&mut id_visitor);
+        id_visitor.visit_body(body);
 
-        let ii_pos = self.position();
-        ii.encode(self).unwrap();
+        let body_pos = self.position();
+        body.encode(self).unwrap();
 
         let tables_pos = self.position();
         let tables_count = {
@@ -56,14 +58,29 @@ pub fn encode_inlined_item(&mut self, ii: InlinedItemRef<'tcx>) -> Lazy<Ast<'tcx
                 ecx: self,
                 count: 0,
             };
-            ii.visit(&mut visitor);
+            visitor.visit_body(body);
             visitor.count
         };
 
+        let nested_pos = self.position();
+        let nested_count = {
+            let mut visitor = NestedBodyEncodingVisitor {
+                ecx: self,
+                count: 0,
+            };
+            visitor.visit_body(body);
+            visitor.count
+        };
+
+        let rvalue_promotable_to_static =
+            self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id];
+
         self.lazy(&Ast {
             id_range: id_visitor.result(),
-            item: Lazy::with_position(ii_pos),
+            body: Lazy::with_position(body_pos),
             side_tables: LazySeq::with_position_and_length(tables_pos, tables_count),
+            nested_bodies: LazySeq::with_position_and_length(nested_pos, nested_count),
+            rvalue_promotable_to_static: rvalue_promotable_to_static
         })
     }
 }
@@ -94,18 +111,36 @@ fn visit_id(&mut self, id: ast::NodeId) {
         encode(tcx.tables().node_types.get(&id).cloned().map(TableEntry::NodeType));
         encode(tcx.tables().item_substs.get(&id).cloned().map(TableEntry::ItemSubsts));
         encode(tcx.tables().adjustments.get(&id).cloned().map(TableEntry::Adjustment));
-        encode(tcx.const_qualif_map.borrow().get(&id).cloned().map(TableEntry::ConstQualif));
     }
 }
 
-/// Decodes an item from its AST in the cdata's metadata and adds it to the
+struct NestedBodyEncodingVisitor<'a, 'b: 'a, 'tcx: 'b> {
+    ecx: &'a mut EncodeContext<'b, 'tcx>,
+    count: usize,
+}
+
+impl<'a, 'b, 'tcx> Visitor<'tcx> for NestedBodyEncodingVisitor<'a, 'b, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        NestedVisitorMap::None
+    }
+
+    fn visit_nested_body(&mut self, body: hir::BodyId) {
+        let body = self.ecx.tcx.map.body(body);
+        body.encode(self.ecx).unwrap();
+        self.count += 1;
+
+        self.visit_body(body);
+    }
+}
+
+/// Decodes an item's body from its AST in the cdata's metadata and adds it to the
 /// ast-map.
-pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata,
-                                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                     ast: Ast<'tcx>,
-                                     orig_did: DefId)
-                                     -> &'tcx InlinedItem {
-    debug!("> Decoding inlined fn: {:?}", tcx.item_path_str(orig_did));
+pub fn decode_body<'a, 'tcx>(cdata: &CrateMetadata,
+                             tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             def_id: DefId,
+                             ast: Ast<'tcx>)
+                             -> &'tcx hir::Body {
+    debug!("> Decoding inlined fn: {}", tcx.item_path_str(def_id));
 
     let cnt = ast.id_range.max.as_usize() - ast.id_range.min.as_usize();
     let start = tcx.sess.reserve_node_ids(cnt);
@@ -115,12 +150,6 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata,
                          max: ast::NodeId::new(start.as_usize() + cnt),
                      }];
 
-    let ii = ast.item.decode((cdata, tcx, id_ranges));
-    let item_node_id = tcx.sess.next_node_id();
-    let ii = ast_map::map_decoded_item(&tcx.map,
-                                       ii,
-                                       item_node_id);
-
     for (id, entry) in ast.side_tables.decode((cdata, tcx, id_ranges)) {
         match entry {
             TableEntry::TypeRelativeDef(def) => {
@@ -135,11 +164,9 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata,
             TableEntry::Adjustment(adj) => {
                 tcx.tables.borrow_mut().adjustments.insert(id, adj);
             }
-            TableEntry::ConstQualif(qualif) => {
-                tcx.const_qualif_map.borrow_mut().insert(id, qualif);
-            }
         }
     }
 
-    ii
+    let body = ast.body.decode((cdata, tcx, id_ranges));
+    ast_map::map_decoded_body(&tcx.map, def_id, body, tcx.sess.next_node_id())
 }
index a9af4118c5957f7266fe05bfdf6252fe58192696..724c164b3b41af747310df2a02c2917b6fb30310 100644 (file)
@@ -799,8 +799,7 @@ fn inject_allocator_crate(&mut self) {
                 config::CrateTypeProcMacro |
                 config::CrateTypeCdylib |
                 config::CrateTypeStaticlib => need_lib_alloc = true,
-                config::CrateTypeRlib |
-                config::CrateTypeMetadata => {}
+                config::CrateTypeRlib => {}
             }
         }
         if !need_lib_alloc && !need_exe_alloc { return }
index 7ec847d24cfa3fc73823ce1a427550454ef172ba..aab4034b7705aee99a5747a42d74bcc44a8e4e15 100644 (file)
@@ -88,13 +88,6 @@ pub struct CrateMetadata {
     pub dllimport_foreign_items: FxHashSet<DefIndex>,
 }
 
-pub struct CachedInlinedItem {
-    /// The NodeId of the RootInlinedParent HIR map entry
-    pub inlined_root: ast::NodeId,
-    /// The local NodeId of the inlined entity
-    pub item_id: ast::NodeId,
-}
-
 pub struct CStore {
     pub dep_graph: DepGraph,
     metas: RefCell<FxHashMap<CrateNum, Rc<CrateMetadata>>>,
@@ -104,8 +97,7 @@ pub struct CStore {
     used_link_args: RefCell<Vec<String>>,
     statically_included_foreign_items: RefCell<FxHashSet<DefIndex>>,
     pub dllimport_foreign_items: RefCell<FxHashSet<DefIndex>>,
-    pub inlined_item_cache: RefCell<DefIdMap<Option<CachedInlinedItem>>>,
-    pub defid_for_inlined_node: RefCell<NodeMap<DefId>>,
+    pub inlined_item_cache: RefCell<DefIdMap<Option<ast::NodeId>>>,
     pub visible_parent_map: RefCell<DefIdMap<DefId>>,
 }
 
@@ -121,7 +113,6 @@ pub fn new(dep_graph: &DepGraph) -> CStore {
             dllimport_foreign_items: RefCell::new(FxHashSet()),
             visible_parent_map: RefCell::new(FxHashMap()),
             inlined_item_cache: RefCell::new(FxHashMap()),
-            defid_for_inlined_node: RefCell::new(FxHashMap()),
         }
     }
 
index 5c96d7f1826fd28e8664d2e607d83fb57e25f04c..64513fa41b219d03938faa1328369aa54df3b1c6 100644 (file)
@@ -13,7 +13,7 @@
 use locator;
 use schema;
 
-use rustc::middle::cstore::{InlinedItem, CrateStore, CrateSource, LibSource, DepKind, ExternCrate};
+use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, ExternCrate};
 use rustc::middle::cstore::{NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro};
 use rustc::hir::def::{self, Def};
 use rustc::middle::lang_items;
@@ -36,6 +36,8 @@
 use rustc_back::target::Target;
 use rustc::hir;
 
+use std::collections::BTreeMap;
+
 impl<'tcx> CrateStore<'tcx> for cstore::CStore {
     fn describe_def(&self, def: DefId) -> Option<Def> {
         self.dep_graph.read(DepNode::MetaData(def));
@@ -128,7 +130,11 @@ fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> &'tcx ty::AdtD
 
     fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name>
     {
-        self.dep_graph.read(DepNode::MetaData(did));
+        // 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)
     }
 
@@ -188,8 +194,7 @@ fn trait_of_item(&self, def_id: DefId) -> Option<DefId> {
         self.get_crate_data(def_id.krate).get_trait_of_item(def_id.index)
     }
 
-    fn associated_item<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                           -> Option<ty::AssociatedItem>
+    fn associated_item(&self, def: DefId) -> Option<ty::AssociatedItem>
     {
         self.dep_graph.read(DepNode::MetaData(def));
         self.get_crate_data(def.krate).get_associated_item(def.index)
@@ -424,94 +429,42 @@ fn load_macro(&self, id: DefId, sess: &Session) -> LoadedMacro {
         })
     }
 
-    fn maybe_get_item_ast<'a>(&'tcx self,
-                              tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              def_id: DefId)
-                              -> Option<(&'tcx InlinedItem, ast::NodeId)>
+    fn maybe_get_item_body<'a>(&'tcx self,
+                               tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                               def_id: DefId)
+                               -> Option<&'tcx hir::Body>
     {
         self.dep_graph.read(DepNode::MetaData(def_id));
 
-        match self.inlined_item_cache.borrow().get(&def_id) {
-            Some(&None) => {
-                return None; // Not inlinable
-            }
-            Some(&Some(ref cached_inlined_item)) => {
+        if let Some(&cached) = self.inlined_item_cache.borrow().get(&def_id) {
+            return cached.map(|root_id| {
                 // Already inline
-                debug!("maybe_get_item_ast({}): already inline as node id {}",
-                          tcx.item_path_str(def_id), cached_inlined_item.item_id);
-                return Some((tcx.map.expect_inlined_item(cached_inlined_item.inlined_root),
-                             cached_inlined_item.item_id));
-            }
-            None => {
-                // Not seen yet
-            }
+                debug!("maybe_get_item_body({}): already inline", tcx.item_path_str(def_id));
+                tcx.map.expect_inlined_body(root_id)
+            });
         }
 
-        debug!("maybe_get_item_ast({}): inlining item", tcx.item_path_str(def_id));
+        debug!("maybe_get_item_body({}): inlining item", tcx.item_path_str(def_id));
 
-        let inlined = self.get_crate_data(def_id.krate).maybe_get_item_ast(tcx, def_id.index);
-
-        let cache_inlined_item = |original_def_id, inlined_item_id, inlined_root_node_id| {
-            let cache_entry = cstore::CachedInlinedItem {
-                inlined_root: inlined_root_node_id,
-                item_id: inlined_item_id,
-            };
-            self.inlined_item_cache
-                .borrow_mut()
-                .insert(original_def_id, Some(cache_entry));
-            self.defid_for_inlined_node
-                .borrow_mut()
-                .insert(inlined_item_id, original_def_id);
-        };
-
-        let find_inlined_item_root = |inlined_item_id| {
-            let mut node = inlined_item_id;
-
-            // If we can't find the inline root after a thousand hops, we can
-            // be pretty sure there's something wrong with the HIR map.
-            for _ in 0 .. 1000 {
-                let parent_node = tcx.map.get_parent_node(node);
-                if parent_node == node {
-                    return node;
-                }
-                node = parent_node;
-            }
-            bug!("cycle in HIR map parent chain")
-        };
+        let inlined = self.get_crate_data(def_id.krate).maybe_get_item_body(tcx, def_id.index);
 
-        match inlined {
-            None => {
-                self.inlined_item_cache
-                    .borrow_mut()
-                    .insert(def_id, None);
-            }
-            Some(&InlinedItem { ref body, .. }) => {
-                let inlined_root_node_id = find_inlined_item_root(body.id);
-                cache_inlined_item(def_id, inlined_root_node_id, inlined_root_node_id);
-            }
-        }
+        self.inlined_item_cache.borrow_mut().insert(def_id, inlined.map(|body| {
+            let root_id = tcx.map.get_parent_node(body.value.id);
+            assert_eq!(tcx.map.get_parent_node(root_id), root_id);
+            root_id
+        }));
 
-        // We can be sure to hit the cache now
-        return self.maybe_get_item_ast(tcx, def_id);
+        inlined
     }
 
-    fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId> {
-        assert!(!def_id.is_local());
-        match self.inlined_item_cache.borrow().get(&def_id) {
-            Some(&Some(ref cached_inlined_item)) => {
-                Some(cached_inlined_item.item_id)
-            }
-            Some(&None) => {
-                None
-            }
-            _ => {
-                bug!("Trying to lookup inlined NodeId for unexpected item");
-            }
-        }
+    fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap<hir::BodyId, hir::Body> {
+        self.dep_graph.read(DepNode::MetaData(def));
+        self.get_crate_data(def.krate).item_body_nested_bodies(def.index)
     }
 
-    fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId> {
-        self.defid_for_inlined_node.borrow().get(&node_id).map(|x| *x)
+    fn const_is_rvalue_promotable_to_static(&self, def: DefId) -> bool {
+        self.dep_graph.read(DepNode::MetaData(def));
+        self.get_crate_data(def.krate).const_is_rvalue_promotable_to_static(def.index)
     }
 
     fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Mir<'tcx> {
index 853a49dffc7b5ec71010c455a28194a022076d34..c27e06c50222be8e123094038dfba0b1424fd07b 100644 (file)
@@ -10,7 +10,7 @@
 
 // Decoding metadata from a single crate's metadata
 
-use astencode::decode_inlined_item;
+use astencode::decode_body;
 use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary};
 use schema::*;
 
@@ -18,7 +18,7 @@
 use rustc::hir;
 use rustc::hir::intravisit::IdRange;
 
-use rustc::middle::cstore::{InlinedItem, LinkagePreference};
+use rustc::middle::cstore::LinkagePreference;
 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;
@@ -32,6 +32,7 @@
 
 use std::borrow::Cow;
 use std::cell::Ref;
+use std::collections::BTreeMap;
 use std::io;
 use std::mem;
 use std::str;
@@ -588,7 +589,7 @@ fn get_variant(&self,
                 ty::FieldDef {
                     did: self.local_def_id(index),
                     name: self.item_name(index),
-                    vis: f.visibility
+                    vis: f.visibility.decode(self)
                 }
             }).collect(),
             disr_val: ConstInt::Infer(data.disr),
@@ -678,7 +679,7 @@ pub fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> {
     pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility {
         match self.is_proc_macro(id) {
             true => ty::Visibility::Public,
-            false => self.entry(id).visibility,
+            false => self.entry(id).visibility.decode(self),
         }
     }
 
@@ -819,20 +820,27 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
         }
     }
 
-    pub fn maybe_get_item_ast(&self,
-                              tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              id: DefIndex)
-                              -> Option<&'tcx InlinedItem> {
-        debug!("Looking up item: {:?}", id);
+    pub fn maybe_get_item_body(&self,
+                               tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                               id: DefIndex)
+                               -> Option<&'tcx hir::Body> {
         if self.is_proc_macro(id) { return None; }
-        let item_doc = self.entry(id);
-        let item_did = self.local_def_id(id);
-        item_doc.ast.map(|ast| {
-            let ast = ast.decode(self);
-            decode_inlined_item(self, tcx, ast, item_did)
+        self.entry(id).ast.map(|ast| {
+            decode_body(self, tcx, self.local_def_id(id), ast.decode(self))
         })
     }
 
+    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()
@@ -885,7 +893,7 @@ pub fn get_associated_item(&self, id: DefIndex) -> Option<ty::AssociatedItem> {
                 ty::AssociatedItem {
                     name: name,
                     kind: ty::AssociatedKind::Const,
-                    vis: item.visibility,
+                    vis: item.visibility.decode(self),
                     defaultness: container.defaultness(),
                     def_id: self.local_def_id(id),
                     container: container.with_def_id(parent),
@@ -898,7 +906,7 @@ pub fn get_associated_item(&self, id: DefIndex) -> Option<ty::AssociatedItem> {
                 ty::AssociatedItem {
                     name: name,
                     kind: ty::AssociatedKind::Method,
-                    vis: item.visibility,
+                    vis: item.visibility.decode(self),
                     defaultness: data.container.defaultness(),
                     def_id: self.local_def_id(id),
                     container: data.container.with_def_id(parent),
@@ -910,7 +918,7 @@ pub fn get_associated_item(&self, id: DefIndex) -> Option<ty::AssociatedItem> {
                 ty::AssociatedItem {
                     name: name,
                     kind: ty::AssociatedKind::Type,
-                    vis: item.visibility,
+                    vis: item.visibility.decode(self),
                     defaultness: container.defaultness(),
                     def_id: self.local_def_id(id),
                     container: container.with_def_id(parent),
@@ -1006,6 +1014,7 @@ pub fn get_implementations_for_trait(&self, filter: Option<DefId>, result: &mut
         let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) {
             Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)),
             Some(None) => return,
+            None if self.proc_macros.is_some() => return,
             None => None,
         };
 
index 6cf1a9e8a390d183e158012749bf6a8e393cfa8b..d3a2b6f1683e228994ae2c66d84836edac885b6e 100644 (file)
@@ -57,9 +57,9 @@
 
 Please specify a valid "kind" value, from one of the following:
 
- * static
- * dylib
- * framework
+* static
+* dylib
+* framework
 
 "##,
 
index cf032013ac962976117a497cd3f9f0c41cd391ab..72dcb4ba9a3a8f3f1ab460f68b133cfc773c9ca4 100644 (file)
@@ -12,8 +12,7 @@
 use index::Index;
 use schema::*;
 
-use rustc::middle::cstore::{InlinedItemRef, LinkMeta};
-use rustc::middle::cstore::{LinkagePreference, NativeLibrary};
+use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary};
 use rustc::hir::def;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId};
 use rustc::hir::map::definitions::DefPathTable;
@@ -34,6 +33,7 @@
 use std::rc::Rc;
 use std::u32;
 use syntax::ast::{self, CRATE_NODE_ID};
+use syntax::codemap::Spanned;
 use syntax::attr;
 use syntax::symbol::Symbol;
 use syntax_pos;
@@ -268,7 +268,7 @@ fn encode_enum_variant_info(&mut self,
 
         Entry {
             kind: EntryKind::Variant(self.lazy(&data)),
-            visibility: enum_vis.simplify(),
+            visibility: self.lazy(&ty::Visibility::from_hir(enum_vis, enum_id, tcx)),
             span: self.lazy(&tcx.def_span(def_id)),
             attributes: self.encode_attributes(&tcx.get_attrs(def_id)),
             children: self.lazy_seq(variant.fields.iter().map(|f| {
@@ -306,7 +306,7 @@ fn encode_info_for_mod(&mut self,
 
         Entry {
             kind: EntryKind::Mod(self.lazy(&data)),
-            visibility: vis.simplify(),
+            visibility: self.lazy(&ty::Visibility::from_hir(vis, id, tcx)),
             span: self.lazy(&md.inner),
             attributes: self.encode_attributes(attrs),
             children: self.lazy_seq(md.item_ids.iter().map(|item_id| {
@@ -327,30 +327,6 @@ fn encode_info_for_mod(&mut self,
     }
 }
 
-trait Visibility {
-    fn simplify(&self) -> ty::Visibility;
-}
-
-impl Visibility for hir::Visibility {
-    fn simplify(&self) -> ty::Visibility {
-        if *self == hir::Public {
-            ty::Visibility::Public
-        } else {
-            ty::Visibility::PrivateExternal
-        }
-    }
-}
-
-impl Visibility for ty::Visibility {
-    fn simplify(&self) -> ty::Visibility {
-        if *self == ty::Visibility::Public {
-            ty::Visibility::Public
-        } else {
-            ty::Visibility::PrivateExternal
-        }
-    }
-}
-
 impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
     fn encode_fields(&mut self, adt_def_id: DefId) {
         let def = self.tcx.lookup_adt_def(adt_def_id);
@@ -386,7 +362,7 @@ fn encode_field(&mut self,
 
         Entry {
             kind: EntryKind::Field,
-            visibility: field.vis.simplify(),
+            visibility: self.lazy(&field.vis),
             span: self.lazy(&tcx.def_span(def_id)),
             attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs),
             children: LazySeq::empty(),
@@ -419,7 +395,7 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
 
         Entry {
             kind: EntryKind::Struct(self.lazy(&data)),
-            visibility: struct_vis.simplify(),
+            visibility: self.lazy(&ty::Visibility::from_hir(struct_vis, struct_id, tcx)),
             span: self.lazy(&tcx.def_span(def_id)),
             attributes: LazySeq::empty(),
             children: LazySeq::empty(),
@@ -466,10 +442,18 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
         let kind = match trait_item.kind {
             ty::AssociatedKind::Const => EntryKind::AssociatedConst(container),
             ty::AssociatedKind::Method => {
-                let fn_data = if let hir::MethodTraitItem(ref sig, _) = ast_item.node {
+                let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node {
+                    let arg_names = match *m {
+                        hir::TraitMethod::Required(ref names) => {
+                            self.encode_fn_arg_names(names)
+                        }
+                        hir::TraitMethod::Provided(body) => {
+                            self.encode_fn_arg_names_for_body(body)
+                        }
+                    };
                     FnData {
                         constness: hir::Constness::NotConst,
-                        arg_names: self.encode_fn_arg_names(&sig.decl),
+                        arg_names: arg_names
                     }
                 } else {
                     bug!()
@@ -485,7 +469,7 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
 
         Entry {
             kind: kind,
-            visibility: trait_item.vis.simplify(),
+            visibility: self.lazy(&trait_item.vis),
             span: self.lazy(&ast_item.span),
             attributes: self.encode_attributes(&ast_item.attrs),
             children: LazySeq::empty(),
@@ -510,13 +494,8 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
-            ast: if let hir::ConstTraitItem(_, Some(_)) = ast_item.node {
-                // We only save the HIR for associated consts with bodies
-                // (InlinedItemRef::from_trait_item panics otherwise)
-                let trait_def_id = trait_item.container.id();
-                Some(self.encode_inlined_item(
-                    InlinedItemRef::from_trait_item(trait_def_id, ast_item, tcx)
-                ))
+            ast: if let hir::TraitItemKind::Const(_, Some(body)) = ast_item.node {
+                Some(self.encode_body(body))
             } else {
                 None
             },
@@ -525,12 +504,9 @@ 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> {
-        let tcx = self.tcx;
-
         let node_id = self.tcx.map.as_local_node_id(def_id).unwrap();
         let ast_item = self.tcx.map.expect_impl_item(node_id);
         let impl_item = self.tcx.associated_item(def_id);
-        let impl_def_id = impl_item.container.id();
 
         let container = match impl_item.defaultness {
             hir::Defaultness::Default { has_value: true } => AssociatedContainer::ImplDefault,
@@ -542,10 +518,10 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
         let kind = match impl_item.kind {
             ty::AssociatedKind::Const => EntryKind::AssociatedConst(container),
             ty::AssociatedKind::Method => {
-                let fn_data = if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node {
+                let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
                     FnData {
                         constness: sig.constness,
-                        arg_names: self.encode_fn_arg_names(&sig.decl),
+                        arg_names: self.encode_fn_arg_names_for_body(body),
                     }
                 } else {
                     bug!()
@@ -559,22 +535,23 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
             ty::AssociatedKind::Type => EntryKind::AssociatedType(container)
         };
 
-        let (ast, mir) = if impl_item.kind == ty::AssociatedKind::Const {
-            (true, true)
-        } else if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node {
+        let (ast, mir) = if let hir::ImplItemKind::Const(_, body) = ast_item.node {
+            (Some(body), true)
+        } else if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
             let generics = self.tcx.item_generics(def_id);
             let types = generics.parent_types as usize + generics.types.len();
             let needs_inline = types > 0 || attr::requests_inline(&ast_item.attrs);
             let is_const_fn = sig.constness == hir::Constness::Const;
+            let ast = if is_const_fn { Some(body) } else { None };
             let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
-            (is_const_fn, needs_inline || is_const_fn || always_encode_mir)
+            (ast, needs_inline || is_const_fn || always_encode_mir)
         } else {
-            (false, false)
+            (None, false)
         };
 
         Entry {
             kind: kind,
-            visibility: impl_item.vis.simplify(),
+            visibility: self.lazy(&impl_item.vis),
             span: self.lazy(&ast_item.span),
             attributes: self.encode_attributes(&ast_item.attrs),
             children: LazySeq::empty(),
@@ -587,27 +564,28 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
-            ast: if ast {
-                Some(self.encode_inlined_item(
-                    InlinedItemRef::from_impl_item(impl_def_id, ast_item, tcx)
-                ))
-            } else {
-                None
-            },
+            ast: ast.map(|body| self.encode_body(body)),
             mir: if mir { self.encode_mir(def_id) } else { None },
         }
     }
 
-    fn encode_fn_arg_names(&mut self, decl: &hir::FnDecl) -> LazySeq<ast::Name> {
-        self.lazy_seq(decl.inputs.iter().map(|arg| {
-            if let PatKind::Binding(_, _, ref path1, _) = arg.pat.node {
-                path1.node
-            } else {
-                Symbol::intern("")
+    fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId)
+                                    -> LazySeq<ast::Name> {
+        let _ignore = self.tcx.dep_graph.in_ignore();
+        let body = self.tcx.map.body(body_id);
+        self.lazy_seq(body.arguments.iter().map(|arg| {
+            match arg.pat.node {
+                PatKind::Binding(_, _, name, _) => name.node,
+                _ => Symbol::intern("")
             }
         }))
     }
 
+    fn encode_fn_arg_names(&mut self, names: &[Spanned<ast::Name>])
+                           -> LazySeq<ast::Name> {
+        self.lazy_seq(names.iter().map(|name| name.node))
+    }
+
     fn encode_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>> {
         self.tcx.mir_map.borrow().get(&def_id).map(|mir| self.lazy(&*mir.borrow()))
     }
@@ -643,10 +621,10 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
             hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic,
             hir::ItemStatic(_, hir::MutImmutable, _) => EntryKind::ImmStatic,
             hir::ItemConst(..) => EntryKind::Const,
-            hir::ItemFn(ref decl, _, constness, ..) => {
+            hir::ItemFn(_, _, constness, .., body) => {
                 let data = FnData {
                     constness: constness,
-                    arg_names: self.encode_fn_arg_names(&decl),
+                    arg_names: self.encode_fn_arg_names_for_body(body),
                 };
 
                 EntryKind::Fn(self.lazy(&data))
@@ -736,7 +714,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
 
         Entry {
             kind: kind,
-            visibility: item.vis.simplify(),
+            visibility: self.lazy(&ty::Visibility::from_hir(&item.vis, item.id, tcx)),
             span: self.lazy(&item.span),
             attributes: self.encode_attributes(&item.attrs),
             children: match item.node {
@@ -817,16 +795,16 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
             },
 
             ast: match item.node {
-                hir::ItemConst(..) |
-                hir::ItemFn(_, _, hir::Constness::Const, ..) => {
-                    Some(self.encode_inlined_item(
-                        InlinedItemRef::from_item(def_id, item, tcx)
-                    ))
+                hir::ItemConst(_, body) |
+                hir::ItemFn(_, _, hir::Constness::Const, _, _, body) => {
+                    Some(self.encode_body(body))
                 }
                 _ => None,
             },
             mir: match item.node {
-                hir::ItemStatic(..) |
+                hir::ItemStatic(..) if self.tcx.sess.opts.debugging_opts.always_encode_mir => {
+                    self.encode_mir(def_id)
+                }
                 hir::ItemConst(..) => self.encode_mir(def_id),
                 hir::ItemFn(_, _, constness, _, ref generics, _) => {
                     let tps_len = generics.ty_params.len();
@@ -849,7 +827,7 @@ fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx
             kind: EntryKind::MacroDef(self.lazy(&MacroDef {
                 body: ::syntax::print::pprust::tts_to_string(&macro_def.body)
             })),
-            visibility: ty::Visibility::Public,
+            visibility: self.lazy(&ty::Visibility::Public),
             span: self.lazy(&macro_def.span),
 
             attributes: self.encode_attributes(&macro_def.attrs),
@@ -937,10 +915,10 @@ fn encode_info_for_foreign_item(&mut self,
         debug!("writing foreign item {}", tcx.node_path_str(nitem.id));
 
         let kind = match nitem.node {
-            hir::ForeignItemFn(ref fndecl, _) => {
+            hir::ForeignItemFn(_, ref names, _) => {
                 let data = FnData {
                     constness: hir::Constness::NotConst,
-                    arg_names: self.encode_fn_arg_names(&fndecl),
+                    arg_names: self.encode_fn_arg_names(names),
                 };
                 EntryKind::ForeignFn(self.lazy(&data))
             }
@@ -950,7 +928,7 @@ fn encode_info_for_foreign_item(&mut self,
 
         Entry {
             kind: kind,
-            visibility: nitem.vis.simplify(),
+            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(),
@@ -1032,7 +1010,7 @@ fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
         let tcx = self.tcx;
         Entry {
             kind: EntryKind::Type,
-            visibility: ty::Visibility::Public,
+            visibility: self.lazy(&ty::Visibility::Public),
             span: self.lazy(&tcx.def_span(def_id)),
             attributes: LazySeq::empty(),
             children: LazySeq::empty(),
@@ -1060,7 +1038,7 @@ fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
 
         Entry {
             kind: EntryKind::Closure(self.lazy(&data)),
-            visibility: ty::Visibility::Public,
+            visibility: self.lazy(&ty::Visibility::Public),
             span: self.lazy(&tcx.def_span(def_id)),
             attributes: self.encode_attributes(&tcx.get_attrs(def_id)),
             children: LazySeq::empty(),
@@ -1186,6 +1164,8 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    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
     }
index 0b6606a00d3c041174759b55f50f5f27c036be39..2bd5a9ea59d04274aeb723bc9d5dac88da80e421 100644 (file)
@@ -201,7 +201,7 @@ pub struct TraitImpls {
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct Entry<'tcx> {
     pub kind: EntryKind<'tcx>,
-    pub visibility: ty::Visibility,
+    pub visibility: Lazy<ty::Visibility>,
     pub span: Lazy<Span>,
     pub attributes: LazySeq<ast::Attribute>,
     pub children: LazySeq<DefIndex>,
index e06d940de7e58238713e82d98a13846ae6ccb87f..63bb1bf20c06c41bccba9d59f7e7fb6f06017c44 100644 (file)
@@ -729,7 +729,7 @@ fn declare_binding(&mut self,
             name: Some(name),
             source_info: Some(source_info),
         });
-        let extent = self.extent_of_innermost_scope();
+        let extent = self.hir.tcx().region_maps.var_scope(var_id);
         self.schedule_drop(source_info.span, extent, &Lvalue::Local(var), var_ty);
         self.var_indices.insert(var_id, var);
 
index 0e4dbb0477716a246acaa97d24c15c02c4d2860d..cfdc1bf27df35411c6f008ba6f4aff42c821980e 100644 (file)
@@ -126,7 +126,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
                                        arguments: A,
                                        abi: Abi,
                                        return_ty: Ty<'gcx>,
-                                       ast_body: &'gcx hir::Expr)
+                                       body: &'gcx hir::Body)
                                        -> Mir<'tcx>
     where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)>
 {
@@ -136,17 +136,16 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
     let span = tcx.map.span(fn_id);
     let mut builder = Builder::new(hir, span, arguments.len(), return_ty);
 
-    let body_id = ast_body.id;
     let call_site_extent =
         tcx.region_maps.lookup_code_extent(
-            CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id });
+            CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body.value.id });
     let arg_extent =
         tcx.region_maps.lookup_code_extent(
-            CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body_id });
+            CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.value.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| {
-            builder.args_and_body(block, &arguments, arg_extent, ast_body)
+            builder.args_and_body(block, &arguments, arg_extent, &body.value)
         }));
         // Attribute epilogue to function's closing brace
         let fn_end = Span { lo: span.hi, ..span };
@@ -197,9 +196,10 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
 
 pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
                                        item_id: ast::NodeId,
-                                       ast_expr: &'tcx hir::Expr)
+                                       body_id: hir::BodyId)
                                        -> Mir<'tcx> {
     let tcx = hir.tcx();
+    let ast_expr = &tcx.map.body(body_id).value;
     let ty = tcx.tables().expr_ty_adjusted(ast_expr);
     let span = tcx.map.span(item_id);
     let mut builder = Builder::new(hir, span, 0, ty);
index c02a1822d736961e39f3b894db8a097664245f76..59a11782e08566744d1e027849a56e60e8506ce4 100644 (file)
@@ -253,7 +253,7 @@ pub fn in_loop_scope<F>(&mut self,
                             f: F)
         where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>)
     {
-        let extent = self.extent_of_innermost_scope();
+        let extent = self.scopes.last().map(|scope| scope.extent).unwrap();
         let loop_scope = LoopScope {
             extent: extent.clone(),
             continue_block: loop_block,
@@ -411,10 +411,6 @@ pub fn source_info(&self, span: Span) -> SourceInfo {
         }
     }
 
-    pub fn extent_of_innermost_scope(&self) -> CodeExtent {
-        self.scopes.last().map(|scope| scope.extent).unwrap()
-    }
-
     /// Returns the extent of the scope which should be exited by a
     /// return.
     pub fn extent_of_return_scope(&self) -> CodeExtent {
index d579cdb042fb3f3b7d4075beacff0eef321d121b..cc65fdede092ff042575c6b4dd388e0344c8abe7 100644 (file)
@@ -575,7 +575,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         }
 
         // Now comes the rote stuff:
-        hir::ExprRepeat(ref v, ref c) => {
+        hir::ExprRepeat(ref v, c) => {
+            let c = &cx.tcx.map.body(c).value;
             ExprKind::Repeat {
                 value: v.to_ref(),
                 count: TypedConstVal {
@@ -585,7 +586,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         ConstVal::Integral(ConstInt::Usize(u)) => u,
                         other => bug!("constant evaluation of repeat count yielded {:?}", other),
                     },
-                },
+                }
             }
         }
         hir::ExprRet(ref v) => ExprKind::Return { value: v.to_ref() },
@@ -780,7 +781,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             let body_id = match cx.tcx.map.find(closure_expr_id) {
                 Some(map::NodeExpr(expr)) => {
                     match expr.node {
-                        hir::ExprClosure(.., body_id, _) => body_id.node_id(),
+                        hir::ExprClosure(.., body, _) => body.node_id,
                         _ => {
                             span_bug!(expr.span, "closure expr is not a closure expr");
                         }
index 617bd81d96a2c90f3f83fe1c86d1ca8651b9ac20..56dadd2d673e1e7fc9bfa7aa9e86c9a358f937c3 100644 (file)
@@ -22,7 +22,6 @@
 
 #![feature(associated_consts)]
 #![feature(box_patterns)]
-#![cfg_attr(stage0, feature(item_like_imports))]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
index e2a516edbc8354ff69a7108d3ba416f03b98d832..cbc53ea3c51c747ae5e38399e6ace1c76d4ee0cf 100644 (file)
@@ -129,16 +129,17 @@ fn build<F>(&'tcx mut self, f: F)
 }
 
 impl<'a, 'gcx> BuildMir<'a, 'gcx> {
-    fn build_const_integer(&mut self, expr: &'gcx hir::Expr) {
+    fn build_const_integer(&mut self, body: hir::BodyId) {
+        let body = self.tcx.map.body(body);
         // FIXME(eddyb) Closures should have separate
         // function definition IDs and expression IDs.
         // Type-checking should not let closures get
         // this far in an integer constant position.
-        if let hir::ExprClosure(..) = expr.node {
+        if let hir::ExprClosure(..) = body.value.node {
             return;
         }
-        self.cx(MirSource::Const(expr.id)).build(|cx| {
-            build::construct_const(cx, expr.id, expr)
+        self.cx(MirSource::Const(body.value.id)).build(|cx| {
+            build::construct_const(cx, body.value.id, body.id())
         });
     }
 }
@@ -151,12 +152,12 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     // Const and static items.
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         match item.node {
-            hir::ItemConst(_, ref expr) => {
+            hir::ItemConst(_, expr) => {
                 self.cx(MirSource::Const(item.id)).build(|cx| {
                     build::construct_const(cx, item.id, expr)
                 });
             }
-            hir::ItemStatic(_, m, ref expr) => {
+            hir::ItemStatic(_, m, expr) => {
                 self.cx(MirSource::Static(item.id, m)).build(|cx| {
                     build::construct_const(cx, item.id, expr)
                 });
@@ -168,7 +169,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
 
     // Trait associated const defaults.
     fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
-        if let hir::ConstTraitItem(_, Some(ref expr)) = item.node {
+        if let hir::TraitItemKind::Const(_, Some(expr)) = item.node {
             self.cx(MirSource::Const(item.id)).build(|cx| {
                 build::construct_const(cx, item.id, expr)
             });
@@ -178,7 +179,7 @@ fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
 
     // Impl associated const.
     fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
-        if let hir::ImplItemKind::Const(_, ref expr) = item.node {
+        if let hir::ImplItemKind::Const(_, expr) = item.node {
             self.cx(MirSource::Const(item.id)).build(|cx| {
                 build::construct_const(cx, item.id, expr)
             });
@@ -188,7 +189,7 @@ fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
 
     // Repeat counts, i.e. [expr; constant].
     fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
-        if let hir::ExprRepeat(_, ref count) = expr.node {
+        if let hir::ExprRepeat(_, count) = expr.node {
             self.build_const_integer(count);
         }
         intravisit::walk_expr(self, expr);
@@ -196,7 +197,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
 
     // Array lengths, i.e. [T; constant].
     fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
-        if let hir::TyArray(_, ref length) = ty.node {
+        if let hir::TyArray(_, length) = ty.node {
             self.build_const_integer(length);
         }
         intravisit::walk_ty(self, ty);
@@ -205,7 +206,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
     // Enum variant discriminant values.
     fn visit_variant(&mut self, v: &'tcx hir::Variant,
                      g: &'tcx hir::Generics, item_id: ast::NodeId) {
-        if let Some(ref expr) = v.node.disr_expr {
+        if let Some(expr) = v.node.disr_expr {
             self.build_const_integer(expr);
         }
         intravisit::walk_variant(self, v, g, item_id);
@@ -214,7 +215,7 @@ fn visit_variant(&mut self, v: &'tcx hir::Variant,
     fn visit_fn(&mut self,
                 fk: FnKind<'tcx>,
                 decl: &'tcx hir::FnDecl,
-                body_id: hir::ExprId,
+                body_id: hir::BodyId,
                 span: Span,
                 id: ast::NodeId) {
         // fetch the fully liberated fn signature (that is, all bound
@@ -227,22 +228,21 @@ fn visit_fn(&mut self,
         };
 
         let (abi, implicit_argument) = if let FnKind::Closure(..) = fk {
-            (Abi::Rust, Some((closure_self_ty(self.tcx, id, body_id.node_id()), None)))
+            (Abi::Rust, Some((closure_self_ty(self.tcx, id, body_id.node_id), None)))
         } else {
             let def_id = self.tcx.map.local_def_id(id);
             (self.tcx.item_type(def_id).fn_abi(), None)
         };
 
+        let body = self.tcx.map.body(body_id);
         let explicit_arguments =
-            decl.inputs
+            body.arguments
                 .iter()
                 .enumerate()
                 .map(|(index, arg)| {
                     (fn_sig.inputs()[index], Some(&*arg.pat))
                 });
 
-        let body = self.tcx.map.expr(body_id);
-
         let arguments = implicit_argument.into_iter().chain(explicit_arguments);
         self.cx(MirSource::Fn(id)).build(|cx| {
             build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body)
index bc150b847786f2c08531e847d08061b2f9600d3d..52bdd014933b8d6438949a179e1afe5cbe041d7a 100644 (file)
@@ -154,8 +154,8 @@ fn visit_ty(&mut self, ty: &'a Ty) {
     }
 
     fn visit_path(&mut self, path: &'a Path, id: NodeId) {
-        if path.global && path.segments.len() > 0 {
-            let ident = path.segments[0].identifier;
+        if path.segments.len() >= 2 && path.is_global() {
+            let ident = path.segments[1].identifier;
             if token::Ident(ident).is_path_segment_keyword() {
                 self.session.add_lint(lint::builtin::SUPER_OR_SELF_IN_GLOBAL_PATH,
                                       id,
index 86f56d003584155205fe623628809f055c4deefb..d1d9a201567bbc6ba022672d3134019f96e9f459 100644 (file)
@@ -26,8 +26,8 @@
 
 use rustc::dep_graph::DepNode;
 use rustc::ty::cast::CastKind;
-use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, compare_lit_exprs};
-use rustc_const_eval::{ConstFnNode, eval_const_expr_partial, lookup_const_by_id};
+use rustc_const_eval::{ConstEvalErr, compare_lit_exprs};
+use rustc_const_eval::{eval_const_expr_partial};
 use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal, MiscCatchAll, Math};
 use rustc_const_eval::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp, NonConstPath};
 use rustc_const_eval::ErrKind::UnresolvedPath;
 use rustc_const_math::{ConstMathErr, Op};
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::DefId;
+use rustc::hir::map::blocks::FnLikeNode;
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::mem_categorization::Categorization;
+use rustc::mir::transform::MirSource;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::traits::Reveal;
 use rustc::util::common::ErrorReported;
-use rustc::util::nodemap::NodeMap;
-use rustc::middle::const_qualif::ConstQualif;
+use rustc::util::nodemap::NodeSet;
 use rustc::lint::builtin::CONST_ERR;
 
 use rustc::hir::{self, PatKind};
 use syntax::ast;
 use syntax_pos::Span;
-use rustc::hir::intravisit::{self, FnKind, Visitor, NestedVisitorMap};
+use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 
 use std::collections::hash_map::Entry;
 use std::cmp::Ordering;
-
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-enum Mode {
-    Const,
-    ConstFn,
-    Static,
-    StaticMut,
-
-    // An expression that occurs outside of any constant context
-    // (i.e. `const`, `static`, array lengths, etc.). The value
-    // can be variable at runtime, but will be promotable to
-    // static memory if we can prove it is actually constant.
-    Var,
-}
+use std::mem;
 
 struct CheckCrateVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mode: Mode,
-    qualif: ConstQualif,
-    rvalue_borrows: NodeMap<hir::Mutability>,
+    in_fn: bool,
+    promotable: bool,
+    mut_rvalue_borrows: NodeSet,
+    param_env: ty::ParameterEnvironment<'tcx>,
 }
 
 impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
-    fn with_mode<F, R>(&mut self, mode: Mode, f: F) -> R
-        where F: FnOnce(&mut CheckCrateVisitor<'a, 'gcx>) -> R
-    {
-        let (old_mode, old_qualif) = (self.mode, self.qualif);
-        self.mode = mode;
-        self.qualif = ConstQualif::empty();
-        let r = f(self);
-        self.mode = old_mode;
-        self.qualif = old_qualif;
-        r
-    }
-
-    fn with_euv<F, R>(&mut self, item_id: Option<ast::NodeId>, f: F) -> R
-        where F: for<'b, 'tcx> FnOnce(&mut euv::ExprUseVisitor<'b, 'gcx, 'tcx>) -> R
-    {
-        let param_env = match item_id {
-            Some(item_id) => ty::ParameterEnvironment::for_item(self.tcx, item_id),
-            None => self.tcx.empty_parameter_environment(),
-        };
-
-        self.tcx
-            .infer_ctxt(None, Some(param_env), Reveal::NotSpecializable)
-            .enter(|infcx| f(&mut euv::ExprUseVisitor::new(self, &infcx)))
-    }
-
-    fn global_expr(&mut self, mode: Mode, expr: &'gcx hir::Expr) -> ConstQualif {
-        assert!(mode != Mode::Var);
-        match self.tcx.const_qualif_map.borrow_mut().entry(expr.id) {
-            Entry::Occupied(entry) => return *entry.get(),
-            Entry::Vacant(entry) => {
-                // Prevent infinite recursion on re-entry.
-                entry.insert(ConstQualif::empty());
-            }
-        }
+    fn check_const_eval(&self, expr: &'gcx hir::Expr) {
         if let Err(err) = eval_const_expr_partial(self.tcx, expr, ExprTypeChecked, None) {
             match err.kind {
                 UnimplementedConstVal(_) => {}
@@ -124,184 +80,78 @@ fn global_expr(&mut self, mode: Mode, expr: &'gcx hir::Expr) -> ConstQualif {
                 }
             }
         }
-        self.with_mode(mode, |this| {
-            this.with_euv(None, |euv| euv.consume_expr(expr));
-            this.visit_expr(expr);
-            this.qualif
-        })
     }
 
-    fn fn_like(&mut self,
-               fk: FnKind<'gcx>,
-               fd: &'gcx hir::FnDecl,
-               b: hir::ExprId,
-               s: Span,
-               fn_id: ast::NodeId)
-               -> ConstQualif {
-        match self.tcx.const_qualif_map.borrow_mut().entry(fn_id) {
-            Entry::Occupied(entry) => return *entry.get(),
-            Entry::Vacant(entry) => {
-                // Prevent infinite recursion on re-entry.
-                entry.insert(ConstQualif::empty());
-            }
+    // Adds the worst effect out of all the values of one type.
+    fn add_type(&mut self, ty: Ty<'gcx>) {
+        if ty.type_contents(self.tcx).interior_unsafe() {
+            self.promotable = false;
         }
 
-        let mode = match fk {
-            FnKind::ItemFn(_, _, _, hir::Constness::Const, ..)
-                => Mode::ConstFn,
-            FnKind::Method(_, m, ..) => {
-                if m.constness == hir::Constness::Const {
-                    Mode::ConstFn
-                } else {
-                    Mode::Var
-                }
-            }
-            _ => Mode::Var,
-        };
-
-        let qualif = self.with_mode(mode, |this| {
-            let body = this.tcx.map.expr(b);
-            this.with_euv(Some(fn_id), |euv| euv.walk_fn(fd, body));
-            intravisit::walk_fn(this, fk, fd, b, s, fn_id);
-            this.qualif
-        });
-
-        // Keep only bits that aren't affected by function body (NON_ZERO_SIZED),
-        // and bits that don't change semantics, just optimizations (PREFER_IN_PLACE).
-        let qualif = qualif & (ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
-
-        self.tcx.const_qualif_map.borrow_mut().insert(fn_id, qualif);
-        qualif
-    }
-
-    fn add_qualif(&mut self, qualif: ConstQualif) {
-        self.qualif = self.qualif | qualif;
-    }
-
-    /// Returns true if the call is to a const fn or method.
-    fn handle_const_fn_call(&mut self, _expr: &hir::Expr, def_id: DefId, ret_ty: Ty<'gcx>) -> bool {
-        match lookup_const_fn_by_id(self.tcx, def_id) {
-            Some(ConstFnNode::Local(fn_like)) => {
-                let qualif = self.fn_like(fn_like.kind(),
-                                          fn_like.decl(),
-                                          fn_like.body(),
-                                          fn_like.span(),
-                                          fn_like.id());
-
-                self.add_qualif(qualif);
-
-                if ret_ty.type_contents(self.tcx).interior_unsafe() {
-                    self.add_qualif(ConstQualif::MUTABLE_MEM);
-                }
-
-                true
-            },
-            Some(ConstFnNode::Inlined(ii)) => {
-                let node_id = ii.body.id;
-
-                let qualif = match self.tcx.const_qualif_map.borrow_mut().entry(node_id) {
-                    Entry::Occupied(entry) => *entry.get(),
-                    _ => bug!("const qualif entry missing for inlined item")
-                };
-
-                self.add_qualif(qualif);
-
-                if ret_ty.type_contents(self.tcx).interior_unsafe() {
-                    self.add_qualif(ConstQualif::MUTABLE_MEM);
-                }
-
-                true
-            },
-            None => false
+        if self.tcx.type_needs_drop_given_env(ty, &self.param_env) {
+            self.promotable = false;
         }
     }
 
-    fn record_borrow(&mut self, id: ast::NodeId, mutbl: hir::Mutability) {
-        match self.rvalue_borrows.entry(id) {
-            Entry::Occupied(mut entry) => {
-                // Merge the two borrows, taking the most demanding
-                // one, mutability-wise.
-                if mutbl == hir::MutMutable {
-                    entry.insert(mutbl);
-                }
-            }
-            Entry::Vacant(entry) => {
-                entry.insert(mutbl);
-            }
-        }
+    fn handle_const_fn_call(&mut self, def_id: DefId, ret_ty: Ty<'gcx>) {
+        self.add_type(ret_ty);
+
+        self.promotable &= if let Some(fn_id) = self.tcx.map.as_local_node_id(def_id) {
+            FnLikeNode::from_node(self.tcx.map.get(fn_id)).map_or(false, |fn_like| {
+                fn_like.constness() == hir::Constness::Const
+            })
+        } else {
+            self.tcx.sess.cstore.is_const_fn(def_id)
+        };
     }
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.map)
+        NestedVisitorMap::None
     }
 
-    fn visit_item(&mut self, i: &'tcx hir::Item) {
-        debug!("visit_item(item={})", self.tcx.map.node_to_string(i.id));
-        assert_eq!(self.mode, Mode::Var);
-        match i.node {
-            hir::ItemStatic(_, hir::MutImmutable, ref expr) => {
-                self.global_expr(Mode::Static, &expr);
-            }
-            hir::ItemStatic(_, hir::MutMutable, ref expr) => {
-                self.global_expr(Mode::StaticMut, &expr);
-            }
-            hir::ItemConst(_, ref expr) => {
-                self.global_expr(Mode::Const, &expr);
-            }
-            hir::ItemEnum(ref enum_definition, _) => {
-                for var in &enum_definition.variants {
-                    if let Some(ref ex) = var.node.disr_expr {
-                        self.global_expr(Mode::Const, &ex);
-                    }
-                }
-            }
-            _ => {
-                intravisit::walk_item(self, i);
+    fn visit_nested_body(&mut self, body: hir::BodyId) {
+        match self.tcx.rvalue_promotable_to_static.borrow_mut().entry(body.node_id) {
+            Entry::Occupied(_) => return,
+            Entry::Vacant(entry) => {
+                // Prevent infinite recursion on re-entry.
+                entry.insert(false);
             }
         }
-    }
 
-    fn visit_trait_item(&mut self, t: &'tcx hir::TraitItem) {
-        match t.node {
-            hir::ConstTraitItem(_, ref default) => {
-                if let Some(ref expr) = *default {
-                    self.global_expr(Mode::Const, &expr);
-                } else {
-                    intravisit::walk_trait_item(self, t);
-                }
-            }
-            _ => self.with_mode(Mode::Var, |v| intravisit::walk_trait_item(v, t)),
-        }
-    }
+        let item_id = self.tcx.map.body_owner(body);
 
-    fn visit_impl_item(&mut self, i: &'tcx hir::ImplItem) {
-        match i.node {
-            hir::ImplItemKind::Const(_, ref expr) => {
-                self.global_expr(Mode::Const, &expr);
-            }
-            _ => self.with_mode(Mode::Var, |v| intravisit::walk_impl_item(v, i)),
+        let outer_in_fn = self.in_fn;
+        self.in_fn = match MirSource::from_node(self.tcx, item_id) {
+            MirSource::Fn(_) => true,
+            _ => false
+        };
+
+        let body = self.tcx.map.body(body);
+        if !self.in_fn {
+            self.check_const_eval(&body.value);
         }
-    }
 
-    fn visit_fn(&mut self,
-                fk: FnKind<'tcx>,
-                fd: &'tcx hir::FnDecl,
-                b: hir::ExprId,
-                s: Span,
-                fn_id: ast::NodeId) {
-        self.fn_like(fk, fd, b, s, fn_id);
+        let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id);
+        let outer_param_env = mem::replace(&mut self.param_env, param_env);
+        self.tcx.infer_ctxt(None, Some(self.param_env.clone()), Reveal::NotSpecializable)
+            .enter(|infcx| euv::ExprUseVisitor::new(self, &infcx).consume_body(body));
+
+        self.visit_body(body);
+
+        self.param_env = outer_param_env;
+        self.in_fn = outer_in_fn;
     }
 
     fn visit_pat(&mut self, p: &'tcx hir::Pat) {
         match p.node {
             PatKind::Lit(ref lit) => {
-                self.global_expr(Mode::Const, &lit);
+                self.check_const_eval(lit);
             }
             PatKind::Range(ref start, ref end) => {
-                self.global_expr(Mode::Const, &start);
-                self.global_expr(Mode::Const, &end);
+                self.check_const_eval(start);
+                self.check_const_eval(end);
 
                 match compare_lit_exprs(self.tcx, p.span, start, end) {
                     Ok(Ordering::Less) |
@@ -315,119 +165,60 @@ fn visit_pat(&mut self, p: &'tcx hir::Pat) {
                     Err(ErrorReported) => {}
                 }
             }
-            _ => intravisit::walk_pat(self, p),
+            _ => {}
         }
+        intravisit::walk_pat(self, p);
     }
 
-    fn visit_block(&mut self, block: &'tcx hir::Block) {
-        // Check all statements in the block
-        for stmt in &block.stmts {
-            match stmt.node {
-                hir::StmtDecl(ref decl, _) => {
-                    match decl.node {
-                        hir::DeclLocal(_) => {}
-                        // Item statements are allowed
-                        hir::DeclItem(_) => continue,
+    fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt) {
+        match stmt.node {
+            hir::StmtDecl(ref decl, _) => {
+                match decl.node {
+                    hir::DeclLocal(_) => {
+                        self.promotable = false;
                     }
+                    // Item statements are allowed
+                    hir::DeclItem(_) => {}
                 }
-                hir::StmtExpr(..) => {}
-                hir::StmtSemi(..) => {}
             }
-            self.add_qualif(ConstQualif::NOT_CONST);
+            hir::StmtExpr(..) |
+            hir::StmtSemi(..) => {
+                self.promotable = false;
+            }
         }
-        intravisit::walk_block(self, block);
+        intravisit::walk_stmt(self, stmt);
     }
 
     fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
-        let mut outer = self.qualif;
-        self.qualif = ConstQualif::empty();
+        let outer = self.promotable;
+        self.promotable = true;
 
         let node_ty = self.tcx.tables().node_id_to_type(ex.id);
         check_expr(self, ex, node_ty);
         check_adjustments(self, ex);
 
-        // Special-case some expressions to avoid certain flags bubbling up.
-        match ex.node {
-            hir::ExprCall(ref callee, ref args) => {
-                for arg in args {
-                    self.visit_expr(&arg)
+        if let hir::ExprMatch(ref discr, ref arms, _) = ex.node {
+            // Compute the most demanding borrow from all the arms'
+            // patterns and set that on the discriminator.
+            let mut mut_borrow = false;
+            for pat in arms.iter().flat_map(|arm| &arm.pats) {
+                if self.mut_rvalue_borrows.remove(&pat.id) {
+                    mut_borrow = true;
                 }
-
-                let inner = self.qualif;
-                self.visit_expr(&callee);
-                // The callee's size doesn't count in the call.
-                let added = self.qualif - inner;
-                self.qualif = inner | (added - ConstQualif::NON_ZERO_SIZED);
             }
-            hir::ExprRepeat(ref element, _) => {
-                self.visit_expr(&element);
-                // The count is checked elsewhere (typeck).
-                let count = match node_ty.sty {
-                    ty::TyArray(_, n) => n,
-                    _ => bug!(),
-                };
-                // [element; 0] is always zero-sized.
-                if count == 0 {
-                    self.qualif.remove(ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
-                }
+            if mut_borrow {
+                self.mut_rvalue_borrows.insert(discr.id);
             }
-            hir::ExprMatch(ref discr, ref arms, _) => {
-                // Compute the most demanding borrow from all the arms'
-                // patterns and set that on the discriminator.
-                let mut borrow = None;
-                for pat in arms.iter().flat_map(|arm| &arm.pats) {
-                    let pat_borrow = self.rvalue_borrows.remove(&pat.id);
-                    match (borrow, pat_borrow) {
-                        (None, _) |
-                        (_, Some(hir::MutMutable)) => {
-                            borrow = pat_borrow;
-                        }
-                        _ => {}
-                    }
-                }
-                if let Some(mutbl) = borrow {
-                    self.record_borrow(discr.id, mutbl);
-                }
-                intravisit::walk_expr(self, ex);
-            }
-            _ => intravisit::walk_expr(self, ex),
         }
 
+        intravisit::walk_expr(self, ex);
+
         // Handle borrows on (or inside the autorefs of) this expression.
-        match self.rvalue_borrows.remove(&ex.id) {
-            Some(hir::MutImmutable) => {
-                // Constants cannot be borrowed if they contain interior mutability as
-                // it means that our "silent insertion of statics" could change
-                // initializer values (very bad).
-                // If the type doesn't have interior mutability, then `ConstQualif::MUTABLE_MEM` has
-                // propagated from another error, so erroring again would be just noise.
-                let tc = node_ty.type_contents(self.tcx);
-                if self.qualif.intersects(ConstQualif::MUTABLE_MEM) && tc.interior_unsafe() {
-                    outer = outer | ConstQualif::NOT_CONST;
-                }
-                // If the reference has to be 'static, avoid in-place initialization
-                // as that will end up pointing to the stack instead.
-                if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
-                    self.qualif = self.qualif - ConstQualif::PREFER_IN_PLACE;
-                    self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
-                }
-            }
-            Some(hir::MutMutable) => {
-                // `&mut expr` means expr could be mutated, unless it's zero-sized.
-                if self.qualif.intersects(ConstQualif::NON_ZERO_SIZED) {
-                    if self.mode == Mode::Var {
-                        outer = outer | ConstQualif::NOT_CONST;
-                        self.add_qualif(ConstQualif::MUTABLE_MEM);
-                    }
-                }
-                if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
-                    self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
-                }
-            }
-            None => {}
+        if self.mut_rvalue_borrows.remove(&ex.id) {
+            self.promotable = false;
         }
 
-        if self.mode == Mode::Var && !self.qualif.intersects(ConstQualif::NOT_CONST) {
+        if self.in_fn && self.promotable {
             match eval_const_expr_partial(self.tcx, ex, ExprTypeChecked, None) {
                 Ok(_) => {}
                 Err(ConstEvalErr { kind: UnimplementedConstVal(_), .. }) |
@@ -448,9 +239,8 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
             }
         }
 
-        self.tcx.const_qualif_map.borrow_mut().insert(ex.id, self.qualif);
-        // Don't propagate certain flags.
-        self.qualif = outer | (self.qualif - ConstQualif::HAS_STATIC_BORROWS);
+        self.tcx.rvalue_promotable_to_static.borrow_mut().insert(ex.id, self.promotable);
+        self.promotable &= outer;
     }
 }
 
@@ -463,7 +253,7 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
 fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node_ty: Ty<'tcx>) {
     match node_ty.sty {
         ty::TyAdt(def, _) if def.has_dtor() => {
-            v.add_qualif(ConstQualif::NEEDS_DROP);
+            v.promotable = false;
         }
         _ => {}
     }
@@ -473,17 +263,17 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
         hir::ExprUnary(..) |
         hir::ExprBinary(..) |
         hir::ExprIndex(..) if v.tcx.tables().method_map.contains_key(&method_call) => {
-            v.add_qualif(ConstQualif::NOT_CONST);
+            v.promotable = false;
         }
         hir::ExprBox(_) => {
-            v.add_qualif(ConstQualif::NOT_CONST);
+            v.promotable = false;
         }
         hir::ExprUnary(op, ref inner) => {
             match v.tcx.tables().node_id_to_type(inner.id).sty {
                 ty::TyRawPtr(_) => {
                     assert!(op == hir::UnDeref);
 
-                    v.add_qualif(ConstQualif::NOT_CONST);
+                    v.promotable = false;
                 }
                 _ => {}
             }
@@ -495,7 +285,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
                             op.node == hir::BiLe || op.node == hir::BiLt ||
                             op.node == hir::BiGe || op.node == hir::BiGt);
 
-                    v.add_qualif(ConstQualif::NOT_CONST);
+                    v.promotable = false;
                 }
                 _ => {}
             }
@@ -505,7 +295,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
             match v.tcx.cast_kinds.borrow().get(&from.id) {
                 None => span_bug!(e.span, "no kind for cast"),
                 Some(&CastKind::PtrAddrCast) | Some(&CastKind::FnPtrAddrCast) => {
-                    v.add_qualif(ConstQualif::NOT_CONST);
+                    v.promotable = false;
                 }
                 _ => {}
             }
@@ -513,33 +303,24 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
         hir::ExprPath(ref qpath) => {
             let def = v.tcx.tables().qpath_def(qpath, e.id);
             match def {
-                Def::VariantCtor(_, CtorKind::Const) => {
-                    // Size is determined by the whole enum, may be non-zero.
-                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-                }
                 Def::VariantCtor(..) | Def::StructCtor(..) |
                 Def::Fn(..) | Def::Method(..) => {}
-                Def::Static(..) => {
-                    match v.mode {
-                        Mode::Static | Mode::StaticMut => {}
-                        Mode::Const | Mode::ConstFn => {}
-                        Mode::Var => v.add_qualif(ConstQualif::NOT_CONST)
-                    }
-                }
-                Def::Const(did) | Def::AssociatedConst(did) => {
-                    let substs = Some(v.tcx.tables().node_id_item_substs(e.id)
-                        .unwrap_or_else(|| v.tcx.intern_substs(&[])));
-                    if let Some((expr, _)) = lookup_const_by_id(v.tcx, did, substs) {
-                        let inner = v.global_expr(Mode::Const, expr);
-                        v.add_qualif(inner);
-                    }
-                }
-                Def::Local(..) if v.mode == Mode::ConstFn => {
-                    // Sadly, we can't determine whether the types are zero-sized.
-                    v.add_qualif(ConstQualif::NOT_CONST | ConstQualif::NON_ZERO_SIZED);
+                Def::AssociatedConst(_) => v.add_type(node_ty),
+                Def::Const(did) => {
+                    v.promotable &= if let Some(node_id) = v.tcx.map.as_local_node_id(did) {
+                        match v.tcx.map.expect_item(node_id).node {
+                            hir::ItemConst(_, body) => {
+                                v.visit_nested_body(body);
+                                v.tcx.rvalue_promotable_to_static.borrow()[&body.node_id]
+                            }
+                            _ => false
+                        }
+                    } else {
+                        v.tcx.sess.cstore.const_is_rvalue_promotable_to_static(did)
+                    };
                 }
                 _ => {
-                    v.add_qualif(ConstQualif::NOT_CONST);
+                    v.promotable = false;
                 }
             }
         }
@@ -560,65 +341,48 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
             } else {
                 Def::Err
             };
-            let is_const = match def {
+            match def {
                 Def::StructCtor(_, CtorKind::Fn) |
-                Def::VariantCtor(_, CtorKind::Fn) => {
-                    // `NON_ZERO_SIZED` is about the call result, not about the ctor itself.
-                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-                    true
-                }
+                Def::VariantCtor(_, CtorKind::Fn) => {}
                 Def::Fn(did) => {
-                    v.handle_const_fn_call(e, did, node_ty)
+                    v.handle_const_fn_call(did, node_ty)
                 }
                 Def::Method(did) => {
                     match v.tcx.associated_item(did).container {
                         ty::ImplContainer(_) => {
-                            v.handle_const_fn_call(e, did, node_ty)
+                            v.handle_const_fn_call(did, node_ty)
                         }
-                        ty::TraitContainer(_) => false
+                        ty::TraitContainer(_) => v.promotable = false
                     }
                 }
-                _ => false
-            };
-            if !is_const {
-                v.add_qualif(ConstQualif::NOT_CONST);
+                _ => v.promotable = false
             }
         }
         hir::ExprMethodCall(..) => {
             let method = v.tcx.tables().method_map[&method_call];
-            let is_const = match v.tcx.associated_item(method.def_id).container {
-                ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty),
-                ty::TraitContainer(_) => false
-            };
-            if !is_const {
-                v.add_qualif(ConstQualif::NOT_CONST);
+            match v.tcx.associated_item(method.def_id).container {
+                ty::ImplContainer(_) => v.handle_const_fn_call(method.def_id, node_ty),
+                ty::TraitContainer(_) => v.promotable = false
             }
         }
         hir::ExprStruct(..) => {
             if let ty::TyAdt(adt, ..) = v.tcx.tables().expr_ty(e).sty {
                 // unsafe_cell_type doesn't necessarily exist with no_core
                 if Some(adt.did) == v.tcx.lang_items.unsafe_cell_type() {
-                    v.add_qualif(ConstQualif::MUTABLE_MEM);
+                    v.promotable = false;
                 }
             }
         }
 
         hir::ExprLit(_) |
-        hir::ExprAddrOf(..) => {
-            v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-        }
-
-        hir::ExprRepeat(..) => {
-            v.add_qualif(ConstQualif::PREFER_IN_PLACE);
-        }
+        hir::ExprAddrOf(..) |
+        hir::ExprRepeat(..) => {}
 
         hir::ExprClosure(..) => {
             // Paths in constant contexts cannot refer to local variables,
             // as there are none, and thus closures can't have upvars there.
             if v.tcx.with_freevars(e.id, |fv| !fv.is_empty()) {
-                assert!(v.mode == Mode::Var,
-                        "global closures can't capture anything");
-                v.add_qualif(ConstQualif::NOT_CONST);
+                v.promotable = false;
             }
         }
 
@@ -647,7 +411,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
         hir::ExprAssign(..) |
         hir::ExprAssignOp(..) |
         hir::ExprInlineAsm(..) => {
-            v.add_qualif(ConstQualif::NOT_CONST);
+            v.promotable = false;
         }
     }
 }
@@ -666,7 +430,7 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp
         Some(Adjust::DerefRef { autoderefs, .. }) => {
             if (0..autoderefs as u32)
                 .any(|autoderef| v.tcx.tables().is_overloaded_autoderef(e.id, autoderef)) {
-                v.add_qualif(ConstQualif::NOT_CONST);
+                v.promotable = false;
             }
         }
     }
@@ -676,9 +440,10 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     tcx.visit_all_item_likes_in_krate(DepNode::CheckConst,
                                       &mut CheckCrateVisitor {
                                           tcx: tcx,
-                                          mode: Mode::Var,
-                                          qualif: ConstQualif::NOT_CONST,
-                                          rvalue_borrows: NodeMap(),
+                                          in_fn: false,
+                                          promotable: false,
+                                          mut_rvalue_borrows: NodeSet(),
+                                          param_env: tcx.empty_parameter_environment(),
                                       }.as_deep_visitor());
     tcx.sess.abort_if_errors();
 }
@@ -687,24 +452,9 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> {
     fn consume(&mut self,
                _consume_id: ast::NodeId,
                _consume_span: Span,
-               cmt: mc::cmt,
-               _mode: euv::ConsumeMode) {
-        let mut cur = &cmt;
-        loop {
-            match cur.cat {
-                Categorization::StaticItem => {
-                    break;
-                }
-                Categorization::Deref(ref cmt, ..) |
-                Categorization::Downcast(ref cmt, _) |
-                Categorization::Interior(ref cmt, _) => cur = cmt,
+               _cmt: mc::cmt,
+               _mode: euv::ConsumeMode) {}
 
-                Categorization::Rvalue(..) |
-                Categorization::Upvar(..) |
-                Categorization::Local(..) => break,
-            }
-        }
-    }
     fn borrow(&mut self,
               borrow_id: ast::NodeId,
               _borrow_span: Span,
@@ -731,21 +481,9 @@ fn borrow(&mut self,
                         // Ignore the dummy immutable borrow created by EUV.
                         break;
                     }
-                    let mutbl = bk.to_mutbl_lossy();
-                    if mutbl == hir::MutMutable && self.mode == Mode::StaticMut {
-                        // Mutable slices are the only `&mut` allowed in
-                        // globals, but only in `static mut`, nowhere else.
-                        // FIXME: This exception is really weird... there isn't
-                        // any fundamental reason to restrict this based on
-                        // type of the expression.  `&mut [1]` has exactly the
-                        // same representation as &mut 1.
-                        match cmt.ty.sty {
-                            ty::TyArray(..) |
-                            ty::TySlice(_) => break,
-                            _ => {}
-                        }
+                    if bk.to_mutbl_lossy() == hir::MutMutable {
+                        self.mut_rvalue_borrows.insert(borrow_id);
                     }
-                    self.record_borrow(borrow_id, mutbl);
                     break;
                 }
                 Categorization::StaticItem => {
index f7e026866e2df04d0bbc7820f0124b78fbf3216a..65a60732fc8074e423790ba73597b0e387316d64 100644 (file)
@@ -115,6 +115,11 @@ fn visit_nested_item(&mut self, id: hir::ItemId) {
         self.visit_item(nested_item)
     }
 
+    fn visit_nested_trait_item(&mut self, trait_item_id: hir::TraitItemId) {
+        let nested_trait_item = self.krate.unwrap().trait_item(trait_item_id);
+        self.visit_trait_item(nested_trait_item)
+    }
+
     fn visit_nested_impl_item(&mut self, impl_item_id: hir::ImplItemId) {
         let nested_impl_item = self.krate.unwrap().impl_item(impl_item_id);
         self.visit_impl_item(nested_impl_item)
@@ -172,7 +177,7 @@ fn visit_ty(&mut self, t: &'v hir::Ty) {
     fn visit_fn(&mut self,
                 fk: hir_visit::FnKind<'v>,
                 fd: &'v hir::FnDecl,
-                b: hir::ExprId,
+                b: hir::BodyId,
                 s: Span,
                 id: NodeId) {
         self.record("FnDecl", Id::None, fd);
index 10f464a9901d0beebb54f19fc72c9852f70447fe..df9fe00e9a88e23d99f9e248d6843b0c12610a14 100644 (file)
@@ -84,7 +84,7 @@ fn visit_expr(&mut self, e: &'ast hir::Expr) {
                 self.with_context(Loop(LoopKind::Loop(source)), |v| v.visit_block(&b));
             }
             hir::ExprClosure(.., b, _) => {
-                self.with_context(Closure, |v| v.visit_body(b));
+                self.with_context(Closure, |v| v.visit_nested_body(b));
             }
             hir::ExprBreak(label, ref opt_expr) => {
                 if opt_expr.is_some() {
index ddb5af1e80c345a00973628fb3cb1a4a97051034..3da4f24b6c2fe077243b34e0c25a60f9dd84f77e 100644 (file)
@@ -39,7 +39,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     fn visit_fn(&mut self,
                 fk: intravisit::FnKind<'tcx>,
                 fd: &'tcx hir::FnDecl,
-                b: hir::ExprId,
+                b: hir::BodyId,
                 s: Span,
                 fn_id: ast::NodeId) {
         // FIXME (@jroesch) change this to be an inference context
@@ -50,9 +50,9 @@ fn visit_fn(&mut self,
                 tcx: infcx.tcx,
                 param_env: &param_env
             };
-            let body = infcx.tcx.map.expr(b);
+            let body = infcx.tcx.map.body(b);
             let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx);
-            euv.walk_fn(fd, body);
+            euv.consume_body(body);
         });
         intravisit::walk_fn(self, fk, fd, b, s, fn_id)
     }
index b5be4aa5e64e2ac25195bbf653f0220238cb6808..ba4fc57276b2ce21a2709b118ef6098d7785676b 100644 (file)
@@ -30,7 +30,7 @@ struct CheckCrateVisitor<'a, 'ast: 'a> {
     // variant definitions with the discriminant expression that applies to
     // each one. If the variant uses the default values (starting from `0`),
     // then `None` is stored.
-    discriminant_map: NodeMap<Option<&'ast hir::Expr>>,
+    discriminant_map: NodeMap<Option<hir::BodyId>>,
     detected_recursive_ids: NodeSet,
 }
 
@@ -66,7 +66,7 @@ fn visit_item(&mut self, it: &'ast hir::Item) {
 
     fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
         match ti.node {
-            hir::ConstTraitItem(_, ref default) => {
+            hir::TraitItemKind::Const(_, ref default) => {
                 if let Some(_) = *default {
                     let mut recursion_visitor = CheckItemRecursionVisitor::new(self, &ti.span);
                     recursion_visitor.visit_trait_item(ti);
@@ -108,7 +108,7 @@ struct CheckItemRecursionVisitor<'a, 'b: 'a, 'ast: 'b> {
     root_span: &'b Span,
     sess: &'b Session,
     ast_map: &'b ast_map::Map<'ast>,
-    discriminant_map: &'a mut NodeMap<Option<&'ast hir::Expr>>,
+    discriminant_map: &'a mut NodeMap<Option<hir::BodyId>>,
     idstack: Vec<ast::NodeId>,
     detected_recursive_ids: &'a mut NodeSet,
 }
@@ -189,7 +189,7 @@ fn populate_enum_discriminants(&mut self, enum_definition: &'ast hir::EnumDef) {
             variant_stack.push(variant.node.data.id());
             // When we find an expression, every variant currently on the stack
             // is affected by that expression.
-            if let Some(ref expr) = variant.node.disr_expr {
+            if let Some(expr) = variant.node.disr_expr {
                 for id in &variant_stack {
                     self.discriminant_map.insert(*id, Some(expr));
                 }
@@ -226,19 +226,15 @@ fn visit_variant(&mut self,
                      _: &'ast hir::Generics,
                      _: ast::NodeId) {
         let variant_id = variant.node.data.id();
-        let maybe_expr;
-        if let Some(get_expr) = self.discriminant_map.get(&variant_id) {
-            // This is necessary because we need to let the `discriminant_map`
-            // borrow fall out of scope, so that we can reborrow farther down.
-            maybe_expr = (*get_expr).clone();
-        } else {
+        let maybe_expr = *self.discriminant_map.get(&variant_id).unwrap_or_else(|| {
             span_bug!(variant.span,
                       "`check_static_recursion` attempted to visit \
                       variant with unknown discriminant")
-        }
+        });
         // If `maybe_expr` is `None`, that's because no discriminant is
         // specified that affects this variant. Thus, no risk of recursion.
         if let Some(expr) = maybe_expr {
+            let expr = &self.ast_map.body(expr).value;
             self.with_item_id_pushed(expr.id, |v| intravisit::walk_expr(v, expr), expr.span);
         }
     }
index 6fe1f0c2b9cc6ca08d83d58424c0e2ed8f2baace..e814050e9609771a0d859249dcd95c173ed7c703 100644 (file)
@@ -95,6 +95,7 @@ pub enum IntrinsicDef {
 mod x86;
 mod arm;
 mod aarch64;
+mod nvptx;
 
 impl Intrinsic {
     pub fn find(name: &str) -> Option<Intrinsic> {
@@ -104,6 +105,8 @@ pub fn find(name: &str) -> Option<Intrinsic> {
             arm::find(name)
         } else if name.starts_with("aarch64_") {
             aarch64::find(name)
+        } else if name.starts_with("nvptx_") {
+            nvptx::find(name)
         } else {
             None
         }
diff --git a/src/librustc_platform_intrinsics/nvptx.rs b/src/librustc_platform_intrinsics/nvptx.rs
new file mode 100644 (file)
index 0000000..8240872
--- /dev/null
@@ -0,0 +1,92 @@
+// 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("nvptx") { return None }
+    Some(match &name["nvptx".len()..] {
+        "_syncthreads" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::VOID,
+            definition: Named("llvm.cuda.syncthreads")
+        },
+        "_block_dim_x" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.ntid.x")
+        },
+        "_block_dim_y" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.ntid.y")
+        },
+        "_block_dim_z" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.ntid.z")
+        },
+        "_block_idx_x" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.ctaid.x")
+        },
+        "_block_idx_y" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.ctaid.y")
+        },
+        "_block_idx_z" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.ctaid.z")
+        },
+        "_grid_dim_x" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.nctaid.x")
+        },
+        "_grid_dim_y" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.nctaid.y")
+        },
+        "_grid_dim_z" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.nctaid.z")
+        },
+        "_thread_idx_x" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.tid.x")
+        },
+        "_thread_idx_y" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.tid.y")
+        },
+        "_thread_idx_z" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.tid.z")
+        },
+        _ => return None,
+    })
+}
index 514d81ecc94f2a9f6b27ca8f5c39520b69f9c1b7..48d4437358c58ef5c58f7e633b517343ee12f51e 100644 (file)
@@ -2,6 +2,7 @@
 authors = ["The Rust Project Developers"]
 name = "rustc_plugin"
 version = "0.0.0"
+build = false
 
 [lib]
 name = "rustc_plugin"
index 75046f6aeb8742fd581b3f669bcdb30ffeb98126..34ebd12de9c18fbc38b56baedf7ff4ddcbf50e1c 100644 (file)
@@ -33,6 +33,9 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index fe2f9713d1beb29ae0cafd35af921d9fb1711572..3700d0295e9639dd50a7a08a85a3263a0d3c92f8 100644 (file)
@@ -64,6 +64,8 @@ pub struct Registry<'a> {
 
     #[doc(hidden)]
     pub attributes: Vec<(String, AttributeType)>,
+
+    whitelisted_custom_derives: Vec<ast::Name>,
 }
 
 impl<'a> Registry<'a> {
@@ -80,6 +82,7 @@ pub fn new(sess: &'a Session, krate_span: Span) -> Registry<'a> {
             llvm_passes: vec![],
             attributes: vec![],
             mir_passes: Vec::new(),
+            whitelisted_custom_derives: Vec::new(),
         }
     }
 
@@ -115,6 +118,21 @@ pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxEx
         }));
     }
 
+    /// This can be used in place of `register_syntax_extension` to register legacy custom derives
+    /// (i.e. attribute syntax extensions whose name begins with `derive_`). Legacy custom
+    /// derives defined by this function do not trigger deprecation warnings when used.
+    #[unstable(feature = "rustc_private", issue = "27812")]
+    #[rustc_deprecated(since = "1.15.0", reason = "replaced by macros 1.1 (RFC 1861)")]
+    pub fn register_custom_derive(&mut self, name: ast::Name, extension: SyntaxExtension) {
+        assert!(name.as_str().starts_with("derive_"));
+        self.whitelisted_custom_derives.push(name);
+        self.register_syntax_extension(name, extension);
+    }
+
+    pub fn take_whitelisted_custom_derives(&mut self) -> Vec<ast::Name> {
+        ::std::mem::replace(&mut self.whitelisted_custom_derives, Vec::new())
+    }
+
     /// Register a macro of the usual kind.
     ///
     /// This is a convenience wrapper for `register_syntax_extension`.
index 145b9176f6b131cf5de102db4b118e05ef77ce6d..81863a3fadfd36f69badeacf39ac631fe6905b38 100644 (file)
@@ -28,7 +28,7 @@
 use rustc::dep_graph::DepNode;
 use rustc::hir::{self, PatKind};
 use rustc::hir::def::{self, Def, CtorKind};
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::itemlikevisit::DeepVisitor;
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
@@ -160,21 +160,19 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             }
             hir::ItemImpl(.., None, _, ref impl_item_refs) => {
                 for impl_item_ref in impl_item_refs {
-                    let impl_item = self.tcx.map.impl_item(impl_item_ref.id);
-                    if impl_item.vis == hir::Public {
-                        self.update(impl_item.id, item_level);
+                    if impl_item_ref.vis == hir::Public {
+                        self.update(impl_item_ref.id.node_id, item_level);
                     }
                 }
             }
             hir::ItemImpl(.., Some(_), _, ref impl_item_refs) => {
                 for impl_item_ref in impl_item_refs {
-                    let impl_item = self.tcx.map.impl_item(impl_item_ref.id);
-                    self.update(impl_item.id, item_level);
+                    self.update(impl_item_ref.id.node_id, item_level);
                 }
             }
-            hir::ItemTrait(.., ref trait_items) => {
-                for trait_item in trait_items {
-                    self.update(trait_item.id, item_level);
+            hir::ItemTrait(.., ref trait_item_refs) => {
+                for trait_item_ref in trait_item_refs {
+                    self.update(trait_item_ref.id.node_id, item_level);
                 }
             }
             hir::ItemStruct(ref def, _) | hir::ItemUnion(ref def, _) => {
@@ -214,15 +212,16 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                     self.reach(item.id).generics().predicates().item_type();
                 }
             }
-            hir::ItemTrait(.., ref trait_items) => {
+            hir::ItemTrait(.., ref trait_item_refs) => {
                 if item_level.is_some() {
                     self.reach(item.id).generics().predicates();
 
-                    for trait_item in trait_items {
-                        let mut reach = self.reach(trait_item.id);
+                    for trait_item_ref in trait_item_refs {
+                        let mut reach = self.reach(trait_item_ref.id.node_id);
                         reach.generics().predicates();
 
-                        if let hir::TypeTraitItem(_, None) = trait_item.node {
+                        if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
+                           !trait_item_ref.defaultness.has_value() {
                             // No type to visit.
                         } else {
                             reach.item_type();
@@ -231,12 +230,12 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                 }
             }
             // Visit everything except for private impl items
-            hir::ItemImpl(.., ref trait_ref, _, ref impl_items) => {
+            hir::ItemImpl(.., ref trait_ref, _, ref impl_item_refs) => {
                 if item_level.is_some() {
                     self.reach(item.id).generics().predicates().impl_trait_ref();
 
-                    for impl_item in impl_items {
-                        let id = impl_item.id.node_id;
+                    for impl_item_ref in impl_item_refs {
+                        let id = impl_item_ref.id.node_id;
                         if trait_ref.is_some() || self.get(id).is_some() {
                             self.reach(id).generics().predicates().item_type();
                         }
@@ -391,7 +390,7 @@ fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
 
 struct PrivacyVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    curitem: ast::NodeId,
+    curitem: DefId,
     in_foreign: bool,
 }
 
@@ -401,12 +400,12 @@ fn item_is_accessible(&self, did: DefId) -> bool {
             Some(node_id) =>
                 ty::Visibility::from_hir(&self.tcx.map.expect_item(node_id).vis, node_id, self.tcx),
             None => self.tcx.sess.cstore.visibility(did),
-        }.is_accessible_from(self.curitem, &self.tcx.map)
+        }.is_accessible_from(self.curitem, self.tcx)
     }
 
     // Checks that a field is in scope.
     fn check_field(&mut self, span: Span, def: &'tcx ty::AdtDef, field: &'tcx ty::FieldDef) {
-        if !def.is_enum() && !field.vis.is_accessible_from(self.curitem, &self.tcx.map) {
+        if !def.is_enum() && !field.vis.is_accessible_from(self.curitem, 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))
@@ -437,7 +436,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item) {
-        let orig_curitem = replace(&mut self.curitem, item.id);
+        let orig_curitem = replace(&mut self.curitem, self.tcx.map.local_def_id(item.id));
         intravisit::walk_item(self, item);
         self.curitem = orig_curitem;
     }
@@ -474,7 +473,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
                 if let Def::StructCtor(_, CtorKind::Fn) = path.def {
                     let adt_def = self.tcx.expect_variant_def(path.def);
                     let private_indexes = adt_def.fields.iter().enumerate().filter(|&(_, field)| {
-                        !field.vis.is_accessible_from(self.curitem, &self.tcx.map)
+                        !field.vis.is_accessible_from(self.curitem, self.tcx)
                     }).map(|(i, _)| i).collect::<Vec<_>>();
 
                     if !private_indexes.is_empty() {
@@ -789,22 +788,19 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                     // methods will be visible as `Public::foo`.
                     let mut found_pub_static = false;
                     for impl_item_ref in impl_item_refs {
-                        let impl_item = self.tcx.map.impl_item(impl_item_ref.id);
-                        match impl_item.node {
-                            hir::ImplItemKind::Const(..) => {
-                                if self.item_is_public(&impl_item.id, &impl_item.vis) {
+                        if self.item_is_public(&impl_item_ref.id.node_id, &impl_item_ref.vis) {
+                            let impl_item = self.tcx.map.impl_item(impl_item_ref.id);
+                            match impl_item_ref.kind {
+                                hir::AssociatedItemKind::Const => {
                                     found_pub_static = true;
                                     intravisit::walk_impl_item(self, impl_item);
                                 }
-                            }
-                            hir::ImplItemKind::Method(ref sig, _) => {
-                                if !sig.decl.has_self() &&
-                                        self.item_is_public(&impl_item.id, &impl_item.vis) {
+                                hir::AssociatedItemKind::Method { has_self: false } => {
                                     found_pub_static = true;
                                     intravisit::walk_impl_item(self, impl_item);
                                 }
+                                _ => {}
                             }
-                            _ => {}
                         }
                     }
                     if found_pub_static {
@@ -940,7 +936,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
             ty::TyAdt(adt, _) => Some(adt.did),
             ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()),
             ty::TyProjection(ref proj) => {
-                if self.required_visibility == ty::Visibility::PrivateExternal {
+                if self.required_visibility == ty::Visibility::Invisible {
                     // Conservatively approximate the whole type alias as public without
                     // recursing into its components when determining impl publicity.
                     // For example, `impl <Type as Trait>::Alias {...}` may be a public impl
@@ -961,10 +957,10 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                 let item = self.tcx.map.expect_item(node_id);
                 let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx);
 
-                if !vis.is_at_least(self.min_visibility, &self.tcx.map) {
+                if !vis.is_at_least(self.min_visibility, self.tcx) {
                     self.min_visibility = vis;
                 }
-                if !vis.is_at_least(self.required_visibility, &self.tcx.map) {
+                if !vis.is_at_least(self.required_visibility, self.tcx) {
                     if self.tcx.sess.features.borrow().pub_restricted || self.has_old_errors {
                         let mut err = struct_span_err!(self.tcx.sess, self.span, E0446,
                             "private type `{}` in public interface", ty);
@@ -996,10 +992,10 @@ fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
             let item = self.tcx.map.expect_item(node_id);
             let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx);
 
-            if !vis.is_at_least(self.min_visibility, &self.tcx.map) {
+            if !vis.is_at_least(self.min_visibility, self.tcx) {
                 self.min_visibility = vis;
             }
-            if !vis.is_at_least(self.required_visibility, &self.tcx.map) {
+            if !vis.is_at_least(self.required_visibility, self.tcx) {
                 if self.tcx.sess.features.borrow().pub_restricted || self.has_old_errors {
                     struct_span_err!(self.tcx.sess, self.span, E0445,
                                      "private trait `{}` in public interface", trait_ref)
@@ -1071,7 +1067,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         let tcx = self.tcx;
         let min = |vis1: ty::Visibility, vis2| {
-            if vis1.is_at_least(vis2, &tcx.map) { vis2 } else { vis1 }
+            if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
         };
 
         let item_visibility = ty::Visibility::from_hir(&item.vis, item.id, tcx);
@@ -1092,14 +1088,15 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                 self.inner_visibility = item_visibility;
                 intravisit::walk_item(self, item);
             }
-            hir::ItemTrait(.., ref trait_items) => {
+            hir::ItemTrait(.., ref trait_item_refs) => {
                 self.check(item.id, item_visibility).generics().predicates();
 
-                for trait_item in trait_items {
-                    let mut check = self.check(trait_item.id, item_visibility);
+                for trait_item_ref in trait_item_refs {
+                    let mut check = self.check(trait_item_ref.id.node_id, item_visibility);
                     check.generics().predicates();
 
-                    if let hir::TypeTraitItem(_, None) = trait_item.node {
+                    if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
+                       !trait_item_ref.defaultness.has_value() {
                         // No type to visit.
                     } else {
                         check.item_type();
@@ -1137,8 +1134,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             // An inherent impl is public when its type is public
             // Subitems of inherent impls have their own publicity
             hir::ItemImpl(.., None, _, ref impl_item_refs) => {
-                let ty_vis = self.check(item.id, ty::Visibility::PrivateExternal)
-                                 .item_type().min_visibility;
+                let ty_vis =
+                    self.check(item.id, ty::Visibility::Invisible).item_type().min_visibility;
                 self.check(item.id, ty_vis).generics().predicates();
 
                 for impl_item_ref in impl_item_refs {
@@ -1156,7 +1153,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             // A trait impl is public when both its type and its trait are public
             // Subitems of trait impls have inherited publicity
             hir::ItemImpl(.., Some(_), _, ref impl_item_refs) => {
-                let vis = self.check(item.id, ty::Visibility::PrivateExternal)
+                let vis = self.check(item.id, ty::Visibility::Invisible)
                               .item_type().impl_trait_ref().min_visibility;
                 self.check(item.id, vis).generics().predicates();
                 for impl_item_ref in impl_item_refs {
@@ -1203,7 +1200,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     // Use the parent map to check the privacy of everything
     let mut visitor = PrivacyVisitor {
-        curitem: ast::DUMMY_NODE_ID,
+        curitem: DefId::local(CRATE_DEF_INDEX),
         in_foreign: false,
         tcx: tcx,
     };
index cd2a2767979144fdcb3272a5205ef71128f8d196..1b3791355d2c35a460f79d58c9e542e2babf4a70 100644 (file)
@@ -40,6 +40,7 @@
 use syntax::ext::expand::mark_tts;
 use syntax::ext::hygiene::Mark;
 use syntax::ext::tt::macro_rules;
+use syntax::parse::token;
 use syntax::symbol::keywords;
 use syntax::visit::{self, Visitor};
 
@@ -112,7 +113,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                 // Extract and intern the module part of the path. For
                 // globs and lists, the path is found directly in the AST;
                 // for simple paths we have to munge the path a little.
-                let module_path: Vec<_> = match view_path.node {
+                let mut module_path: Vec<_> = match view_path.node {
                     ViewPathSimple(_, ref full_path) => {
                         full_path.segments
                                  .split_last()
@@ -132,6 +133,12 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                     }
                 };
 
+                // This can be removed once warning cycle #36888 is complete.
+                if module_path.len() >= 2 && module_path[0].name == keywords::CrateRoot.name() &&
+                   token::Ident(module_path[1]).is_path_segment_keyword() {
+                    module_path.remove(0);
+                }
+
                 // Build up the import directives.
                 let is_prelude = attr::contains_name(&item.attrs, "prelude_import");
 
@@ -193,18 +200,16 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                                     let rename = node.rename.unwrap_or(node.name);
                                     (module_path.clone(), node.name, rename)
                                 } else {
-                                    let ident = match module_path.last() {
-                                        Some(&ident) => ident,
-                                        None => {
-                                            resolve_error(
-                                                self,
-                                                source_item.span,
-                                                ResolutionError::
-                                                SelfImportOnlyInImportListWithNonEmptyPrefix
-                                            );
-                                            continue;
-                                        }
-                                    };
+                                    let ident = *module_path.last().unwrap();
+                                    if ident.name == keywords::CrateRoot.name() {
+                                        resolve_error(
+                                            self,
+                                            source_item.span,
+                                            ResolutionError::
+                                            SelfImportOnlyInImportListWithNonEmptyPrefix
+                                        );
+                                        continue;
+                                    }
                                     let module_path = module_path.split_last().unwrap().1;
                                     let rename = node.rename.unwrap_or(ident);
                                     (module_path.to_vec(), ident, rename)
@@ -224,7 +229,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                     ViewPathGlob(_) => {
                         let subclass = GlobImport {
                             is_prelude: is_prelude,
-                            max_vis: Cell::new(ty::Visibility::PrivateExternal),
+                            max_vis: Cell::new(ty::Visibility::Invisible),
                         };
                         self.add_import_directive(
                             module_path, subclass, view_path.span, item.id, vis, expansion,
@@ -260,16 +265,16 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
             ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root
 
             ItemKind::Mod(..) => {
-                let def = Def::Mod(self.definitions.local_def_id(item.id));
+                let def_id = self.definitions.local_def_id(item.id);
+                let module_kind = ModuleKind::Def(Def::Mod(def_id), ident.name);
                 let module = self.arenas.alloc_module(ModuleData {
                     no_implicit_prelude: parent.no_implicit_prelude || {
                         attr::contains_name(&item.attrs, "no_implicit_prelude")
                     },
-                    normal_ancestor_id: Some(item.id),
-                    ..ModuleData::new(Some(parent), ModuleKind::Def(def, ident.name))
+                    ..ModuleData::new(Some(parent), module_kind, def_id)
                 });
                 self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
-                self.module_map.insert(item.id, module);
+                self.module_map.insert(def_id, module);
 
                 // Descend into the module.
                 self.current_module = module;
@@ -300,7 +305,8 @@ 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 = self.new_module(parent, ModuleKind::Def(def, ident.name), true);
+                let module_kind = ModuleKind::Def(def, ident.name);
+                let module = self.new_module(parent, module_kind, parent.normal_ancestor_id);
                 self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
 
                 for variant in &(*enum_definition).variants {
@@ -350,8 +356,8 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                 let def_id = self.definitions.local_def_id(item.id);
 
                 // Add all the items within to a new module.
-                let module =
-                    self.new_module(parent, ModuleKind::Def(Def::Trait(def_id), ident.name), true);
+                let module_kind = ModuleKind::Def(Def::Trait(def_id), ident.name);
+                let module = self.new_module(parent, module_kind, parent.normal_ancestor_id);
                 self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
                 self.current_module = module;
             }
@@ -399,15 +405,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 block_id = block.id;
-
-            debug!("(building reduced graph for block) creating a new anonymous module for block \
-                    {}",
-                   block_id);
-
-            let new_module = self.new_module(parent, ModuleKind::Block(block_id), true);
-            self.module_map.insert(block_id, new_module);
-            self.current_module = new_module; // Descend into the block.
+            let module =
+                self.new_module(parent, ModuleKind::Block(block.id), parent.normal_ancestor_id);
+            self.block_map.insert(block.id, module);
+            self.current_module = module; // Descend into the block.
         }
     }
 
@@ -416,57 +417,38 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, chi
         let ident = Ident::with_empty_ctxt(child.name);
         let def = child.def;
         let def_id = def.def_id();
-        let vis = match def {
-            Def::Macro(..) => ty::Visibility::Public,
-            _ if parent.is_trait() => ty::Visibility::Public,
-            _ => self.session.cstore.visibility(def_id),
-        };
+        let vis = self.session.cstore.visibility(def_id);
 
         match def {
             Def::Mod(..) | Def::Enum(..) => {
-                let module = self.new_module(parent, ModuleKind::Def(def, ident.name), false);
+                let module = self.new_module(parent, ModuleKind::Def(def, ident.name), def_id);
                 self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
             }
-            Def::Variant(..) => {
+            Def::Variant(..) | Def::TyAlias(..) => {
                 self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
             }
-            Def::VariantCtor(..) => {
-                self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
-            }
-            Def::Fn(..) |
-            Def::Static(..) |
-            Def::Const(..) |
-            Def::AssociatedConst(..) |
-            Def::Method(..) => {
+            Def::Fn(..) | Def::Static(..) | Def::Const(..) |
+            Def::VariantCtor(..) | Def::StructCtor(..) => {
                 self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
             }
             Def::Trait(..) => {
-                let module = self.new_module(parent, ModuleKind::Def(def, ident.name), false);
+                let module_kind = ModuleKind::Def(def, ident.name);
+                let module = self.new_module(parent, module_kind, parent.normal_ancestor_id);
                 self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
 
-                // If this is a trait, add all the trait item names to the trait info.
-                let trait_item_def_ids = self.session.cstore.associated_item_def_ids(def_id);
-                for trait_item_def_id in trait_item_def_ids {
-                    let trait_item_name = self.session.cstore.def_key(trait_item_def_id)
-                                              .disambiguated_data.data.get_opt_name()
-                                              .expect("opt_item_name returned None for trait");
-                    self.trait_item_map.insert((trait_item_name, def_id), false);
-                }
-            }
-            Def::TyAlias(..) | Def::AssociatedTy(..) => {
-                self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
-            }
-            Def::Struct(..) => {
-                self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
+                for child in self.session.cstore.item_children(def_id) {
+                    let ns = if let Def::AssociatedTy(..) = child.def { TypeNS } else { ValueNS };
+                    let ident = Ident::with_empty_ctxt(child.name);
+                    self.define(module, ident, ns, (child.def, ty::Visibility::Public,
+                                                    DUMMY_SP, Mark::root()));
 
-                // Record field names for error reporting.
-                let field_names = self.session.cstore.struct_field_names(def_id);
-                self.insert_field_names(def_id, field_names);
-            }
-            Def::StructCtor(..) => {
-                self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
+                    let has_self = self.session.cstore.associated_item(child.def.def_id())
+                                       .map_or(false, |item| item.method_has_self_argument);
+                    self.trait_item_map.insert((def_id, child.name, ns), (child.def, has_self));
+                }
+                module.populated.set(true);
             }
-            Def::Union(..) => {
+            Def::Struct(..) | Def::Union(..) => {
                 self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
 
                 // Record field names for error reporting.
@@ -476,15 +458,7 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, chi
             Def::Macro(..) => {
                 self.define(parent, ident, MacroNS, (def, vis, DUMMY_SP, Mark::root()));
             }
-            Def::Local(..) |
-            Def::PrimTy(..) |
-            Def::TyParam(..) |
-            Def::Upvar(..) |
-            Def::Label(..) |
-            Def::SelfTy(..) |
-            Def::Err => {
-                bug!("unexpected definition: {:?}", def);
-            }
+            _ => bug!("unexpected definition: {:?}", def)
         }
     }
 
@@ -492,12 +466,10 @@ fn get_extern_crate_root(&mut self, cnum: CrateNum) -> 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 {
-                populated: Cell::new(false),
-                ..ModuleData::new(None, ModuleKind::Def(Def::Mod(def_id), name))
-            })
+            arenas.alloc_module(ModuleData::new(None, module_kind, def_id))
         })
     }
 
@@ -751,18 +723,15 @@ fn visit_trait_item(&mut self, item: &'a TraitItem) {
 
         // Add the item to the trait info.
         let item_def_id = self.resolver.definitions.local_def_id(item.id);
-        let mut is_static_method = false;
-        let (def, ns) = match item.node {
-            TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS),
-            TraitItemKind::Method(ref sig, _) => {
-                is_static_method = !sig.decl.has_self();
-                (Def::Method(item_def_id), ValueNS)
-            }
-            TraitItemKind::Type(..) => (Def::AssociatedTy(item_def_id), TypeNS),
+        let (def, ns, has_self) = match item.node {
+            TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS, false),
+            TraitItemKind::Method(ref sig, _) =>
+                (Def::Method(item_def_id), ValueNS, sig.decl.has_self()),
+            TraitItemKind::Type(..) => (Def::AssociatedTy(item_def_id), TypeNS, false),
             TraitItemKind::Macro(_) => bug!(),  // handled above
         };
 
-        self.resolver.trait_item_map.insert((item.ident.name, def_id), is_static_method);
+        self.resolver.trait_item_map.insert((def_id, item.ident.name, ns), (def, has_self));
 
         let vis = ty::Visibility::Public;
         self.resolver.define(parent, item.ident, ns, (def, vis, item.span, self.expansion));
index d54f4e7b20c7a709fe2972823ee177c23dfc1f2d..2fada8a9ec212f0e051129115a002eb27d71c34b 100644 (file)
@@ -860,6 +860,26 @@ fn foo(f: i32, g: i32) {} // ok!
 ```
 "##,
 
+E0422: r##"
+You are trying to use an identifier that is either undefined or not a struct.
+Erroneous code example:
+``` compile_fail,E0422
+fn main () {
+    let x = Foo { x: 1, y: 2 };
+}
+```
+In this case, `Foo` is undefined, so it inherently isn't anything, and
+definitely not a struct.
+```compile_fail
+fn main () {
+    let foo = 1;
+    let x = foo { x: 1, y: 2 };
+}
+```
+In this case, `foo` is defined, but is not a struct, so Rust can't use it as
+one.
+"##,
+
 E0423: r##"
 A `struct` variant name was used like a function name.
 
@@ -1519,7 +1539,12 @@ fn print_on_failure(state: &State) {
 //  E0419, merged into 531
 //  E0420, merged into 532
 //  E0421, merged into 531
-//  E0422, merged into 531/532
     E0531, // unresolved pattern path kind `name`
 //  E0427, merged into 530
+    E0573,
+    E0574,
+    E0575,
+    E0576,
+    E0577,
+    E0578,
 }
index f73227681c5e159a1ace316489174e15ac233d27..865195d3db488e3914ae34ac82ec3a633c333d93 100644 (file)
@@ -33,7 +33,6 @@
 extern crate rustc;
 
 use self::Namespace::*;
-use self::FallbackSuggestion::*;
 use self::TypeParameters::*;
 use self::RibKind::*;
 
 use rustc::session::Session;
 use rustc::lint;
 use rustc::hir::def::*;
-use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
+use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
 use rustc::ty;
 use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
 use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet};
 
 use syntax::ext::hygiene::{Mark, SyntaxContext};
-use syntax::ast::{self, FloatTy};
-use syntax::ast::{CRATE_NODE_ID, Name, NodeId, Ident, SpannedIdent, IntTy, UintTy};
+use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy};
 use syntax::ext::base::SyntaxExtension;
 use syntax::ext::base::Determinacy::{Determined, Undetermined};
 use syntax::symbol::{Symbol, keywords};
 mod build_reduced_graph;
 mod resolve_imports;
 
-enum SuggestionType {
-    Macro(String),
-    Function(Symbol),
-    NotFound,
+/// A free importable items suggested in case of resolution failure.
+struct ImportSuggestion {
+    path: Path,
 }
 
-/// Candidates for a name resolution failure
-struct SuggestedCandidates {
-    name: String,
-    candidates: Vec<Path>,
+/// A field or associated item from self type suggested in case of resolution failure.
+enum AssocSuggestion {
+    Field,
+    MethodWithSelf,
+    AssocItem,
 }
 
 enum ResolutionError<'a> {
@@ -103,10 +101,6 @@ enum ResolutionError<'a> {
     OuterTypeParameterContext,
     /// error E0403: the name is already used for a type parameter in this type parameter list
     NameAlreadyUsedInTypeParameterList(Name, &'a Span),
-    /// error E0404: is not a trait
-    IsNotATrait(&'a str, &'a str),
-    /// error E0405: use of undeclared trait name
-    UndeclaredTraitName(&'a str, SuggestedCandidates),
     /// error E0407: method is not a member of trait
     MethodNotMemberOfTrait(Name, &'a str),
     /// error E0437: type is not a member of trait
@@ -117,27 +111,10 @@ enum ResolutionError<'a> {
     VariableNotBoundInPattern(Name, usize, usize),
     /// error E0409: variable is bound with different mode in pattern #{} than in pattern #1
     VariableBoundWithDifferentMode(Name, usize, Span),
-    /// error E0411: use of `Self` outside of an impl or trait
-    SelfUsedOutsideImplOrTrait,
-    /// error E0412: use of undeclared
-    UseOfUndeclared(&'a str, &'a str, SuggestedCandidates),
     /// error E0415: identifier is bound more than once in this parameter list
     IdentifierBoundMoreThanOnceInParameterList(&'a str),
     /// error E0416: identifier is bound more than once in the same pattern
     IdentifierBoundMoreThanOnceInSamePattern(&'a str),
-    /// error E0423: is a struct variant name, but this expression uses it like a function name
-    StructVariantUsedAsFunction(&'a str),
-    /// error E0424: `self` is not available in a static method
-    SelfNotAvailableInStaticMethod,
-    /// error E0425: unresolved name
-    UnresolvedName {
-        path: &'a str,
-        message: &'a str,
-        context: UnresolvedNameContext<'a>,
-        is_static_method: bool,
-        is_field: bool,
-        def: Def,
-    },
     /// error E0426: use of undeclared label
     UndeclaredLabel(&'a str),
     /// error E0429: `self` imports are only allowed within a { } list
@@ -156,37 +133,18 @@ enum ResolutionError<'a> {
     AttemptToUseNonConstantValueInConstant,
     /// error E0530: X bindings cannot shadow Ys
     BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>),
-    /// error E0531: unresolved pattern path kind `name`
-    PatPathUnresolved(&'a str, &'a Path),
-    /// error E0532: expected pattern path kind, found another pattern path kind
-    PatPathUnexpected(&'a str, &'a str, &'a Path),
-}
-
-/// Context of where `ResolutionError::UnresolvedName` arose.
-#[derive(Clone, PartialEq, Eq, Debug)]
-enum UnresolvedNameContext<'a> {
-    /// `PathIsMod(parent)` indicates that a given path, used in
-    /// expression context, actually resolved to a module rather than
-    /// a value. The optional expression attached to the variant is the
-    /// the parent of the erroneous path expression.
-    PathIsMod(Option<&'a Expr>),
-
-    /// `Other` means we have no extra information about the context
-    /// of the unresolved name error. (Maybe we could eliminate all
-    /// such cases; but for now, this is an information-free default.)
-    Other,
 }
 
-fn resolve_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
-                                 span: syntax_pos::Span,
-                                 resolution_error: ResolutionError<'c>) {
+fn resolve_error<'sess, 'a>(resolver: &'sess Resolver,
+                            span: Span,
+                            resolution_error: ResolutionError<'a>) {
     resolve_struct_error(resolver, span, resolution_error).emit();
 }
 
-fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
-                                        span: syntax_pos::Span,
-                                        resolution_error: ResolutionError<'c>)
-                                        -> DiagnosticBuilder<'a> {
+fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
+                                   span: Span,
+                                   resolution_error: ResolutionError<'a>)
+                                   -> DiagnosticBuilder<'sess> {
     match resolution_error {
         ResolutionError::TypeParametersFromOuterFunction => {
             let mut err = struct_span_err!(resolver.session,
@@ -213,26 +171,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
              err.span_label(span, &format!("already used"));
              err.span_label(first_use_span.clone(), &format!("first use of `{}`", name));
              err
-
-        }
-        ResolutionError::IsNotATrait(name, kind_name) => {
-            let mut err = struct_span_err!(resolver.session,
-                                           span,
-                                           E0404,
-                                           "`{}` is not a trait",
-                                           name);
-            err.span_label(span, &format!("expected trait, found {}", kind_name));
-            err
-        }
-        ResolutionError::UndeclaredTraitName(name, candidates) => {
-            let mut err = struct_span_err!(resolver.session,
-                                           span,
-                                           E0405,
-                                           "trait `{}` is not in scope",
-                                           name);
-            show_candidates(&mut err, &candidates);
-            err.span_label(span, &format!("`{}` is not in scope", name));
-            err
         }
         ResolutionError::MethodNotMemberOfTrait(method, trait_) => {
             let mut err = struct_span_err!(resolver.session,
@@ -289,25 +227,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
             err.span_label(first_binding_span, &format!("first binding"));
             err
         }
-        ResolutionError::SelfUsedOutsideImplOrTrait => {
-            let mut err = struct_span_err!(resolver.session,
-                                           span,
-                                           E0411,
-                                           "use of `Self` outside of an impl or trait");
-            err.span_label(span, &format!("used outside of impl or trait"));
-            err
-        }
-        ResolutionError::UseOfUndeclared(kind, name, candidates) => {
-            let mut err = struct_span_err!(resolver.session,
-                                           span,
-                                           E0412,
-                                           "{} `{}` is undefined or not in scope",
-                                           kind,
-                                           name);
-            show_candidates(&mut err, &candidates);
-            err.span_label(span, &format!("undefined or not in scope"));
-            err
-        }
         ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
             let mut err = struct_span_err!(resolver.session,
                              span,
@@ -326,69 +245,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
             err.span_label(span, &format!("used in a pattern more than once"));
             err
         }
-        ResolutionError::StructVariantUsedAsFunction(path_name) => {
-            let mut err = struct_span_err!(resolver.session,
-                             span,
-                             E0423,
-                             "`{}` is the name of a struct or struct variant, but this expression \
-                             uses it like a function name",
-                             path_name);
-            err.span_label(span, &format!("struct called like a function"));
-            err
-        }
-        ResolutionError::SelfNotAvailableInStaticMethod => {
-            let mut err = struct_span_err!(resolver.session,
-                             span,
-                             E0424,
-                             "`self` is not available in a static method");
-            err.span_label(span, &format!("not available in static method"));
-            err.note(&format!("maybe a `self` argument is missing?"));
-            err
-        }
-        ResolutionError::UnresolvedName { path, message: msg, context, is_static_method,
-                                          is_field, def } => {
-            let mut err = struct_span_err!(resolver.session,
-                                           span,
-                                           E0425,
-                                           "unresolved name `{}`",
-                                           path);
-            if msg != "" {
-                err.span_label(span, &msg);
-            } else {
-                err.span_label(span, &format!("unresolved name"));
-            }
-
-            match context {
-                UnresolvedNameContext::Other => {
-                    if msg.is_empty() && is_static_method && is_field {
-                        err.help("this is an associated function, you don't have access to \
-                                  this type's fields or methods");
-                    }
-                }
-                UnresolvedNameContext::PathIsMod(parent) => {
-                    err.help(&match parent.map(|parent| &parent.node) {
-                        Some(&ExprKind::Field(_, ident)) => {
-                            format!("to reference an item from the `{module}` module, \
-                                     use `{module}::{ident}`",
-                                    module = path,
-                                    ident = ident.node)
-                        }
-                        Some(&ExprKind::MethodCall(ident, ..)) => {
-                            format!("to call a function from the `{module}` module, \
-                                     use `{module}::{ident}(..)`",
-                                    module = path,
-                                    ident = ident.node)
-                        }
-                        _ => {
-                            format!("{def} `{module}` cannot be used as an expression",
-                                    def = def.kind_name(),
-                                    module = path)
-                        }
-                    });
-                }
-            }
-            err
-        }
         ResolutionError::UndeclaredLabel(name) => {
             let mut err = struct_span_err!(resolver.session,
                                            span,
@@ -463,23 +319,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
             err.span_label(binding.span, msg);
             err
         }
-        ResolutionError::PatPathUnresolved(expected_what, path) => {
-            struct_span_err!(resolver.session,
-                             span,
-                             E0531,
-                             "unresolved {} `{}`",
-                             expected_what,
-                             path)
-        }
-        ResolutionError::PatPathUnexpected(expected_what, found_what, path) => {
-            struct_span_err!(resolver.session,
-                             span,
-                             E0532,
-                             "expected {}, found {} `{}`",
-                             expected_what,
-                             found_what,
-                             path)
-        }
     }
 }
 
@@ -521,6 +360,163 @@ fn descr(self) -> &'static str {
     }
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum PathSource<'a> {
+    // Type paths `Path`.
+    Type,
+    // Trait paths in bounds or impls.
+    Trait,
+    // Expression paths `path`, with optional parent context.
+    Expr(Option<&'a ExprKind>),
+    // Paths in path patterns `Path`.
+    Pat,
+    // Paths in struct expressions and patterns `Path { .. }`.
+    Struct,
+    // Paths in tuple struct patterns `Path(..)`.
+    TupleStruct,
+    // `m::A::B` in `<T as m::A>::B::C`.
+    TraitItem(Namespace),
+    // Path in `pub(path)`
+    Visibility,
+    // Path in `use a::b::{...};`
+    ImportPrefix,
+}
+
+impl<'a> PathSource<'a> {
+    fn namespace(self) -> Namespace {
+        match self {
+            PathSource::Type | PathSource::Trait | PathSource::Struct |
+            PathSource::Visibility | PathSource::ImportPrefix => TypeNS,
+            PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct => ValueNS,
+            PathSource::TraitItem(ns) => ns,
+        }
+    }
+
+    fn global_by_default(self) -> bool {
+        match self {
+            PathSource::Visibility | PathSource::ImportPrefix => true,
+            PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
+            PathSource::Struct | PathSource::TupleStruct |
+            PathSource::Trait | PathSource::TraitItem(..) => false,
+        }
+    }
+
+    fn defer_to_typeck(self) -> bool {
+        match self {
+            PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
+            PathSource::Struct | PathSource::TupleStruct => true,
+            PathSource::Trait | PathSource::TraitItem(..) |
+            PathSource::Visibility | PathSource::ImportPrefix => false,
+        }
+    }
+
+    fn descr_expected(self) -> &'static str {
+        match self {
+            PathSource::Type => "type",
+            PathSource::Trait => "trait",
+            PathSource::Pat => "unit struct/variant or constant",
+            PathSource::Struct => "struct, variant or union type",
+            PathSource::TupleStruct => "tuple struct/variant",
+            PathSource::Visibility => "module",
+            PathSource::ImportPrefix => "module or enum",
+            PathSource::TraitItem(ns) => match ns {
+                TypeNS => "associated type",
+                ValueNS => "method or associated constant",
+                MacroNS => bug!("associated macro"),
+            },
+            PathSource::Expr(parent) => match parent {
+                // "function" here means "anything callable" rather than `Def::Fn`,
+                // this is not precise but usually more helpful than just "value".
+                Some(&ExprKind::Call(..)) => "function",
+                _ => "value",
+            },
+        }
+    }
+
+    fn is_expected(self, def: Def) -> bool {
+        match self {
+            PathSource::Type => match def {
+                Def::Struct(..) | Def::Union(..) | Def::Enum(..) |
+                Def::Trait(..) | Def::TyAlias(..) | Def::AssociatedTy(..) |
+                Def::PrimTy(..) | Def::TyParam(..) | Def::SelfTy(..) => true,
+                _ => false,
+            },
+            PathSource::Trait => match def {
+                Def::Trait(..) => true,
+                _ => false,
+            },
+            PathSource::Expr(..) => match def {
+                Def::StructCtor(_, CtorKind::Const) | Def::StructCtor(_, CtorKind::Fn) |
+                Def::VariantCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Fn) |
+                Def::Const(..) | Def::Static(..) | Def::Local(..) | Def::Upvar(..) |
+                Def::Fn(..) | Def::Method(..) | Def::AssociatedConst(..) => true,
+                _ => false,
+            },
+            PathSource::Pat => match def {
+                Def::StructCtor(_, CtorKind::Const) |
+                Def::VariantCtor(_, CtorKind::Const) |
+                Def::Const(..) | Def::AssociatedConst(..) => true,
+                _ => false,
+            },
+            PathSource::TupleStruct => match def {
+                Def::StructCtor(_, CtorKind::Fn) | Def::VariantCtor(_, CtorKind::Fn) => true,
+                _ => false,
+            },
+            PathSource::Struct => match def {
+                Def::Struct(..) | Def::Union(..) | Def::Variant(..) |
+                Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => true,
+                _ => false,
+            },
+            PathSource::TraitItem(ns) => match def {
+                Def::AssociatedConst(..) | Def::Method(..) if ns == ValueNS => true,
+                Def::AssociatedTy(..) if ns == TypeNS => true,
+                _ => false,
+            },
+            PathSource::ImportPrefix => match def {
+                Def::Mod(..) | Def::Enum(..) => true,
+                _ => false,
+            },
+            PathSource::Visibility => match def {
+                Def::Mod(..) => true,
+                _ => false,
+            },
+        }
+    }
+
+    fn error_code(self, has_unexpected_resolution: bool) -> &'static str {
+        __diagnostic_used!(E0404);
+        __diagnostic_used!(E0405);
+        __diagnostic_used!(E0412);
+        __diagnostic_used!(E0422);
+        __diagnostic_used!(E0423);
+        __diagnostic_used!(E0425);
+        __diagnostic_used!(E0531);
+        __diagnostic_used!(E0532);
+        __diagnostic_used!(E0573);
+        __diagnostic_used!(E0574);
+        __diagnostic_used!(E0575);
+        __diagnostic_used!(E0576);
+        __diagnostic_used!(E0577);
+        __diagnostic_used!(E0578);
+        match (self, has_unexpected_resolution) {
+            (PathSource::Trait, true) => "E0404",
+            (PathSource::Trait, false) => "E0405",
+            (PathSource::Type, true) => "E0573",
+            (PathSource::Type, false) => "E0412",
+            (PathSource::Struct, true) => "E0574",
+            (PathSource::Struct, false) => "E0422",
+            (PathSource::Expr(..), true) => "E0423",
+            (PathSource::Expr(..), false) => "E0425",
+            (PathSource::Pat, true) | (PathSource::TupleStruct, true) => "E0532",
+            (PathSource::Pat, false) | (PathSource::TupleStruct, false) => "E0531",
+            (PathSource::TraitItem(..), true) => "E0575",
+            (PathSource::TraitItem(..), false) => "E0576",
+            (PathSource::Visibility, true) | (PathSource::ImportPrefix, true) => "E0577",
+            (PathSource::Visibility, false) | (PathSource::ImportPrefix, false) => "E0578",
+        }
+    }
+}
+
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub enum Namespace {
     TypeNS,
@@ -573,15 +569,27 @@ fn visit_local(&mut self, local: &'tcx Local) {
         self.resolve_local(local);
     }
     fn visit_ty(&mut self, ty: &'tcx Ty) {
-        self.resolve_type(ty);
+        if let TyKind::Path(ref qself, ref path) = ty.node {
+            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))
+                          .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 {
+            self.visit_ty(element);
+            self.with_constant_rib(|this| {
+                this.visit_expr(length);
+            });
+            return;
+        }
+        visit::walk_ty(self, ty);
     }
     fn visit_poly_trait_ref(&mut self,
                             tref: &'tcx ast::PolyTraitRef,
                             m: &'tcx ast::TraitBoundModifier) {
-        let ast::Path { ref segments, span, global } = tref.trait_ref.path;
-        let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
-        let def = self.resolve_trait_reference(&path, global, None, span);
-        self.record_def(tref.trait_ref.ref_id, def);
+        self.smart_resolve_path(tref.trait_ref.ref_id, None,
+                                &tref.trait_ref.path, PathSource::Trait);
         visit::walk_poly_trait_ref(self, tref, m);
     }
     fn visit_variant(&mut self,
@@ -667,13 +675,6 @@ fn visit_fn(&mut self,
 
 pub type ErrorMessage = Option<(Span, String)>;
 
-enum FallbackSuggestion {
-    NoSuggestion,
-    Field,
-    TraitItem,
-    TraitMethod(String),
-}
-
 #[derive(Copy, Clone)]
 enum TypeParameters<'a, 'b> {
     NoTypeParameters,
@@ -733,7 +734,7 @@ fn new(kind: RibKind<'a>) -> Rib<'a> {
 }
 
 /// A definition along with the index of the rib it was found on
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 struct LocalDef {
     ribs: Option<(Namespace, usize)>,
     def: Def,
@@ -751,13 +752,13 @@ fn item(self) -> Option<&'a NameBinding<'a>> {
             _ => None,
         }
     }
-}
 
-#[derive(Copy, Clone, PartialEq)]
-enum PathScope {
-    Global,
-    Lexical,
-    Import,
+    fn def(self) -> Def {
+        match self {
+            LexicalScopeBinding::Item(binding) => binding.def(),
+            LexicalScopeBinding::Def(def) => def,
+        }
+    }
 }
 
 #[derive(Clone)]
@@ -778,12 +779,12 @@ pub struct ModuleData<'a> {
     parent: Option<Module<'a>>,
     kind: ModuleKind,
 
-    // The node id of the closest normal module (`mod`) ancestor (including this module).
-    normal_ancestor_id: Option<NodeId>,
+    // The def id of the closest normal module (`mod`) ancestor (including this module).
+    normal_ancestor_id: DefId,
 
     resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
     legacy_macro_resolutions: RefCell<Vec<(Mark, Ident, Span)>>,
-    macro_resolutions: RefCell<Vec<(Box<[Ident]>, PathScope, Span)>>,
+    macro_resolutions: RefCell<Vec<(Box<[Ident]>, Span)>>,
 
     // Macro invocations that can expand into items in this module.
     unresolved_invocations: RefCell<FxHashSet<Mark>>,
@@ -805,11 +806,11 @@ pub struct ModuleData<'a> {
 pub type Module<'a> = &'a ModuleData<'a>;
 
 impl<'a> ModuleData<'a> {
-    fn new(parent: Option<Module<'a>>, kind: ModuleKind) -> Self {
+    fn new(parent: Option<Module<'a>>, kind: ModuleKind, normal_ancestor_id: DefId) -> Self {
         ModuleData {
             parent: parent,
             kind: kind,
-            normal_ancestor_id: None,
+            normal_ancestor_id: normal_ancestor_id,
             resolutions: RefCell::new(FxHashMap()),
             legacy_macro_resolutions: RefCell::new(Vec::new()),
             macro_resolutions: RefCell::new(Vec::new()),
@@ -818,7 +819,7 @@ fn new(parent: Option<Module<'a>>, kind: ModuleKind) -> Self {
             glob_importers: RefCell::new(Vec::new()),
             globs: RefCell::new((Vec::new())),
             traits: RefCell::new(None),
-            populated: Cell::new(true),
+            populated: Cell::new(normal_ancestor_id.is_local()),
         }
     }
 
@@ -855,7 +856,7 @@ fn is_trait(&self) -> bool {
     }
 
     fn is_local(&self) -> bool {
-        self.normal_ancestor_id.is_some()
+        self.normal_ancestor_id.is_local()
     }
 }
 
@@ -1033,7 +1034,7 @@ pub struct Resolver<'a> {
 
     prelude: Option<Module<'a>>,
 
-    trait_item_map: FxHashMap<(Name, DefId), bool /* is static method? */>,
+    trait_item_map: FxHashMap<(DefId, Name, Namespace), (Def, bool /* has self */)>,
 
     // Names of fields of an item `DefId` accessible with dot syntax.
     // Used for hints during error reporting.
@@ -1070,7 +1071,7 @@ pub struct Resolver<'a> {
     pub export_map: ExportMap,
     pub trait_map: TraitMap,
 
-    // A map from nodes to modules, both normal (`mod`) modules and anonymous modules.
+    // A map from nodes to anonymous modules.
     // Anonymous modules are pseudo-modules that are implicitly created around items
     // contained within blocks.
     //
@@ -1084,7 +1085,8 @@ pub struct Resolver<'a> {
     //
     // There will be an anonymous module created around `g` with the ID of the
     // entry block for `f`.
-    module_map: NodeMap<Module<'a>>,
+    block_map: NodeMap<Module<'a>>,
+    module_map: FxHashMap<DefId, Module<'a>>,
     extern_crate_roots: FxHashMap<(CrateNum, bool /* MacrosOnly? */), Module<'a>>,
 
     pub make_glob_map: bool,
@@ -1111,6 +1113,7 @@ pub struct Resolver<'a> {
     lexical_macro_resolutions: Vec<(Name, &'a Cell<LegacyScope<'a>>)>,
     macro_map: FxHashMap<DefId, Rc<SyntaxExtension>>,
     macro_exports: Vec<Export>,
+    pub whitelisted_legacy_custom_derives: Vec<Name>,
 
     // Maps the `Mark` of an expansion to its containing module or block.
     invocations: FxHashMap<Mark, &'a InvocationData<'a>>,
@@ -1159,28 +1162,24 @@ fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBindi
     }
 }
 
-impl<'a> ty::NodeIdTree for Resolver<'a> {
-    fn is_descendant_of(&self, mut node: NodeId, ancestor: NodeId) -> bool {
-        while node != ancestor {
-            node = match self.module_map[&node].parent {
-                Some(parent) => parent.normal_ancestor_id.unwrap(),
-                None => return false,
-            }
-        }
-        true
+impl<'a, 'b: 'a> ty::DefIdTree for &'a Resolver<'b> {
+    fn parent(self, id: DefId) -> Option<DefId> {
+        match id.krate {
+            LOCAL_CRATE => self.definitions.def_key(id.index).parent,
+            _ => self.session.cstore.def_key(id).parent,
+        }.map(|index| DefId { index: index, ..id })
     }
 }
 
 impl<'a> hir::lowering::Resolver for Resolver<'a> {
     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, global, ref mut def } = *path;
+        let hir::Path { ref segments, span, ref mut def } = *path;
         let path: Vec<_> = segments.iter().map(|seg| Ident::with_empty_ctxt(seg.name)).collect();
-        let scope = if global { PathScope::Global } else { PathScope::Lexical };
-        match self.resolve_path(&path, scope, Some(namespace), Some(span)) {
+        match self.resolve_path(&path, Some(namespace), Some(span)) {
             PathResult::Module(module) => *def = module.def().unwrap(),
             PathResult::NonModule(path_res) if path_res.depth == 0 => *def = path_res.base_def,
-            PathResult::NonModule(..) => match self.resolve_path(&path, scope, None, Some(span)) {
+            PathResult::NonModule(..) => match self.resolve_path(&path, None, Some(span)) {
                 PathResult::Failed(msg, _) => {
                     resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
                 }
@@ -1209,14 +1208,14 @@ pub fn new(session: &'a Session,
                crate_loader: &'a mut CrateLoader,
                arenas: &'a ResolverArenas<'a>)
                -> Resolver<'a> {
-        let root_def = Def::Mod(DefId::local(CRATE_DEF_INDEX));
+        let root_def_id = DefId::local(CRATE_DEF_INDEX);
+        let root_module_kind = ModuleKind::Def(Def::Mod(root_def_id), keywords::Invalid.name());
         let graph_root = arenas.alloc_module(ModuleData {
-            normal_ancestor_id: Some(CRATE_NODE_ID),
             no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"),
-            ..ModuleData::new(None, ModuleKind::Def(root_def, keywords::Invalid.name()))
+            ..ModuleData::new(None, root_module_kind, root_def_id)
         });
-        let mut module_map = NodeMap();
-        module_map.insert(CRATE_NODE_ID, graph_root);
+        let mut module_map = FxHashMap();
+        module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root);
 
         let mut definitions = Definitions::new();
         DefCollector::new(&mut definitions).collect_root();
@@ -1261,6 +1260,7 @@ pub fn new(session: &'a Session,
             export_map: NodeMap(),
             trait_map: NodeMap(),
             module_map: module_map,
+            block_map: NodeMap(),
             extern_crate_roots: FxHashMap(),
 
             make_glob_map: make_glob_map == MakeGlobMap::Yes,
@@ -1292,6 +1292,7 @@ pub fn new(session: &'a Session,
             macro_exports: Vec::new(),
             invocations: invocations,
             name_already_seen: FxHashMap(),
+            whitelisted_legacy_custom_derives: Vec::new(),
         }
     }
 
@@ -1330,12 +1331,9 @@ pub fn resolve_crate(&mut self, krate: &Crate) {
         self.crate_loader.postprocess(krate);
     }
 
-    fn new_module(&self, parent: Module<'a>, kind: ModuleKind, local: bool) -> Module<'a> {
-        self.arenas.alloc_module(ModuleData {
-            normal_ancestor_id: if local { self.current_module.normal_ancestor_id } else { None },
-            populated: Cell::new(local),
-            ..ModuleData::new(Some(parent), kind)
-        })
+    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 record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span)
@@ -1402,11 +1400,9 @@ fn resolve_ident_in_lexical_scope(&mut self,
         for i in (0 .. self.ribs[ns].len()).rev() {
             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(if let Some(span) = record_used {
-                    self.adjust_local_def(LocalDef { ribs: Some((ns, i)), def: def }, span)
-                } else {
-                    def
-                }));
+                return Some(LexicalScopeBinding::Def(
+                    self.adjust_local_def(LocalDef { ribs: Some((ns, i)), def: def }, record_used)
+                ));
             }
 
             if let ModuleRibKind(module) = self.ribs[ns][i].kind {
@@ -1468,6 +1464,7 @@ fn resolve_crate_var(&mut self, mut crate_var_ctxt: SyntaxContext) -> Module<'a>
     fn with_scope<F>(&mut self, id: NodeId, f: F)
         where F: FnOnce(&mut Resolver)
     {
+        let id = self.definitions.local_def_id(id);
         let module = self.module_map.get(&id).cloned(); // clones a reference
         if let Some(module) = module {
             // Move down in the graph.
@@ -1531,7 +1528,7 @@ fn resolve_item(&mut self, item: &Item) {
             }
 
             ItemKind::DefaultImpl(_, ref trait_ref) => {
-                self.with_optional_trait_ref(Some(trait_ref), |_, _| {}, None);
+                self.with_optional_trait_ref(Some(trait_ref), |_, _| {});
             }
             ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
                 self.resolve_implementation(generics,
@@ -1596,34 +1593,9 @@ fn resolve_item(&mut self, item: &Item) {
 
             ItemKind::Use(ref view_path) => {
                 match view_path.node {
-                    ast::ViewPathList(ref prefix, ref items) => {
-                        let path: Vec<_> =
-                            prefix.segments.iter().map(|seg| seg.identifier).collect();
-                        // Resolve prefix of an import with empty braces (issue #28388)
-                        if items.is_empty() && !prefix.segments.is_empty() {
-                            let (scope, span) = (PathScope::Import, prefix.span);
-                            // FIXME(#38012) This should be a module path, not anything in TypeNS.
-                            let result =
-                                self.resolve_path(&path, scope, Some(TypeNS), Some(span));
-                            let (def, msg) = match result {
-                                PathResult::Module(module) => (module.def().unwrap(), None),
-                                PathResult::NonModule(res) if res.depth == 0 =>
-                                    (res.base_def, None),
-                                PathResult::NonModule(_) => {
-                                    // Resolve a module path for better errors
-                                    match self.resolve_path(&path, scope, None, Some(span)) {
-                                        PathResult::Failed(msg, _) => (Def::Err, Some(msg)),
-                                        _ => unreachable!(),
-                                    }
-                                }
-                                PathResult::Indeterminate => unreachable!(),
-                                PathResult::Failed(msg, _) => (Def::Err, Some(msg)),
-                            };
-                            if let Some(msg) = msg {
-                                resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
-                            }
-                            self.record_def(item.id, PathResolution::new(def));
-                        }
+                    ast::ViewPathList(ref prefix, ref items) if items.is_empty() => {
+                        // Resolve prefix of an import with empty braces (issue #28388).
+                        self.smart_resolve_path(item.id, None, prefix, PathSource::ImportPrefix);
                     }
                     _ => {}
                 }
@@ -1696,56 +1668,6 @@ fn with_constant_rib<F>(&mut self, f: F)
         self.ribs[ValueNS].pop();
     }
 
-    fn resolve_trait_reference(&mut self,
-                               path: &[Ident],
-                               global: bool,
-                               generics: Option<&Generics>,
-                               span: Span)
-                               -> PathResolution {
-        let scope = if global { PathScope::Global } else { PathScope::Lexical };
-        let def = match self.resolve_path(path, scope, None, Some(span)) {
-            PathResult::Module(module) => Some(module.def().unwrap()),
-            PathResult::NonModule(..) => return err_path_resolution(),
-            PathResult::Failed(msg, false) => {
-                resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
-                return err_path_resolution();
-            }
-            _ => match self.resolve_path(path, scope, Some(TypeNS), None) {
-                PathResult::NonModule(path_resolution) => Some(path_resolution.base_def),
-                _ => None,
-            },
-        };
-
-        if let Some(def) = def {
-            if let Def::Trait(_) = def {
-                return PathResolution::new(def);
-            }
-
-            let mut err = resolve_struct_error(self, span, {
-                ResolutionError::IsNotATrait(&names_to_string(path), def.kind_name())
-            });
-            if let Some(generics) = generics {
-                if let Some(span) = generics.span_for_name(&names_to_string(path)) {
-                    err.span_label(span, &"type parameter defined here");
-                }
-            }
-
-            // If it's a typedef, give a note
-            if let Def::TyAlias(..) = def {
-                err.note(&format!("type aliases cannot be used for traits"));
-            }
-            err.emit();
-        } else {
-            // find possible candidates
-            let is_trait = |def| match def { Def::Trait(_) => true, _ => false };
-            let candidates = self.lookup_candidates(path.last().unwrap().name, TypeNS, is_trait);
-
-            let path = names_to_string(path);
-            resolve_error(self, span, ResolutionError::UndeclaredTraitName(&path, candidates));
-        }
-        err_path_resolution()
-    }
-
     fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T
         where F: FnOnce(&mut Resolver) -> T
     {
@@ -1756,24 +1678,17 @@ fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T
         result
     }
 
-    fn with_optional_trait_ref<T, F>(&mut self,
-                                     opt_trait_ref: Option<&TraitRef>,
-                                     f: F,
-                                     generics: Option<&Generics>)
-        -> T
+    fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T
         where F: FnOnce(&mut Resolver, Option<DefId>) -> T
     {
         let mut new_val = None;
         let mut new_id = None;
         if let Some(trait_ref) = opt_trait_ref {
-            let ast::Path { ref segments, span, global } = trait_ref.path;
-            let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
-            let path_res = self.resolve_trait_reference(&path, global, generics, span);
-            assert!(path_res.depth == 0);
-            self.record_def(trait_ref.ref_id, path_res);
-            if path_res.base_def != Def::Err {
-                new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
-                new_id = Some(path_res.base_def.def_id());
+            let def = self.smart_resolve_path(trait_ref.ref_id, None,
+                                              &trait_ref.path, PathSource::Trait).base_def;
+            if def != Def::Err {
+                new_val = Some((def.def_id(), trait_ref.clone()));
+                new_id = Some(def.def_id());
             }
             visit::walk_trait_ref(self, trait_ref);
         }
@@ -1821,6 +1736,7 @@ fn resolve_implementation(&mut self,
                                     // If this is a trait impl, ensure the const
                                     // exists in trait
                                     this.check_trait_item(impl_item.ident.name,
+                                                          ValueNS,
                                                           impl_item.span,
                                         |n, s| ResolutionError::ConstNotMemberOfTrait(n, s));
                                     visit::walk_impl_item(this, impl_item);
@@ -1829,6 +1745,7 @@ fn resolve_implementation(&mut self,
                                     // If this is a trait impl, ensure the method
                                     // exists in trait
                                     this.check_trait_item(impl_item.ident.name,
+                                                          ValueNS,
                                                           impl_item.span,
                                         |n, s| ResolutionError::MethodNotMemberOfTrait(n, s));
 
@@ -1845,6 +1762,7 @@ fn resolve_implementation(&mut self,
                                     // If this is a trait impl, ensure the type
                                     // exists in trait
                                     this.check_trait_item(impl_item.ident.name,
+                                                          TypeNS,
                                                           impl_item.span,
                                         |n, s| ResolutionError::TypeNotMemberOfTrait(n, s));
 
@@ -1855,18 +1773,18 @@ fn resolve_implementation(&mut self,
                         }
                     });
                 });
-            }, Some(&generics));
+            });
         });
     }
 
-    fn check_trait_item<F>(&self, name: Name, span: Span, err: F)
+    fn check_trait_item<F>(&self, name: Name, ns: Namespace, span: Span, err: F)
         where F: FnOnce(Name, &str) -> ResolutionError
     {
         // If there is a TraitRef in scope for an impl, then the method must be in the
         // trait.
         if let Some((did, ref trait_ref)) = self.current_trait_ref {
-            if !self.trait_item_map.contains_key(&(name, did)) {
-                let path_str = path_names_to_string(&trait_ref.path, 0);
+            if !self.trait_item_map.contains_key(&(did, name, ns)) {
+                let path_str = path_names_to_string(&trait_ref.path);
                 resolve_error(self, span, err(name, &path_str));
             }
         }
@@ -1967,7 +1885,7 @@ fn resolve_block(&mut self, block: &Block) {
         debug!("(resolving block) entering block");
         // Move down in the graph, if there's an anonymous module rooted here.
         let orig_module = self.current_module;
-        let anonymous_module = self.module_map.get(&block.id).cloned(); // clones a reference
+        let anonymous_module = self.block_map.get(&block.id).cloned(); // clones a reference
 
         let mut num_macro_definition_ribs = 0;
         if let Some(anonymous_module) = anonymous_module {
@@ -2006,58 +1924,6 @@ fn resolve_block(&mut self, block: &Block) {
         debug!("(resolving block) leaving block");
     }
 
-    fn resolve_type(&mut self, ty: &Ty) {
-        if let TyKind::Path(ref maybe_qself, ref path) = ty.node {
-            // This is a path in the type namespace. Walk through scopes looking for it.
-            if let Some(def) =
-                    self.resolve_possibly_assoc_item(ty.id, maybe_qself.as_ref(), path, TypeNS) {
-                match def.base_def {
-                    Def::Mod(..) if def.depth == 0 => {
-                        self.session.span_err(path.span, "expected type, found module");
-                        self.record_def(ty.id, err_path_resolution());
-                    }
-                    _ => {
-                        // Write the result into the def map.
-                        debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}",
-                               path_names_to_string(path, 0), ty.id, def);
-                        self.record_def(ty.id, def);
-                   }
-                }
-            } else {
-                self.record_def(ty.id, err_path_resolution());
-                // Keep reporting some errors even if they're ignored above.
-                let kind = if maybe_qself.is_some() { "associated type" } else { "type name" };
-                let is_invalid_self_type_name = {
-                    path.segments.len() > 0 &&
-                    maybe_qself.is_none() &&
-                    path.segments[0].identifier.name == keywords::SelfType.name()
-                };
-
-                if is_invalid_self_type_name {
-                    resolve_error(self, ty.span, ResolutionError::SelfUsedOutsideImplOrTrait);
-                } else {
-                    let type_name = path.segments.last().unwrap().identifier.name;
-                    let candidates = self.lookup_candidates(type_name, TypeNS, |def| {
-                        match def {
-                            Def::Trait(_) |
-                            Def::Enum(_) |
-                            Def::Struct(_) |
-                            Def::Union(_) |
-                            Def::TyAlias(_) => true,
-                            _ => false,
-                        }
-                    });
-
-                    let name = &path_names_to_string(path, 0);
-                    let error = ResolutionError::UseOfUndeclared(kind, name, candidates);
-                    resolve_error(self, ty.span, error);
-                }
-            }
-        }
-        // Resolve embedded types.
-        visit::walk_ty(self, ty);
-    }
-
     fn fresh_binding(&mut self,
                      ident: &SpannedIdent,
                      pat_id: NodeId,
@@ -2111,61 +1977,6 @@ fn fresh_binding(&mut self,
         PathResolution::new(def)
     }
 
-    fn resolve_pattern_path<ExpectedFn>(&mut self,
-                                        pat_id: NodeId,
-                                        qself: Option<&QSelf>,
-                                        path: &Path,
-                                        namespace: Namespace,
-                                        expected_fn: ExpectedFn,
-                                        expected_what: &str)
-        where ExpectedFn: FnOnce(Def) -> bool
-    {
-        let resolution = if let Some(resolution) = self.resolve_possibly_assoc_item(pat_id,
-                                                                        qself, path, namespace) {
-            if resolution.depth == 0 {
-                if expected_fn(resolution.base_def) || resolution.base_def == Def::Err {
-                    resolution
-                } else {
-                    resolve_error(
-                        self,
-                        path.span,
-                        ResolutionError::PatPathUnexpected(expected_what,
-                                                           resolution.kind_name(), path)
-                    );
-                    err_path_resolution()
-                }
-            } else {
-                // Not fully resolved associated item `T::A::B` or `<T as Tr>::A::B`
-                // or `<T>::A::B`. If `B` should be resolved in value namespace then
-                // it needs to be added to the trait map.
-                if namespace == ValueNS {
-                    let item_name = path.segments.last().unwrap().identifier.name;
-                    let traits = self.get_traits_containing_item(item_name);
-                    self.trait_map.insert(pat_id, traits);
-                }
-                resolution
-            }
-        } else {
-            let error = ResolutionError::PatPathUnresolved(expected_what, path);
-            resolve_error(self, path.span, error);
-            err_path_resolution()
-        };
-
-        self.record_def(pat_id, resolution);
-    }
-
-    fn resolve_struct_path(&mut self, node_id: NodeId, path: &Path) {
-        // Resolution logic is equivalent for expressions and patterns,
-        // reuse `resolve_pattern_path` for both.
-        self.resolve_pattern_path(node_id, None, path, TypeNS, |def| {
-            match def {
-                Def::Struct(..) | Def::Union(..) | Def::Variant(..) |
-                Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => true,
-                _ => false,
-            }
-        }, "struct, variant or union type");
-    }
-
     fn resolve_pattern(&mut self,
                        pat: &Pat,
                        pat_src: PatternSource,
@@ -2221,28 +2032,15 @@ fn resolve_pattern(&mut self,
                 }
 
                 PatKind::TupleStruct(ref path, ..) => {
-                    self.resolve_pattern_path(pat.id, None, path, ValueNS, |def| {
-                        match def {
-                            Def::StructCtor(_, CtorKind::Fn) |
-                            Def::VariantCtor(_, CtorKind::Fn) => true,
-                            _ => false,
-                        }
-                    }, "tuple struct/variant");
+                    self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct);
                 }
 
                 PatKind::Path(ref qself, ref path) => {
-                    self.resolve_pattern_path(pat.id, qself.as_ref(), path, ValueNS, |def| {
-                        match def {
-                            Def::StructCtor(_, CtorKind::Const) |
-                            Def::VariantCtor(_, CtorKind::Const) |
-                            Def::Const(..) | Def::AssociatedConst(..) => true,
-                            _ => false,
-                        }
-                    }, "unit struct/variant or constant");
+                    self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Pat);
                 }
 
                 PatKind::Struct(ref path, ..) => {
-                    self.resolve_struct_path(pat.id, path);
+                    self.smart_resolve_path(pat.id, None, path, PathSource::Struct);
                 }
 
                 _ => {}
@@ -2253,34 +2051,245 @@ fn resolve_pattern(&mut self,
         visit::walk_pat(self, pat);
     }
 
-    /// Handles paths that may refer to associated items
-    fn resolve_possibly_assoc_item(&mut self,
+    // High-level and context dependent path resolution routine.
+    // Resolves the path and records the resolution into definition map.
+    // If resolution fails tries several techniques to find likely
+    // resolution candidates, suggest imports or other help, and report
+    // errors in user friendly way.
+    fn smart_resolve_path(&mut self,
+                          id: NodeId,
+                          qself: Option<&QSelf>,
+                          path: &Path,
+                          source: PathSource)
+                          -> PathResolution {
+        let segments = &path.segments.iter().map(|seg| seg.identifier).collect::<Vec<_>>();
+        self.smart_resolve_path_fragment(id, qself, segments, path.span, source)
+    }
+
+    fn smart_resolve_path_fragment(&mut self,
                                    id: NodeId,
-                                   maybe_qself: Option<&QSelf>,
-                                   path: &Path,
-                                   ns: Namespace)
-                                   -> Option<PathResolution> {
-        let ast::Path { ref segments, global, span } = *path;
-        let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
-        let scope = if global { PathScope::Global } else { PathScope::Lexical };
-
-        if let Some(qself) = maybe_qself {
+                                   qself: Option<&QSelf>,
+                                   path: &[Ident],
+                                   span: Span,
+                                   source: PathSource)
+                                   -> PathResolution {
+        let ns = source.namespace();
+        let is_expected = &|def| source.is_expected(def);
+
+        // Base error is amended with one short label and possibly some longer helps/notes.
+        let report_errors = |this: &mut Self, def: Option<Def>| {
+            // Make the base error.
+            let expected = source.descr_expected();
+            let path_str = names_to_string(path);
+            let code = source.error_code(def.is_some());
+            let base_msg = if let Some(def) = def {
+                format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str)
+            } else {
+                format!("unresolved {} `{}`", expected, path_str)
+            };
+            let mut err = this.session.struct_span_err_with_code(span, &base_msg, code);
+
+            // Emit special messages for unresolved `Self` and `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"));
+                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 \
+                                               methods with `self` parameter"));
+                return err;
+            }
+
+            // Try to lookup the name in more relaxed fashion for better error reporting.
+            let name = path.last().unwrap().name;
+            let candidates = this.lookup_import_candidates(name, ns, is_expected);
+            if !candidates.is_empty() {
+                // Report import candidates as help and proceed searching for labels.
+                show_candidates(&mut err, &candidates, def.is_some());
+            }
+            if path.len() == 1 && this.self_type_is_available() {
+                if let Some(candidate) = this.lookup_assoc_candidate(name, ns, is_expected) {
+                    let self_is_available = this.self_value_is_available(path[0].ctxt);
+                    match candidate {
+                        AssocSuggestion::Field => {
+                            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 \
+                                                               methods with `self` parameter"));
+                            }
+                        }
+                        AssocSuggestion::MethodWithSelf if self_is_available => {
+                            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));
+                        }
+                    }
+                    return err;
+                }
+            }
+
+            // Try context dependent help if relaxed lookup didn't work.
+            if let Some(def) = def {
+                match (def, source) {
+                    (Def::Macro(..), _) => {
+                        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"));
+                        return err;
+                    }
+                    (Def::Mod(..), PathSource::Expr(Some(parent))) => match *parent {
+                        ExprKind::Field(_, ident) => {
+                            err.span_label(span, &format!("did you mean `{}::{}`?",
+                                                           path_str, ident.node));
+                            return err;
+                        }
+                        ExprKind::MethodCall(ident, ..) => {
+                            err.span_label(span, &format!("did you mean `{}::{}(...)`?",
+                                                           path_str, ident.node));
+                            return err;
+                        }
+                        _ => {}
+                    },
+                    _ if ns == ValueNS && is_struct_like(def) => {
+                        err.span_label(span, &format!("did you mean `{} {{ /* fields */ }}`?",
+                                                       path_str));
+                        return err;
+                    }
+                    _ => {}
+                }
+            }
+
+            // Try Levenshtein if nothing else worked.
+            if path.len() == 1 {
+                if let Some(candidate) = this.lookup_typo_candidate(name, ns, is_expected) {
+                    err.span_label(span, &format!("did you mean `{}`?", candidate));
+                    return err;
+                }
+            }
+
+            // Fallback labels.
+            if def.is_some() {
+                err.span_label(span, &format!("not a {}", expected));
+            } else {
+                err.span_label(span, &format!("no resolution found"));
+            }
+            err
+        };
+        let report_errors = |this: &mut Self, def: Option<Def>| {
+            report_errors(this, def).emit();
+            err_path_resolution()
+        };
+
+        let resolution = match self.resolve_qpath_anywhere(id, qself, path, ns, span,
+                                                           source.defer_to_typeck(),
+                                                           source.global_by_default()) {
+            Some(resolution) if resolution.depth == 0 => {
+                if is_expected(resolution.base_def) || resolution.base_def == Def::Err {
+                    resolution
+                } else {
+                    report_errors(self, Some(resolution.base_def))
+                }
+            }
+            Some(resolution) if source.defer_to_typeck() => {
+                // Not fully resolved associated item `T::A::B` or `<T as Tr>::A::B`
+                // or `<T>::A::B`. If `B` should be resolved in value namespace then
+                // it needs to be added to the trait map.
+                if ns == ValueNS {
+                    let item_name = path.last().unwrap().name;
+                    let traits = self.get_traits_containing_item(item_name, ns);
+                    self.trait_map.insert(id, traits);
+                }
+                resolution
+            }
+            _ => report_errors(self, None)
+        };
+
+        if let PathSource::TraitItem(..) = source {} else {
+            // Avoid recording definition of `A::B` in `<T as A>::B::C`.
+            self.record_def(id, resolution);
+        }
+        resolution
+    }
+
+    fn self_type_is_available(&mut self) -> bool {
+        let binding = self.resolve_ident_in_lexical_scope(keywords::SelfType.ident(), TypeNS, None);
+        if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false }
+    }
+
+    fn self_value_is_available(&mut self, ctxt: SyntaxContext) -> bool {
+        let ident = Ident { name: keywords::SelfValue.name(), ctxt: ctxt };
+        let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None);
+        if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false }
+    }
+
+    // Resolve in alternative namespaces if resolution in the primary namespace fails.
+    fn resolve_qpath_anywhere(&mut self,
+                              id: NodeId,
+                              qself: Option<&QSelf>,
+                              path: &[Ident],
+                              primary_ns: Namespace,
+                              span: Span,
+                              defer_to_typeck: bool,
+                              global_by_default: bool)
+                              -> Option<PathResolution> {
+        let mut fin_res = None;
+        // FIXME: can't resolve paths in macro namespace yet, macros are
+        // processed by the little special hack below.
+        for (i, ns) in [primary_ns, TypeNS, ValueNS, /*MacroNS*/].iter().cloned().enumerate() {
+            if i == 0 || ns != primary_ns {
+                match self.resolve_qpath(id, qself, path, ns, span, global_by_default) {
+                    // If defer_to_typeck, then resolution > no resolution,
+                    // otherwise full resolution > partial resolution > no resolution.
+                    Some(res) if res.depth == 0 || defer_to_typeck => return Some(res),
+                    res => if fin_res.is_none() { fin_res = res },
+                };
+            }
+        }
+        if primary_ns != MacroNS && path.len() == 1 &&
+                self.macro_names.contains(&path[0].name) {
+            // Return some dummy definition, it's enough for error reporting.
+            return Some(PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX))));
+        }
+        fin_res
+    }
+
+    /// Handles paths that may refer to associated items.
+    fn resolve_qpath(&mut self,
+                     id: NodeId,
+                     qself: Option<&QSelf>,
+                     path: &[Ident],
+                     ns: Namespace,
+                     span: Span,
+                     global_by_default: bool)
+                     -> Option<PathResolution> {
+        if let Some(qself) = qself {
             if qself.position == 0 {
                 // FIXME: Create some fake resolution that can't possibly be a type.
                 return Some(PathResolution {
-                    base_def: Def::Mod(self.definitions.local_def_id(ast::CRATE_NODE_ID)),
+                    base_def: Def::Mod(DefId::local(CRATE_DEF_INDEX)),
                     depth: path.len(),
                 });
             }
-            // Make sure the trait is valid.
-            self.resolve_trait_reference(&path[..qself.position], global, None, span);
+            // Make sure `A::B` in `<T as A>::B::C` is a trait item.
+            let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
+            let mut res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
+                                                           span, PathSource::TraitItem(ns));
+            if res.base_def != Def::Err {
+                res.depth += path.len() - qself.position - 1;
+            }
+            return Some(res);
         }
 
-        let result = match self.resolve_path(&path, scope, Some(ns), Some(span)) {
-            PathResult::NonModule(path_res) => match path_res.base_def {
-                Def::Trait(..) if maybe_qself.is_some() => return None,
-                _ => path_res,
-            },
+        let result = match self.resolve_path(&path, Some(ns), Some(span)) {
+            PathResult::NonModule(path_res) => path_res,
             PathResult::Module(module) if !module.is_normal() => {
                 PathResolution::new(module.def().unwrap())
             }
@@ -2297,11 +2306,11 @@ fn resolve_possibly_assoc_item(&mut self,
             // Such behavior is required for backward compatibility.
             // The same fallback is used when `a` resolves to nothing.
             PathResult::Module(..) | PathResult::Failed(..)
-                    if scope == PathScope::Lexical && (ns == TypeNS || path.len() > 1) &&
+                    if (ns == TypeNS || path.len() > 1) &&
                        self.primitive_type_table.primitive_types.contains_key(&path[0].name) => {
                 PathResolution {
                     base_def: Def::PrimTy(self.primitive_type_table.primitive_types[&path[0].name]),
-                    depth: segments.len() - 1,
+                    depth: path.len() - 1,
                 }
             }
             PathResult::Module(module) => PathResolution::new(module.def().unwrap()),
@@ -2309,15 +2318,16 @@ fn resolve_possibly_assoc_item(&mut self,
                 resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
                 err_path_resolution()
             }
-            _ => return None,
+            PathResult::Failed(..) => return None,
+            PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"),
         };
 
-        if path.len() == 1 || result.base_def == Def::Err {
+        if path.len() == 1 || global_by_default || result.base_def == Def::Err {
             return Some(result);
         }
 
         let unqualified_result = {
-            match self.resolve_path(&[*path.last().unwrap()], PathScope::Lexical, Some(ns), None) {
+            match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) {
                 PathResult::NonModule(path_res) => path_res.base_def,
                 PathResult::Module(module) => module.def().unwrap(),
                 _ => return Some(result),
@@ -2333,32 +2343,24 @@ fn resolve_possibly_assoc_item(&mut self,
 
     fn resolve_path(&mut self,
                     path: &[Ident],
-                    scope: PathScope,
                     opt_ns: Option<Namespace>, // `None` indicates a module path
                     record_used: Option<Span>)
                     -> PathResult<'a> {
-        let (mut module, allow_self) = match scope {
-            PathScope::Lexical => (None, true),
-            PathScope::Import => (Some(self.graph_root), true),
-            PathScope::Global => (Some(self.graph_root), false),
-        };
-        let mut allow_super = allow_self;
+        let mut module = None;
+        let mut allow_super = true;
 
         for (i, &ident) in path.iter().enumerate() {
             let is_last = i == path.len() - 1;
             let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
 
-            if i == 0 && allow_self && ns == TypeNS && ident.name == keywords::SelfValue.name() {
-                module = Some(self.module_map[&self.current_module.normal_ancestor_id.unwrap()]);
-                continue
-            } else if i == 0 && allow_self && ns == TypeNS && ident.name == "$crate" {
-                module = Some(self.resolve_crate_var(ident.ctxt));
+            if i == 0 && ns == TypeNS && ident.name == keywords::SelfValue.name() {
+                module = Some(self.module_map[&self.current_module.normal_ancestor_id]);
                 continue
             } else if allow_super && ns == TypeNS && ident.name == keywords::Super.name() {
                 let current_module = if i == 0 { self.current_module } else { module.unwrap() };
-                let self_module = self.module_map[&current_module.normal_ancestor_id.unwrap()];
+                let self_module = self.module_map[&current_module.normal_ancestor_id];
                 if let Some(parent) = self_module.parent {
-                    module = Some(self.module_map[&parent.normal_ancestor_id.unwrap()]);
+                    module = Some(self.module_map[&parent.normal_ancestor_id]);
                     continue
                 } else {
                     let msg = "There are too many initial `super`s.".to_string();
@@ -2367,6 +2369,14 @@ fn resolve_path(&mut self,
             }
             allow_super = false;
 
+            if i == 0 && ns == TypeNS && ident.name == keywords::CrateRoot.name() {
+                module = Some(self.graph_root);
+                continue
+            } else if i == 0 && ns == TypeNS && ident.name == "$crate" {
+                module = Some(self.resolve_crate_var(ident.ctxt));
+                continue
+            }
+
             let binding = if let Some(module) = module {
                 self.resolve_ident_in_module(module, ident, ns, false, record_used)
             } else if opt_ns == Some(MacroNS) {
@@ -2413,10 +2423,10 @@ fn resolve_path(&mut self,
                     let msg = if module.and_then(ModuleData::def) == self.graph_root.def() {
                         let is_mod = |def| match def { Def::Mod(..) => true, _ => false };
                         let mut candidates =
-                            self.lookup_candidates(ident.name, TypeNS, is_mod).candidates;
-                        candidates.sort_by_key(|path| (path.segments.len(), path.to_string()));
+                            self.lookup_import_candidates(ident.name, TypeNS, is_mod);
+                        candidates.sort_by_key(|c| (c.path.segments.len(), c.path.to_string()));
                         if let Some(candidate) = candidates.get(0) {
-                            format!("Did you mean `{}`?", candidate)
+                            format!("Did you mean `{}`?", candidate.path)
                         } else {
                             format!("Maybe a missing `extern crate {};`?", ident)
                         }
@@ -2430,11 +2440,11 @@ fn resolve_path(&mut self,
             }
         }
 
-        PathResult::Module(module.unwrap())
+        PathResult::Module(module.unwrap_or(self.graph_root))
     }
 
     // Resolve a local definition, potentially adjusting for closures.
-    fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Def {
+    fn adjust_local_def(&mut self, local_def: LocalDef, record_used: Option<Span>) -> Def {
         let ribs = match local_def.ribs {
             Some((ns, i)) => &self.ribs[ns][i + 1..],
             None => &[] as &[_],
@@ -2442,7 +2452,7 @@ fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Def {
         let mut def = local_def.def;
         match def {
             Def::Upvar(..) => {
-                span_bug!(span, "unexpected {:?} in bindings", def)
+                span_bug!(record_used.unwrap_or(DUMMY_SP), "unexpected {:?} in bindings", def)
             }
             Def::Local(def_id) => {
                 for rib in ribs {
@@ -2465,28 +2475,32 @@ fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Def {
                                           .entry(function_id)
                                           .or_insert_with(|| vec![]);
                             let depth = vec.len();
-                            vec.push(Freevar {
-                                def: prev_def,
-                                span: span,
-                            });
-
                             def = Def::Upvar(def_id, depth, function_id);
-                            seen.insert(node_id, depth);
+
+                            if let Some(span) = record_used {
+                                vec.push(Freevar {
+                                    def: prev_def,
+                                    span: span,
+                                });
+                                seen.insert(node_id, depth);
+                            }
                         }
                         ItemRibKind | MethodRibKind(_) => {
                             // This was an attempt to access an upvar inside a
                             // named function item. This is not allowed, so we
                             // report an error.
-                            resolve_error(self,
-                                          span,
-                                          ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
+                            if let Some(span) = record_used {
+                                resolve_error(self, span,
+                                        ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
+                            }
                             return Def::Err;
                         }
                         ConstantItemRibKind => {
                             // Still doesn't deal with upvars
-                            resolve_error(self,
-                                          span,
-                                          ResolutionError::AttemptToUseNonConstantValueInConstant);
+                            if let Some(span) = record_used {
+                                resolve_error(self, span,
+                                        ResolutionError::AttemptToUseNonConstantValueInConstant);
+                            }
                             return Def::Err;
                         }
                     }
@@ -2502,15 +2516,18 @@ fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Def {
                         ItemRibKind => {
                             // This was an attempt to use a type parameter outside
                             // its scope.
-
-                            resolve_error(self,
-                                          span,
-                                          ResolutionError::TypeParametersFromOuterFunction);
+                            if let Some(span) = record_used {
+                                resolve_error(self, span,
+                                              ResolutionError::TypeParametersFromOuterFunction);
+                            }
                             return Def::Err;
                         }
                         ConstantItemRibKind => {
                             // see #9186
-                            resolve_error(self, span, ResolutionError::OuterTypeParameterContext);
+                            if let Some(span) = record_used {
+                                resolve_error(self, span,
+                                              ResolutionError::OuterTypeParameterContext);
+                            }
                             return Def::Err;
                         }
                     }
@@ -2546,7 +2563,13 @@ fn with_empty_ribs<T, F>(&mut self, f: F) -> T
         result
     }
 
-    fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion {
+    fn lookup_assoc_candidate<FilterFn>(&mut self,
+                                        name: Name,
+                                        ns: Namespace,
+                                        filter_fn: FilterFn)
+                                        -> Option<AssocSuggestion>
+        where FilterFn: Fn(Def) -> bool
+    {
         fn extract_node_id(t: &Ty) -> Option<NodeId> {
             match t.node {
                 TyKind::Path(None, _) => Some(t.id),
@@ -2558,51 +2581,59 @@ fn extract_node_id(t: &Ty) -> Option<NodeId> {
             }
         }
 
-        if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) {
-            // Look for a field with the same name in the current self_type.
-            if let Some(resolution) = self.def_map.get(&node_id) {
-                match resolution.base_def {
-                    Def::Struct(did) | Def::Union(did) if resolution.depth == 0 => {
-                        if let Some(field_names) = self.field_names.get(&did) {
-                            if field_names.iter().any(|&field_name| name == field_name) {
-                                return Field;
+        // Fields are generally expected in the same contexts as locals.
+        if filter_fn(Def::Local(DefId::local(CRATE_DEF_INDEX))) {
+            if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) {
+                // Look for a field with the same name in the current self_type.
+                if let Some(resolution) = self.def_map.get(&node_id) {
+                    match resolution.base_def {
+                        Def::Struct(did) | Def::Union(did) if resolution.depth == 0 => {
+                            if let Some(field_names) = self.field_names.get(&did) {
+                                if field_names.iter().any(|&field_name| name == field_name) {
+                                    return Some(AssocSuggestion::Field);
+                                }
                             }
                         }
+                        _ => {}
                     }
-                    _ => {}
                 }
             }
         }
 
-        // Look for a method in the current trait.
-        if let Some((trait_did, ref trait_ref)) = self.current_trait_ref {
-            if let Some(&is_static_method) = self.trait_item_map.get(&(name, trait_did)) {
-                if is_static_method {
-                    return TraitMethod(path_names_to_string(&trait_ref.path, 0));
-                } else {
-                    return TraitItem;
+        // Look for associated items in the current trait.
+        if let Some((trait_did, _)) = self.current_trait_ref {
+            if let Some(&(def, has_self)) = self.trait_item_map.get(&(trait_did, name, ns)) {
+                if filter_fn(def) {
+                    return Some(if has_self {
+                        AssocSuggestion::MethodWithSelf
+                    } else {
+                        AssocSuggestion::AssocItem
+                    });
                 }
             }
         }
 
-        NoSuggestion
+        None
     }
 
-    fn find_best_match(&mut self, name: &str) -> SuggestionType {
-        if let Some(macro_name) = self.macro_names.iter().find(|&n| n == &name) {
-            return SuggestionType::Macro(format!("{}!", macro_name));
+    fn lookup_typo_candidate<FilterFn>(&mut self,
+                                       name: Name,
+                                       ns: Namespace,
+                                       filter_fn: FilterFn)
+                                       -> Option<Name>
+        where FilterFn: Fn(Def) -> bool
+    {
+        // FIXME: bindings in ribs provide quite modest set of candidates,
+        // extend it with other names in scope.
+        let names = self.ribs[ns].iter().rev().flat_map(|rib| {
+            rib.bindings.iter().filter_map(|(ident, def)| {
+                if filter_fn(*def) { Some(&ident.name) } else { None }
+            })
+        });
+        match find_best_match_for_name(names, &name.as_str(), None) {
+            Some(found) if found != name => Some(found),
+            _ => None,
         }
-
-        let names = self.ribs[ValueNS]
-                    .iter()
-                    .rev()
-                    .flat_map(|rib| rib.bindings.keys().map(|ident| &ident.name));
-
-        if let Some(found) = find_best_match_for_name(names, name, None) {
-            if found != name {
-                return SuggestionType::Function(found);
-            }
-        } SuggestionType::NotFound
     }
 
     fn resolve_labeled_block(&mut self, label: Option<SpannedIdent>, id: NodeId, block: &Block) {
@@ -2617,7 +2648,7 @@ fn resolve_labeled_block(&mut self, label: Option<SpannedIdent>, id: NodeId, blo
         }
     }
 
-    fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
+    fn resolve_expr(&mut self, expr: &Expr, parent: Option<&ExprKind>) {
         // First, record candidate traits for this expression if it could
         // result in the invocation of a method call.
 
@@ -2625,144 +2656,13 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
 
         // Next, resolve the node.
         match expr.node {
-            ExprKind::Path(ref maybe_qself, ref path) => {
-                // This is a local path in the value namespace. Walk through
-                // scopes looking for it.
-                if let Some(path_res) = self.resolve_possibly_assoc_item(expr.id,
-                                                            maybe_qself.as_ref(), path, ValueNS) {
-                    // Check if struct variant
-                    let is_struct_variant = match path_res.base_def {
-                        Def::VariantCtor(_, CtorKind::Fictive) => true,
-                        _ => false,
-                    };
-                    if is_struct_variant {
-                        let path_name = path_names_to_string(path, 0);
-
-                        let mut err = resolve_struct_error(self,
-                                        expr.span,
-                                        ResolutionError::StructVariantUsedAsFunction(&path_name));
-
-                        let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
-                                          path_name);
-                        err.help(&msg);
-                        err.emit();
-                        self.record_def(expr.id, err_path_resolution());
-                    } else {
-                        // Write the result into the def map.
-                        debug!("(resolving expr) resolved `{}`",
-                               path_names_to_string(path, 0));
-
-                        // Partial resolutions will need the set of traits in scope,
-                        // so they can be completed during typeck.
-                        if path_res.depth != 0 {
-                            let method_name = path.segments.last().unwrap().identifier.name;
-                            let traits = self.get_traits_containing_item(method_name);
-                            self.trait_map.insert(expr.id, traits);
-                        }
-
-                        self.record_def(expr.id, path_res);
-                    }
-                } else {
-                    // Be helpful if the name refers to a struct
-                    let path_name = path_names_to_string(path, 0);
-                    let ast::Path { ref segments, global, .. } = *path;
-                    let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
-                    let scope = if global { PathScope::Global } else { PathScope::Lexical };
-                    let type_res = match self.resolve_path(&path, scope, Some(TypeNS), None) {
-                        PathResult::NonModule(type_res) => Some(type_res),
-                        _ => None,
-                    };
-
-                    self.record_def(expr.id, err_path_resolution());
-
-                    if let Some(Def::Struct(..)) = type_res.map(|r| r.base_def) {
-                        let error_variant =
-                            ResolutionError::StructVariantUsedAsFunction(&path_name);
-                        let mut err = resolve_struct_error(self, expr.span, error_variant);
-
-                        let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
-                                          path_name);
-
-                        err.help(&msg);
-                        err.emit();
-                    } else {
-                        // Keep reporting some errors even if they're ignored above.
-                        let mut method_scope = false;
-                        let mut is_static = false;
-                        self.ribs[ValueNS].iter().rev().all(|rib| {
-                            method_scope = match rib.kind {
-                                MethodRibKind(is_static_) => {
-                                    is_static = is_static_;
-                                    true
-                                }
-                                ItemRibKind | ConstantItemRibKind => false,
-                                _ => return true, // Keep advancing
-                            };
-                            false // Stop advancing
-                        });
-
-                        if method_scope && keywords::SelfValue.name() == &*path_name {
-                            let error = ResolutionError::SelfNotAvailableInStaticMethod;
-                            resolve_error(self, expr.span, error);
-                        } else {
-                            let fallback =
-                                self.find_fallback_in_self_type(path.last().unwrap().name);
-                            let (mut msg, is_field) = match fallback {
-                                NoSuggestion => {
-                                    // limit search to 5 to reduce the number
-                                    // of stupid suggestions
-                                    (match self.find_best_match(&path_name) {
-                                        SuggestionType::Macro(s) => {
-                                            format!("the macro `{}`", s)
-                                        }
-                                        SuggestionType::Function(s) => format!("`{}`", s),
-                                        SuggestionType::NotFound => "".to_string(),
-                                    }, false)
-                                }
-                                Field => {
-                                    (if is_static && method_scope {
-                                        "".to_string()
-                                    } else {
-                                        format!("`self.{}`", path_name)
-                                    }, true)
-                                }
-                                TraitItem => (format!("to call `self.{}`", path_name), false),
-                                TraitMethod(path_str) =>
-                                    (format!("to call `{}::{}`", path_str, path_name), false),
-                            };
-
-                            let mut context = UnresolvedNameContext::Other;
-                            let mut def = Def::Err;
-                            if !msg.is_empty() {
-                                msg = format!("did you mean {}?", msg);
-                            } else {
-                                // we display a help message if this is a module
-                                if let PathResult::Module(module) =
-                                        self.resolve_path(&path, scope, None, None) {
-                                    def = module.def().unwrap();
-                                    context = UnresolvedNameContext::PathIsMod(parent);
-                                }
-                            }
-
-                            let error = ResolutionError::UnresolvedName {
-                                path: &path_name,
-                                message: &msg,
-                                context: context,
-                                is_static_method: method_scope && is_static,
-                                is_field: is_field,
-                                def: def,
-                            };
-                            resolve_error(self, expr.span, error);
-                        }
-                    }
-                }
-
+            ExprKind::Path(ref qself, ref path) => {
+                self.smart_resolve_path(expr.id, qself.as_ref(), path, PathSource::Expr(parent));
                 visit::walk_expr(self, expr);
             }
 
             ExprKind::Struct(ref path, ..) => {
-                self.resolve_struct_path(expr.id, path);
-
+                self.smart_resolve_path(expr.id, None, path, PathSource::Struct);
                 visit::walk_expr(self, expr);
             }
 
@@ -2825,12 +2725,13 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                 self.ribs[ValueNS].pop();
             }
 
+            // Equivalent to `visit::walk_expr` + passing some context to children.
             ExprKind::Field(ref subexpression, _) => {
-                self.resolve_expr(subexpression, Some(expr));
+                self.resolve_expr(subexpression, Some(&expr.node));
             }
             ExprKind::MethodCall(_, ref types, ref arguments) => {
                 let mut arguments = arguments.iter();
-                self.resolve_expr(arguments.next().unwrap(), Some(expr));
+                self.resolve_expr(arguments.next().unwrap(), Some(&expr.node));
                 for argument in arguments {
                     self.resolve_expr(argument, None);
                 }
@@ -2839,6 +2740,19 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                 }
             }
 
+            ExprKind::Repeat(ref element, ref count) => {
+                self.visit_expr(element);
+                self.with_constant_rib(|this| {
+                    this.visit_expr(count);
+                });
+            }
+            ExprKind::Call(ref callee, ref arguments) => {
+                self.resolve_expr(callee, Some(&expr.node));
+                for argument in arguments {
+                    self.resolve_expr(argument, None);
+                }
+            }
+
             _ => {
                 visit::walk_expr(self, expr);
             }
@@ -2852,13 +2766,13 @@ fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
                 // field, we need to add any trait methods we find that match
                 // the field name so that we can do some nice error reporting
                 // later on in typeck.
-                let traits = self.get_traits_containing_item(name.node.name);
+                let traits = self.get_traits_containing_item(name.node.name, ValueNS);
                 self.trait_map.insert(expr.id, traits);
             }
             ExprKind::MethodCall(name, ..) => {
                 debug!("(recording candidate traits for expr) recording traits for {}",
                        expr.id);
-                let traits = self.get_traits_containing_item(name.node.name);
+                let traits = self.get_traits_containing_item(name.node.name, ValueNS);
                 self.trait_map.insert(expr.id, traits);
             }
             _ => {
@@ -2867,20 +2781,20 @@ fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
         }
     }
 
-    fn get_traits_containing_item(&mut self, name: Name) -> Vec<TraitCandidate> {
+    fn get_traits_containing_item(&mut self, name: Name, ns: Namespace) -> Vec<TraitCandidate> {
         debug!("(getting traits containing item) looking for '{}'", name);
 
         let mut found_traits = Vec::new();
         // Look for the current trait.
         if let Some((trait_def_id, _)) = self.current_trait_ref {
-            if self.trait_item_map.contains_key(&(name, trait_def_id)) {
+            if self.trait_item_map.contains_key(&(trait_def_id, name, ns)) {
                 found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: None });
             }
         }
 
         let mut search_module = self.current_module;
         loop {
-            self.get_traits_in_module_containing_item(name, search_module, &mut found_traits);
+            self.get_traits_in_module_containing_item(name, ns, search_module, &mut found_traits);
             match search_module.kind {
                 ModuleKind::Block(..) => search_module = search_module.parent.unwrap(),
                 _ => break,
@@ -2889,7 +2803,7 @@ fn get_traits_containing_item(&mut self, name: Name) -> Vec<TraitCandidate> {
 
         if let Some(prelude) = self.prelude {
             if !search_module.no_implicit_prelude {
-                self.get_traits_in_module_containing_item(name, prelude, &mut found_traits);
+                self.get_traits_in_module_containing_item(name, ns, prelude, &mut found_traits);
             }
         }
 
@@ -2898,6 +2812,7 @@ fn get_traits_containing_item(&mut self, name: Name) -> Vec<TraitCandidate> {
 
     fn get_traits_in_module_containing_item(&mut self,
                                             name: Name,
+                                            ns: Namespace,
                                             module: Module,
                                             found_traits: &mut Vec<TraitCandidate>) {
         let mut traits = module.traits.borrow_mut();
@@ -2914,7 +2829,7 @@ fn get_traits_in_module_containing_item(&mut self,
 
         for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
             let trait_def_id = binding.def().def_id();
-            if self.trait_item_map.contains_key(&(name, trait_def_id)) {
+            if self.trait_item_map.contains_key(&(trait_def_id, name, ns)) {
                 let import_id = match binding.kind {
                     NameBindingKind::Import { directive, .. } => {
                         self.maybe_unused_trait_imports.insert(directive.id);
@@ -2935,14 +2850,16 @@ fn get_traits_in_module_containing_item(&mut self,
     ///
     /// NOTE: The method does not look into imports, but this is not a problem,
     /// since we report the definitions (thus, the de-aliased imports).
-    fn lookup_candidates<FilterFn>(&mut self,
-                                   lookup_name: Name,
-                                   namespace: Namespace,
-                                   filter_fn: FilterFn) -> SuggestedCandidates
-        where FilterFn: Fn(Def) -> bool {
-
-        let mut lookup_results = Vec::new();
+    fn lookup_import_candidates<FilterFn>(&mut self,
+                                          lookup_name: Name,
+                                          namespace: Namespace,
+                                          filter_fn: FilterFn)
+                                          -> Vec<ImportSuggestion>
+        where FilterFn: Fn(Def) -> bool
+    {
+        let mut candidates = Vec::new();
         let mut worklist = Vec::new();
+        let mut seen_modules = FxHashSet();
         worklist.push((self.graph_root, Vec::new(), false));
 
         while let Some((in_module,
@@ -2954,6 +2871,8 @@ fn lookup_candidates<FilterFn>(&mut self,
 
                 // avoid imports entirely
                 if name_binding.is_import() && !name_binding.is_extern_crate() { return; }
+                // avoid non-importable candidates as well
+                if !name_binding.is_importable() { return; }
 
                 // collect results based on the filter function
                 if ident.name == lookup_name && ns == namespace {
@@ -2964,7 +2883,6 @@ fn lookup_candidates<FilterFn>(&mut self,
                         segms.push(ident.into());
                         let path = Path {
                             span: span,
-                            global: false,
                             segments: segms,
                         };
                         // the entity is accessible in the following cases:
@@ -2975,7 +2893,7 @@ fn lookup_candidates<FilterFn>(&mut self,
                         // declared as public (due to pruning, we don't explore
                         // outside crate private modules => no need to check this)
                         if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
-                            lookup_results.push(path);
+                            candidates.push(ImportSuggestion { path: path });
                         }
                     }
                 }
@@ -2989,7 +2907,7 @@ fn lookup_candidates<FilterFn>(&mut self,
                     if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
                         // add the module to the lookup
                         let is_extern = in_module_is_extern || name_binding.is_extern_crate();
-                        if !worklist.iter().any(|&(m, ..)| m.def() == module.def()) {
+                        if seen_modules.insert(module.def_id().unwrap()) {
                             worklist.push((module, path_segments, is_extern));
                         }
                     }
@@ -2997,56 +2915,48 @@ fn lookup_candidates<FilterFn>(&mut self,
             })
         }
 
-        SuggestedCandidates {
-            name: lookup_name.as_str().to_string(),
-            candidates: lookup_results,
-        }
+        candidates
     }
 
     fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
         debug!("(recording def) recording {:?} for {}", resolution, node_id);
+        assert!(resolution.depth == 0 || resolution.base_def != Def::Err);
         if let Some(prev_res) = self.def_map.insert(node_id, resolution) {
             panic!("path resolved multiple times ({:?} before, {:?} now)", prev_res, resolution);
         }
     }
 
     fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
-        let (segments, span, id) = match *vis {
-            ast::Visibility::Public => return ty::Visibility::Public,
-            ast::Visibility::Crate(_) => return ty::Visibility::Restricted(ast::CRATE_NODE_ID),
-            ast::Visibility::Restricted { ref path, id } => (&path.segments, path.span, id),
+        match *vis {
+            ast::Visibility::Public => ty::Visibility::Public,
+            ast::Visibility::Crate(..) => ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
             ast::Visibility::Inherited => {
-                return ty::Visibility::Restricted(self.current_module.normal_ancestor_id.unwrap());
+                ty::Visibility::Restricted(self.current_module.normal_ancestor_id)
             }
-        };
-
-        let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
-        let mut path_resolution = err_path_resolution();
-        let vis = match self.resolve_path(&path, PathScope::Import, None, Some(span)) {
-            PathResult::Module(module) => {
-                path_resolution = PathResolution::new(module.def().unwrap());
-                ty::Visibility::Restricted(module.normal_ancestor_id.unwrap())
-            }
-            PathResult::Failed(msg, _) => {
-                self.session.span_err(span, &format!("failed to resolve module path. {}", msg));
-                ty::Visibility::Public
+            ast::Visibility::Restricted { ref path, id } => {
+                let def = self.smart_resolve_path(id, None, path, PathSource::Visibility).base_def;
+                if def == Def::Err {
+                    ty::Visibility::Public
+                } else {
+                    let vis = ty::Visibility::Restricted(def.def_id());
+                    if self.is_accessible(vis) {
+                        vis
+                    } else {
+                        self.session.span_err(path.span, "visibilities can only be restricted \
+                                                          to ancestor modules");
+                        ty::Visibility::Public
+                    }
+                }
             }
-            _ => ty::Visibility::Public,
-        };
-        self.def_map.insert(id, path_resolution);
-        if !self.is_accessible(vis) {
-            let msg = format!("visibilities can only be restricted to ancestor modules");
-            self.session.span_err(span, &msg);
         }
-        vis
     }
 
     fn is_accessible(&self, vis: ty::Visibility) -> bool {
-        vis.is_accessible_from(self.current_module.normal_ancestor_id.unwrap(), self)
+        vis.is_accessible_from(self.current_module.normal_ancestor_id, self)
     }
 
     fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool {
-        vis.is_accessible_from(module.normal_ancestor_id.unwrap(), self)
+        vis.is_accessible_from(module.normal_ancestor_id, self)
     }
 
     fn report_errors(&mut self) {
@@ -3189,80 +3099,72 @@ fn report_conflict(&mut self,
     }
 }
 
-fn names_to_string(names: &[Ident]) -> String {
-    let mut first = true;
+fn is_struct_like(def: Def) -> bool {
+    match def {
+        Def::VariantCtor(_, CtorKind::Fictive) => true,
+        _ => PathSource::Struct.is_expected(def),
+    }
+}
+
+fn is_self_type(path: &[Ident], namespace: Namespace) -> bool {
+    namespace == TypeNS && path.len() == 1 && path[0].name == keywords::SelfType.name()
+}
+
+fn is_self_value(path: &[Ident], namespace: Namespace) -> bool {
+    namespace == ValueNS && path.len() == 1 && path[0].name == keywords::SelfValue.name()
+}
+
+fn names_to_string(idents: &[Ident]) -> String {
     let mut result = String::new();
-    for ident in names {
-        if first {
-            first = false
-        } else {
-            result.push_str("::")
+    for (i, ident) in idents.iter().filter(|i| i.name != keywords::CrateRoot.name()).enumerate() {
+        if i > 0 {
+            result.push_str("::");
         }
         result.push_str(&ident.name.as_str());
     }
     result
 }
 
-fn path_names_to_string(path: &Path, depth: usize) -> String {
-    let names: Vec<_> =
-        path.segments[..path.segments.len() - depth].iter().map(|seg| seg.identifier).collect();
-    names_to_string(&names)
+fn path_names_to_string(path: &Path) -> String {
+    names_to_string(&path.segments.iter().map(|seg| seg.identifier).collect::<Vec<_>>())
 }
 
 /// 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,
-                   candidates: &SuggestedCandidates) {
-
-    let paths = &candidates.candidates;
-
-    if paths.len() > 0 {
-        // don't show more than MAX_CANDIDATES results, so
-        // we're consistent with the trait suggestions
-        const MAX_CANDIDATES: usize = 5;
-
-        // we want consistent results across executions, but candidates are produced
-        // by iterating through a hash map, so make sure they are ordered:
-        let mut path_strings: Vec<_> = paths.into_iter()
-                                            .map(|p| path_names_to_string(&p, 0))
-                                            .collect();
-        path_strings.sort();
-
-        // behave differently based on how many candidates we have:
-        if !paths.is_empty() {
-            if paths.len() == 1 {
-                session.help(
-                    &format!("you can import it into scope: `use {};`.",
-                        &path_strings[0]),
-                );
-            } else {
-                session.help("you can import several candidates \
-                    into scope (`use ...;`):");
-                let count = path_strings.len() as isize - MAX_CANDIDATES as isize + 1;
-
-                for (idx, path_string) in path_strings.iter().enumerate() {
-                    if idx == MAX_CANDIDATES - 1 && count > 1 {
-                        session.help(
-                            &format!("  and {} other candidates", count).to_string(),
-                        );
-                        break;
-                    } else {
-                        session.help(
-                            &format!("  `{}`", path_string).to_string(),
-                        );
-                    }
-                }
-            }
-        }
-    } else {
-        // nothing found:
-        session.help(
-            &format!("no candidates by the name of `{}` found in your \
-            project; maybe you misspelled the name or forgot to import \
-            an external crate?", candidates.name.to_string()),
-        );
+                   candidates: &[ImportSuggestion],
+                   better: bool) {
+    // don't show more than MAX_CANDIDATES results, so
+    // we're consistent with the trait suggestions
+    const MAX_CANDIDATES: usize = 5;
+
+    // we want consistent results across executions, but candidates are produced
+    // by iterating through a hash map, so make sure they are ordered:
+    let mut path_strings: Vec<_> =
+        candidates.into_iter().map(|c| path_names_to_string(&c.path)).collect();
+    path_strings.sort();
+
+    let better = if better { "better " } else { "" };
+    let msg_diff = match path_strings.len() {
+        1 => " is found in another module, you can import it",
+        _ => "s are found in other modules, you can import them",
     };
+    session.help(&format!("possible {}candidate{} into scope:", better, msg_diff));
+
+    let count = path_strings.len() as isize - MAX_CANDIDATES as isize + 1;
+    for (idx, path_string) in path_strings.iter().enumerate() {
+        if idx == MAX_CANDIDATES - 1 && count > 1 {
+            session.help(
+                &format!("  and {} other candidates", count).to_string(),
+            );
+            break;
+        } else {
+            session.help(
+                &format!("  `use {};`", path_string).to_string(),
+            );
+        }
+    }
 }
 
 /// A somewhat inefficient routine to obtain the name of a module.
index 204d1127fc48dc90aba8710e48e5cbda9710bae9..44cc580ad123b727af7b0ef976e66881c1cd3df0 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use {AmbiguityError, Resolver, ResolutionError, resolve_error};
-use {Module, ModuleKind, NameBinding, NameBindingKind, PathScope, PathResult};
+use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult};
 use Namespace::{self, MacroNS};
 use build_reduced_graph::BuildReducedGraphVisitor;
 use resolve_imports::ImportResolver;
@@ -30,6 +30,7 @@
 use syntax::feature_gate::{emit_feature_err, GateIssue};
 use syntax::fold::Folder;
 use syntax::ptr::P;
+use syntax::symbol::keywords;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::visit::Visitor;
 use syntax_pos::{Span, DUMMY_SP};
@@ -87,7 +88,7 @@ fn next_node_id(&mut self) -> ast::NodeId {
 
     fn get_module_scope(&mut self, id: ast::NodeId) -> Mark {
         let mark = Mark::fresh();
-        let module = self.module_map[&id];
+        let module = self.module_map[&self.definitions.local_def_id(id)];
         self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData {
             module: Cell::new(module),
             def_index: module.def_id().unwrap().index,
@@ -105,15 +106,13 @@ 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.global = true;
+                    path.segments[0].identifier.name = keywords::CrateRoot.name();
                     let module = self.0.resolve_crate_var(ident.ctxt);
-                    if module.is_local() {
-                        path.segments.remove(0);
-                    } else {
-                        path.segments[0].identifier = match module.kind {
-                            ModuleKind::Def(_, name) => ast::Ident::with_empty_ctxt(name),
+                    if !module.is_local() {
+                        path.segments.insert(1, match module.kind {
+                            ModuleKind::Def(_, name) => ast::Ident::with_empty_ctxt(name).into(),
                             _ => unreachable!(),
-                        };
+                        })
                     }
                 }
                 path
@@ -123,6 +122,10 @@ fn fold_path(&mut self, mut path: ast::Path) -> ast::Path {
         EliminateCrateVar(self).fold_item(item).expect_one("")
     }
 
+    fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool {
+        self.whitelisted_legacy_custom_derives.contains(&name)
+    }
+
     fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion) {
         let invocation = self.invocations[&mark];
         self.collect_def_ids(invocation, expansion);
@@ -151,7 +154,7 @@ fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
         let binding = self.arenas.alloc_name_binding(NameBinding {
             kind: NameBindingKind::Def(Def::Macro(def_id)),
             span: DUMMY_SP,
-            vis: ty::Visibility::PrivateExternal,
+            vis: ty::Visibility::Invisible,
             expansion: Mark::root(),
         });
         self.builtin_macros.insert(ident.name, binding);
@@ -182,7 +185,7 @@ fn find_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>) -> Option<ast::At
 
     fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                      -> Result<Rc<SyntaxExtension>, Determinacy> {
-        let ast::Path { ref segments, global, span } = *path;
+        let ast::Path { ref segments, span } = *path;
         if segments.iter().any(|segment| segment.parameters.is_some()) {
             let kind =
                 if segments.last().unwrap().parameters.is_some() { "macro" } else { "module" };
@@ -191,12 +194,11 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
             return Err(Determinacy::Determined);
         }
 
-        let path_scope = if global { PathScope::Global } else { PathScope::Lexical };
         let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
         let invocation = self.invocations[&scope];
         self.current_module = invocation.module.get();
 
-        if path.len() > 1 || global {
+        if path.len() > 1 {
             if !self.use_extern_macros {
                 let msg = "non-ident macro paths are experimental";
                 let feature = "use_extern_macros";
@@ -204,7 +206,7 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                 return Err(Determinacy::Determined);
             }
 
-            let ext = match self.resolve_path(&path, path_scope, Some(MacroNS), None) {
+            let ext = match self.resolve_path(&path, Some(MacroNS), None) {
                 PathResult::NonModule(path_res) => match path_res.base_def {
                     Def::Err => Err(Determinacy::Determined),
                     def @ _ => Ok(self.get_macro(def)),
@@ -214,7 +216,7 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                 _ => Err(Determinacy::Determined),
             };
             self.current_module.macro_resolutions.borrow_mut()
-                .push((path.into_boxed_slice(), path_scope, span));
+                .push((path.into_boxed_slice(), span));
             return ext;
         }
 
@@ -351,8 +353,8 @@ pub fn resolve_legacy_scope(&mut self,
 
     pub fn finalize_current_module_macro_resolutions(&mut self) {
         let module = self.current_module;
-        for &(ref path, scope, span) in module.macro_resolutions.borrow().iter() {
-            match self.resolve_path(path, scope, Some(MacroNS), Some(span)) {
+        for &(ref path, span) in module.macro_resolutions.borrow().iter() {
+            match self.resolve_path(path, Some(MacroNS), Some(span)) {
                 PathResult::NonModule(_) => {},
                 PathResult::Failed(msg, _) => {
                     resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
index 8bc0bfb41ff753d175bf0a5edb697d13a43e13e5..41d8f16b88dfd4849200d72eaf157f564c717e30 100644 (file)
 
 use {AmbiguityError, Module, PerNS};
 use Namespace::{self, TypeNS, MacroNS};
-use {NameBinding, NameBindingKind, PathResult, PathScope, PrivacyError};
+use {NameBinding, NameBindingKind, PathResult, PrivacyError};
 use Resolver;
 use {names_to_string, module_to_string};
 use {resolve_error, ResolutionError};
 
 use rustc::ty;
 use rustc::lint::builtin::PRIVATE_IN_PUBLIC;
+use rustc::hir::def_id::DefId;
 use rustc::hir::def::*;
 
 use syntax::ast::{Ident, NodeId};
 use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
 use syntax::ext::hygiene::Mark;
+use syntax::parse::token;
 use syntax::symbol::keywords;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax_pos::Span;
@@ -128,6 +130,7 @@ fn binding(&self) -> Option<&'a NameBinding<'a>> {
 impl<'a> Resolver<'a> {
     fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace)
                   -> &'a RefCell<NameResolution<'a>> {
+        let ident = ident.unhygienize();
         *module.resolutions.borrow_mut().entry((ident, ns))
                .or_insert_with(|| self.arenas.alloc_name_resolution())
     }
@@ -141,7 +144,6 @@ pub fn resolve_ident_in_module(&mut self,
                                    ignore_unresolved_invocations: bool,
                                    record_used: Option<Span>)
                                    -> Result<&'a NameBinding<'a>, Determinacy> {
-        let ident = ident.unhygienize();
         self.populate_module_if_necessary(module);
 
         let resolution = self.resolution(module, ident, ns)
@@ -273,7 +275,7 @@ pub fn add_import_directive(&mut self,
 
     // Given a binding and an import directive that resolves to it,
     // return the corresponding binding defined by the import directive.
-    pub fn import(&mut self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
+    pub fn import(&self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
                   -> &'a NameBinding<'a> {
         let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) ||
                      !directive.is_glob() && binding.is_extern_crate() { // c.f. `PRIVATE_IN_PUBLIC`
@@ -307,7 +309,6 @@ pub fn try_define(&mut self,
                       ns: Namespace,
                       binding: &'a NameBinding<'a>)
                       -> Result<(), &'a NameBinding<'a>> {
-        let ident = ident.unhygienize();
         self.update_resolution(module, ident, ns, |this, resolution| {
             if let Some(old_binding) = resolution.binding {
                 if binding.is_glob_import() {
@@ -316,7 +317,7 @@ pub fn try_define(&mut self,
                         resolution.shadows_glob = Some(binding);
                     } else if binding.def() != old_binding.def() {
                         resolution.binding = Some(this.ambiguity(old_binding, binding));
-                    } else if !old_binding.vis.is_at_least(binding.vis, this) {
+                    } else if !old_binding.vis.is_at_least(binding.vis, &*this) {
                         // We are glob-importing the same item but with greater visibility.
                         resolution.binding = Some(binding);
                     }
@@ -339,7 +340,7 @@ pub fn try_define(&mut self,
         })
     }
 
-    pub fn ambiguity(&mut self, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>)
+    pub fn ambiguity(&self, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>)
                      -> &'a NameBinding<'a> {
         self.arenas.alloc_name_binding(NameBinding {
             kind: NameBindingKind::Ambiguity { b1: b1, b2: b2, legacy: false },
@@ -414,9 +415,9 @@ fn deref_mut(&mut self) -> &mut Resolver<'b> {
     }
 }
 
-impl<'a, 'b: 'a> ty::NodeIdTree for ImportResolver<'a, 'b> {
-    fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool {
-        self.resolver.is_descendant_of(node, ancestor)
+impl<'a, 'b: 'a> ty::DefIdTree for &'a ImportResolver<'a, 'b> {
+    fn parent(self, id: DefId) -> Option<DefId> {
+        self.resolver.parent(id)
     }
 }
 
@@ -489,8 +490,8 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
             let vis = directive.vis.get();
             // For better failure detection, pretend that the import will not define any names
             // while resolving its module path.
-            directive.vis.set(ty::Visibility::PrivateExternal);
-            let result = self.resolve_path(&directive.module_path, PathScope::Import, None, None);
+            directive.vis.set(ty::Visibility::Invisible);
+            let result = self.resolve_path(&directive.module_path, None, None);
             directive.vis.set(vis);
 
             match result {
@@ -553,15 +554,17 @@ 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, PathScope::Import, None, Some(span));
+        let module_result = self.resolve_path(&module_path, None, Some(span));
         let module = match module_result {
             PathResult::Module(module) => module,
             PathResult::Failed(msg, _) => {
-                let mut path = vec![keywords::SelfValue.ident()];
-                path.extend(module_path);
-                let result = self.resolve_path(&path, PathScope::Import, None, None);
-                return if let PathResult::Module(..) = result {
-                    Some(format!("Did you mean `self::{}`?", &names_to_string(module_path)))
+                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));
+                }
+                return if let Some(PathResult::Module(..)) = self_result {
+                    Some(format!("Did you mean `{}`?", names_to_string(&self_path)))
                 } else {
                     Some(msg)
                 };
@@ -577,8 +580,8 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<Stri
             }
             GlobImport { is_prelude, ref max_vis } => {
                 if !is_prelude &&
-                   max_vis.get() != ty::Visibility::PrivateExternal && // Allow empty globs.
-                   !max_vis.get().is_at_least(directive.vis.get(), self) {
+                   max_vis.get() != ty::Visibility::Invisible && // Allow empty globs.
+                   !max_vis.get().is_at_least(directive.vis.get(), &*self) {
                     let msg = "A non-empty glob must import something with the glob's visibility";
                     self.session.span_err(directive.span, msg);
                 }
@@ -641,7 +644,7 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<Stri
         self.per_ns(|this, ns| {
             if let Ok(binding) = result[ns].get() {
                 let vis = directive.vis.get();
-                if !binding.pseudo_vis().is_at_least(vis, this) {
+                if !binding.pseudo_vis().is_at_least(vis, &*this) {
                     reexport_error = Some((ns, binding));
                 } else {
                     any_successful_reexport = true;
@@ -714,7 +717,7 @@ fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
         }
 
         // Record the destination of this import
-        self.def_map.insert(directive.id, PathResolution::new(module.def().unwrap()));
+        self.record_def(directive.id, PathResolution::new(module.def().unwrap()));
     }
 
     // Miscellaneous post-processing, including recording reexports, reporting conflicts,
@@ -749,7 +752,7 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
             match binding.kind {
                 NameBindingKind::Import { binding: orig_binding, directive, .. } => {
                     if ns == TypeNS && orig_binding.is_variant() &&
-                       !orig_binding.vis.is_at_least(binding.vis, self) {
+                       !orig_binding.vis.is_at_least(binding.vis, &*self) {
                         let msg = format!("variant `{}` is private, and cannot be reexported \
                                            (error E0364), consider declaring its enum as `pub`",
                                           ident);
@@ -787,6 +790,8 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
 }
 
 fn import_path_to_string(names: &[Ident], subclass: &ImportDirectiveSubclass) -> String {
+    let global = !names.is_empty() && names[0].name == keywords::CrateRoot.name();
+    let names = if global { &names[1..] } else { names };
     if names.is_empty() {
         import_directive_subclass_to_string(subclass)
     } else {
index fc235aaf9276b7450fa4cfec91e900776573fb80..0a6281bf8c54ccaf4357f956fc97844fe136a41d 100644 (file)
@@ -135,6 +135,7 @@ pub struct EnumData {
     pub variants: Vec<NodeId>,
     pub visibility: Visibility,
     pub docs: String,
+    pub sig: Signature,
 }
 
 /// Data for extern crates.
@@ -169,6 +170,7 @@ pub struct FunctionData {
     pub visibility: Visibility,
     pub parent: Option<DefId>,
     pub docs: String,
+    pub sig: Signature,
 }
 
 /// Data about a function call.
@@ -253,6 +255,7 @@ pub struct MethodData {
     pub parent: Option<DefId>,
     pub visibility: Visibility,
     pub docs: String,
+    pub sig: Signature,
 }
 
 /// Data for modules.
@@ -267,6 +270,7 @@ pub struct ModData {
     pub items: Vec<NodeId>,
     pub visibility: Visibility,
     pub docs: String,
+    pub sig: Signature,
 }
 
 /// Data for a reference to a module.
@@ -290,6 +294,7 @@ pub struct StructData {
     pub fields: Vec<NodeId>,
     pub visibility: Visibility,
     pub docs: String,
+    pub sig: Signature,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -303,6 +308,7 @@ pub struct StructVariantData {
     pub scope: NodeId,
     pub parent: Option<DefId>,
     pub docs: String,
+    pub sig: Signature,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -316,6 +322,7 @@ pub struct TraitData {
     pub items: Vec<NodeId>,
     pub visibility: Visibility,
     pub docs: String,
+    pub sig: Signature,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -329,6 +336,7 @@ pub struct TupleVariantData {
     pub scope: NodeId,
     pub parent: Option<DefId>,
     pub docs: String,
+    pub sig: Signature,
 }
 
 /// Data for a typedef.
@@ -342,6 +350,7 @@ pub struct TypeDefData {
     pub visibility: Visibility,
     pub parent: Option<DefId>,
     pub docs: String,
+    pub sig: Option<Signature>,
 }
 
 /// Data for a reference to a type or trait.
@@ -386,6 +395,7 @@ pub struct VariableData {
     pub type_value: String,
     pub visibility: Visibility,
     pub docs: String,
+    pub sig: Option<Signature>,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -405,3 +415,28 @@ pub struct VariableRefData {
     pub scope: NodeId,
     pub ref_id: DefId,
 }
+
+
+/// Encodes information about the signature of a definition. This should have
+/// enough information to create a nice display about a definition without
+/// access to the source code.
+#[derive(Clone, Debug, RustcEncodable)]
+pub struct Signature {
+    pub span: Span,
+    pub text: String,
+    // These identify the main identifier for the defintion as byte offsets into
+    // `text`. E.g., of `foo` in `pub fn foo(...)`
+    pub ident_start: usize,
+    pub ident_end: usize,
+    pub defs: Vec<SigElement>,
+    pub refs: Vec<SigElement>,
+}
+
+/// An element of a signature. `start` and `end` are byte offsets into the `text`
+/// of the parent `Signature`.
+#[derive(Clone, Debug, RustcEncodable)]
+pub struct SigElement {
+    pub id: DefId,
+    pub start: usize,
+    pub end: usize,
+}
index afa78a05a63a897c4a49ca447b4f326c3e22808c..093a739c69ffadbc6550653cdff9f222ae474c1b 100644 (file)
@@ -143,19 +143,20 @@ pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
     // a str representation of the entire prefix.
     fn process_path_prefixes(&self, path: &ast::Path) -> Vec<(Span, String)> {
         let spans = self.span.spans_for_path_segments(path);
+        let segments = &path.segments[if path.is_global() { 1 } else { 0 }..];
 
         // Paths to enums seem to not match their spans - the span includes all the
         // variants too. But they seem to always be at the end, so I hope we can cope with
         // always using the first ones. So, only error out if we don't have enough spans.
         // What could go wrong...?
-        if spans.len() < path.segments.len() {
+        if spans.len() < segments.len() {
             if generated_code(path.span) {
                 return vec![];
             }
             error!("Mis-calculated spans for path '{}'. Found {} spans, expected {}. Found spans:",
                    path_to_string(path),
                    spans.len(),
-                   path.segments.len());
+                   segments.len());
             for s in &spans {
                 let loc = self.sess.codemap().lookup_char_pos(s.lo);
                 error!("    '{}' in {}, line {}",
@@ -170,14 +171,13 @@ fn process_path_prefixes(&self, path: &ast::Path) -> Vec<(Span, String)> {
         let mut result: Vec<(Span, String)> = vec![];
 
         let mut segs = vec![];
-        for (i, (seg, span)) in path.segments.iter().zip(&spans).enumerate() {
+        for (i, (seg, span)) in segments.iter().zip(&spans).enumerate() {
             segs.push(seg.clone());
             let sub_path = ast::Path {
                 span: *span, // span for the last segment
-                global: path.global,
                 segments: segs,
             };
-            let qualname = if i == 0 && path.global {
+            let qualname = if i == 0 && path.is_global() {
                 format!("::{}", path_to_string(&sub_path))
             } else {
                 path_to_string(&sub_path)
@@ -189,20 +189,11 @@ fn process_path_prefixes(&self, path: &ast::Path) -> Vec<(Span, String)> {
         result
     }
 
-    // The global arg allows us to override the global-ness of the path (which
-    // actually means 'does the path start with `::`', rather than 'is the path
-    // semantically global). We use the override for `use` imports (etc.) where
-    // the syntax is non-global, but the semantics are global.
-    fn write_sub_paths(&mut self, path: &ast::Path, global: bool) {
+    fn write_sub_paths(&mut self, path: &ast::Path) {
         let sub_paths = self.process_path_prefixes(path);
-        for (i, &(ref span, ref qualname)) in sub_paths.iter().enumerate() {
-            let qualname = if i == 0 && global && !path.global {
-                format!("::{}", qualname)
-            } else {
-                qualname.clone()
-            };
+        for (span, qualname) in sub_paths {
             self.dumper.mod_ref(ModRefData {
-                span: *span,
+                span: span,
                 qualname: qualname,
                 scope: self.cur_scope,
                 ref_id: None
@@ -212,22 +203,16 @@ fn write_sub_paths(&mut self, path: &ast::Path, global: bool) {
 
     // As write_sub_paths, but does not process the last ident in the path (assuming it
     // will be processed elsewhere). See note on write_sub_paths about global.
-    fn write_sub_paths_truncated(&mut self, path: &ast::Path, global: bool) {
+    fn write_sub_paths_truncated(&mut self, path: &ast::Path) {
         let sub_paths = self.process_path_prefixes(path);
         let len = sub_paths.len();
         if len <= 1 {
             return;
         }
 
-        let sub_paths = &sub_paths[..len-1];
-        for (i, &(ref span, ref qualname)) in sub_paths.iter().enumerate() {
-            let qualname = if i == 0 && global && !path.global {
-                format!("::{}", qualname)
-            } else {
-                qualname.clone()
-            };
+        for (span, qualname) in sub_paths.into_iter().take(len - 1) {
             self.dumper.mod_ref(ModRefData {
-                span: *span,
+                span: span,
                 qualname: qualname,
                 scope: self.cur_scope,
                 ref_id: None
@@ -372,6 +357,7 @@ fn process_formals(&mut self, formals: &'l [ast::Arg], qualname: &str) {
                         parent: None,
                         visibility: Visibility::Inherited,
                         docs: String::new(),
+                        sig: None,
                     }.lower(self.tcx));
                 }
             }
@@ -444,6 +430,7 @@ fn process_method(&mut self,
                     parent: trait_id,
                     visibility: vis,
                     docs: docs_for_attrs(attrs),
+                    sig: method_data.sig,
                 }.lower(self.tcx));
             }
 
@@ -515,6 +502,7 @@ fn process_generic_params(&mut self,
                     visibility: Visibility::Inherited,
                     parent: None,
                     docs: String::new(),
+                    sig: None,
                 }.lower(self.tcx));
             }
         }
@@ -587,6 +575,7 @@ fn process_assoc_const(&mut self,
                 parent: Some(parent_id),
                 visibility: vis,
                 docs: docs_for_attrs(attrs),
+                sig: None,
             }.lower(self.tcx));
         }
 
@@ -630,11 +619,10 @@ fn process_struct(&mut self,
                 fields: fields,
                 visibility: From::from(&item.vis),
                 docs: docs_for_attrs(&item.attrs),
+                sig: self.save_ctxt.sig_base(item),
             }.lower(self.tcx));
         }
 
-
-        // fields
         for field in def.fields() {
             self.process_struct_field_def(field, item.id);
             self.visit_ty(&field.ty);
@@ -663,6 +651,18 @@ fn process_enum(&mut self,
             qualname.push_str("::");
             qualname.push_str(&name);
 
+            let text = self.span.signature_string_for_span(variant.span);
+            let ident_start = text.find(&name).unwrap();
+            let ident_end = ident_start + name.len();
+            let sig = Signature {
+                span: variant.span,
+                text: text,
+                ident_start: ident_start,
+                ident_end: ident_end,
+                defs: vec![],
+                refs: vec![],
+            };
+
             match variant.node.data {
                 ast::VariantData::Struct(ref fields, _) => {
                     let sub_span = self.span.span_for_first_ident(variant.span);
@@ -684,6 +684,7 @@ fn process_enum(&mut self,
                             scope: enum_data.scope,
                             parent: Some(make_def_id(item.id, &self.tcx.map)),
                             docs: docs_for_attrs(&variant.node.attrs),
+                            sig: sig,
                         }.lower(self.tcx));
                     }
                 }
@@ -709,6 +710,7 @@ fn process_enum(&mut self,
                             scope: enum_data.scope,
                             parent: Some(make_def_id(item.id, &self.tcx.map)),
                             docs: docs_for_attrs(&variant.node.attrs),
+                            sig: sig,
                         }.lower(self.tcx));
                     }
                 }
@@ -793,6 +795,7 @@ fn process_trait(&mut self,
                 items: methods.iter().map(|i| i.id).collect(),
                 visibility: From::from(&item.vis),
                 docs: docs_for_attrs(&item.attrs),
+                sig: self.save_ctxt.sig_base(item),
             }.lower(self.tcx));
         }
 
@@ -935,7 +938,7 @@ fn process_path(&mut self, id: NodeId, path: &ast::Path, ref_kind: Option<record
             Def::Union(..) |
             Def::Variant(..) |
             Def::TyAlias(..) |
-            Def::AssociatedTy(..) => self.write_sub_paths_truncated(path, false),
+            Def::AssociatedTy(..) => self.write_sub_paths_truncated(path),
             _ => {}
         }
     }
@@ -946,7 +949,7 @@ fn process_struct_lit(&mut self,
                           fields: &'l [ast::Field],
                           variant: &'l ty::VariantDef,
                           base: &'l Option<P<ast::Expr>>) {
-        self.write_sub_paths_truncated(path, false);
+        self.write_sub_paths_truncated(path);
 
         if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) {
             down_cast_data!(struct_lit_data, TypeRefData, ex.span);
@@ -1058,6 +1061,7 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
                     parent: None,
                     visibility: Visibility::Inherited,
                     docs: String::new(),
+                    sig: None,
                 }.lower(self.tcx));
             }
         }
@@ -1201,7 +1205,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                                 visibility: From::from(&item.vis),
                             }.lower(self.tcx));
                         }
-                        self.write_sub_paths_truncated(path, true);
+                        self.write_sub_paths_truncated(path);
                     }
                     ast::ViewPathGlob(ref path) => {
                         // Make a comma-separated list of names of imported modules.
@@ -1225,7 +1229,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                                 visibility: From::from(&item.vis),
                             }.lower(self.tcx));
                         }
-                        self.write_sub_paths(path, true);
+                        self.write_sub_paths(path);
                     }
                     ast::ViewPathList(ref path, ref list) => {
                         for plid in list {
@@ -1237,7 +1241,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                             }
                         }
 
-                        self.write_sub_paths(path, true);
+                        self.write_sub_paths(path);
                     }
                 }
             }
@@ -1272,10 +1276,10 @@ fn visit_item(&mut self, item: &'l ast::Item) {
             Struct(ref def, ref ty_params) => self.process_struct(item, def, ty_params),
             Enum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
             Impl(..,
-                          ref ty_params,
-                          ref trait_ref,
-                          ref typ,
-                          ref impl_items) => {
+                 ref ty_params,
+                 ref trait_ref,
+                 ref typ,
+                 ref impl_items) => {
                 self.process_impl(item, ty_params, trait_ref, &typ, impl_items)
             }
             Trait(_, ref generics, ref trait_refs, ref methods) =>
@@ -1298,6 +1302,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                         visibility: From::from(&item.vis),
                         parent: None,
                         docs: docs_for_attrs(&item.attrs),
+                        sig: Some(self.save_ctxt.sig_base(item)),
                     }.lower(self.tcx));
                 }
 
@@ -1340,7 +1345,7 @@ fn visit_ty(&mut self, t: &'l ast::Ty) {
                     }.lower(self.tcx));
                 }
 
-                self.write_sub_paths_truncated(path, false);
+                self.write_sub_paths_truncated(path);
 
                 visit::walk_path(self, path);
             }
@@ -1507,6 +1512,7 @@ fn visit_arm(&mut self, arm: &'l ast::Arm) {
                             parent: None,
                             visibility: Visibility::Inherited,
                             docs: String::new(),
+                            sig: None,
                         }.lower(self.tcx));
                     }
                 }
index 5847575742342680efc3ed8742c77c1f44c8f436..18ae3a7fa9ea8b1c83ded974401100d642048b28 100644 (file)
@@ -15,7 +15,7 @@
 use syntax::codemap::CodeMap;
 use syntax_pos::Span;
 
-use data::{self, Visibility};
+use data::{self, Visibility, SigElement};
 
 // FIXME: this should be pub(crate), but the current snapshot doesn't allow it yet
 pub trait Lower {
@@ -97,6 +97,7 @@ pub struct EnumData {
     pub variants: Vec<DefId>,
     pub visibility: Visibility,
     pub docs: String,
+    pub sig: Signature,
 }
 
 impl Lower for data::EnumData {
@@ -113,6 +114,7 @@ fn lower(self, tcx: TyCtxt) -> EnumData {
             variants: self.variants.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(),
             visibility: self.visibility,
             docs: self.docs,
+            sig: self.sig.lower(tcx),
         }
     }
 }
@@ -176,6 +178,7 @@ pub struct FunctionData {
     pub visibility: Visibility,
     pub parent: Option<DefId>,
     pub docs: String,
+    pub sig: Signature,
 }
 
 impl Lower for data::FunctionData {
@@ -193,6 +196,7 @@ fn lower(self, tcx: TyCtxt) -> FunctionData {
             visibility: self.visibility,
             parent: self.parent,
             docs: self.docs,
+            sig: self.sig.lower(tcx),
         }
     }
 }
@@ -341,6 +345,7 @@ pub struct MethodData {
     pub visibility: Visibility,
     pub parent: Option<DefId>,
     pub docs: String,
+    pub sig: Signature,
 }
 
 impl Lower for data::MethodData {
@@ -358,6 +363,7 @@ fn lower(self, tcx: TyCtxt) -> MethodData {
             visibility: self.visibility,
             parent: self.parent,
             docs: self.docs,
+            sig: self.sig.lower(tcx),
         }
     }
 }
@@ -374,6 +380,7 @@ pub struct ModData {
     pub items: Vec<DefId>,
     pub visibility: Visibility,
     pub docs: String,
+    pub sig: Signature,
 }
 
 impl Lower for data::ModData {
@@ -390,6 +397,7 @@ fn lower(self, tcx: TyCtxt) -> ModData {
             items: self.items.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(),
             visibility: self.visibility,
             docs: self.docs,
+            sig: self.sig.lower(tcx),
         }
     }
 }
@@ -428,6 +436,7 @@ pub struct StructData {
     pub fields: Vec<DefId>,
     pub visibility: Visibility,
     pub docs: String,
+    pub sig: Signature,
 }
 
 impl Lower for data::StructData {
@@ -445,6 +454,7 @@ fn lower(self, tcx: TyCtxt) -> StructData {
             fields: self.fields.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(),
             visibility: self.visibility,
             docs: self.docs,
+            sig: self.sig.lower(tcx),
         }
     }
 }
@@ -460,6 +470,7 @@ pub struct StructVariantData {
     pub scope: DefId,
     pub parent: Option<DefId>,
     pub docs: String,
+    pub sig: Signature,
 }
 
 impl Lower for data::StructVariantData {
@@ -476,6 +487,7 @@ fn lower(self, tcx: TyCtxt) -> StructVariantData {
             scope: make_def_id(self.scope, &tcx.map),
             parent: self.parent,
             docs: self.docs,
+            sig: self.sig.lower(tcx),
         }
     }
 }
@@ -491,6 +503,7 @@ pub struct TraitData {
     pub items: Vec<DefId>,
     pub visibility: Visibility,
     pub docs: String,
+    pub sig: Signature,
 }
 
 impl Lower for data::TraitData {
@@ -507,6 +520,7 @@ fn lower(self, tcx: TyCtxt) -> TraitData {
             items: self.items.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(),
             visibility: self.visibility,
             docs: self.docs,
+            sig: self.sig.lower(tcx),
         }
     }
 }
@@ -522,6 +536,7 @@ pub struct TupleVariantData {
     pub scope: DefId,
     pub parent: Option<DefId>,
     pub docs: String,
+    pub sig: Signature,
 }
 
 impl Lower for data::TupleVariantData {
@@ -538,6 +553,7 @@ fn lower(self, tcx: TyCtxt) -> TupleVariantData {
             scope: make_def_id(self.scope, &tcx.map),
             parent: self.parent,
             docs: self.docs,
+            sig: self.sig.lower(tcx),
         }
     }
 }
@@ -553,6 +569,7 @@ pub struct TypeDefData {
     pub visibility: Visibility,
     pub parent: Option<DefId>,
     pub docs: String,
+    pub sig: Option<Signature>,
 }
 
 impl Lower for data::TypeDefData {
@@ -568,6 +585,7 @@ fn lower(self, tcx: TyCtxt) -> TypeDefData {
             visibility: self.visibility,
             parent: self.parent,
             docs: self.docs,
+            sig: self.sig.map(|s| s.lower(tcx)),
         }
     }
 }
@@ -656,6 +674,7 @@ pub struct VariableData {
     pub parent: Option<DefId>,
     pub visibility: Visibility,
     pub docs: String,
+    pub sig: Option<Signature>,
 }
 
 impl Lower for data::VariableData {
@@ -674,6 +693,7 @@ fn lower(self, tcx: TyCtxt) -> VariableData {
             parent: self.parent,
             visibility: self.visibility,
             docs: self.docs,
+            sig: self.sig.map(|s| s.lower(tcx)),
         }
     }
 }
@@ -700,3 +720,30 @@ fn lower(self, tcx: TyCtxt) -> VariableRefData {
         }
     }
 }
+
+#[derive(Clone, Debug, RustcEncodable)]
+pub struct Signature {
+    pub span: SpanData,
+    pub text: String,
+    // These identify the main identifier for the defintion as byte offsets into
+    // `text`. E.g., of `foo` in `pub fn foo(...)`
+    pub ident_start: usize,
+    pub ident_end: usize,
+    pub defs: Vec<SigElement>,
+    pub refs: Vec<SigElement>,
+}
+
+impl Lower for data::Signature {
+    type Target = Signature;
+
+    fn lower(self, tcx: TyCtxt) -> Signature {
+        Signature {
+            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            text: self.text,
+            ident_start: self.ident_start,
+            ident_end: self.ident_end,
+            defs: self.defs,
+            refs: self.refs,
+        }
+    }
+}
index d56aae18a7cd1f65e49a64d55bacc1acbf47082b..342c33af2f8963854b65a15e5a60e6c0e76c78a9 100644 (file)
@@ -14,7 +14,7 @@
 use rustc_serialize::json::as_json;
 
 use external_data::*;
-use data::{VariableKind, Visibility};
+use data::{VariableKind, Visibility, SigElement};
 use dump::Dump;
 use super::Format;
 
@@ -179,6 +179,7 @@ struct Def {
     children: Vec<Id>,
     decl_id: Option<Id>,
     docs: String,
+    sig: Option<JsonSignature>,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -221,6 +222,7 @@ fn from(data: EnumData) -> Option<Def> {
                 children: data.variants.into_iter().map(|id| From::from(id)).collect(),
                 decl_id: None,
                 docs: data.docs,
+                sig: Some(From::from(data.sig)),
             }),
             _ => None,
         }
@@ -240,6 +242,7 @@ fn from(data: TupleVariantData) -> Option<Def> {
             children: vec![],
             decl_id: None,
             docs: data.docs,
+            sig: Some(From::from(data.sig)),
         })
     }
 }
@@ -256,6 +259,7 @@ fn from(data: StructVariantData) -> Option<Def> {
             children: vec![],
             decl_id: None,
             docs: data.docs,
+            sig: Some(From::from(data.sig)),
         })
     }
 }
@@ -273,6 +277,7 @@ fn from(data: StructData) -> Option<Def> {
             children: data.fields.into_iter().map(|id| From::from(id)).collect(),
             decl_id: None,
             docs: data.docs,
+            sig: Some(From::from(data.sig)),
         }),
             _ => None,
         }
@@ -292,6 +297,7 @@ fn from(data: TraitData) -> Option<Def> {
                 parent: None,
                 decl_id: None,
                 docs: data.docs,
+                sig: Some(From::from(data.sig)),
             }),
             _ => None,
         }
@@ -311,6 +317,7 @@ fn from(data: FunctionData) -> Option<Def> {
                 parent: data.parent.map(|id| From::from(id)),
                 decl_id: None,
                 docs: data.docs,
+                sig: Some(From::from(data.sig)),
             }),
             _ => None,
         }
@@ -330,6 +337,7 @@ fn from(data: MethodData) -> Option<Def> {
                 parent: data.parent.map(|id| From::from(id)),
                 decl_id: data.decl_id.map(|id| From::from(id)),
                 docs: data.docs,
+                sig: Some(From::from(data.sig)),
             }),
             _ => None,
         }
@@ -348,6 +356,7 @@ fn from(data: MacroData) -> Option<Def> {
             parent: None,
             decl_id: None,
             docs: data.docs,
+            sig: None,
         })
     }
 }
@@ -365,6 +374,7 @@ fn from(data:ModData) -> Option<Def> {
                 parent: None,
                 decl_id: None,
                 docs: data.docs,
+                sig: Some(From::from(data.sig)),
             }),
             _ => None,
         }
@@ -384,11 +394,13 @@ fn from(data: TypeDefData) -> Option<Def> {
                 parent: data.parent.map(|id| From::from(id)),
                 decl_id: None,
                 docs: String::new(),
+                sig: data.sig.map(|s| From::from(s)),
             }),
             _ => None,
         }
     }
 }
+
 impl From<VariableData> for Option<Def> {
     fn from(data: VariableData) -> Option<Def> {
         match data.visibility {
@@ -408,8 +420,49 @@ fn from(data: VariableData) -> Option<Def> {
                 parent: data.parent.map(|id| From::from(id)),
                 decl_id: None,
                 docs: data.docs,
+                sig: data.sig.map(|s| From::from(s)),
             }),
             _ => None,
         }
     }
 }
+
+#[derive(Debug, RustcEncodable)]
+pub struct JsonSignature {
+    span: SpanData,
+    text: String,
+    ident_start: usize,
+    ident_end: usize,
+    defs: Vec<JsonSigElement>,
+    refs: Vec<JsonSigElement>,
+}
+
+impl From<Signature> for JsonSignature {
+    fn from(data: Signature) -> JsonSignature {
+        JsonSignature {
+            span: data.span,
+            text: data.text,
+            ident_start: data.ident_start,
+            ident_end: data.ident_end,
+            defs: data.defs.into_iter().map(|s| From::from(s)).collect(),
+            refs: data.refs.into_iter().map(|s| From::from(s)).collect(),
+        }
+    }
+}
+
+#[derive(Debug, RustcEncodable)]
+pub struct JsonSigElement {
+    id: Id,
+    start: usize,
+    end: usize,
+}
+
+impl From<SigElement> for JsonSigElement {
+    fn from(data: SigElement) -> JsonSigElement {
+        JsonSigElement {
+            id: From::from(data.id),
+            start: data.start,
+            end: data.end,
+        }
+    }
+}
index f97272ad5440960a7d112fa3b4f8f4138ee89245..16c06a556df0e74932559e5e2dddbe1140a78bb9 100644 (file)
@@ -14,7 +14,7 @@
 use rustc_serialize::json::as_json;
 
 use external_data::*;
-use data::VariableKind;
+use data::{VariableKind, SigElement};
 use dump::Dump;
 use super::Format;
 
@@ -86,6 +86,7 @@ fn mod_data(&mut self, data: ModData) {
             children: data.items.into_iter().map(|id| From::from(id)).collect(),
             decl_id: None,
             docs: data.docs,
+            sig: Some(From::from(data.sig)),
         };
         if def.span.file_name != def.value {
             // If the module is an out-of-line defintion, then we'll make the
@@ -223,6 +224,7 @@ struct Def {
     children: Vec<Id>,
     decl_id: Option<Id>,
     docs: String,
+    sig: Option<JsonSignature>,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -264,6 +266,7 @@ fn from(data: EnumData) -> Def {
             children: data.variants.into_iter().map(|id| From::from(id)).collect(),
             decl_id: None,
             docs: data.docs,
+            sig: Some(From::from(data.sig)),
         }
     }
 }
@@ -280,6 +283,7 @@ fn from(data: TupleVariantData) -> Def {
             children: vec![],
             decl_id: None,
             docs: data.docs,
+            sig: Some(From::from(data.sig)),
         }
     }
 }
@@ -295,6 +299,7 @@ fn from(data: StructVariantData) -> Def {
             children: vec![],
             decl_id: None,
             docs: data.docs,
+            sig: Some(From::from(data.sig)),
         }
     }
 }
@@ -310,6 +315,7 @@ fn from(data: StructData) -> Def {
             children: data.fields.into_iter().map(|id| From::from(id)).collect(),
             decl_id: None,
             docs: data.docs,
+            sig: Some(From::from(data.sig)),
         }
     }
 }
@@ -325,6 +331,7 @@ fn from(data: TraitData) -> Def {
             children: data.items.into_iter().map(|id| From::from(id)).collect(),
             decl_id: None,
             docs: data.docs,
+            sig: Some(From::from(data.sig)),
         }
     }
 }
@@ -340,6 +347,7 @@ fn from(data: FunctionData) -> Def {
             children: vec![],
             decl_id: None,
             docs: data.docs,
+            sig: Some(From::from(data.sig)),
         }
     }
 }
@@ -355,6 +363,7 @@ fn from(data: MethodData) -> Def {
             children: vec![],
             decl_id: data.decl_id.map(|id| From::from(id)),
             docs: data.docs,
+            sig: Some(From::from(data.sig)),
         }
     }
 }
@@ -370,10 +379,10 @@ fn from(data: MacroData) -> Def {
             children: vec![],
             decl_id: None,
             docs: data.docs,
+            sig: None,
         }
     }
 }
-
 impl From<TypeDefData> for Def {
     fn from(data: TypeDefData) -> Def {
         Def {
@@ -386,6 +395,7 @@ fn from(data: TypeDefData) -> Def {
             children: vec![],
             decl_id: None,
             docs: String::new(),
+            sig: data.sig.map(|s| From::from(s)),
         }
     }
 }
@@ -406,6 +416,7 @@ fn from(data: VariableData) -> Def {
             children: vec![],
             decl_id: None,
             docs: data.docs,
+            sig: None,
         }
     }
 }
@@ -496,3 +507,43 @@ fn from(data: MacroUseData) -> MacroRef {
         }
     }
 }
+
+#[derive(Debug, RustcEncodable)]
+pub struct JsonSignature {
+    span: SpanData,
+    text: String,
+    ident_start: usize,
+    ident_end: usize,
+    defs: Vec<JsonSigElement>,
+    refs: Vec<JsonSigElement>,
+}
+
+impl From<Signature> for JsonSignature {
+    fn from(data: Signature) -> JsonSignature {
+        JsonSignature {
+            span: data.span,
+            text: data.text,
+            ident_start: data.ident_start,
+            ident_end: data.ident_end,
+            defs: data.defs.into_iter().map(|s| From::from(s)).collect(),
+            refs: data.refs.into_iter().map(|s| From::from(s)).collect(),
+        }
+    }
+}
+
+#[derive(Debug, RustcEncodable)]
+pub struct JsonSigElement {
+    id: Id,
+    start: usize,
+    end: usize,
+}
+
+impl From<SigElement> for JsonSigElement {
+    fn from(data: SigElement) -> JsonSigElement {
+        JsonSigElement {
+            id: From::from(data.id),
+            start: data.start,
+            end: data.end,
+        }
+    }
+}
index 862345fd46eb6ce743ab50bfa07f398b993adaeb..43e3b1dd2b50a9d5e62d225da8f5c777698d5861 100644 (file)
@@ -152,6 +152,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     visibility: From::from(&item.vis),
                     parent: None,
                     docs: docs_for_attrs(&item.attrs),
+                    sig: self.sig_base(item),
                 }))
             }
             ast::ItemKind::Static(ref typ, mt, ref expr) => {
@@ -179,6 +180,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     type_value: ty_to_string(&typ),
                     visibility: From::from(&item.vis),
                     docs: docs_for_attrs(&item.attrs),
+                    sig: Some(self.sig_base(item)),
                 }))
             }
             ast::ItemKind::Const(ref typ, ref expr) => {
@@ -197,6 +199,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     type_value: ty_to_string(&typ),
                     visibility: From::from(&item.vis),
                     docs: docs_for_attrs(&item.attrs),
+                    sig: Some(self.sig_base(item)),
                 }))
             }
             ast::ItemKind::Mod(ref m) => {
@@ -207,6 +210,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
 
                 let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Mod);
                 filter!(self.span_utils, sub_span, item.span, None);
+
                 Some(Data::ModData(ModData {
                     id: item.id,
                     name: item.ident.to_string(),
@@ -217,6 +221,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),
                 }))
             }
             ast::ItemKind::Enum(ref def, _) => {
@@ -239,6 +244,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     variants: def.variants.iter().map(|v| v.node.data.id()).collect(),
                     visibility: From::from(&item.vis),
                     docs: docs_for_attrs(&item.attrs),
+                    sig: self.sig_base(item),
                 }))
             }
             ast::ItemKind::Impl(.., ref trait_ref, ref typ, _) => {
@@ -287,18 +293,34 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
         }
     }
 
-    pub fn get_field_data(&self, field: &ast::StructField,
-                          scope: NodeId) -> Option<VariableData> {
+    pub fn get_field_data(&self,
+                          field: &ast::StructField,
+                          scope: NodeId)
+                          -> Option<VariableData> {
         if let Some(ident) = field.ident {
+            let name = ident.to_string();
             let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident);
-            let def_id = self.tcx.map.local_def_id(field.id);
-            let typ = self.tcx.item_type(def_id).to_string();
             let sub_span = self.span_utils.sub_span_before_token(field.span, token::Colon);
             filter!(self.span_utils, sub_span, field.span, None);
+            let def_id = self.tcx.map.local_def_id(field.id);
+            let typ = self.tcx.item_type(def_id).to_string();
+
+            let span = field.span;
+            let text = self.span_utils.snippet(field.span);
+            let ident_start = text.find(&name).unwrap();
+            let ident_end = ident_start + name.len();
+            let sig = Signature {
+                span: span,
+                text: text,
+                ident_start: ident_start,
+                ident_end: ident_end,
+                defs: vec![],
+                refs: vec![],
+            };
             Some(VariableData {
                 id: field.id,
                 kind: VariableKind::Field,
-                name: ident.to_string(),
+                name: name,
                 qualname: qualname,
                 span: sub_span.unwrap(),
                 scope: scope,
@@ -307,6 +329,7 @@ pub fn get_field_data(&self, field: &ast::StructField,
                 type_value: typ,
                 visibility: From::from(&field.vis),
                 docs: docs_for_attrs(&field.attrs),
+                sig: Some(sig),
             })
         } else {
             None
@@ -326,7 +349,7 @@ pub fn get_method_data(&self, id: ast::NodeId,
                     match item.node {
                         hir::ItemImpl(.., ref ty, _) => {
                             let mut result = String::from("<");
-                            result.push_str(&rustc::hir::print::ty_to_string(&ty));
+                            result.push_str(&self.tcx.map.node_to_pretty_string(ty.id));
 
                             let trait_id = self.tcx.trait_id_of_impl(impl_id);
                             let mut decl_id = None;
@@ -388,9 +411,23 @@ pub fn get_method_data(&self, id: ast::NodeId,
 
         let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn);
         filter!(self.span_utils, sub_span, span, None);
+
+        let name = name.to_string();
+        let text = self.span_utils.signature_string_for_span(span);
+        let ident_start = text.find(&name).unwrap();
+        let ident_end = ident_start + name.len();
+        let sig = Signature {
+            span: span,
+            text: text,
+            ident_start: ident_start,
+            ident_end: ident_end,
+            defs: vec![],
+            refs: vec![],
+        };
+
         Some(FunctionData {
             id: id,
-            name: name.to_string(),
+            name: name,
             qualname: qualname,
             declaration: decl_id,
             span: sub_span.unwrap(),
@@ -400,6 +437,7 @@ pub fn get_method_data(&self, id: ast::NodeId,
             visibility: vis,
             parent: parent_scope,
             docs: docs,
+            sig: sig,
         })
     }
 
@@ -695,6 +733,21 @@ fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> {
         }
     }
 
+    fn sig_base(&self, item: &ast::Item) -> Signature {
+        let text = self.span_utils.signature_string_for_span(item.span);
+        let name = item.ident.to_string();
+        let ident_start = text.find(&name).expect("Name not in signature?");
+        let ident_end = ident_start + name.len();
+        Signature {
+            span: mk_sp(item.span.lo, item.span.lo + BytePos(text.len() as u32)),
+            text: text,
+            ident_start: ident_start,
+            ident_end: ident_end,
+            defs: vec![],
+            refs: vec![],
+        }
+    }
+
     #[inline]
     pub fn enclosing_scope(&self, id: NodeId) -> NodeId {
         self.tcx.map.get_enclosing_scope(id).unwrap_or(CRATE_NODE_ID)
index e06aefd865f1ba6486c1dadf5ab4bb10081f0f84..448bb2e761749c380ba4620ee669ef262b502c37 100644 (file)
@@ -19,7 +19,9 @@
 use syntax::ast;
 use syntax::parse::lexer::{self, Reader, StringReader};
 use syntax::parse::token::{self, Token};
+use syntax::parse::parser::Parser;
 use syntax::symbol::keywords;
+use syntax::tokenstream::TokenTree;
 use syntax_pos::*;
 
 #[derive(Clone)]
@@ -87,6 +89,12 @@ pub fn retokenise_span(&self, span: Span) -> StringReader<'a> {
         lexer::StringReader::new(s.diagnostic(), filemap)
     }
 
+    fn span_to_tts(&self, span: Span) -> Vec<TokenTree> {
+        let srdr = self.retokenise_span(span);
+        let mut p = Parser::new(&self.sess.parse_sess, Box::new(srdr), None, false);
+        p.parse_all_token_trees().expect("Couldn't re-parse span")
+    }
+
     // Re-parses a path and returns the span for the last identifier in the path
     pub fn span_for_last_ident(&self, span: Span) -> Option<Span> {
         let mut result = None;
@@ -308,6 +316,42 @@ pub fn spans_with_brackets(&self, span: Span, nesting: isize, limit: isize) -> V
         }
     }
 
+    /// `span` must be the span for an item such as a function or struct. This
+    /// function returns the program text from the start of the span until the
+    /// end of the 'signature' part, that is up to, but not including an opening
+    /// brace or semicolon.
+    pub fn signature_string_for_span(&self, span: Span) -> String {
+        let mut toks = self.span_to_tts(span).into_iter();
+        let mut prev = toks.next().unwrap();
+        let first_span = prev.get_span();
+        let mut angle_count = 0;
+        for tok in toks {
+            if let TokenTree::Token(_, ref tok) = prev {
+                angle_count += match *tok {
+                    token::Eof => { break; }
+                    token::Lt => 1,
+                    token::Gt => -1,
+                    token::BinOp(token::Shl) => 2,
+                    token::BinOp(token::Shr) => -2,
+                    _ => 0,
+                };
+            }
+            if angle_count > 0 {
+                prev = tok;
+                continue;
+            }
+            if let TokenTree::Token(_, token::Semi) = tok {
+                return self.snippet(mk_sp(first_span.lo, prev.get_span().hi));
+            } else if let TokenTree::Delimited(_, ref d) = tok {
+                if d.delim == token::Brace {
+                    return self.snippet(mk_sp(first_span.lo, prev.get_span().hi));
+                }
+            }
+            prev = tok;
+        }
+        self.snippet(span)
+    }
+
     pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option<Span> {
         let mut toks = self.retokenise_span(span);
         let mut prev = toks.real_token();
diff --git a/src/librustc_trans/README.md b/src/librustc_trans/README.md
new file mode 100644 (file)
index 0000000..cd43cbd
--- /dev/null
@@ -0,0 +1 @@
+See [librustc/README.md](../librustc/README.md).
diff --git a/src/librustc_trans/README.txt b/src/librustc_trans/README.txt
deleted file mode 100644 (file)
index 1f416d5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-See the README.md in ../librustc.
index 8b4343af1990f53f0f8ee6901f08104d78343057..81e4b4d1f21c76c84ed115ac748d519a007617ff 100644 (file)
@@ -24,6 +24,9 @@
 use cabi_mips64;
 use cabi_asmjs;
 use cabi_msp430;
+use cabi_sparc;
+use cabi_nvptx;
+use cabi_nvptx64;
 use machine::{llalign_of_min, llsize_of, llsize_of_alloc};
 use type_::Type;
 use type_of;
@@ -58,7 +61,7 @@ mod attr_impl {
     // The subset of llvm::Attribute needed for arguments, packed into a bitfield.
     bitflags! {
         #[derive(Default, Debug)]
-        flags ArgAttribute : u8 {
+        flags ArgAttribute : u16 {
             const ByVal     = 1 << 0,
             const NoAlias   = 1 << 1,
             const NoCapture = 1 << 2,
@@ -67,6 +70,7 @@ mod attr_impl {
             const SExt      = 1 << 5,
             const StructRet = 1 << 6,
             const ZExt      = 1 << 7,
+            const InReg     = 1 << 8,
         }
     }
 }
@@ -80,7 +84,7 @@ macro_rules! for_each_kind {
 impl ArgAttribute {
     fn for_each_kind<F>(&self, mut f: F) where F: FnMut(llvm::Attribute) {
         for_each_kind!(self, f,
-                       ByVal, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt)
+                       ByVal, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg)
     }
 }
 
@@ -351,6 +355,7 @@ pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             Win64 => llvm::X86_64_Win64,
             SysV64 => llvm::X86_64_SysV,
             Aapcs => llvm::ArmAapcsCallConv,
+            PtxKernel => llvm::PtxKernel,
 
             // These API constants ought to be more specific...
             Cdecl => llvm::CCallConv,
@@ -573,7 +578,14 @@ pub fn adjust_for_abi<'a, 'tcx>(&mut self,
         }
 
         match &ccx.sess().target.target.arch[..] {
-            "x86" => cabi_x86::compute_abi_info(ccx, self),
+            "x86" => {
+                let flavor = if abi == Abi::Fastcall {
+                    cabi_x86::Flavor::Fastcall
+                } else {
+                    cabi_x86::Flavor::General
+                };
+                cabi_x86::compute_abi_info(ccx, self, flavor);
+            },
             "x86_64" => if abi == Abi::SysV64 {
                 cabi_x86_64::compute_abi_info(ccx, self);
             } else if abi == Abi::Win64 || ccx.sess().target.target.options.is_like_windows {
@@ -598,6 +610,9 @@ pub fn adjust_for_abi<'a, 'tcx>(&mut self,
             "asmjs" => cabi_asmjs::compute_abi_info(ccx, self),
             "wasm32" => cabi_asmjs::compute_abi_info(ccx, self),
             "msp430" => cabi_msp430::compute_abi_info(ccx, self),
+            "sparc" => cabi_sparc::compute_abi_info(ccx, self),
+            "nvptx" => cabi_nvptx::compute_abi_info(ccx, self),
+            "nvptx64" => cabi_nvptx64::compute_abi_info(ccx, self),
             a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
         }
 
index 648dc4c24c9a658c79426f2b53d2f5c707ca7f6a..defbb44448a9f3a5f4b7ce77ecc494086f5a9f61 100644 (file)
@@ -191,7 +191,8 @@ pub fn link_binary(sess: &Session,
     let mut out_filenames = Vec::new();
     for &crate_type in sess.crate_types.borrow().iter() {
         // Ignore executable crates if we have -Z no-trans, as they will error.
-        if sess.opts.debugging_opts.no_trans &&
+        if (sess.opts.debugging_opts.no_trans ||
+            !sess.opts.output_types.should_trans()) &&
            crate_type == config::CrateTypeExecutable {
             continue;
         }
@@ -200,15 +201,16 @@ pub fn link_binary(sess: &Session,
            bug!("invalid output type `{:?}` for target os `{}`",
                 crate_type, sess.opts.target_triple);
         }
-        let out_file = link_binary_output(sess, trans, crate_type, outputs,
-                                          crate_name);
-        out_filenames.push(out_file);
+        let mut out_files = link_binary_output(sess, trans, crate_type, outputs, crate_name);
+        out_filenames.append(&mut out_files);
     }
 
     // Remove the temporary object file and metadata if we aren't saving temps
     if !sess.opts.cg.save_temps {
-        for obj in object_filenames(trans, outputs) {
-            remove(sess, &obj);
+        if sess.opts.output_types.should_trans() {
+            for obj in object_filenames(trans, outputs) {
+                remove(sess, &obj);
+            }
         }
         remove(sess, &outputs.with_extension("metadata.o"));
     }
@@ -254,18 +256,25 @@ fn is_writeable(p: &Path) -> bool {
     }
 }
 
+fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilenames) -> PathBuf {
+    let out_filename = outputs.single_output_file.clone()
+        .unwrap_or(outputs
+            .out_directory
+            .join(&format!("lib{}{}.rmeta", crate_name, sess.opts.cg.extra_filename)));
+    check_file_is_writeable(&out_filename, sess);
+    out_filename
+}
+
 pub fn filename_for_input(sess: &Session,
                           crate_type: config::CrateType,
                           crate_name: &str,
                           outputs: &OutputFilenames) -> PathBuf {
     let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
+
     match crate_type {
         config::CrateTypeRlib => {
             outputs.out_directory.join(&format!("lib{}.rlib", libname))
         }
-        config::CrateTypeMetadata => {
-            outputs.out_directory.join(&format!("lib{}.rmeta", libname))
-        }
         config::CrateTypeCdylib |
         config::CrateTypeProcMacro |
         config::CrateTypeDylib => {
@@ -323,27 +332,41 @@ pub fn each_linked_rlib(sess: &Session,
     }
 }
 
+fn out_filename(sess: &Session,
+                crate_type: config::CrateType,
+                outputs: &OutputFilenames,
+                crate_name: &str)
+                -> PathBuf {
+    let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
+    let out_filename = outputs.outputs.get(&OutputType::Exe)
+                              .and_then(|s| s.to_owned())
+                              .or_else(|| outputs.single_output_file.clone())
+                              .unwrap_or(default_filename);
+
+    check_file_is_writeable(&out_filename, sess);
+
+    out_filename
+}
+
+// Make sure files are writeable.  Mac, FreeBSD, and Windows system linkers
+// check this already -- however, the Linux linker will happily overwrite a
+// read-only file.  We should be consistent.
+fn check_file_is_writeable(file: &Path, sess: &Session) {
+    if !is_writeable(file) {
+        sess.fatal(&format!("output file {} is not writeable -- check its \
+                            permissions", file.display()));
+    }
+}
+
 fn link_binary_output(sess: &Session,
                       trans: &CrateTranslation,
                       crate_type: config::CrateType,
                       outputs: &OutputFilenames,
-                      crate_name: &str) -> PathBuf {
+                      crate_name: &str) -> Vec<PathBuf> {
     let objects = object_filenames(trans, outputs);
-    let default_filename = filename_for_input(sess, crate_type, crate_name,
-                                              outputs);
-    let out_filename = outputs.outputs.get(&OutputType::Exe)
-                              .and_then(|s| s.to_owned())
-                              .or_else(|| outputs.single_output_file.clone())
-                              .unwrap_or(default_filename);
 
-    // Make sure files are writeable.  Mac, FreeBSD, and Windows system linkers
-    // check this already -- however, the Linux linker will happily overwrite a
-    // read-only file.  We should be consistent.
-    for file in objects.iter().chain(Some(&out_filename)) {
-        if !is_writeable(file) {
-            sess.fatal(&format!("output file {} is not writeable -- check its \
-                                permissions", file.display()));
-        }
+    for file in &objects {
+        check_file_is_writeable(file, sess);
     }
 
     let tmpdir = match TempDir::new("rustc") {
@@ -351,24 +374,33 @@ fn link_binary_output(sess: &Session,
         Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)),
     };
 
-    match crate_type {
-        config::CrateTypeRlib => {
-            link_rlib(sess, Some(trans), &objects, &out_filename,
-                      tmpdir.path()).build();
-        }
-        config::CrateTypeStaticlib => {
-            link_staticlib(sess, &objects, &out_filename, tmpdir.path());
-        }
-        config::CrateTypeMetadata => {
-            emit_metadata(sess, trans, &out_filename);
-        }
-        _ => {
-            link_natively(sess, crate_type, &objects, &out_filename, trans,
-                          outputs, tmpdir.path());
+    let mut out_filenames = vec![];
+
+    if outputs.outputs.contains_key(&OutputType::Metadata) {
+        let out_filename = filename_for_metadata(sess, crate_name, outputs);
+        emit_metadata(sess, trans, &out_filename);
+        out_filenames.push(out_filename);
+    }
+
+    if outputs.outputs.should_trans() {
+        let out_filename = out_filename(sess, crate_type, outputs, crate_name);
+        match crate_type {
+            config::CrateTypeRlib => {
+                link_rlib(sess, Some(trans), &objects, &out_filename,
+                          tmpdir.path()).build();
+            }
+            config::CrateTypeStaticlib => {
+                link_staticlib(sess, &objects, &out_filename, tmpdir.path());
+            }
+            _ => {
+                link_natively(sess, crate_type, &objects, &out_filename, trans,
+                              outputs, tmpdir.path());
+            }
         }
+        out_filenames.push(out_filename);
     }
 
-    out_filename
+    out_filenames
 }
 
 fn object_filenames(trans: &CrateTranslation,
index f137bfff034d0e37c7cc9af7afd364a86d42064b..0ef3f351a2a4bffdb58292beb058e482a73416cc 100644 (file)
@@ -34,7 +34,6 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool {
 
         config::CrateTypeDylib     |
         config::CrateTypeRlib      |
-        config::CrateTypeMetadata  |
         config::CrateTypeProcMacro => false,
     }
 }
index eef464eb7f4dc61098e64884dd9f9a70ae1ac756..5f16291892387fb6b2622895a4979b37625b0618 100644 (file)
@@ -149,7 +149,6 @@ pub fn crate_export_threshold(crate_type: config::CrateType)
         config::CrateTypeProcMacro  |
         config::CrateTypeCdylib     => SymbolExportLevel::C,
         config::CrateTypeRlib       |
-        config::CrateTypeMetadata   |
         config::CrateTypeDylib      => SymbolExportLevel::Rust,
     }
 }
index de8814f143e04f62b4c07b046a7c5ac0039b01f7..dac1e3b8dc1ce6a65ddf6d73a6105822cf6d3ad1 100644 (file)
@@ -19,7 +19,7 @@
 use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef};
 use llvm::SMDiagnosticRef;
 use {CrateTranslation, ModuleLlvm, ModuleSource, ModuleTranslation};
-use util::common::time;
+use util::common::{time, time_depth, set_time_depth};
 use util::common::path2cstr;
 use util::fs::link_or_copy;
 use errors::{self, Handler, Level, DiagnosticBuilder};
@@ -701,8 +701,8 @@ pub fn run_passes(sess: &Session,
 
     for output_type in output_types.keys() {
         match *output_type {
-            OutputType::Bitcode => { modules_config.emit_bc = true; },
-            OutputType::LlvmAssembly => { modules_config.emit_ir = true; },
+            OutputType::Bitcode => { modules_config.emit_bc = true; }
+            OutputType::LlvmAssembly => { modules_config.emit_ir = true; }
             OutputType::Assembly => {
                 modules_config.emit_asm = true;
                 // If we're not using the LLVM assembler, this function
@@ -711,8 +711,9 @@ pub fn run_passes(sess: &Session,
                 if !sess.opts.output_types.contains_key(&OutputType::Assembly) {
                     metadata_config.emit_obj = true;
                 }
-            },
-            OutputType::Object => { modules_config.emit_obj = true; },
+            }
+            OutputType::Object => { modules_config.emit_obj = true; }
+            OutputType::Metadata => { metadata_config.emit_obj = true; }
             OutputType::Exe => {
                 modules_config.emit_obj = true;
                 metadata_config.emit_obj = true;
@@ -853,6 +854,7 @@ pub fn run_passes(sess: &Session,
                 user_wants_objects = true;
                 copy_if_one_unit(OutputType::Object, true);
             }
+            OutputType::Metadata |
             OutputType::Exe |
             OutputType::DepInfo => {}
         }
@@ -1033,7 +1035,10 @@ fn run_work_multithreaded(sess: &Session,
 
         let incr_comp_session_dir = sess.incr_comp_session_dir_opt().map(|r| r.clone());
 
+        let depth = time_depth();
         thread::Builder::new().name(format!("codegen-{}", i)).spawn(move || {
+            set_time_depth(depth);
+
             let diag_handler = Handler::with_emitter(true, false, box diag_emitter);
 
             // Must construct cgcx inside the proc because it has non-Send
index 76bb1c56af3818aa155be237b4bb5da7292aded4..47b76658bdd1481689e5c960e8c7862004c232df 100644 (file)
@@ -807,8 +807,7 @@ enum MetadataKind {
             config::CrateTypeStaticlib |
             config::CrateTypeCdylib => MetadataKind::None,
 
-            config::CrateTypeRlib |
-            config::CrateTypeMetadata => MetadataKind::Uncompressed,
+            config::CrateTypeRlib => MetadataKind::Uncompressed,
 
             config::CrateTypeDylib |
             config::CrateTypeProcMacro => MetadataKind::Compressed,
@@ -1191,7 +1190,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     // Skip crate items and just output metadata in -Z no-trans mode.
     if tcx.sess.opts.debugging_opts.no_trans ||
-       tcx.sess.crate_types.borrow().iter().all(|ct| ct == &config::CrateTypeMetadata) {
+       tcx.sess.opts.output_types.contains_key(&config::OutputType::Metadata) {
         let linker_info = LinkerInfo::new(&shared_ccx, &ExportedSymbols::empty());
         return CrateTranslation {
             modules: modules,
diff --git a/src/librustc_trans/cabi_nvptx.rs b/src/librustc_trans/cabi_nvptx.rs
new file mode 100644 (file)
index 0000000..5ece19f
--- /dev/null
@@ -0,0 +1,53 @@
+// 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.
+
+// Reference: PTX Writer's Guide to Interoperability
+// http://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability
+
+#![allow(non_upper_case_globals)]
+
+use llvm::Struct;
+
+use abi::{self, ArgType, FnType};
+use context::CrateContext;
+use type_::Type;
+
+fn ty_size(ty: Type) -> usize {
+    abi::ty_size(ty, 4)
+}
+
+fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
+    if ret.ty.kind() == Struct && ty_size(ret.ty) > 32 {
+        ret.make_indirect(ccx);
+    } else {
+        ret.extend_integer_width_to(32);
+    }
+}
+
+fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
+    if arg.ty.kind() == Struct && ty_size(arg.ty) > 32 {
+        arg.make_indirect(ccx);
+    } else {
+        arg.extend_integer_width_to(32);
+    }
+}
+
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
+    if !fty.ret.is_ignore() {
+        classify_ret_ty(ccx, &mut fty.ret);
+    }
+
+    for arg in &mut fty.args {
+        if arg.is_ignore() {
+            continue;
+        }
+        classify_arg_ty(ccx, arg);
+    }
+}
diff --git a/src/librustc_trans/cabi_nvptx64.rs b/src/librustc_trans/cabi_nvptx64.rs
new file mode 100644 (file)
index 0000000..880c6cf
--- /dev/null
@@ -0,0 +1,53 @@
+// 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.
+
+// Reference: PTX Writer's Guide to Interoperability
+// http://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability
+
+#![allow(non_upper_case_globals)]
+
+use llvm::Struct;
+
+use abi::{self, ArgType, FnType};
+use context::CrateContext;
+use type_::Type;
+
+fn ty_size(ty: Type) -> usize {
+    abi::ty_size(ty, 8)
+}
+
+fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
+    if ret.ty.kind() == Struct && ty_size(ret.ty) > 64 {
+        ret.make_indirect(ccx);
+    } else {
+        ret.extend_integer_width_to(64);
+    }
+}
+
+fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
+    if arg.ty.kind() == Struct && ty_size(arg.ty) > 64 {
+        arg.make_indirect(ccx);
+    } else {
+        arg.extend_integer_width_to(64);
+    }
+}
+
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
+    if !fty.ret.is_ignore() {
+        classify_ret_ty(ccx, &mut fty.ret);
+    }
+
+    for arg in &mut fty.args {
+        if arg.is_ignore() {
+            continue;
+        }
+        classify_arg_ty(ccx, arg);
+    }
+}
diff --git a/src/librustc_trans/cabi_sparc.rs b/src/librustc_trans/cabi_sparc.rs
new file mode 100644 (file)
index 0000000..25fe53e
--- /dev/null
@@ -0,0 +1,108 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(non_upper_case_globals)]
+
+use libc::c_uint;
+use std::cmp;
+use llvm;
+use llvm::{Integer, Pointer, Float, Double, Vector};
+use abi::{self, align_up_to, ArgType, FnType};
+use context::CrateContext;
+use type_::Type;
+
+fn ty_align(ty: Type) -> usize {
+    abi::ty_align(ty, 4)
+}
+
+fn ty_size(ty: Type) -> usize {
+    abi::ty_size(ty, 4)
+}
+
+fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
+    if is_reg_ty(ret.ty) {
+        ret.extend_integer_width_to(32);
+    } else {
+        ret.make_indirect(ccx);
+    }
+}
+
+fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut usize) {
+    let orig_offset = *offset;
+    let size = ty_size(arg.ty) * 8;
+    let mut align = ty_align(arg.ty);
+
+    align = cmp::min(cmp::max(align, 4), 8);
+    *offset = align_up_to(*offset, align);
+    *offset += align_up_to(size, align * 8) / 8;
+
+    if !is_reg_ty(arg.ty) {
+        arg.cast = Some(struct_ty(ccx, arg.ty));
+        arg.pad = padding_ty(ccx, align, orig_offset);
+    } else {
+        arg.extend_integer_width_to(32);
+    }
+}
+
+fn is_reg_ty(ty: Type) -> bool {
+    return match ty.kind() {
+        Integer
+        | Pointer
+        | Float
+        | Double
+        | Vector => true,
+        _ => false
+    };
+}
+
+fn padding_ty(ccx: &CrateContext, align: usize, offset: usize) -> Option<Type> {
+    if ((align - 1 ) & offset) > 0 {
+        Some(Type::i32(ccx))
+    } else {
+        None
+    }
+}
+
+fn coerce_to_int(ccx: &CrateContext, size: usize) -> Vec<Type> {
+    let int_ty = Type::i32(ccx);
+    let mut args = Vec::new();
+
+    let mut n = size / 32;
+    while n > 0 {
+        args.push(int_ty);
+        n -= 1;
+    }
+
+    let r = size % 32;
+    if r > 0 {
+        unsafe {
+            args.push(Type::from_ref(llvm::LLVMIntTypeInContext(ccx.llcx(), r as c_uint)));
+        }
+    }
+
+    args
+}
+
+fn struct_ty(ccx: &CrateContext, ty: Type) -> Type {
+    let size = ty_size(ty) * 8;
+    Type::struct_(ccx, &coerce_to_int(ccx, size), false)
+}
+
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
+    if !fty.ret.is_ignore() {
+        classify_ret_ty(ccx, &mut fty.ret);
+    }
+
+    let mut offset = if fty.ret.is_indirect() { 4 } else { 0 };
+    for arg in &mut fty.args {
+        if arg.is_ignore() { continue; }
+        classify_arg_ty(ccx, arg, &mut offset);
+    }
+}
index ce85234f2034af36cb720a14a387df6065a75544..fea005f3d77da388194cdaf7a9f4d1734b544dd0 100644 (file)
 use super::common::*;
 use super::machine::*;
 
-pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
+#[derive(PartialEq)]
+pub enum Flavor {
+    General,
+    Fastcall
+}
+
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType, flavor: Flavor) {
     if !fty.ret.is_ignore() {
         if fty.ret.ty.kind() == Struct {
             // Returning a structure. Most often, this will use
@@ -51,4 +57,46 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
             arg.extend_integer_width_to(32);
         }
     }
+
+    if flavor == Flavor::Fastcall {
+        // Mark arguments as InReg like clang does it,
+        // so our fastcall is compatible with C/C++ fastcall.
+
+        // Clang reference: lib/CodeGen/TargetInfo.cpp
+        // See X86_32ABIInfo::shouldPrimitiveUseInReg(), X86_32ABIInfo::updateFreeRegs()
+
+        // IsSoftFloatABI is only set to true on ARM platforms,
+        // which in turn can't be x86?
+
+        let mut free_regs = 2;
+
+        for arg in &mut fty.args {
+            if arg.is_ignore() || arg.is_indirect() { continue; }
+
+            if arg.ty.kind() == Float {
+                continue;
+            }
+
+            let size = llbitsize_of_real(ccx, arg.ty);
+            let size_in_regs = (size + 31) / 32;
+
+            if size_in_regs == 0 {
+                continue;
+            }
+
+            if size_in_regs > free_regs {
+                break;
+            }
+
+            free_regs -= size_in_regs;
+
+            if size <= 32 && (arg.ty.kind() == Pointer || arg.ty.kind() == Integer) {
+                arg.attrs.set(ArgAttribute::InReg);
+            }
+
+            if free_regs == 0 {
+                break;
+            }
+        }
+    }
 }
index ac832b6f746fd7262a037623af2e99e97800da46..1abe25ea6073e6579dbb0e464076b04f896430d3 100644 (file)
@@ -27,6 +27,7 @@
 use common::{
     self, CrateContext, FunctionContext, SharedCrateContext
 };
+use adt::MaybeSizedValue;
 use consts;
 use declare;
 use value::Value;
@@ -364,7 +365,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
 
     // Call the by-ref closure body with `self` in a cleanup scope,
     // to drop `self` when the body returns, or in case it unwinds.
-    let self_scope = fcx.schedule_drop_mem(llenv, closure_ty);
+    let self_scope = fcx.schedule_drop_mem(MaybeSizedValue::sized(llenv), closure_ty);
 
     let llfn = callee.reify(bcx.ccx);
     let llret;
index add820748acfcd5325107a8292a73e5d9b3671d2..4e59ea3f6c5ed71664a5bc9078684291ee03fdf7 100644 (file)
 //! corresponds to a normal exit from a block (for example, an expression
 //! completing evaluation successfully without panic).
 
-use llvm::{BasicBlockRef, ValueRef};
+use llvm::BasicBlockRef;
 use base;
+use adt::MaybeSizedValue;
 use common::{BlockAndBuilder, FunctionContext, Funclet};
 use glue;
 use type_::Type;
-use value::Value;
 use rustc::ty::Ty;
 
 pub struct CleanupScope<'tcx> {
@@ -36,7 +36,7 @@ pub struct CleanupScope<'tcx> {
 
 #[derive(Copy, Clone)]
 pub struct DropValue<'tcx> {
-    val: ValueRef,
+    val: MaybeSizedValue,
     ty: Ty<'tcx>,
     skip_dtor: bool,
 }
@@ -94,7 +94,7 @@ fn get_landing_pad<'a>(&self, fcx: &FunctionContext<'a, 'tcx>) -> BasicBlockRef
 
 impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
     /// Schedules a (deep) drop of `val`, which is a pointer to an instance of `ty`
-    pub fn schedule_drop_mem(&self, val: ValueRef, ty: Ty<'tcx>) -> CleanupScope<'tcx> {
+    pub fn schedule_drop_mem(&self, val: MaybeSizedValue, ty: Ty<'tcx>) -> CleanupScope<'tcx> {
         if !self.ccx.shared().type_needs_drop(ty) { return CleanupScope::noop(); }
         let drop = DropValue {
             val: val,
@@ -102,8 +102,6 @@ pub fn schedule_drop_mem(&self, val: ValueRef, ty: Ty<'tcx>) -> CleanupScope<'tc
             skip_dtor: false,
         };
 
-        debug!("schedule_drop_mem(val={:?}, ty={:?}) skip_dtor={}", Value(val), ty, drop.skip_dtor);
-
         CleanupScope::new(self, drop)
     }
 
@@ -112,7 +110,8 @@ pub fn schedule_drop_mem(&self, val: ValueRef, ty: Ty<'tcx>) -> CleanupScope<'tc
     /// `ty`. The scheduled code handles extracting the discriminant
     /// and dropping the contents associated with that variant
     /// *without* executing any associated drop implementation.
-    pub fn schedule_drop_adt_contents(&self, val: ValueRef, ty: Ty<'tcx>) -> CleanupScope<'tcx> {
+    pub fn schedule_drop_adt_contents(&self, val: MaybeSizedValue, ty: Ty<'tcx>)
+        -> CleanupScope<'tcx> {
         // `if` below could be "!contents_needs_drop"; skipping drop
         // is just an optimization, so sound to be conservative.
         if !self.ccx.shared().type_needs_drop(ty) { return CleanupScope::noop(); }
@@ -123,9 +122,6 @@ pub fn schedule_drop_adt_contents(&self, val: ValueRef, ty: Ty<'tcx>) -> Cleanup
             skip_dtor: true,
         };
 
-        debug!("schedule_drop_adt_contents(val={:?}, ty={:?}) skip_dtor={}",
-               Value(val), ty, drop.skip_dtor);
-
         CleanupScope::new(self, drop)
     }
 }
index d8c212745376d69225bd2ff424dd1c15f4731f62..2bc42a461528da2bfb28b779341c40ad1e8ec73c 100644 (file)
 
 use rustc::hir::map as hir_map;
 use rustc::hir::def_id::DefId;
-use rustc::middle::lang_items::{ExchangeFreeFnLangItem, ExchangeMallocFnLangItem};
+use rustc::middle::lang_items::{BoxFreeFnLangItem, ExchangeMallocFnLangItem};
 use rustc::traits;
-use rustc::ty::subst::{Substs, Subst};
+use rustc::ty::subst::{Kind, Substs, Subst};
 use rustc::ty::{self, TypeFoldable, TyCtxt};
 use rustc::ty::adjustment::CustomCoerceUnsized;
 use rustc::mir::{self, Location};
 use rustc::mir::visit as mir_visit;
 use rustc::mir::visit::Visitor as MirVisitor;
 
-use rustc_const_eval as const_eval;
-
 use syntax::abi::Abi;
 use syntax_pos::DUMMY_SP;
 use base::custom_coerce_unsize_info;
 
 use trans_item::{TransItem, DefPathBasedNames};
 
+use std::iter;
+
 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
 pub enum TransItemCollectionMode {
     Eager,
@@ -342,19 +342,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
 
             recursion_depth_reset = None;
 
-            // Scan the MIR in order to find function calls, closures, and
-            // drop-glue
-            let mir = scx.tcx().item_mir(def_id);
-
-            let empty_substs = scx.empty_substs_for_def_id(def_id);
-            let visitor = MirNeighborCollector {
-                scx: scx,
-                mir: &mir,
-                output: &mut neighbors,
-                param_substs: empty_substs
-            };
-
-            visit_mir_and_promoted(visitor, &mir);
+            collect_neighbours(scx, Instance::mono(scx, def_id), &mut neighbors);
         }
         TransItem::Fn(instance) => {
             // Keep track of the monomorphization recursion depth
@@ -363,18 +351,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
                                                                recursion_depths));
             check_type_length_limit(scx.tcx(), instance);
 
-            // Scan the MIR in order to find function calls, closures, and
-            // drop-glue
-            let mir = scx.tcx().item_mir(instance.def);
-
-            let visitor = MirNeighborCollector {
-                scx: scx,
-                mir: &mir,
-                output: &mut neighbors,
-                param_substs: instance.substs
-            };
-
-            visit_mir_and_promoted(visitor, &mir);
+            collect_neighbours(scx, instance, &mut neighbors);
         }
     }
 
@@ -561,33 +538,12 @@ fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
                     // This is not a callee, but we still have to look for
                     // references to `const` items
                     if let mir::Literal::Item { def_id, substs } = constant.literal {
-                        let tcx = self.scx.tcx();
                         let substs = monomorphize::apply_param_substs(self.scx,
                                                                       self.param_substs,
                                                                       &substs);
 
-                        // If the constant referred to here is an associated
-                        // item of a trait, we need to resolve it to the actual
-                        // constant in the corresponding impl. Luckily
-                        // const_eval::lookup_const_by_id() does that for us.
-                        if let Some((expr, _)) = const_eval::lookup_const_by_id(tcx,
-                                                                                def_id,
-                                                                                Some(substs)) {
-                            // The hir::Expr we get here is the initializer of
-                            // the constant, what we really want is the item
-                            // DefId.
-                            let const_node_id = tcx.map.get_parent(expr.id);
-                            let def_id = if tcx.map.is_inlined_node_id(const_node_id) {
-                                tcx.sess.cstore.defid_for_inlined_node(const_node_id).unwrap()
-                            } else {
-                                tcx.map.local_def_id(const_node_id)
-                            };
-
-                            collect_const_item_neighbours(self.scx,
-                                                          def_id,
-                                                          substs,
-                                                          self.output);
-                        }
+                        let instance = Instance::new(def_id, substs).resolve_const(self.scx);
+                        collect_neighbours(self.scx, instance, self.output);
                     }
 
                     None
@@ -723,23 +679,17 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
 
     debug!("find_drop_glue_neighbors: {}", type_to_string(scx.tcx(), ty));
 
-    // Make sure the exchange_free_fn() lang-item gets translated if
-    // there is a boxed value.
-    if let ty::TyBox(_) = ty.sty {
-        let exchange_free_fn_def_id = scx.tcx()
-                                         .lang_items
-                                         .require(ExchangeFreeFnLangItem)
-                                         .unwrap_or_else(|e| scx.sess().fatal(&e));
-
-        assert!(can_have_local_instance(scx.tcx(), exchange_free_fn_def_id));
-        let fn_substs = scx.empty_substs_for_def_id(exchange_free_fn_def_id);
-        let exchange_free_fn_trans_item =
+    // Make sure the BoxFreeFn lang-item gets translated if there is a boxed value.
+    if let ty::TyBox(content_type) = ty.sty {
+        let def_id = scx.tcx().require_lang_item(BoxFreeFnLangItem);
+        assert!(can_have_local_instance(scx.tcx(), def_id));
+        let box_free_fn_trans_item =
             create_fn_trans_item(scx,
-                                 exchange_free_fn_def_id,
-                                 fn_substs,
+                                 def_id,
+                                 scx.tcx().mk_substs(iter::once(Kind::from(content_type))),
                                  scx.tcx().intern_substs(&[]));
 
-        output.push(exchange_free_fn_trans_item);
+        output.push(box_free_fn_trans_item);
     }
 
     // If the type implements Drop, also add a translation item for the
@@ -1126,6 +1076,11 @@ fn visit_item(&mut self, item: &'v hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _: &'v hir::TraitItem) {
+        // Even if there's a default body with no explicit generics,
+        // it's still generic over some `Self: Trait`, so not a root.
+    }
+
     fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
         match ii.node {
             hir::ImplItemKind::Method(hir::MethodSig {
@@ -1232,29 +1187,20 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, '
     }
 }
 
-// There are no translation items for constants themselves but their
-// initializers might still contain something that produces translation items,
-// such as cast that introduce a new vtable.
-fn collect_const_item_neighbours<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
-                                           def_id: DefId,
-                                           substs: &'tcx Substs<'tcx>,
-                                           output: &mut Vec<TransItem<'tcx>>)
+/// Scan the MIR in order to find function calls, closures, and drop-glue
+fn collect_neighbours<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
+                                instance: Instance<'tcx>,
+                                output: &mut Vec<TransItem<'tcx>>)
 {
-    // Scan the MIR in order to find function calls, closures, and
-    // drop-glue
-    let mir = scx.tcx().item_mir(def_id);
+    let mir = scx.tcx().item_mir(instance.def);
 
-    let visitor = MirNeighborCollector {
+    let mut visitor = MirNeighborCollector {
         scx: scx,
         mir: &mir,
         output: output,
-        param_substs: substs
+        param_substs: instance.substs
     };
 
-    visit_mir_and_promoted(visitor, &mir);
-}
-
-fn visit_mir_and_promoted<'tcx, V: MirVisitor<'tcx>>(mut visitor: V, mir: &mir::Mir<'tcx>) {
     visitor.visit_mir(&mir);
     for promoted in &mir.promoted {
         visitor.visit_mir(promoted);
index f292a70965004c0a2c3964b043d1842cc1889e5b..d9179d6a6fa73888a7f9e4a5c4fad00562364518 100644 (file)
@@ -737,14 +737,6 @@ pub fn drop_glues<'a>(&'a self)
         &self.local().drop_glues
     }
 
-    pub fn local_node_for_inlined_defid<'a>(&'a self, def_id: DefId) -> Option<ast::NodeId> {
-        self.sess().cstore.local_node_for_inlined_defid(def_id)
-    }
-
-    pub fn defid_for_inlined_node<'a>(&'a self, node_id: ast::NodeId) -> Option<DefId> {
-        self.sess().cstore.defid_for_inlined_node(node_id)
-    }
-
     pub fn instances<'a>(&'a self) -> &'a RefCell<FxHashMap<Instance<'tcx>, ValueRef>> {
         &self.local().instances
     }
index 5fb4a0e088f6293c26390662f45501519c89fdec..3989dae553ffca928818fe265bd40b83702ac7f9 100644 (file)
 // Code relating to drop glue.
 
 use std;
+use std::iter;
 
 use llvm;
 use llvm::{ValueRef, get_param};
-use middle::lang_items::ExchangeFreeFnLangItem;
+use middle::lang_items::BoxFreeFnLangItem;
 use rustc::ty::subst::{Substs};
 use rustc::traits;
 use rustc::ty::{self, AdtKind, Ty, TypeFoldable};
-use adt;
+use rustc::ty::subst::Kind;
+use adt::{self, MaybeSizedValue};
 use base::*;
 use callee::Callee;
 use common::*;
 
 use syntax_pos::DUMMY_SP;
 
-pub fn trans_exchange_free_dyn<'a, 'tcx>(
+pub fn trans_exchange_free_ty<'a, 'tcx>(
     bcx: &BlockAndBuilder<'a, 'tcx>,
-    v: ValueRef,
-    size: ValueRef,
-    align: ValueRef
+    ptr: MaybeSizedValue,
+    content_ty: Ty<'tcx>
 ) {
-    let def_id = langcall(bcx.tcx(), None, "", ExchangeFreeFnLangItem);
-    let args = [bcx.pointercast(v, Type::i8p(bcx.ccx)), size, align];
-    let callee = Callee::def(bcx.ccx, def_id, bcx.tcx().intern_substs(&[]));
+    let def_id = langcall(bcx.tcx(), None, "", BoxFreeFnLangItem);
+    let substs = bcx.tcx().mk_substs(iter::once(Kind::from(content_ty)));
+    let callee = Callee::def(bcx.ccx, def_id, substs);
 
-    let ccx = bcx.ccx;
-    let fn_ty = callee.direct_fn_type(ccx, &[]);
+    let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
 
-    let llret = bcx.call(callee.reify(ccx), &args[..], None);
+    let llret = bcx.call(callee.reify(bcx.ccx),
+        &[ptr.value, ptr.meta][..1 + ptr.has_meta() as usize], None);
     fn_ty.apply_attrs_callsite(llret);
 }
 
-pub fn trans_exchange_free_ty<'a, 'tcx>(
-    bcx: &BlockAndBuilder<'a, 'tcx>, ptr: ValueRef, content_ty: Ty<'tcx>
-) {
-    assert!(bcx.ccx.shared().type_is_sized(content_ty));
-    let sizing_type = sizing_type_of(bcx.ccx, content_ty);
-    let content_size = llsize_of_alloc(bcx.ccx, sizing_type);
-
-    // `Box<ZeroSizeType>` does not allocate.
-    if content_size != 0 {
-        let content_align = align_of(bcx.ccx, content_ty);
-        let ccx = bcx.ccx;
-        trans_exchange_free_dyn(bcx, ptr, C_uint(ccx, content_size), C_uint(ccx, content_align));
-    }
-}
-
 pub fn get_drop_glue_type<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty<'tcx> {
     assert!(t.is_normalized_for_trans());
 
@@ -107,13 +93,13 @@ pub fn get_drop_glue_type<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, t: Ty<'t
     }
 }
 
-fn drop_ty<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>, v: ValueRef, t: Ty<'tcx>) {
-    call_drop_glue(bcx, v, t, false, None)
+fn drop_ty<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>, args: MaybeSizedValue, t: Ty<'tcx>) {
+    call_drop_glue(bcx, args, t, false, None)
 }
 
 pub fn call_drop_glue<'a, 'tcx>(
     bcx: &BlockAndBuilder<'a, 'tcx>,
-    v: ValueRef,
+    mut args: MaybeSizedValue,
     t: Ty<'tcx>,
     skip_dtor: bool,
     funclet: Option<&'a Funclet>,
@@ -129,14 +115,13 @@ pub fn call_drop_glue<'a, 'tcx>(
         };
         let glue = get_drop_glue_core(ccx, g);
         let glue_type = get_drop_glue_type(ccx.shared(), t);
-        let ptr = if glue_type != t {
-            bcx.pointercast(v, type_of(ccx, glue_type).ptr_to())
-        } else {
-            v
-        };
+        if glue_type != t {
+            args.value = bcx.pointercast(args.value, type_of(ccx, glue_type).ptr_to());
+        }
 
         // No drop-hint ==> call standard drop glue
-        bcx.call(glue, &[ptr], funclet.map(|b| b.bundle()));
+        bcx.call(glue, &[args.value, args.meta][..1 + args.has_meta() as usize],
+            funclet.map(|b| b.bundle()));
     }
 }
 
@@ -189,7 +174,7 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi
     let (llfn, _) = ccx.drop_glues().borrow().get(&g).unwrap().clone();
 
     let fcx = FunctionContext::new(ccx, llfn);
-    let bcx = fcx.get_entry_block();
+    let mut bcx = fcx.get_entry_block();
 
     ccx.stats().n_glues_created.set(ccx.stats().n_glues_created.get() + 1);
     // All glue functions take values passed *by alias*; this is a
@@ -205,9 +190,15 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi
     // non-null, (and maybe we need to continue doing so), but we now
     // must definitely check for special bit-patterns corresponding to
     // the special dtor markings.
-    let v0 = get_param(llfn, 0);
     let t = g.ty();
 
+    let value = get_param(llfn, 0);
+    let ptr = if ccx.shared().type_is_sized(t) {
+        MaybeSizedValue::sized(value)
+    } else {
+        MaybeSizedValue::unsized_(value, get_param(llfn, 1))
+    };
+
     let skip_dtor = match g {
         DropGlueKind::Ty(_) => false,
         DropGlueKind::TyContents(_) => true
@@ -219,56 +210,76 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi
             // special. It may move to library and have Drop impl. As
             // a safe-guard, assert TyBox not used with TyContents.
             assert!(!skip_dtor);
-            if !bcx.ccx.shared().type_is_sized(content_ty) {
-                let llval = get_dataptr(&bcx, v0);
-                let llbox = bcx.load(llval);
-                drop_ty(&bcx, v0, content_ty);
-                // FIXME(#36457) -- we should pass unsized values to drop glue as two arguments
-                let info = get_meta(&bcx, v0);
-                let info = bcx.load(info);
-                let (llsize, llalign) = size_and_align_of_dst(&bcx, content_ty, info);
-
-                // `Box<ZeroSizeType>` does not allocate.
-                let needs_free = bcx.icmp(llvm::IntNE, llsize, C_uint(bcx.ccx, 0u64));
-                if const_to_opt_uint(needs_free) == Some(0) {
-                    bcx
-                } else {
-                    let next_cx = bcx.fcx().build_new_block("next");
-                    let cond_cx = bcx.fcx().build_new_block("cond");
-                    bcx.cond_br(needs_free, cond_cx.llbb(), next_cx.llbb());
-                    trans_exchange_free_dyn(&cond_cx, llbox, llsize, llalign);
-                    cond_cx.br(next_cx.llbb());
-                    next_cx
-                }
+            let ptr = if !bcx.ccx.shared().type_is_sized(content_ty) {
+                let llbox = bcx.load(get_dataptr(&bcx, ptr.value));
+                let info = bcx.load(get_meta(&bcx, ptr.value));
+                MaybeSizedValue::unsized_(llbox, info)
             } else {
-                let llval = v0;
-                let llbox = bcx.load(llval);
-                drop_ty(&bcx, llbox, content_ty);
-                trans_exchange_free_ty(&bcx, llbox, content_ty);
-                bcx
-            }
+                MaybeSizedValue::sized(bcx.load(ptr.value))
+            };
+            drop_ty(&bcx, ptr, content_ty);
+            trans_exchange_free_ty(&bcx, ptr, content_ty);
+            bcx
         }
         ty::TyDynamic(..) => {
             // No support in vtable for distinguishing destroying with
             // versus without calling Drop::drop. Assert caller is
             // okay with always calling the Drop impl, if any.
-            // FIXME(#36457) -- we should pass unsized values to drop glue as two arguments
             assert!(!skip_dtor);
-            let data_ptr = get_dataptr(&bcx, v0);
-            let vtable_ptr = bcx.load(get_meta(&bcx, v0));
-            let dtor = bcx.load(vtable_ptr);
-            bcx.call(dtor, &[bcx.pointercast(bcx.load(data_ptr), Type::i8p(bcx.ccx))], None);
+            let dtor = bcx.load(ptr.meta);
+            bcx.call(dtor, &[ptr.value], None);
             bcx
         }
         ty::TyAdt(def, ..) if def.dtor_kind().is_present() && !skip_dtor => {
-            trans_custom_dtor(bcx, t, v0, def.is_union())
+            let shallow_drop = def.is_union();
+            let tcx = bcx.tcx();
+
+            let def = t.ty_adt_def().unwrap();
+
+            // Be sure to put the contents into a scope so we can use an invoke
+            // instruction to call the user destructor but still call the field
+            // destructors if the user destructor panics.
+            //
+            // FIXME (#14875) panic-in-drop semantics might be unsupported; we
+            // might well consider changing below to more direct code.
+            // Issue #23611: schedule cleanup of contents, re-inspecting the
+            // discriminant (if any) in case of variant swap in drop code.
+            let contents_scope = if !shallow_drop {
+                bcx.fcx().schedule_drop_adt_contents(ptr, t)
+            } else {
+                CleanupScope::noop()
+            };
+
+            let trait_ref = ty::Binder(ty::TraitRef {
+                def_id: tcx.lang_items.drop_trait().unwrap(),
+                substs: tcx.mk_substs_trait(t, &[])
+            });
+            let vtbl = match fulfill_obligation(bcx.ccx.shared(), DUMMY_SP, trait_ref) {
+                traits::VtableImpl(data) => data,
+                _ => bug!("dtor for {:?} is not an impl???", t)
+            };
+            let dtor_did = def.destructor().unwrap();
+            let callee = Callee::def(bcx.ccx, dtor_did, vtbl.substs);
+            let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
+            let llret;
+            let args = &[ptr.value, ptr.meta][..1 + ptr.has_meta() as usize];
+            if let Some(landing_pad) = contents_scope.landing_pad {
+                let normal_bcx = bcx.fcx().build_new_block("normal-return");
+                llret = bcx.invoke(callee.reify(ccx), args, normal_bcx.llbb(), landing_pad, None);
+                bcx = normal_bcx;
+            } else {
+                llret = bcx.call(callee.reify(bcx.ccx), args, None);
+            }
+            fn_ty.apply_attrs_callsite(llret);
+            contents_scope.trans(&bcx);
+            bcx
         }
         ty::TyAdt(def, ..) if def.is_union() => {
             bcx
         }
         _ => {
             if bcx.ccx.shared().type_needs_drop(t) {
-                drop_structural_ty(bcx, v0, t)
+                drop_structural_ty(bcx, ptr, t)
             } else {
                 bcx
             }
@@ -277,68 +288,6 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi
     bcx.ret_void();
 }
 
-fn trans_custom_dtor<'a, 'tcx>(mut bcx: BlockAndBuilder<'a, 'tcx>,
-                               t: Ty<'tcx>,
-                               v0: ValueRef,
-                               shallow_drop: bool)
-                               -> BlockAndBuilder<'a, 'tcx>
-{
-    debug!("trans_custom_dtor t: {}", t);
-    let tcx = bcx.tcx();
-
-    let def = t.ty_adt_def().unwrap();
-
-    // Be sure to put the contents into a scope so we can use an invoke
-    // instruction to call the user destructor but still call the field
-    // destructors if the user destructor panics.
-    //
-    // FIXME (#14875) panic-in-drop semantics might be unsupported; we
-    // might well consider changing below to more direct code.
-    // Issue #23611: schedule cleanup of contents, re-inspecting the
-    // discriminant (if any) in case of variant swap in drop code.
-    let contents_scope = if !shallow_drop {
-        bcx.fcx().schedule_drop_adt_contents(v0, t)
-    } else {
-        CleanupScope::noop()
-    };
-
-    let (sized_args, unsized_args);
-    let args: &[ValueRef] = if bcx.ccx.shared().type_is_sized(t) {
-        sized_args = [v0];
-        &sized_args
-    } else {
-        // FIXME(#36457) -- we should pass unsized values to drop glue as two arguments
-        unsized_args = [
-            bcx.load(get_dataptr(&bcx, v0)),
-            bcx.load(get_meta(&bcx, v0))
-        ];
-        &unsized_args
-    };
-
-    let trait_ref = ty::Binder(ty::TraitRef {
-        def_id: tcx.lang_items.drop_trait().unwrap(),
-        substs: tcx.mk_substs_trait(t, &[])
-    });
-    let vtbl = match fulfill_obligation(bcx.ccx.shared(), DUMMY_SP, trait_ref) {
-        traits::VtableImpl(data) => data,
-        _ => bug!("dtor for {:?} is not an impl???", t)
-    };
-    let dtor_did = def.destructor().unwrap();
-    let callee = Callee::def(bcx.ccx, dtor_did, vtbl.substs);
-    let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
-    let llret;
-    if let Some(landing_pad) = contents_scope.landing_pad {
-        let normal_bcx = bcx.fcx().build_new_block("normal-return");
-        llret = bcx.invoke(callee.reify(bcx.ccx), args, normal_bcx.llbb(), landing_pad, None);
-        bcx = normal_bcx;
-    } else {
-        llret = bcx.call(callee.reify(bcx.ccx), args, None);
-    }
-    fn_ty.apply_attrs_callsite(llret);
-    contents_scope.trans(&bcx);
-    bcx
-}
-
 pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
                                        t: Ty<'tcx>, info: ValueRef)
                                        -> (ValueRef, ValueRef) {
@@ -448,7 +397,7 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
 
 // Iterates through the elements of a structural type, dropping them.
 fn drop_structural_ty<'a, 'tcx>(cx: BlockAndBuilder<'a, 'tcx>,
-                                av: ValueRef,
+                                ptr: MaybeSizedValue,
                                 t: Ty<'tcx>)
                                 -> BlockAndBuilder<'a, 'tcx> {
     fn iter_variant<'a, 'tcx>(cx: &BlockAndBuilder<'a, 'tcx>,
@@ -460,60 +409,47 @@ fn iter_variant<'a, 'tcx>(cx: &BlockAndBuilder<'a, 'tcx>,
         for (i, field) in variant.fields.iter().enumerate() {
             let arg = monomorphize::field_ty(tcx, substs, field);
             let field_ptr = adt::trans_field_ptr(&cx, t, av, Disr::from(variant.disr_val), i);
-            drop_ty(&cx, field_ptr, arg);
+            drop_ty(&cx, MaybeSizedValue::sized(field_ptr), arg);
         }
     }
 
-    let value = if cx.ccx.shared().type_is_sized(t) {
-        adt::MaybeSizedValue::sized(av)
-    } else {
-        // FIXME(#36457) -- we should pass unsized values as two arguments
-        let data = cx.load(get_dataptr(&cx, av));
-        let info = cx.load(get_meta(&cx, av));
-        adt::MaybeSizedValue::unsized_(data, info)
-    };
-
     let mut cx = cx;
     match t.sty {
         ty::TyClosure(def_id, substs) => {
             for (i, upvar_ty) in substs.upvar_tys(def_id, cx.tcx()).enumerate() {
-                let llupvar = adt::trans_field_ptr(&cx, t, value, Disr(0), i);
-                drop_ty(&cx, llupvar, upvar_ty);
+                let llupvar = adt::trans_field_ptr(&cx, t, ptr, Disr(0), i);
+                drop_ty(&cx, MaybeSizedValue::sized(llupvar), upvar_ty);
             }
         }
         ty::TyArray(_, n) => {
-            let base = get_dataptr(&cx, value.value);
+            let base = get_dataptr(&cx, ptr.value);
             let len = C_uint(cx.ccx, n);
             let unit_ty = t.sequence_element_type(cx.tcx());
-            cx = tvec::slice_for_each(&cx, base, unit_ty, len, |bb, vv| drop_ty(bb, vv, unit_ty));
+            cx = tvec::slice_for_each(&cx, base, unit_ty, len,
+                |bb, vv| drop_ty(bb, MaybeSizedValue::sized(vv), unit_ty));
         }
         ty::TySlice(_) | ty::TyStr => {
             let unit_ty = t.sequence_element_type(cx.tcx());
-            cx = tvec::slice_for_each(&cx, value.value, unit_ty, value.meta,
-                |bb, vv| drop_ty(bb, vv, unit_ty));
+            cx = tvec::slice_for_each(&cx, ptr.value, unit_ty, ptr.meta,
+                |bb, vv| drop_ty(bb, MaybeSizedValue::sized(vv), unit_ty));
         }
         ty::TyTuple(ref args) => {
             for (i, arg) in args.iter().enumerate() {
-                let llfld_a = adt::trans_field_ptr(&cx, t, value, Disr(0), i);
-                drop_ty(&cx, llfld_a, *arg);
+                let llfld_a = adt::trans_field_ptr(&cx, t, ptr, Disr(0), i);
+                drop_ty(&cx, MaybeSizedValue::sized(llfld_a), *arg);
             }
         }
         ty::TyAdt(adt, substs) => match adt.adt_kind() {
             AdtKind::Struct => {
                 let VariantInfo { fields, discr } = VariantInfo::from_ty(cx.tcx(), t, None);
                 for (i, &Field(_, field_ty)) in fields.iter().enumerate() {
-                    let llfld_a = adt::trans_field_ptr(&cx, t, value, Disr::from(discr), i);
-
-                    let val = if cx.ccx.shared().type_is_sized(field_ty) {
-                        llfld_a
+                    let llfld_a = adt::trans_field_ptr(&cx, t, ptr, Disr::from(discr), i);
+                    let ptr = if cx.ccx.shared().type_is_sized(field_ty) {
+                        MaybeSizedValue::sized(llfld_a)
                     } else {
-                        // FIXME(#36457) -- we should pass unsized values as two arguments
-                        let scratch = alloc_ty(&cx, field_ty, "__fat_ptr_iter");
-                        cx.store(llfld_a, get_dataptr(&cx, scratch));
-                        cx.store(value.meta, get_meta(&cx, scratch));
-                        scratch
+                        MaybeSizedValue::unsized_(llfld_a, ptr.meta)
                     };
-                    drop_ty(&cx, val, field_ty);
+                    drop_ty(&cx, ptr, field_ty);
                 }
             }
             AdtKind::Union => {
@@ -525,17 +461,16 @@ fn iter_variant<'a, 'tcx>(cx: &BlockAndBuilder<'a, 'tcx>,
                 // NB: we must hit the discriminant first so that structural
                 // comparison know not to proceed when the discriminants differ.
 
-                match adt::trans_switch(&cx, t, av, false) {
+                match adt::trans_switch(&cx, t, ptr.value, false) {
                     (adt::BranchKind::Single, None) => {
                         if n_variants != 0 {
                             assert!(n_variants == 1);
-                            iter_variant(&cx, t, adt::MaybeSizedValue::sized(av),
-                                            &adt.variants[0], substs);
+                            iter_variant(&cx, t, ptr, &adt.variants[0], substs);
                         }
                     }
                     (adt::BranchKind::Switch, Some(lldiscrim_a)) => {
                         let tcx = cx.tcx();
-                        drop_ty(&cx, lldiscrim_a, tcx.types.isize);
+                        drop_ty(&cx, MaybeSizedValue::sized(lldiscrim_a), tcx.types.isize);
 
                         // Create a fall-through basic block for the "else" case of
                         // the switch instruction we're about to generate. Note that
@@ -561,7 +496,7 @@ fn iter_variant<'a, 'tcx>(cx: &BlockAndBuilder<'a, 'tcx>,
                             let variant_cx = cx.fcx().build_new_block(&variant_cx_name);
                             let case_val = adt::trans_case(&cx, t, Disr::from(variant.disr_val));
                             variant_cx.add_case(llswitch, case_val, variant_cx.llbb());
-                            iter_variant(&variant_cx, t, value, variant, substs);
+                            iter_variant(&variant_cx, t, ptr, variant, substs);
                             variant_cx.br(next_cx.llbb());
                         }
                         cx = next_cx;
index 2fb0e8c24c540de4200c1c78074b316772837125..0d3e1853f011eb001cb0f8219e6cf1996b6c3b5a 100644 (file)
@@ -103,9 +103,12 @@ pub mod back {
 mod cabi_mips;
 mod cabi_mips64;
 mod cabi_msp430;
+mod cabi_nvptx;
+mod cabi_nvptx64;
 mod cabi_powerpc;
 mod cabi_powerpc64;
 mod cabi_s390x;
+mod cabi_sparc;
 mod cabi_x86;
 mod cabi_x86_64;
 mod cabi_x86_win64;
index 5ad52b3d252cb1c29089560b4f651257f850c7d5..71ac7c0d252048ce818eabb0708251b05c073f72 100644 (file)
@@ -14,7 +14,7 @@
 use rustc::ty::{self, layout};
 use rustc::mir;
 use abi::{Abi, FnType, ArgType};
-use adt;
+use adt::{self, MaybeSizedValue};
 use base::{self, Lifetime};
 use callee::{Callee, CalleeData, Fn, Intrinsic, NamedTupleConstructor, Virtual};
 use common::{self, BlockAndBuilder, Funclet};
@@ -38,8 +38,6 @@
 use super::operand::OperandRef;
 use super::operand::OperandValue::{Pair, Ref, Immediate};
 
-use std::ptr;
-
 impl<'a, 'tcx> MirContext<'a, 'tcx> {
     pub fn trans_block(&mut self, bb: mir::BasicBlock,
         funclets: &IndexVec<mir::BasicBlock, Option<Funclet>>) {
@@ -244,35 +242,27 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
                 let lvalue = self.trans_lvalue(&bcx, location);
                 let drop_fn = glue::get_drop_glue(bcx.ccx, ty);
                 let drop_ty = glue::get_drop_glue_type(bcx.ccx.shared(), ty);
-                let is_sized = bcx.ccx.shared().type_is_sized(ty);
-                let llvalue = if is_sized {
-                    if drop_ty != ty {
+                let ptr = if bcx.ccx.shared().type_is_sized(ty) {
+                    let value = if drop_ty != ty {
                         bcx.pointercast(lvalue.llval, type_of::type_of(bcx.ccx, drop_ty).ptr_to())
                     } else {
                         lvalue.llval
-                    }
+                    };
+                    MaybeSizedValue::sized(value)
                 } else {
-                    // FIXME(#36457) Currently drop glue takes sized
-                    // values as a `*(data, meta)`, but elsewhere in
-                    // MIR we pass `(data, meta)` as two separate
-                    // arguments. It would be better to fix drop glue,
-                    // but I am shooting for a quick fix to #35546
-                    // here that can be cleanly backported to beta, so
-                    // I want to avoid touching all of trans.
-                    let scratch = base::alloc_ty(&bcx, ty, "drop");
-                    Lifetime::Start.call(&bcx, scratch);
-                    bcx.store(lvalue.llval, base::get_dataptr(&bcx, scratch));
-                    bcx.store(lvalue.llextra, base::get_meta(&bcx, scratch));
-                    scratch
+                    MaybeSizedValue::unsized_(lvalue.llval, lvalue.llextra)
                 };
+                let args = &[ptr.value, ptr.meta][..1 + ptr.has_meta() as usize];
                 if let Some(unwind) = unwind {
-                    bcx.invoke(drop_fn,
-                               &[llvalue],
-                               self.blocks[target],
-                               llblock(self, unwind),
-                               cleanup_bundle);
+                    bcx.invoke(
+                        drop_fn,
+                        args,
+                        self.blocks[target],
+                        llblock(self, unwind),
+                        cleanup_bundle
+                    );
                 } else {
-                    bcx.call(drop_fn, &[llvalue], cleanup_bundle);
+                    bcx.call(drop_fn, args, cleanup_bundle);
                     funclet_br(self, bcx, target);
                 }
             }
@@ -429,7 +419,7 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
                     }
                     _ => None
                 };
-                let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
+                let mut intrinsic = intrinsic.as_ref().map(|s| &s[..]);
 
                 if intrinsic == Some("move_val_init") {
                     let &(_, target) = destination.as_ref().unwrap();
@@ -441,65 +431,6 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
                     return;
                 }
 
-                // FIXME: This should proxy to the drop glue in the future when the ABI matches;
-                // most of the below code was copied from the match arm for TerminatorKind::Drop.
-                if intrinsic == Some("drop_in_place") {
-                    let &(_, target) = destination.as_ref().unwrap();
-                    let ty = if let ty::TyFnDef(_, substs, _) = callee.ty.sty {
-                        substs.type_at(0)
-                    } else {
-                        bug!("Unexpected ty: {}", callee.ty);
-                    };
-
-                    // Double check for necessity to drop
-                    if !bcx.ccx.shared().type_needs_drop(ty) {
-                        funclet_br(self, bcx, target);
-                        return;
-                    }
-
-                    let ptr = self.trans_operand(&bcx, &args[0]);
-                    let (llval, llextra) = match ptr.val {
-                        Immediate(llptr) => (llptr, ptr::null_mut()),
-                        Pair(llptr, llextra) => (llptr, llextra),
-                        Ref(_) => bug!("Deref of by-Ref type {:?}", ptr.ty)
-                    };
-
-                    let drop_fn = glue::get_drop_glue(bcx.ccx, ty);
-                    let drop_ty = glue::get_drop_glue_type(bcx.ccx.shared(), ty);
-                    let is_sized = bcx.ccx.shared().type_is_sized(ty);
-                    let llvalue = if is_sized {
-                        if drop_ty != ty {
-                            bcx.pointercast(llval, type_of::type_of(bcx.ccx, drop_ty).ptr_to())
-                        } else {
-                            llval
-                        }
-                    } else {
-                        // FIXME(#36457) Currently drop glue takes sized
-                        // values as a `*(data, meta)`, but elsewhere in
-                        // MIR we pass `(data, meta)` as two separate
-                        // arguments. It would be better to fix drop glue,
-                        // but I am shooting for a quick fix to #35546
-                        // here that can be cleanly backported to beta, so
-                        // I want to avoid touching all of trans.
-                        let scratch = base::alloc_ty(&bcx, ty, "drop");
-                        Lifetime::Start.call(&bcx, scratch);
-                        bcx.store(llval, base::get_dataptr(&bcx, scratch));
-                        bcx.store(llextra, base::get_meta(&bcx, scratch));
-                        scratch
-                    };
-                    if let Some(unwind) = *cleanup {
-                        bcx.invoke(drop_fn,
-                            &[llvalue],
-                            self.blocks[target],
-                            llblock(self, unwind),
-                            cleanup_bundle);
-                    } else {
-                        bcx.call(drop_fn, &[llvalue], cleanup_bundle);
-                        funclet_br(self, bcx, target);
-                    }
-                    return;
-                }
-
                 if intrinsic == Some("transmute") {
                     let &(ref dest, target) = destination.as_ref().unwrap();
                     self.with_lvalue_ref(&bcx, dest, |this, dest| {
@@ -517,6 +448,26 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
                 }).collect::<Vec<_>>();
                 let fn_ty = callee.direct_fn_type(bcx.ccx, &extra_args);
 
+                if intrinsic == Some("drop_in_place") {
+                    let &(_, target) = destination.as_ref().unwrap();
+                    let ty = if let ty::TyFnDef(_, substs, _) = callee.ty.sty {
+                        substs.type_at(0)
+                    } else {
+                        bug!("Unexpected ty: {}", callee.ty);
+                    };
+
+                    // Double check for necessity to drop
+                    if !bcx.ccx.shared().type_needs_drop(ty) {
+                        funclet_br(self, bcx, target);
+                        return;
+                    }
+
+                    let drop_fn = glue::get_drop_glue(bcx.ccx, ty);
+                    let llty = fn_ty.llvm_type(bcx.ccx).ptr_to();
+                    callee.data = Fn(bcx.pointercast(drop_fn, llty));
+                    intrinsic = None;
+                }
+
                 // The arguments we'll be passing. Plus one to account for outptr, if used.
                 let arg_count = fn_ty.args.len() + fn_ty.ret.is_indirect() as usize;
                 let mut llargs = Vec::with_capacity(arg_count);
index 08f68f8d49c78a8465ff7c5ec56d239a10e0b729..1cedaa0a4e1a4ee68d9da82dd60fd881c41befff 100644 (file)
@@ -18,7 +18,6 @@
 use rustc::infer::TransNormalize;
 use rustc::mir;
 use rustc::mir::tcx::LvalueTy;
-use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::cast::{CastTy, IntTy};
 use rustc::ty::subst::Substs;
@@ -36,7 +35,7 @@
 use value::Value;
 
 use syntax::ast;
-use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::Span;
 
 use std::fmt;
 use std::ptr;
@@ -238,24 +237,10 @@ fn new(ccx: &'a CrateContext<'a, 'tcx>,
     }
 
     fn trans_def(ccx: &'a CrateContext<'a, 'tcx>,
-                 mut instance: Instance<'tcx>,
+                 instance: Instance<'tcx>,
                  args: IndexVec<mir::Local, Const<'tcx>>)
                  -> Result<Const<'tcx>, ConstEvalErr> {
-        // Try to resolve associated constants.
-        if let Some(trait_id) = ccx.tcx().trait_of_item(instance.def) {
-            let trait_ref = ty::TraitRef::new(trait_id, instance.substs);
-            let trait_ref = ty::Binder(trait_ref);
-            let vtable = common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref);
-            if let traits::VtableImpl(vtable_impl) = vtable {
-                let name = ccx.tcx().item_name(instance.def);
-                let ac = ccx.tcx().associated_items(vtable_impl.impl_def_id)
-                    .find(|item| item.kind == ty::AssociatedKind::Const && item.name == name);
-                if let Some(ac) = ac {
-                    instance = Instance::new(ac.def_id, vtable_impl.substs);
-                }
-            }
-        }
-
+        let instance = instance.resolve_const(ccx.shared());
         let mir = ccx.tcx().item_mir(instance.def);
         MirConstContext::new(ccx, &mir, instance.substs, args).trans()
     }
index 8f05cc793ef224f73b35f4eed64d3273b706874d..4b31d5b7f88de1ac9258351683a9c222e41e8c72 100644 (file)
 use common::*;
 use rustc::hir::def_id::DefId;
 use rustc::infer::TransNormalize;
+use rustc::traits;
 use rustc::ty::fold::{TypeFolder, TypeFoldable};
 use rustc::ty::subst::{Subst, Substs};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::util::ppaux;
 use rustc::util::common::MemoizationMap;
+
+use syntax::codemap::DUMMY_SP;
+
 use std::fmt;
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
@@ -30,15 +34,35 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-impl<'tcx> Instance<'tcx> {
+impl<'a, 'tcx> Instance<'tcx> {
     pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
                -> Instance<'tcx> {
         assert!(substs.regions().all(|&r| r == ty::ReErased));
         Instance { def: def_id, substs: substs }
     }
-    pub fn mono<'a>(scx: &SharedCrateContext<'a, 'tcx>, def_id: DefId) -> Instance<'tcx> {
+
+    pub fn mono(scx: &SharedCrateContext<'a, 'tcx>, def_id: DefId) -> Instance<'tcx> {
         Instance::new(def_id, scx.empty_substs_for_def_id(def_id))
     }
+
+    /// For associated constants from traits, return the impl definition.
+    pub fn resolve_const(&self, scx: &SharedCrateContext<'a, 'tcx>) -> Self {
+        if let Some(trait_id) = scx.tcx().trait_of_item(self.def) {
+            let trait_ref = ty::TraitRef::new(trait_id, self.substs);
+            let trait_ref = ty::Binder(trait_ref);
+            let vtable = fulfill_obligation(scx, DUMMY_SP, trait_ref);
+            if let traits::VtableImpl(vtable_impl) = vtable {
+                let name = scx.tcx().item_name(self.def);
+                let ac = scx.tcx().associated_items(vtable_impl.impl_def_id)
+                    .find(|item| item.kind == ty::AssociatedKind::Const && item.name == name);
+                if let Some(ac) = ac {
+                    return Instance::new(ac.def_id, vtable_impl.substs);
+                }
+            }
+        }
+
+        *self
+    }
 }
 
 /// Monomorphizes a type from the AST by first applying the in-scope
index 527bee832956a7c25d2e76d04a21abc8b1ff2aa0..6e0d8d08e70421152238c4f8f078733a391f755d 100644 (file)
@@ -187,12 +187,11 @@ fn predefine_drop_glue(ccx: &CrateContext<'a, 'tcx>,
         assert_eq!(dg.ty(), glue::get_drop_glue_type(ccx.shared(), dg.ty()));
         let t = dg.ty();
 
-        let sig = tcx.mk_fn_sig(iter::once(tcx.mk_mut_ptr(tcx.types.i8)), tcx.mk_nil(), false);
+        let sig = tcx.mk_fn_sig(iter::once(tcx.mk_mut_ptr(t)), tcx.mk_nil(), false);
 
-        // Create a FnType for fn(*mut i8) and substitute the real type in
-        // later - that prevents FnType from splitting fat pointers up.
-        let mut fn_ty = FnType::new(ccx, Abi::Rust, &sig, &[]);
-        fn_ty.args[0].original_ty = type_of::type_of(ccx, t).ptr_to();
+        debug!("predefine_drop_glue: sig={}", sig);
+
+        let fn_ty = FnType::new(ccx, Abi::Rust, &sig, &[]);
         let llfnty = fn_ty.llvm_type(ccx);
 
         assert!(declare::get_defined_value(ccx, symbol_name).is_none());
index 71270963f8057c4e9618031a0e3860e81e2e0a09..75c25a605af252cd6a57138c857d4cafe6d3b033 100644 (file)
 
 use rustc_const_eval::eval_length;
 use rustc_data_structures::accumulate_vec::AccumulateVec;
-use hir::{self, SelfKind};
+use hir;
 use hir::def::Def;
 use hir::def_id::DefId;
-use hir::print as pprust;
 use middle::resolve_lifetime as rl;
 use rustc::lint;
 use rustc::ty::subst::{Kind, Subst, Substs};
@@ -227,6 +226,7 @@ pub fn ast_region_to_region<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 }
 
 fn report_elision_failure(
+    tcx: TyCtxt,
     db: &mut DiagnosticBuilder,
     params: Vec<ElisionFailureInfo>)
 {
@@ -241,13 +241,14 @@ fn report_elision_failure(
 
     for (i, info) in elided_params.into_iter().enumerate() {
         let ElisionFailureInfo {
-            name, lifetime_count: n, have_bound_regions
+            parent, index, lifetime_count: n, have_bound_regions
         } = info;
 
-        let help_name = if name.is_empty() {
-            format!("argument {}", i + 1)
+        let help_name = if let Some(body) = parent {
+            let arg = &tcx.map.body(body).arguments[index];
+            format!("`{}`", tcx.map.node_to_pretty_string(arg.pat.id))
         } else {
-            format!("`{}`", name)
+            format!("argument {}", index + 1)
         };
 
         m.push_str(&(if n == 1 {
@@ -315,7 +316,7 @@ pub fn opt_ast_region_to_region(&self,
                     err.span_label(ampersand_span, &format!("expected lifetime parameter"));
 
                     if let Some(params) = params {
-                        report_elision_failure(&mut err, params);
+                        report_elision_failure(self.tcx(), &mut err, params);
                     }
                     err.emit();
                     ty::ReStatic
@@ -540,15 +541,16 @@ fn create_substs_for_ast_path(&self,
     /// corresponding to each input type/pattern.
     fn find_implied_output_region<I>(&self,
                                      input_tys: &[Ty<'tcx>],
-                                     input_pats: I) -> ElidedLifetime
-        where I: Iterator<Item=String>
+                                     parent: Option<hir::BodyId>,
+                                     input_indices: I) -> ElidedLifetime
+        where I: Iterator<Item=usize>
     {
         let tcx = self.tcx();
         let mut lifetimes_for_params = Vec::with_capacity(input_tys.len());
         let mut possible_implied_output_region = None;
         let mut lifetimes = 0;
 
-        for input_type in input_tys.iter() {
+        for (input_type, index) in input_tys.iter().zip(input_indices) {
             let mut regions = FxHashSet();
             let have_bound_regions = tcx.collect_regions(input_type, &mut regions);
 
@@ -564,11 +566,9 @@ fn find_implied_output_region<I>(&self,
                 possible_implied_output_region = regions.iter().cloned().next();
             }
 
-            // Use a placeholder for `name` because computing it can be
-            // expensive and we don't want to do it until we know it's
-            // necessary.
             lifetimes_for_params.push(ElisionFailureInfo {
-                name: String::new(),
+                parent: parent,
+                index: index,
                 lifetime_count: regions.len(),
                 have_bound_regions: have_bound_regions
             });
@@ -577,11 +577,6 @@ fn find_implied_output_region<I>(&self,
         if lifetimes == 1 {
             Ok(*possible_implied_output_region.unwrap())
         } else {
-            // Fill in the expensive `name` fields now that we know they're
-            // needed.
-            for (info, input_pat) in lifetimes_for_params.iter_mut().zip(input_pats) {
-                info.name = input_pat;
-            }
             Err(Some(lifetimes_for_params))
         }
     }
@@ -618,8 +613,8 @@ fn convert_parenthesized_parameters(&self,
         let inputs = self.tcx().mk_type_list(data.inputs.iter().map(|a_t| {
             self.ast_ty_arg_to_ty(&binding_rscope, None, region_substs, a_t)
         }));
-        let input_params = iter::repeat(String::new()).take(inputs.len());
-        let implied_output_region = self.find_implied_output_region(&inputs, input_params);
+        let input_params = 0..inputs.len();
+        let implied_output_region = self.find_implied_output_region(&inputs, None, input_params);
 
         let (output, output_span) = match data.output {
             Some(ref output_ty) => {
@@ -689,7 +684,7 @@ fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
             }
             _ => {
                 span_fatal!(self.tcx().sess, path.span, E0245, "`{}` is not a trait",
-                            path);
+                            self.tcx().map.node_to_pretty_string(trait_ref.ref_id));
             }
         }
     }
@@ -976,7 +971,7 @@ fn ast_ty_to_object_trait_ref(&self,
                 let mut err = struct_span_err!(tcx.sess, ty.span, E0178,
                                                "expected a path on the left-hand side \
                                                 of `+`, not `{}`",
-                                               pprust::ty_to_string(ty));
+                                               tcx.map.node_to_pretty_string(ty.id));
                 err.span_label(ty.span, &format!("expected a path"));
                 let hi = bounds.iter().map(|x| match *x {
                     hir::TraitTyParamBound(ref tr, _) => tr.span.hi,
@@ -988,22 +983,21 @@ fn ast_ty_to_object_trait_ref(&self,
                     expn_id: ty.span.expn_id,
                 });
                 match (&ty.node, full_span) {
-                    (&hir::TyRptr(None, ref mut_ty), Some(full_span)) => {
-                        let mutbl_str = if mut_ty.mutbl == hir::MutMutable { "mut " } else { "" };
+                    (&hir::TyRptr(ref lifetime, ref mut_ty), Some(full_span)) => {
+                        let ty_str = hir::print::to_string(&tcx.map, |s| {
+                            use syntax::print::pp::word;
+                            use syntax::print::pprust::PrintState;
+
+                            word(&mut s.s, "&")?;
+                            s.print_opt_lifetime(lifetime)?;
+                            s.print_mutability(mut_ty.mutbl)?;
+                            s.popen()?;
+                            s.print_type(&mut_ty.ty)?;
+                            s.print_bounds(" +", bounds)?;
+                            s.pclose()
+                        });
                         err.span_suggestion(full_span, "try adding parentheses (per RFC 438):",
-                                            format!("&{}({} +{})",
-                                                    mutbl_str,
-                                                    pprust::ty_to_string(&mut_ty.ty),
-                                                    pprust::bounds_to_string(bounds)));
-                    }
-                    (&hir::TyRptr(Some(ref lt), ref mut_ty), Some(full_span)) => {
-                        let mutbl_str = if mut_ty.mutbl == hir::MutMutable { "mut " } else { "" };
-                        err.span_suggestion(full_span, "try adding parentheses (per RFC 438):",
-                                            format!("&{} {}({} +{})",
-                                                    pprust::lifetime_to_string(lt),
-                                                    mutbl_str,
-                                                    pprust::ty_to_string(&mut_ty.ty),
-                                                    pprust::bounds_to_string(bounds)));
+                                            ty_str);
                     }
 
                     _ => {
@@ -1519,14 +1513,7 @@ pub fn def_to_ty(&self,
                 self.set_tainted_by_errors();
                 return self.tcx().types.err;
             }
-            _ => {
-                struct_span_err!(tcx.sess, span, E0248,
-                           "found value `{}` used as a type",
-                            tcx.item_path_str(path.def.def_id()))
-                           .span_label(span, &format!("value used as a type"))
-                           .emit();
-                return self.tcx().types.err;
-            }
+            _ => span_bug!(span, "unexpected definition: {:?}", path.def)
         }
     }
 
@@ -1579,6 +1566,7 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
                                                               bf.abi,
                                                               None,
                                                               &bf.decl,
+                                                              None,
                                                               anon_scope,
                                                               anon_scope);
 
@@ -1671,8 +1659,9 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
                 };
                 self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0
             }
-            hir::TyArray(ref ty, ref e) => {
-                if let Ok(length) = eval_length(tcx.global_tcx(), &e, "array length") {
+            hir::TyArray(ref ty, length) => {
+                let e = &tcx.map.body(length).value;
+                if let Ok(length) = eval_length(tcx.global_tcx(), e, "array length") {
                     tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), length)
                 } else {
                     self.tcx().types.err
@@ -1702,26 +1691,28 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
 
     pub fn ty_of_arg(&self,
                      rscope: &RegionScope,
-                     a: &hir::Arg,
+                     ty: &hir::Ty,
                      expected_ty: Option<Ty<'tcx>>)
                      -> Ty<'tcx>
     {
-        match a.ty.node {
+        match ty.node {
             hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
-            hir::TyInfer => self.ty_infer(a.ty.span),
-            _ => self.ast_ty_to_ty(rscope, &a.ty),
+            hir::TyInfer => self.ty_infer(ty.span),
+            _ => self.ast_ty_to_ty(rscope, ty),
         }
     }
 
     pub fn ty_of_method(&self,
                         sig: &hir::MethodSig,
-                        untransformed_self_ty: Ty<'tcx>,
+                        opt_self_value_ty: Option<Ty<'tcx>>,
+                        body: Option<hir::BodyId>,
                         anon_scope: Option<AnonTypeScope>)
                         -> &'tcx ty::BareFnTy<'tcx> {
         self.ty_of_method_or_bare_fn(sig.unsafety,
                                      sig.abi,
-                                     Some(untransformed_self_ty),
+                                     opt_self_value_ty,
                                      &sig.decl,
+                                     body,
                                      None,
                                      anon_scope)
     }
@@ -1730,16 +1721,18 @@ pub fn ty_of_bare_fn(&self,
                          unsafety: hir::Unsafety,
                          abi: abi::Abi,
                          decl: &hir::FnDecl,
+                         body: hir::BodyId,
                          anon_scope: Option<AnonTypeScope>)
                          -> &'tcx ty::BareFnTy<'tcx> {
-        self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, None, anon_scope)
+        self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, Some(body), None, anon_scope)
     }
 
     fn ty_of_method_or_bare_fn(&self,
                                unsafety: hir::Unsafety,
                                abi: abi::Abi,
-                               opt_untransformed_self_ty: Option<Ty<'tcx>>,
+                               opt_self_value_ty: Option<Ty<'tcx>>,
                                decl: &hir::FnDecl,
+                               body: Option<hir::BodyId>,
                                arg_anon_scope: Option<AnonTypeScope>,
                                ret_anon_scope: Option<AnonTypeScope>)
                                -> &'tcx ty::BareFnTy<'tcx>
@@ -1750,38 +1743,29 @@ fn ty_of_method_or_bare_fn(&self,
         // declaration are bound to that function type.
         let rb = MaybeWithAnonTypes::new(BindingRscope::new(), arg_anon_scope);
 
-        // `implied_output_region` is the region that will be assumed for any
-        // region parameters in the return type. In accordance with the rules for
-        // lifetime elision, we can determine it in two ways. First (determined
-        // here), if self is by-reference, then the implied output region is the
-        // region of the self parameter.
-        let (self_ty, explicit_self) = match (opt_untransformed_self_ty, decl.get_self()) {
-            (Some(untransformed_self_ty), Some(explicit_self)) => {
-                let self_type = self.determine_self_type(&rb, untransformed_self_ty,
-                                                         &explicit_self);
-                (Some(self_type), Some(ExplicitSelf::determine(untransformed_self_ty, self_type)))
-            }
-            _ => (None, None),
-        };
+        let input_tys: Vec<Ty> =
+            decl.inputs.iter().map(|a| self.ty_of_arg(&rb, a, None)).collect();
 
-        // HACK(eddyb) replace the fake self type in the AST with the actual type.
-        let arg_params = if self_ty.is_some() {
-            &decl.inputs[1..]
-        } else {
-            &decl.inputs[..]
-        };
-        let arg_tys: Vec<Ty> =
-            arg_params.iter().map(|a| self.ty_of_arg(&rb, a, None)).collect();
+        let has_self = opt_self_value_ty.is_some();
+        let explicit_self = opt_self_value_ty.map(|self_value_ty| {
+            ExplicitSelf::determine(self_value_ty, input_tys[0])
+        });
 
-        // Second, if there was exactly one lifetime (either a substitution or a
-        // reference) in the arguments, then any anonymous regions in the output
-        // have that lifetime.
         let implied_output_region = match explicit_self {
+            // `implied_output_region` is the region that will be assumed for any
+            // region parameters in the return type. In accordance with the rules for
+            // lifetime elision, we can determine it in two ways. First (determined
+            // here), if self is by-reference, then the implied output region is the
+            // region of the self parameter.
             Some(ExplicitSelf::ByReference(region, _)) => Ok(*region),
+
+            // Second, if there was exactly one lifetime (either a substitution or a
+            // reference) in the arguments, then any anonymous regions in the output
+            // have that lifetime.
             _ => {
-                self.find_implied_output_region(&arg_tys,
-                                                arg_params.iter()
-                                                    .map(|a| pprust::pat_to_string(&a.pat)))
+                let arg_tys = &input_tys[has_self as usize..];
+                let arg_params = has_self as usize..input_tys.len();
+                self.find_implied_output_region(arg_tys, body, arg_params)
 
             }
         };
@@ -1800,37 +1784,13 @@ fn ty_of_method_or_bare_fn(&self,
             unsafety: unsafety,
             abi: abi,
             sig: ty::Binder(self.tcx().mk_fn_sig(
-                self_ty.into_iter().chain(arg_tys),
+                input_tys.into_iter(),
                 output_ty,
                 decl.variadic
             )),
         })
     }
 
-    fn determine_self_type<'a>(&self,
-                               rscope: &RegionScope,
-                               untransformed_self_ty: Ty<'tcx>,
-                               explicit_self: &hir::ExplicitSelf)
-                               -> Ty<'tcx>
-    {
-        match explicit_self.node {
-            SelfKind::Value(..) => untransformed_self_ty,
-            SelfKind::Region(ref lifetime, mutability) => {
-                let region =
-                    self.opt_ast_region_to_region(
-                                             rscope,
-                                             explicit_self.span,
-                                             lifetime);
-                self.tcx().mk_ref(region,
-                    ty::TypeAndMut {
-                        ty: untransformed_self_ty,
-                        mutbl: mutability
-                    })
-            }
-            SelfKind::Explicit(ref ast_type, _) => self.ast_ty_to_ty(rscope, &ast_type)
-        }
-    }
-
     pub fn ty_of_closure(&self,
         unsafety: hir::Unsafety,
         decl: &hir::FnDecl,
index ff50ee11b390e674a703b9cdd9837a22676da5af..9b86196b3ece234b91eb760575bd23989362d14d 100644 (file)
@@ -527,7 +527,8 @@ fn check_pat_path(&self,
         let report_unexpected_def = |def: Def| {
             span_err!(tcx.sess, pat.span, E0533,
                       "expected unit struct/variant or constant, found {} `{}`",
-                      def.kind_name(), qpath);
+                      def.kind_name(),
+                      hir::print::to_string(&tcx.map, |s| s.print_qpath(qpath, false)));
         };
 
         // Resolve the path and check the definition for errors.
@@ -568,7 +569,8 @@ fn check_pat_tuple_struct(&self,
         };
         let report_unexpected_def = |def: Def| {
             let msg = format!("expected tuple struct/variant, found {} `{}`",
-                              def.kind_name(), qpath);
+                              def.kind_name(),
+                              hir::print::to_string(&tcx.map, |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();
             on_error();
index 4fba29def226c6eb0a0ed0fa359962e245eac116..0b9cf38fa073316a3d1adffa112f545029a1a013 100644 (file)
@@ -13,7 +13,6 @@
 use CrateCtxt;
 use hir::def::Def;
 use hir::def_id::{DefId, LOCAL_CRATE};
-use hir::print;
 use rustc::{infer, traits};
 use rustc::ty::{self, LvaluePreference, Ty};
 use syntax::symbol::Symbol;
@@ -203,7 +202,7 @@ fn confirm_builtin_call(&self,
                 if let &ty::TyAdt(adt_def, ..) = t {
                     if adt_def.is_enum() {
                         if let hir::ExprCall(ref expr, _) = call_expr.node {
-                            unit_variant = Some(print::expr_to_string(expr))
+                            unit_variant = Some(self.tcx.map.node_to_pretty_string(expr.id))
                         }
                     }
                 }
index 1d81ed7d35956145de42a0d8d23ab3fb2bb67006..9412c9105c7aa572758785457f3ce5c366622efe 100644 (file)
@@ -25,7 +25,7 @@ pub fn check_expr_closure(&self,
                               expr: &hir::Expr,
                               _capture: hir::CaptureClause,
                               decl: &'gcx hir::FnDecl,
-                              body_id: hir::ExprId,
+                              body_id: hir::BodyId,
                               expected: Expectation<'tcx>)
                               -> Ty<'tcx> {
         debug!("check_expr_closure(expr={:?},expected={:?})",
@@ -39,7 +39,7 @@ pub fn check_expr_closure(&self,
             Some(ty) => self.deduce_expectations_from_expected_type(ty),
             None => (None, None),
         };
-        let body = self.tcx.map.expr(body_id);
+        let body = self.tcx.map.body(body_id);
         self.check_closure(expr, expected_kind, decl, body, expected_sig)
     }
 
@@ -47,7 +47,7 @@ fn check_closure(&self,
                      expr: &hir::Expr,
                      opt_kind: Option<ty::ClosureKind>,
                      decl: &'gcx hir::FnDecl,
-                     body: &'gcx hir::Expr,
+                     body: &'gcx hir::Body,
                      expected_sig: Option<ty::FnSig<'tcx>>)
                      -> Ty<'tcx> {
         debug!("check_closure opt_kind={:?} expected_sig={:?}",
@@ -73,10 +73,10 @@ fn check_closure(&self,
 
         debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type);
 
-        let fn_sig = self.tcx
-            .liberate_late_bound_regions(self.tcx.region_maps.call_site_extent(expr.id, body.id),
-                                         &fn_ty.sig);
-        let fn_sig = (**self).normalize_associated_types_in(body.span, body.id, &fn_sig);
+        let extent = self.tcx.region_maps.call_site_extent(expr.id, body.value.id);
+        let fn_sig = self.tcx.liberate_late_bound_regions(extent, &fn_ty.sig);
+        let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
+                                                            body.value.id, &fn_sig);
 
         check_fn(self,
                  hir::Unsafety::Normal,
@@ -84,7 +84,7 @@ fn check_closure(&self,
                  &fn_sig,
                  decl,
                  expr.id,
-                 &body);
+                 body);
 
         // Tuple up the arguments and insert the resulting function type into
         // the `closures` table.
index 478de1673170f79ea03cb1836a421d3cccf88c19..be10b77bd8b90c33ea0e5ea6c13c28945329a26e 100644 (file)
@@ -8,14 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::hir;
+use rustc::hir::{self, ImplItemKind, TraitItemKind};
 use rustc::infer::{self, InferOk};
 use rustc::middle::free_region::FreeRegionMap;
 use rustc::ty;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
 use rustc::ty::error::{ExpectedFound, TypeError};
 use rustc::ty::subst::{Subst, Substs};
-use rustc::hir::{ImplItemKind, TraitItem_, Ty_};
 use rustc::util::common::ErrorReported;
 
 use syntax::ast;
@@ -450,37 +449,24 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
         TypeError::Mutability => {
             if let Some(trait_m_node_id) = tcx.map.as_local_node_id(trait_m.def_id) {
                 let trait_m_iter = match tcx.map.expect_trait_item(trait_m_node_id).node {
-                    TraitItem_::MethodTraitItem(ref trait_m_sig, _) => {
+                    TraitItemKind::Method(ref trait_m_sig, _) => {
                         trait_m_sig.decl.inputs.iter()
                     }
-                    _ => bug!("{:?} is not a MethodTraitItem", trait_m),
+                    _ => bug!("{:?} is not a TraitItemKind::Method", trait_m),
                 };
 
-                impl_m_iter.zip(trait_m_iter)
-                           .find(|&(ref impl_arg, ref trait_arg)| {
-                               match (&impl_arg.ty.node, &trait_arg.ty.node) {
-                                   (&Ty_::TyRptr(_, ref impl_mt), &Ty_::TyRptr(_, ref trait_mt)) |
-                                   (&Ty_::TyPtr(ref impl_mt), &Ty_::TyPtr(ref trait_mt)) => {
-                                       impl_mt.mutbl != trait_mt.mutbl
-                                   }
-                                   _ => false,
-                               }
-                           })
-                           .map(|(ref impl_arg, ref trait_arg)| {
-                               match (impl_arg.to_self(), trait_arg.to_self()) {
-                                   (Some(impl_self), Some(trait_self)) => {
-                                       (impl_self.span, Some(trait_self.span))
-                                   }
-                                   (None, None) => (impl_arg.ty.span, Some(trait_arg.ty.span)),
-                                   _ => {
-                                       bug!("impl and trait fns have different first args, impl: \
-                                             {:?}, trait: {:?}",
-                                            impl_arg,
-                                            trait_arg)
-                                   }
-                               }
-                           })
-                           .unwrap_or((cause.span, tcx.map.span_if_local(trait_m.def_id)))
+                impl_m_iter.zip(trait_m_iter).find(|&(ref impl_arg, ref trait_arg)| {
+                    match (&impl_arg.node, &trait_arg.node) {
+                        (&hir::TyRptr(_, ref impl_mt), &hir::TyRptr(_, ref trait_mt)) |
+                        (&hir::TyPtr(ref impl_mt), &hir::TyPtr(ref trait_mt)) => {
+                            impl_mt.mutbl != trait_mt.mutbl
+                        }
+                        _ => false,
+                    }
+                }).map(|(ref impl_arg, ref trait_arg)| {
+                    (impl_arg.span, Some(trait_arg.span))
+                })
+                .unwrap_or_else(|| (cause.span, tcx.map.span_if_local(trait_m.def_id)))
             } else {
                 (cause.span, tcx.map.span_if_local(trait_m.def_id))
             }
@@ -489,10 +475,10 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
             if let Some(trait_m_node_id) = tcx.map.as_local_node_id(trait_m.def_id) {
                 let (trait_m_output, trait_m_iter) =
                     match tcx.map.expect_trait_item(trait_m_node_id).node {
-                        TraitItem_::MethodTraitItem(ref trait_m_sig, _) => {
+                        TraitItemKind::Method(ref trait_m_sig, _) => {
                             (&trait_m_sig.decl.output, trait_m_sig.decl.inputs.iter())
                         }
-                        _ => bug!("{:?} is not a MethodTraitItem", trait_m),
+                        _ => bug!("{:?} is not a TraitItemKind::Method", trait_m),
                     };
 
                 let impl_iter = impl_sig.inputs().iter();
@@ -503,7 +489,7 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
                          .filter_map(|(((impl_arg_ty, trait_arg_ty), impl_arg), trait_arg)| {
                              match infcx.sub_types(true, &cause, trait_arg_ty, impl_arg_ty) {
                                  Ok(_) => None,
-                                 Err(_) => Some((impl_arg.ty.span, Some(trait_arg.ty.span))),
+                                 Err(_) => Some((impl_arg.span, Some(trait_arg.span))),
                              }
                          })
                          .next()
@@ -688,13 +674,13 @@ fn compare_number_of_method_arguments<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         let trait_m_node_id = tcx.map.as_local_node_id(trait_m.def_id);
         let trait_span = if let Some(trait_id) = trait_m_node_id {
             match tcx.map.expect_trait_item(trait_id).node {
-                TraitItem_::MethodTraitItem(ref trait_m_sig, _) => {
+                TraitItemKind::Method(ref trait_m_sig, _) => {
                     if let Some(arg) = trait_m_sig.decl.inputs.get(if trait_number_args > 0 {
                         trait_number_args - 1
                     } else {
                         0
                     }) {
-                        Some(arg.pat.span)
+                        Some(arg.span)
                     } else {
                         trait_item_span
                     }
@@ -712,7 +698,7 @@ fn compare_number_of_method_arguments<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 } else {
                     0
                 }) {
-                    arg.pat.span
+                    arg.span
                 } else {
                     impl_m_span
                 }
@@ -839,7 +825,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             // Add a label to the Span containing just the type of the item
             let trait_c_node_id = tcx.map.as_local_node_id(trait_c.def_id).unwrap();
             let trait_c_span = match tcx.map.expect_trait_item(trait_c_node_id).node {
-                TraitItem_::ConstTraitItem(ref ty, _) => ty.span,
+                TraitItemKind::Const(ref ty, _) => ty.span,
                 _ => bug!("{:?} is not a trait const", trait_c),
             };
 
index 183a2a48ff523664a30cf9dd0d165bdefb64244c..c733c0856c6da2d12ad75e949413eef0ff1bfa8a 100644 (file)
@@ -48,7 +48,7 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let i_n_tps = tcx.item_generics(def_id).types.len();
     if i_n_tps != n_tps {
         let span = match it.node {
-            hir::ForeignItemFn(_, ref generics) => generics.span,
+            hir::ForeignItemFn(_, _, ref generics) => generics.span,
             hir::ForeignItemStatic(..) => it.span
         };
 
index 6353b45200bc977db61b89d3b985c86d27fb18eb..9b8e77301e52480f5cb19576ffaaf51a44dec640 100644 (file)
@@ -344,7 +344,7 @@ pub fn resolve_ufcs(&self,
         self.tcx.check_stability(def.def_id(), expr_id, span);
 
         if let probe::InherentImplPick = pick.kind {
-            if !pick.item.vis.is_accessible_from(self.body_id, &self.tcx.map) {
+            if !self.tcx.vis_is_accessible_from(pick.item.vis, self.body_id) {
                 let msg = format!("{} `{}` is private", def.kind_name(), method_name);
                 self.tcx.sess.span_err(span, &msg);
             }
index 06158366f5cda18dd7cbdf28cf337ca4aabffb36..1962534c397166d00861acf6c47ddb9f8095b89a 100644 (file)
@@ -503,7 +503,7 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
                 continue
             }
 
-            if !item.vis.is_accessible_from(self.body_id, &self.tcx.map) {
+            if !self.tcx.vis_is_accessible_from(item.vis, self.body_id) {
                 self.private_candidate = Some(item.def());
                 continue
             }
index 86bfede87b333c6d6e7a7897c8d95d991fdf905c..04ec9292d1410ee727c3684ffe90b060adcb2df1 100644 (file)
@@ -26,7 +26,6 @@
 use errors::DiagnosticBuilder;
 use syntax_pos::Span;
 
-use rustc::hir::print as pprust;
 use rustc::hir;
 use rustc::infer::type_variable::TypeVariableOrigin;
 
@@ -266,7 +265,7 @@ macro_rules! report_function {
                 let msg = if let Some(callee) = rcvr_expr {
                     format!("{}; use overloaded call notation instead (e.g., `{}()`)",
                             msg,
-                            pprust::expr_to_string(callee))
+                            self.tcx.map.node_to_pretty_string(callee.id))
                 } else {
                     msg
                 };
@@ -463,6 +462,9 @@ fn visit_item(&mut self, i: &'v hir::Item) {
                 }
             }
 
+            fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+            }
+
             fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
             }
         }
index 3086721852deb82732883dc9de9e50057d11d718..7275fbd12036b308768b7fc53259bf3c8e28384b 100644 (file)
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir::{self, PatKind};
-use rustc::hir::print as pprust;
 use rustc::middle::lang_items;
 use rustc_back::slice;
 use rustc_const_eval::eval_length;
@@ -550,14 +549,25 @@ fn visit_item(&mut self, i: &'tcx hir::Item) {
 
     fn visit_ty(&mut self, t: &'tcx hir::Ty) {
         match t.node {
-            hir::TyArray(_, ref expr) => {
-                check_const_with_type(self.ccx, &expr, self.ccx.tcx.types.usize, expr.id);
+            hir::TyArray(_, length) => {
+                check_const_with_type(self.ccx, length, self.ccx.tcx.types.usize, length.node_id);
             }
             _ => {}
         }
 
         intravisit::walk_ty(self, t);
     }
+
+    fn visit_expr(&mut self, e: &'tcx hir::Expr) {
+        match e.node {
+            hir::ExprRepeat(_, count) => {
+                check_const_with_type(self.ccx, count, self.ccx.tcx.types.usize, count.node_id);
+            }
+            _ => {}
+        }
+
+        intravisit::walk_expr(self, e);
+    }
 }
 
 impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
@@ -565,6 +575,10 @@ fn visit_item(&mut self, i: &'tcx hir::Item) {
         check_item_body(self.ccx, i);
     }
 
+    fn visit_trait_item(&mut self, _item: &'tcx hir::TraitItem) {
+        // done as part of `visit_item` above
+    }
+
     fn visit_impl_item(&mut self, _item: &'tcx hir::ImplItem) {
         // done as part of `visit_item` above
     }
@@ -635,28 +649,28 @@ pub fn check_drop_impls(ccx: &CrateCtxt) -> CompileResult {
 
 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                            decl: &'tcx hir::FnDecl,
-                           body_id: hir::ExprId,
+                           body_id: hir::BodyId,
                            fn_id: ast::NodeId,
                            span: Span) {
-    let body = ccx.tcx.map.expr(body_id);
+    let body = ccx.tcx.map.body(body_id);
 
     let raw_fty = ccx.tcx.item_type(ccx.tcx.map.local_def_id(fn_id));
     let fn_ty = match raw_fty.sty {
         ty::TyFnDef(.., f) => f,
-        _ => span_bug!(body.span, "check_bare_fn: function type expected")
+        _ => span_bug!(body.value.span, "check_bare_fn: function type expected")
     };
 
     check_abi(ccx, span, fn_ty.abi);
 
     ccx.inherited(fn_id).enter(|inh| {
         // Compute the fty from point of view of inside fn.
-        let fn_scope = inh.tcx.region_maps.call_site_extent(fn_id, body_id.node_id());
+        let fn_scope = inh.tcx.region_maps.call_site_extent(fn_id, body_id.node_id);
         let fn_sig =
             fn_ty.sig.subst(inh.tcx, &inh.parameter_environment.free_substs);
         let fn_sig =
             inh.tcx.liberate_late_bound_regions(fn_scope, &fn_sig);
         let fn_sig =
-            inh.normalize_associated_types_in(body.span, body_id.node_id(), &fn_sig);
+            inh.normalize_associated_types_in(body.value.span, body_id.node_id, &fn_sig);
 
         let fcx = check_fn(&inh, fn_ty.unsafety, fn_id, &fn_sig, decl, fn_id, body);
 
@@ -666,8 +680,8 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         fcx.check_casts();
         fcx.select_all_obligations_or_error(); // Casts can introduce new obligations.
 
-        fcx.regionck_fn(fn_id, decl, body_id);
-        fcx.resolve_type_vars_in_fn(decl, body, fn_id);
+        fcx.regionck_fn(fn_id, body);
+        fcx.resolve_type_vars_in_body(body, fn_id);
     });
 }
 
@@ -736,32 +750,9 @@ fn visit_pat(&mut self, p: &'gcx hir::Pat) {
         intravisit::walk_pat(self, p);
     }
 
-    fn visit_block(&mut self, b: &'gcx hir::Block) {
-        // non-obvious: the `blk` variable maps to region lb, so
-        // we have to keep this up-to-date.  This
-        // is... unfortunate.  It'd be nice to not need this.
-        intravisit::walk_block(self, b);
-    }
-
-    // Since an expr occurs as part of the type fixed size arrays we
-    // need to record the type for that node
-    fn visit_ty(&mut self, t: &'gcx hir::Ty) {
-        match t.node {
-            hir::TyArray(ref ty, ref count_expr) => {
-                self.visit_ty(&ty);
-                self.fcx.check_expr_with_hint(&count_expr, self.fcx.tcx.types.usize);
-            }
-            hir::TyBareFn(ref function_declaration) => {
-                intravisit::walk_fn_decl_nopat(self, &function_declaration.decl);
-                walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes);
-            }
-            _ => intravisit::walk_ty(self, t)
-        }
-    }
-
     // Don't descend into the bodies of nested closures
     fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl,
-                _: hir::ExprId, _: Span, _: ast::NodeId) { }
+                _: hir::BodyId, _: Span, _: ast::NodeId) { }
 }
 
 /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
@@ -776,7 +767,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
                             fn_sig: &ty::FnSig<'tcx>,
                             decl: &'gcx hir::FnDecl,
                             fn_id: ast::NodeId,
-                            body: &'gcx hir::Expr)
+                            body: &'gcx hir::Body)
                             -> FnCtxt<'a, 'gcx, 'tcx>
 {
     let mut fn_sig = fn_sig.clone();
@@ -785,7 +776,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
 
     // Create the function context.  This is either derived from scratch or,
     // in the case of function expressions, based on the outer context.
-    let mut fcx = FnCtxt::new(inherited, None, body.id);
+    let mut fcx = FnCtxt::new(inherited, None, body.value.id);
     let ret_ty = fn_sig.output();
     *fcx.ps.borrow_mut() = UnsafetyState::function(unsafety, unsafety_id);
 
@@ -794,36 +785,26 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
     fn_sig = fcx.tcx.mk_fn_sig(fn_sig.inputs().iter().cloned(), &fcx.ret_ty.unwrap(),
                                fn_sig.variadic);
 
-    {
-        let mut visit = GatherLocalsVisitor { fcx: &fcx, };
-
-        // Add formal parameters.
-        for (arg_ty, input) in fn_sig.inputs().iter().zip(&decl.inputs) {
-            // The type of the argument must be well-formed.
-            //
-            // NB -- this is now checked in wfcheck, but that
-            // currently only results in warnings, so we issue an
-            // old-style WF obligation here so that we still get the
-            // errors that we used to get.
-            fcx.register_old_wf_obligation(arg_ty, input.ty.span, traits::MiscObligation);
-
-            // Create type variables for each argument.
-            input.pat.each_binding(|_bm, pat_id, sp, _path| {
-                let var_ty = visit.assign(sp, pat_id, None);
-                fcx.require_type_is_sized(var_ty, sp, traits::VariableType(pat_id));
-            });
+    GatherLocalsVisitor { fcx: &fcx, }.visit_body(body);
 
-            // Check the pattern.
-            fcx.check_pat(&input.pat, arg_ty);
-            fcx.write_ty(input.id, arg_ty);
-        }
+    // Add formal parameters.
+    for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) {
+        // The type of the argument must be well-formed.
+        //
+        // NB -- this is now checked in wfcheck, but that
+        // currently only results in warnings, so we issue an
+        // old-style WF obligation here so that we still get the
+        // errors that we used to get.
+        fcx.register_old_wf_obligation(arg_ty, arg.pat.span, traits::MiscObligation);
 
-        visit.visit_expr(body);
+        // Check the pattern.
+        fcx.check_pat(&arg.pat, arg_ty);
+        fcx.write_ty(arg.id, arg_ty);
     }
 
     inherited.tables.borrow_mut().liberated_fn_sigs.insert(fn_id, fn_sig);
 
-    fcx.check_expr_coercable_to_type(body, fcx.ret_ty.unwrap());
+    fcx.check_expr_coercable_to_type(&body.value, fcx.ret_ty.unwrap());
 
     fcx
 }
@@ -848,8 +829,8 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
     let _indenter = indenter();
     match it.node {
       // Consts can play a role in type-checking, so they are included here.
-      hir::ItemStatic(.., ref e) |
-      hir::ItemConst(_, ref e) => check_const(ccx, &e, it.id),
+      hir::ItemStatic(.., e) |
+      hir::ItemConst(_, e) => check_const(ccx, e, it.id),
       hir::ItemEnum(ref enum_definition, _) => {
         check_enum_variants(ccx,
                             it.span,
@@ -908,7 +889,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
                     err.emit();
                 }
 
-                if let hir::ForeignItemFn(ref fn_decl, _) = item.node {
+                if let hir::ForeignItemFn(ref fn_decl, _, _) = item.node {
                     require_c_abi_if_variadic(ccx.tcx, fn_decl, m.abi, item.span);
                 }
             }
@@ -933,8 +914,8 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
         for impl_item_ref in impl_item_refs {
             let impl_item = ccx.tcx.map.impl_item(impl_item_ref.id);
             match impl_item.node {
-                hir::ImplItemKind::Const(_, ref expr) => {
-                    check_const(ccx, &expr, impl_item.id)
+                hir::ImplItemKind::Const(_, expr) => {
+                    check_const(ccx, expr, impl_item.id)
                 }
                 hir::ImplItemKind::Method(ref sig, body_id) => {
                     check_bare_fn(ccx, &sig.decl, body_id, impl_item.id, impl_item.span);
@@ -945,18 +926,19 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
             }
         }
       }
-      hir::ItemTrait(.., ref trait_items) => {
-        for trait_item in trait_items {
+      hir::ItemTrait(.., ref trait_item_refs) => {
+        for trait_item_ref in trait_item_refs {
+            let trait_item = ccx.tcx.map.trait_item(trait_item_ref.id);
             match trait_item.node {
-                hir::ConstTraitItem(_, Some(ref expr)) => {
-                    check_const(ccx, &expr, trait_item.id)
+                hir::TraitItemKind::Const(_, Some(expr)) => {
+                    check_const(ccx, expr, trait_item.id)
                 }
-                hir::MethodTraitItem(ref sig, Some(body_id)) => {
+                hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body_id)) => {
                     check_bare_fn(ccx, &sig.decl, body_id, trait_item.id, trait_item.span);
                 }
-                hir::MethodTraitItem(_, None) |
-                hir::ConstTraitItem(_, None) |
-                hir::TypeTraitItem(..) => {
+                hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) |
+                hir::TraitItemKind::Const(_, None) |
+                hir::TraitItemKind::Type(..) => {
                     // Nothing to do.
                 }
             }
@@ -1122,7 +1104,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                         compare_impl_method(ccx,
                                             &ty_impl_item,
                                             impl_item.span,
-                                            body_id.node_id(),
+                                            body_id.node_id,
                                             &ty_trait_item,
                                             impl_trait_ref,
                                             trait_span,
@@ -1132,7 +1114,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             compare_impl_method(ccx,
                                                 &ty_impl_item,
                                                 impl_item.span,
-                                                body_id.node_id(),
+                                                body_id.node_id,
                                                 &ty_trait_item,
                                                 impl_trait_ref,
                                                 trait_span,
@@ -1243,37 +1225,38 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
 /// Checks a constant with a given type.
 fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
-                                   expr: &'tcx hir::Expr,
+                                   body: hir::BodyId,
                                    expected_type: Ty<'tcx>,
                                    id: ast::NodeId) {
+    let body = ccx.tcx.map.body(body);
     ccx.inherited(id).enter(|inh| {
-        let fcx = FnCtxt::new(&inh, None, expr.id);
-        fcx.require_type_is_sized(expected_type, expr.span, traits::ConstSized);
+        let fcx = FnCtxt::new(&inh, None, body.value.id);
+        fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
 
         // Gather locals in statics (because of block expressions).
         // This is technically unnecessary because locals in static items are forbidden,
         // but prevents type checking from blowing up before const checking can properly
         // emit an error.
-        GatherLocalsVisitor { fcx: &fcx }.visit_expr(expr);
+        GatherLocalsVisitor { fcx: &fcx }.visit_body(body);
 
-        fcx.check_expr_coercable_to_type(expr, expected_type);
+        fcx.check_expr_coercable_to_type(&body.value, expected_type);
 
         fcx.select_all_obligations_and_apply_defaults();
-        fcx.closure_analyze(expr);
+        fcx.closure_analyze(body);
         fcx.select_obligations_where_possible();
         fcx.check_casts();
         fcx.select_all_obligations_or_error();
 
-        fcx.regionck_expr(expr);
-        fcx.resolve_type_vars_in_expr(expr, id);
+        fcx.regionck_expr(body);
+        fcx.resolve_type_vars_in_body(body, id);
     });
 }
 
 fn check_const<'a, 'tcx>(ccx: &CrateCtxt<'a,'tcx>,
-                         expr: &'tcx hir::Expr,
+                         body: hir::BodyId,
                          id: ast::NodeId) {
     let decl_ty = ccx.tcx.item_type(ccx.tcx.map.local_def_id(id));
-    check_const_with_type(ccx, expr, decl_ty, id);
+    check_const_with_type(ccx, body, decl_ty, id);
 }
 
 /// Checks whether a type can be represented in memory. In particular, it
@@ -1348,8 +1331,8 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 
     let repr_type_ty = ccx.tcx.enum_repr_type(Some(&hint)).to_ty(ccx.tcx);
     for v in vs {
-        if let Some(ref e) = v.node.disr_expr {
-            check_const_with_type(ccx, e, repr_type_ty, e.id);
+        if let Some(e) = v.node.disr_expr {
+            check_const_with_type(ccx, e, repr_type_ty, e.node_id);
         }
     }
 
@@ -1365,11 +1348,11 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
             let variant_i_node_id = ccx.tcx.map.as_local_node_id(variants[i].did).unwrap();
             let variant_i = ccx.tcx.map.expect_variant(variant_i_node_id);
             let i_span = match variant_i.node.disr_expr {
-                Some(ref expr) => expr.span,
+                Some(expr) => ccx.tcx.map.span(expr.node_id),
                 None => ccx.tcx.map.span(variant_i_node_id)
             };
             let span = match v.node.disr_expr {
-                Some(ref expr) => expr.span,
+                Some(expr) => ccx.tcx.map.span(expr.node_id),
                 None => v.span
             };
             struct_span_err!(ccx.tcx.sess, span, E0081,
@@ -1643,12 +1626,8 @@ pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
         match self.locals.borrow().get(&nid) {
             Some(&t) => t,
             None => {
-                struct_span_err!(self.tcx.sess, span, E0513,
-                                 "no type for local variable {}",
-                                 self.tcx.map.node_to_string(nid))
-                    .span_label(span, &"no type for variable")
-                    .emit();
-                self.tcx.types.err
+                span_bug!(span, "no type for local variable {}",
+                          self.tcx.map.node_to_string(nid));
             }
         }
     }
@@ -3009,7 +2988,7 @@ fn check_field(&self,
                     debug!("struct named {:?}",  base_t);
                     if let Some(field) = base_def.struct_variant().find_field_named(field.node) {
                         let field_ty = self.field_ty(expr.span, field, substs);
-                        if field.vis.is_accessible_from(self.body_id, &self.tcx().map) {
+                        if self.tcx.vis_is_accessible_from(field.vis, self.body_id) {
                             autoderef.finalize(lvalue_pref, Some(base));
                             self.write_autoderef_adjustment(base.id, autoderefs, base_t);
 
@@ -3065,7 +3044,9 @@ fn check_field(&self,
                 }
                 ty::TyRawPtr(..) => {
                     err.note(&format!("`{0}` is a native pointer; perhaps you need to deref with \
-                                      `(*{0}).{1}`", pprust::expr_to_string(base), field.node));
+                                      `(*{0}).{1}`",
+                                      self.tcx.map.node_to_pretty_string(base.id),
+                                      field.node));
                 }
                 _ => {}
             }
@@ -3116,7 +3097,7 @@ fn check_tup_field(&self,
                     base_def.struct_variant().fields.get(idx.node).and_then(|field| {
                         let field_ty = self.field_ty(expr.span, field, substs);
                         private_candidate = Some((base_def.did, field_ty));
-                        if field.vis.is_accessible_from(self.body_id, &self.tcx().map) {
+                        if self.tcx.vis_is_accessible_from(field.vis, self.body_id) {
                             self.tcx.check_stability(field.did, expr.id, expr.span);
                             Some(field_ty)
                         } else {
@@ -3479,11 +3460,8 @@ fn check_expr_with_expectation_and_lvalue_pref(&self,
         self.diverges.set(self.diverges.get() | old_diverges);
         self.has_errors.set(self.has_errors.get() | old_has_errors);
 
-        debug!("type of expr({}) {} is...", expr.id,
-               pprust::expr_to_string(expr));
-        debug!("... {:?}, expected is {:?}",
-               ty,
-               expected);
+        debug!("type of {} is...", self.tcx.map.node_to_string(expr.id));
+        debug!("... {:?}, expected is {:?}", ty, expected);
 
         // Add adjustments to !-expressions
         if ty.is_never() {
@@ -3821,10 +3799,6 @@ fn check_expr_kind(&self,
               self.check_method_call(expr, name, args, &tps[..], expected, lvalue_pref)
           }
           hir::ExprCast(ref e, ref t) => {
-            if let hir::TyArray(_, ref count_expr) = t.node {
-                self.check_expr_with_hint(&count_expr, tcx.types.usize);
-            }
-
             // Find the type of `e`. Supply hints based on the type we are casting to,
             // if appropriate.
             let t_cast = self.to_ty(t);
@@ -3886,9 +3860,9 @@ fn check_expr_kind(&self,
             }
             tcx.mk_array(unified, args.len())
           }
-          hir::ExprRepeat(ref element, ref count_expr) => {
-            self.check_expr_has_type(&count_expr, tcx.types.usize);
-            let count = eval_length(self.tcx.global_tcx(), &count_expr, "repeat count")
+          hir::ExprRepeat(ref element, count) => {
+            let count_expr = &tcx.map.body(count).value;
+            let count = eval_length(self.tcx.global_tcx(), count_expr, "repeat count")
                   .unwrap_or(0);
 
             let uty = match expected {
index eb08e70d4c3e445d0a4da8ae9be41a0f98020fcc..bd63eb6ad25effeb2aa95536a598c8f5b48ba62d 100644 (file)
@@ -113,12 +113,13 @@ macro_rules! ignore_err {
 // PUBLIC ENTRY POINTS
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-    pub fn regionck_expr(&self, e: &'gcx hir::Expr) {
-        let mut rcx = RegionCtxt::new(self, RepeatingScope(e.id), e.id, Subject(e.id));
+    pub fn regionck_expr(&self, body: &'gcx hir::Body) {
+        let id = body.value.id;
+        let mut rcx = RegionCtxt::new(self, RepeatingScope(id), id, Subject(id));
         if self.err_count_since_creation() == 0 {
             // regionck assumes typeck succeeded
-            rcx.visit_expr(e);
-            rcx.visit_region_obligations(e.id);
+            rcx.visit_body(body);
+            rcx.visit_region_obligations(id);
         }
         rcx.resolve_regions_and_report_errors();
     }
@@ -140,15 +141,14 @@ pub fn regionck_item(&self,
 
     pub fn regionck_fn(&self,
                        fn_id: ast::NodeId,
-                       decl: &hir::FnDecl,
-                       body_id: hir::ExprId) {
+                       body: &'gcx hir::Body) {
         debug!("regionck_fn(id={})", fn_id);
-        let node_id = body_id.node_id();
+        let node_id = body.value.id;
         let mut rcx = RegionCtxt::new(self, RepeatingScope(node_id), node_id, Subject(fn_id));
 
         if self.err_count_since_creation() == 0 {
             // regionck assumes typeck succeeded
-            rcx.visit_fn_body(fn_id, decl, body_id, self.tcx.map.span(fn_id));
+            rcx.visit_fn_body(fn_id, body, self.tcx.map.span(fn_id));
         }
 
         rcx.free_region_map.relate_free_regions_from_predicates(
@@ -267,15 +267,16 @@ pub fn resolve_expr_type_adjusted(&mut self, expr: &hir::Expr) -> Ty<'tcx> {
 
     fn visit_fn_body(&mut self,
                      id: ast::NodeId, // the id of the fn itself
-                     fn_decl: &hir::FnDecl,
-                     body_id: hir::ExprId,
+                     body: &'gcx hir::Body,
                      span: Span)
     {
         // When we enter a function, we can derive
         debug!("visit_fn_body(id={})", id);
 
+        let body_id = body.id();
+
         let call_site = self.tcx.region_maps.lookup_code_extent(
-            region::CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id() });
+            region::CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id });
         let old_call_site_scope = self.set_call_site_scope(Some(call_site));
 
         let fn_sig = {
@@ -298,20 +299,18 @@ fn visit_fn_body(&mut self,
         let fn_sig_tys: Vec<_> =
             fn_sig.inputs().iter().cloned().chain(Some(fn_sig.output())).collect();
 
-        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.region_maps.node_extent(body_id.node_id()),
-                          &fn_decl.inputs[..]);
-        let body = self.tcx.map.expr(body_id);
-        self.visit_expr(body);
-        self.visit_region_obligations(body_id.node_id());
+        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.region_maps.node_extent(body_id.node_id), &body.arguments);
+        self.visit_body(body);
+        self.visit_region_obligations(body_id.node_id);
 
         let call_site_scope = self.call_site_scope.unwrap();
-        debug!("visit_fn_body body.id {} call_site_scope: {:?}",
-               body.id, call_site_scope);
+        debug!("visit_fn_body body.id {:?} call_site_scope: {:?}",
+               body.id(), call_site_scope);
         let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope));
         self.type_of_node_must_outlive(infer::CallReturn(span),
-                                       body_id.node_id(),
+                                       body_id.node_id,
                                        call_site_region);
 
         self.region_bound_pairs.truncate(old_region_bounds_pairs_len);
@@ -478,12 +477,13 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
     // regions, until regionck, as described in #3238.
 
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.map)
+        NestedVisitorMap::None
     }
 
-    fn visit_fn(&mut self, _fk: intravisit::FnKind<'gcx>, fd: &'gcx hir::FnDecl,
-                b: hir::ExprId, span: Span, id: ast::NodeId) {
-        self.visit_fn_body(id, fd, b, span)
+    fn visit_fn(&mut self, _fk: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl,
+                b: hir::BodyId, span: Span, id: ast::NodeId) {
+        let body = self.tcx.map.body(b);
+        self.visit_fn_body(id, body, span)
     }
 
     //visit_pat: visit_pat, // (..) see above
@@ -826,8 +826,8 @@ fn walk_cast(&mut self,
 
     fn check_expr_fn_block(&mut self,
                            expr: &'gcx hir::Expr,
-                           body_id: hir::ExprId) {
-        let repeating_scope = self.set_repeating_scope(body_id.node_id());
+                           body_id: hir::BodyId) {
+        let repeating_scope = self.set_repeating_scope(body_id.node_id);
         intravisit::walk_expr(self, expr);
         self.set_repeating_scope(repeating_scope);
     }
@@ -1113,7 +1113,7 @@ fn link_fn_args(&self, body_scope: CodeExtent, args: &[hir::Arg]) {
         for arg in args {
             let arg_ty = self.node_ty(arg.id);
             let re_scope = self.tcx.mk_region(ty::ReScope(body_scope));
-            let arg_cmt = mc.cat_rvalue(arg.id, arg.ty.span, re_scope, arg_ty);
+            let arg_cmt = mc.cat_rvalue(arg.id, arg.pat.span, re_scope, arg_ty);
             debug!("arg_ty={:?} arg_cmt={:?} arg={:?}",
                    arg_ty,
                    arg_cmt,
index 63d20416bded57bddc768bd720962c6975df04b9..5d927a503a116036bbf092882e80dcd4b7b32d4b 100644 (file)
 // PUBLIC ENTRY POINTS
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-    pub fn closure_analyze(&self, body: &'gcx hir::Expr) {
+    pub fn closure_analyze(&self, body: &'gcx hir::Body) {
         let mut seed = SeedBorrowKind::new(self);
-        seed.visit_expr(body);
+        seed.visit_body(body);
 
         let mut adjust = AdjustBorrowKind::new(self, seed.temp_closure_kinds);
-        adjust.visit_expr(body);
+        adjust.visit_body(body);
 
         // it's our job to process these.
         assert!(self.deferred_call_resolutions.borrow().is_empty());
@@ -79,13 +79,15 @@ struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 
 impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
-        NestedVisitorMap::OnlyBodies(&self.fcx.tcx.map)
+        NestedVisitorMap::None
     }
 
     fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
         match expr.node {
             hir::ExprClosure(cc, _, body_id, _) => {
-                self.check_closure(expr, cc, body_id);
+                let body = self.fcx.tcx.map.body(body_id);
+                self.visit_body(body);
+                self.check_closure(expr, cc);
             }
 
             _ => { }
@@ -102,8 +104,7 @@ fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>) -> SeedBorrowKind<'a, 'gcx, 'tcx> {
 
     fn check_closure(&mut self,
                      expr: &hir::Expr,
-                     capture_clause: hir::CaptureClause,
-                     _body_id: hir::ExprId)
+                     capture_clause: hir::CaptureClause)
     {
         let closure_def_id = self.fcx.tcx.map.local_def_id(expr.id);
         if !self.fcx.tables.borrow().closure_kinds.contains_key(&closure_def_id) {
@@ -156,23 +157,21 @@ fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
     fn analyze_closure(&mut self,
                        id: ast::NodeId,
                        span: Span,
-                       decl: &hir::FnDecl,
-                       body_id: hir::ExprId) {
+                       body: &hir::Body) {
         /*!
          * Analysis starting point.
          */
 
-        debug!("analyze_closure(id={:?}, body.id={:?})", id, body_id);
+        debug!("analyze_closure(id={:?}, body.id={:?})", id, body.id());
 
         {
-            let body = self.fcx.tcx.map.expr(body_id);
             let mut euv =
                 euv::ExprUseVisitor::with_options(self,
                                                   self.fcx,
                                                   mc::MemCategorizationOptions {
                                                       during_closure_kind_inference: true
                                                   });
-            euv.walk_fn(decl, body);
+            euv.consume_body(body);
         }
 
         // Now that we've analyzed the closure, we know how each
@@ -491,18 +490,21 @@ fn adjust_closure_kind(&mut self,
 
 impl<'a, 'gcx, 'tcx> Visitor<'gcx> for AdjustBorrowKind<'a, 'gcx, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
-        NestedVisitorMap::OnlyBodies(&self.fcx.tcx.map)
+        NestedVisitorMap::None
     }
 
     fn visit_fn(&mut self,
                 fn_kind: intravisit::FnKind<'gcx>,
                 decl: &'gcx hir::FnDecl,
-                body: hir::ExprId,
+                body: hir::BodyId,
                 span: Span,
                 id: ast::NodeId)
     {
         intravisit::walk_fn(self, fn_kind, decl, body, span, id);
-        self.analyze_closure(id, span, decl, body);
+
+        let body = self.fcx.tcx.map.body(body);
+        self.visit_body(body);
+        self.analyze_closure(id, span, body);
     }
 }
 
index ffdb56753fdc1a028550ff20930843aca48e8334..c80db7fa4d0e02b47c5ab4b2b800f63f8065b886 100644 (file)
@@ -159,10 +159,10 @@ fn check_item_well_formed(&mut self, item: &hir::Item) {
         }
     }
 
-    fn check_trait_or_impl_item(&mut self,
-                                item_id: ast::NodeId,
-                                span: Span,
-                                sig_if_method: Option<&hir::MethodSig>) {
+    fn check_associated_item(&mut self,
+                             item_id: ast::NodeId,
+                             span: Span,
+                             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;
@@ -337,7 +337,7 @@ fn check_trait(&mut self, item: &hir::Item) {
 
     fn check_item_fn(&mut self,
                      item: &hir::Item,
-                     body_id: hir::ExprId)
+                     body_id: hir::BodyId)
     {
         self.for_item(item).with_fcx(|fcx, this| {
             let free_substs = &fcx.parameter_environment.free_substs;
@@ -354,7 +354,7 @@ fn check_item_fn(&mut self,
             let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
 
             let mut implied_bounds = vec![];
-            let free_id_outlive = fcx.tcx.region_maps.call_site_extent(item.id, body_id.node_id());
+            let free_id_outlive = fcx.tcx.region_maps.call_site_extent(item.id, body_id.node_id);
             this.check_fn_or_method(fcx, item.span, bare_fn_ty, &predicates,
                                     free_id_outlive, &mut implied_bounds);
             implied_bounds
@@ -478,7 +478,7 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
             return;
         }
 
-        let span = method_sig.decl.inputs[0].pat.span;
+        let span = method_sig.decl.inputs[0].span;
 
         let free_substs = &fcx.parameter_environment.free_substs;
         let method_ty = fcx.tcx.item_type(method.def_id);
@@ -607,10 +607,10 @@ fn visit_item(&mut self, i: &hir::Item) {
     fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
         debug!("visit_trait_item: {:?}", trait_item);
         let method_sig = match trait_item.node {
-            hir::TraitItem_::MethodTraitItem(ref sig, _) => Some(sig),
+            hir::TraitItemKind::Method(ref sig, _) => Some(sig),
             _ => None
         };
-        self.check_trait_or_impl_item(trait_item.id, trait_item.span, method_sig);
+        self.check_associated_item(trait_item.id, trait_item.span, method_sig);
         intravisit::walk_trait_item(self, trait_item)
     }
 
@@ -620,7 +620,7 @@ fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) {
             hir::ImplItemKind::Method(ref sig, _) => Some(sig),
             _ => None
         };
-        self.check_trait_or_impl_item(impl_item.id, impl_item.span, method_sig);
+        self.check_associated_item(impl_item.id, impl_item.span, method_sig);
         intravisit::walk_impl_item(self, impl_item)
     }
 }
index 56de75995fd2e820bc4929c1a74eeb51ebbaa82f..9a2bfbf715af9785bb6432e24c9264dd63d65459 100644 (file)
 use syntax::ast;
 use syntax_pos::Span;
 
-use rustc::hir::print::pat_to_string;
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
-use rustc::hir::{self, PatKind};
+use rustc::hir;
 
 ///////////////////////////////////////////////////////////////////////////
-// Entry point functions
+// Entry point
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-    pub fn resolve_type_vars_in_expr(&self, e: &'gcx hir::Expr, item_id: ast::NodeId) {
+    pub fn resolve_type_vars_in_body(&self,
+                                     body: &'gcx hir::Body,
+                                     item_id: ast::NodeId) {
         assert_eq!(self.writeback_errors.get(), false);
         let mut wbcx = WritebackCx::new(self);
-        wbcx.visit_expr(e);
-        wbcx.visit_upvar_borrow_map();
-        wbcx.visit_closures();
-        wbcx.visit_liberated_fn_sigs();
-        wbcx.visit_fru_field_types();
-        wbcx.visit_deferred_obligations(item_id);
-        wbcx.visit_type_nodes();
-    }
-
-    pub fn resolve_type_vars_in_fn(&self,
-                                   decl: &'gcx hir::FnDecl,
-                                   body: &'gcx hir::Expr,
-                                   item_id: ast::NodeId) {
-        assert_eq!(self.writeback_errors.get(), false);
-        let mut wbcx = WritebackCx::new(self);
-        wbcx.visit_expr(body);
-        for arg in &decl.inputs {
+        for arg in &body.arguments {
             wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id);
-            wbcx.visit_pat(&arg.pat);
-
-            // Privacy needs the type for the whole pattern, not just each binding
-            if let PatKind::Binding(..) = arg.pat.node {} else {
-                wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.pat.id);
-            }
         }
+        wbcx.visit_body(body);
         wbcx.visit_upvar_borrow_map();
         wbcx.visit_closures();
         wbcx.visit_liberated_fn_sigs();
@@ -188,7 +168,7 @@ fn fix_scalar_binary_expr(&mut self, e: &hir::Expr) {
 
 impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
-        NestedVisitorMap::OnlyBodies(&self.fcx.tcx.map)
+        NestedVisitorMap::None
     }
 
     fn visit_stmt(&mut self, s: &'gcx hir::Stmt) {
@@ -211,10 +191,13 @@ fn visit_expr(&mut self, e: &'gcx hir::Expr) {
         self.visit_method_map_entry(ResolvingExpr(e.span),
                                     MethodCall::expr(e.id));
 
-        if let hir::ExprClosure(_, ref decl, ..) = e.node {
-            for input in &decl.inputs {
-                self.visit_node_id(ResolvingExpr(e.span), input.id);
+        if let hir::ExprClosure(_, _, body, _) = e.node {
+            let body = self.fcx.tcx.map.body(body);
+            for arg in &body.arguments {
+                self.visit_node_id(ResolvingExpr(e.span), arg.id);
             }
+
+            self.visit_body(body);
         }
 
         intravisit::walk_expr(self, e);
@@ -237,7 +220,7 @@ fn visit_pat(&mut self, p: &'gcx hir::Pat) {
         self.visit_node_id(ResolvingPattern(p.span), p.id);
 
         debug!("Type for pattern binding {} (id {}) resolved to {:?}",
-               pat_to_string(p),
+               self.tcx().map.node_to_pretty_string(p.id),
                p.id,
                self.tcx().tables().node_id_to_type(p.id));
 
@@ -254,20 +237,6 @@ fn visit_local(&mut self, l: &'gcx hir::Local) {
         self.write_ty_to_tcx(l.id, var_ty);
         intravisit::walk_local(self, l);
     }
-
-    fn visit_ty(&mut self, t: &'gcx hir::Ty) {
-        match t.node {
-            hir::TyArray(ref ty, ref count_expr) => {
-                self.visit_ty(&ty);
-                self.write_ty_to_tcx(count_expr.id, self.tcx().types.usize);
-            }
-            hir::TyBareFn(ref function_declaration) => {
-                intravisit::walk_fn_decl_nopat(self, &function_declaration.decl);
-                walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes);
-            }
-            _ => intravisit::walk_ty(self, t)
-        }
-    }
 }
 
 impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
index 0034a85f8e29e0b156da2ddf5d281f872b691189..cd9453770a6ab28ff7a3e63af12db965a526fcec 100644 (file)
@@ -50,6 +50,9 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index 0e5a16987c12e408e9315cadd82ca3848872ae16..3bbe5aa1fef376272fd19e28e1f57ae5f4b741ae 100644 (file)
@@ -58,6 +58,9 @@ fn visit_item(&mut self, item: &Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index 2e8206ec959678297bd00f183307b3b857f65ac4..bc1ead07c0ea7f77a042135dab3fbff32825a3eb 100644 (file)
@@ -67,13 +67,15 @@ fn check_primitive_impl(&self,
             }
         }
     }
+}
 
+impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
     /// Checks exactly one impl for orphan rules and other such
     /// restrictions.  In this fn, it can happen that multiple errors
     /// apply to a specific impl, so just return after reporting one
     /// to prevent inundating the user with a bunch of similar error
     /// reports.
-    fn check_item(&self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         let def_id = self.tcx.map.local_def_id(item.id);
         match item.node {
             hir::ItemImpl(.., None, ref ty, _) => {
@@ -368,7 +370,7 @@ fn check_item(&self, item: &hir::Item) {
                                       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",
-                                             item_trait_ref.path))
+                            self.tcx.map.node_to_pretty_string(item_trait_ref.ref_id)))
                         .emit();
                     return;
                 }
@@ -378,11 +380,8 @@ fn check_item(&self, item: &hir::Item) {
             }
         }
     }
-}
 
-impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
-        self.check_item(item);
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
     }
 
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
index 815811675a54bff05321ee3fef482003bb8bf6c7..a09bdf0533a151ecd7373192412932bcf0561d6f 100644 (file)
@@ -205,6 +205,9 @@ fn visit_item(&mut self, item: &'v hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index 6d5de8f250655e614603578355481a5ed210bc34..c4c7c699f65f62ba5c8a74524587d35e9de8e51d 100644 (file)
@@ -107,6 +107,9 @@ fn visit_item(&mut self, item: &'v hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index fba77d171797e1da459a8cb77716523cf671d078..fd51b38e1b557464becb775ed9503b21ed415853 100644 (file)
@@ -82,7 +82,7 @@
 use syntax::symbol::{Symbol, keywords};
 use syntax_pos::Span;
 
-use rustc::hir::{self, map as hir_map, print as pprust};
+use rustc::hir::{self, map as hir_map};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::DefId;
@@ -204,6 +204,13 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
         intravisit::walk_ty(self, ty);
     }
 
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+        self.with_collect_item_sig(trait_item.id, || {
+            convert_trait_item(self.ccx, trait_item)
+        });
+        intravisit::walk_trait_item(self, trait_item);
+    }
+
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
         self.with_collect_item_sig(impl_item.id, || {
             convert_impl_item(self.ccx, impl_item)
@@ -633,7 +640,8 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             id: ast::NodeId,
                             sig: &hir::MethodSig,
                             untransformed_rcvr_ty: Ty<'tcx>,
-                            rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) {
+                            body: Option<hir::BodyId>,
+                            rcvr_ty_predicates: &ty::GenericPredicates<'tcx>,) {
     let def_id = ccx.tcx.map.local_def_id(id);
     let ty_generics = generics_of_def_id(ccx, def_id);
 
@@ -644,8 +652,14 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         ImplContainer(_) => Some(AnonTypeScope::new(def_id)),
         TraitContainer(_) => None
     };
+    let assoc_item = ccx.tcx.associated_item(def_id);
+    let self_value_ty = if assoc_item.method_has_self_argument {
+        Some(untransformed_rcvr_ty)
+    } else {
+        None
+    };
     let fty = AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
-                                    sig, untransformed_rcvr_ty, anon_scope);
+                                    sig, self_value_ty, body, anon_scope);
 
     let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
                                 ccx.tcx.map.span(id), def_id);
@@ -785,56 +799,12 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
 
             tcx.predicates.borrow_mut().insert(def_id, ty_predicates.clone());
         },
-        hir::ItemTrait(.., ref trait_items) => {
+        hir::ItemTrait(..) => {
             generics_of_def_id(ccx, def_id);
             trait_def_of_item(ccx, it);
             let _: Result<(), ErrorReported> = // any error is already reported, can ignore
                 ccx.ensure_super_predicates(it.span, def_id);
             convert_trait_predicates(ccx, it);
-            let trait_predicates = tcx.item_predicates(def_id);
-
-            debug!("convert: trait_bounds={:?}", trait_predicates);
-
-            // FIXME: is the ordering here important? I think it is.
-            let container = TraitContainer(def_id);
-
-            // Convert all the associated constants.
-            for trait_item in trait_items {
-                if let hir::ConstTraitItem(ref ty, _) = trait_item.node {
-                    let const_def_id = ccx.tcx.map.local_def_id(trait_item.id);
-                    generics_of_def_id(ccx, const_def_id);
-                    let ty = ccx.icx(&trait_predicates)
-                        .to_ty(&ExplicitRscope, ty);
-                    tcx.item_types.borrow_mut().insert(const_def_id, ty);
-                    convert_associated_const(ccx, container, trait_item.id, ty)
-                }
-            }
-
-            // Convert all the associated types.
-            for trait_item in trait_items {
-                if let hir::TypeTraitItem(_, ref opt_ty) = trait_item.node {
-                    let type_def_id = ccx.tcx.map.local_def_id(trait_item.id);
-                    generics_of_def_id(ccx, type_def_id);
-
-                    let typ = opt_ty.as_ref().map({
-                        |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
-                    });
-
-                    convert_associated_type(ccx, container, trait_item.id, typ);
-                }
-            }
-
-            // Convert all the methods
-            for trait_item in trait_items {
-                if let hir::MethodTraitItem(ref sig, _) = trait_item.node {
-                    convert_method(ccx,
-                                   container,
-                                   trait_item.id,
-                                   sig,
-                                   tcx.mk_self_type(),
-                                   &trait_predicates);
-                }
-            }
         },
         hir::ItemStruct(ref struct_def, _) |
         hir::ItemUnion(ref struct_def, _) => {
@@ -866,6 +836,48 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
     }
 }
 
+fn convert_trait_item(ccx: &CrateCtxt, trait_item: &hir::TraitItem) {
+    let tcx = ccx.tcx;
+
+    // we can lookup details about the trait because items are visited
+    // before trait-items
+    let trait_def_id = tcx.map.get_parent_did(trait_item.id);
+    let trait_predicates = tcx.item_predicates(trait_def_id);
+
+    match trait_item.node {
+        hir::TraitItemKind::Const(ref ty, _) => {
+            let const_def_id = ccx.tcx.map.local_def_id(trait_item.id);
+            generics_of_def_id(ccx, const_def_id);
+            let ty = ccx.icx(&trait_predicates)
+                        .to_ty(&ExplicitRscope, &ty);
+            tcx.item_types.borrow_mut().insert(const_def_id, ty);
+            convert_associated_const(ccx, TraitContainer(trait_def_id),
+                                     trait_item.id, ty);
+        }
+
+        hir::TraitItemKind::Type(_, ref opt_ty) => {
+            let type_def_id = ccx.tcx.map.local_def_id(trait_item.id);
+            generics_of_def_id(ccx, type_def_id);
+
+            let typ = opt_ty.as_ref().map({
+                |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
+            });
+
+            convert_associated_type(ccx, TraitContainer(trait_def_id), trait_item.id, typ);
+        }
+
+        hir::TraitItemKind::Method(ref sig, ref method) => {
+            let body = match *method {
+                hir::TraitMethod::Required(_) => None,
+                hir::TraitMethod::Provided(body) => Some(body)
+            };
+            convert_method(ccx, TraitContainer(trait_def_id),
+                           trait_item.id, sig, tcx.mk_self_type(),
+                           body, &trait_predicates);
+        }
+    }
+}
+
 fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) {
     let tcx = ccx.tcx;
 
@@ -901,10 +913,10 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) {
             convert_associated_type(ccx, ImplContainer(impl_def_id), impl_item.id, Some(typ));
         }
 
-        hir::ImplItemKind::Method(ref sig, _) => {
+        hir::ImplItemKind::Method(ref sig, body) => {
             convert_method(ccx, ImplContainer(impl_def_id),
                            impl_item.id, sig, impl_self_ty,
-                           &impl_predicates);
+                           Some(body), &impl_predicates);
         }
     }
 }
@@ -1029,7 +1041,7 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, e: &hir::Expr)
                           -> Option<ty::Disr> {
-        debug!("disr expr, checking {}", pprust::expr_to_string(e));
+        debug!("disr expr, checking {}", ccx.tcx.map.node_to_pretty_string(e.id));
 
         let ty_hint = repr_ty.to_ty(ccx.tcx);
         let print_err = |cv: ConstVal| {
@@ -1088,7 +1100,8 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let mut prev_disr = None::<ty::Disr>;
     let variants = def.variants.iter().map(|v| {
         let wrapped_disr = prev_disr.map_or(initial, |d| d.wrap_incr());
-        let disr = if let Some(ref e) = v.node.disr_expr {
+        let disr = if let Some(e) = v.node.disr_expr {
+            let e = &tcx.map.body(e).value;
             evaluate_disr_expr(ccx, repr_type, e)
         } else if let Some(disr) = repr_type.disr_incr(tcx, prev_disr) {
             Some(disr)
@@ -1290,12 +1303,13 @@ fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                                  ast_generics: &hir::Generics,
                                                  trait_predicates: &ty::GenericPredicates<'tcx>,
                                                  self_trait_ref: ty::TraitRef<'tcx>,
-                                                 trait_items: &[hir::TraitItem])
+                                                 trait_item_refs: &[hir::TraitItemRef])
                                                  -> Vec<ty::Predicate<'tcx>>
     {
-        trait_items.iter().flat_map(|trait_item| {
+        trait_item_refs.iter().flat_map(|trait_item_ref| {
+            let trait_item = ccx.tcx.map.trait_item(trait_item_ref.id);
             let bounds = match trait_item.node {
-                hir::TypeTraitItem(ref bounds, _) => bounds,
+                hir::TraitItemKind::Type(ref bounds, _) => bounds,
                 _ => {
                     return vec![].into_iter();
                 }
@@ -1363,7 +1377,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         let ast_generics = match node {
             NodeTraitItem(item) => {
                 match item.node {
-                    MethodTraitItem(ref sig, _) => &sig.generics,
+                    TraitItemKind::Method(ref sig, _) => &sig.generics,
                     _ => &no_generics
                 }
             }
@@ -1420,7 +1434,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             NodeForeignItem(item) => {
                 match item.node {
                     ForeignItemStatic(..) => &no_generics,
-                    ForeignItemFn(_, ref generics) => generics
+                    ForeignItemFn(_, _, ref generics) => generics
                 }
             }
 
@@ -1521,9 +1535,9 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                     ItemStatic(ref t, ..) | ItemConst(ref t, _) => {
                         ccx.icx(&()).to_ty(&StaticRscope::new(&ccx.tcx), &t)
                     }
-                    ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
+                    ItemFn(ref decl, unsafety, _, abi, ref generics, body) => {
                         let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl,
-                                                          Some(AnonTypeScope::new(def_id)));
+                                                          body, Some(AnonTypeScope::new(def_id)));
                         let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id);
                         ccx.tcx.mk_fn_def(def_id, substs, tofd)
                     }
@@ -1563,7 +1577,7 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 let abi = ccx.tcx.map.get_foreign_abi(node_id);
 
                 match foreign_item.node {
-                    ForeignItemFn(ref fn_decl, ref generics) => {
+                    ForeignItemFn(ref fn_decl, _, ref generics) => {
                         compute_type_of_foreign_fn_decl(
                             ccx, ccx.tcx.map.local_def_id(foreign_item.id),
                             fn_decl, generics, abi)
@@ -1628,7 +1642,7 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     let no_generics = hir::Generics::empty();
     let generics = match it.node {
-        hir::ForeignItemFn(_, ref generics) => generics,
+        hir::ForeignItemFn(_, _, ref generics) => generics,
         hir::ForeignItemStatic(..) => &no_generics
     };
 
@@ -2058,13 +2072,13 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
                 ccx.tcx.sess.struct_span_err(ast_ty.span,
                               &format!("use of SIMD type `{}` in FFI is highly experimental and \
                                         may result in invalid code",
-                                       pprust::ty_to_string(ast_ty)))
+                                       ccx.tcx.map.node_to_pretty_string(ast_ty.id)))
                     .help("add #![feature(simd_ffi)] to the crate attributes to enable")
                     .emit();
             }
         };
         for (input, ty) in decl.inputs.iter().zip(&input_tys) {
-            check(&input.ty, ty)
+            check(&input, ty)
         }
         if let hir::Return(ref ty) = decl.output {
             check(&ty, output)
index 71507063ffc43cd8296dc6454a28745e14d2ef21..d3b671f2a4d6e05ee026dd921176c9cbb4bf6ae8 100644 (file)
@@ -1378,8 +1378,8 @@ fn main() {
 
 You have two possibilities to solve this situation:
 
- * Give an explicit definition of the expression
- * Infer the expression
+* Give an explicit definition of the expression
+* Infer the expression
 
 Examples:
 
@@ -2861,25 +2861,6 @@ struct Bar<S, T> { x: Foo<S, T> }
 ```
 "##,
 
-E0248: r##"
-This error indicates an attempt to use a value where a type is expected. For
-example:
-
-```compile_fail,E0248
-enum Foo {
-    Bar(u32)
-}
-
-fn do_something(x: Foo::Bar) { }
-```
-
-In this example, we're attempting to take a type of `Foo::Bar` in the
-do_something function. This is not legal: `Foo::Bar` is a value of type `Foo`,
-not a distinct static type. Likewise, it's not legal to attempt to
-`impl Foo::Bar`: instead, you must `impl Foo` and then pattern match to specify
-behavior for specific enum variants.
-"##,
-
 E0569: r##"
 If an impl has a generic parameter with the `#[may_dangle]` attribute, then
 that impl must be declared as an `unsafe impl. For example:
@@ -3885,45 +3866,6 @@ struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
 ```
 "##,
 
-E0513: r##"
-The type of the variable couldn't be found out.
-
-Erroneous code example:
-
-```compile_fail,E0513
-use std::mem;
-
-unsafe {
-    let size = mem::size_of::<u32>();
-    mem::transmute_copy::<u32, [u8; size]>(&8_8);
-    // error: no type for local variable
-}
-```
-
-To fix this error, please use a constant size instead of `size`. To make
-this error more obvious, you could run:
-
-```compile_fail,E0080
-use std::mem;
-
-unsafe {
-    mem::transmute_copy::<u32, [u8; mem::size_of::<u32>()]>(&8_8);
-    // error: constant evaluation error
-}
-```
-
-So now, you can fix your code by setting the size directly:
-
-```
-use std::mem;
-
-unsafe {
-    mem::transmute_copy::<u32, [u8; 4]>(&8_8);
-    // `u32` is 4 bytes so we replace the `mem::size_of` call with its size
-}
-```
-"##,
-
 E0516: r##"
 The `typeof` keyword is currently reserved but unimplemented.
 Erroneous code example:
@@ -4247,6 +4189,7 @@ fn main() {
     E0245, // not a trait
 //  E0246, // invalid recursive type
 //  E0247,
+//  E0248, // value used as a type, now reported earlier during resolution as E0412
 //  E0249,
 //  E0319, // trait impls for defaulted traits allowed just for structs/enums
     E0320, // recursive overflow during dropck
index 9f5b73d9b30752ed45f31aead3cda46a24e9958b..ce495e6fb4cd8a8cc689a4bcdb54e888e5cebf59 100644 (file)
@@ -87,6 +87,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem) { }
+
     fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) { }
 }
 
index 131ecfc6e0c78339d9ddb0e4972e70a33b081690..3f5e443a20a6854b575a7a57fdf197102483da43 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::ty;
 use rustc::ty::subst::Substs;
 
 #[derive(Clone)]
 pub struct ElisionFailureInfo {
-    pub name: String,
+    /// Where we can find the argument pattern.
+    pub parent: Option<hir::BodyId>,
+    /// The index of the argument in the original definition.
+    pub index: usize,
     pub lifetime_count: usize,
     pub have_bound_regions: bool
 }
index 39f996ee62b541e4d7cc003a54227908c7f73c77..507079a4f874cd93e017458416e75fd1c644695b 100644 (file)
@@ -120,6 +120,9 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index 851cfcd87231f8a8790a1c6fafa1ec75ba1c8d48..d4d3edbcb126e8732f82b03d5ef4e1718a2a758f 100644 (file)
@@ -258,6 +258,9 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index 94e9fdbfc3e2ce703ef67bd07c1d82820e5ff1b8..cba5e1ba6f3184b2f928ce29ed60d915ff5c4726 100644 (file)
@@ -10,6 +10,8 @@
 
 //! Support for inlining external documentation into the current AST.
 
+use std::collections::BTreeMap;
+use std::io;
 use std::iter::once;
 
 use syntax::ast;
 
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::DefId;
-use rustc::hir::print as pprust;
 use rustc::ty;
 use rustc::util::nodemap::FxHashSet;
 
-use rustc_const_eval::lookup_const_by_id;
-
 use core::{DocContext, DocAccessLevels};
 use doctree;
 use clean::{self, GetDefId};
@@ -345,8 +344,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
         match item.kind {
             ty::AssociatedKind::Const => {
                 let default = if item.defaultness.has_value() {
-                    Some(pprust::expr_to_string(
-                        lookup_const_by_id(tcx, item.def_id, None).unwrap().0))
+                    Some(print_inlined_const(cx, item.def_id))
                 } else {
                     None
                 };
@@ -476,17 +474,33 @@ fn fill_in(cx: &DocContext, did: DefId, items: &mut Vec<clean::Item>) {
     }
 }
 
-fn build_const(cx: &DocContext, did: DefId) -> clean::Constant {
-    let (expr, ty) = lookup_const_by_id(cx.tcx, did, None).unwrap_or_else(|| {
-        panic!("expected lookup_const_by_id to succeed for {:?}", did);
-    });
-    debug!("converting constant expr {:?} to snippet", expr);
-    let sn = pprust::expr_to_string(expr);
-    debug!("got snippet {}", sn);
+struct InlinedConst {
+    nested_bodies: BTreeMap<hir::BodyId, hir::Body>
+}
+
+impl hir::print::PpAnn for InlinedConst {
+    fn nested(&self, state: &mut hir::print::State, nested: hir::print::Nested)
+              -> io::Result<()> {
+        if let hir::print::Nested::Body(body) = nested {
+            state.print_expr(&self.nested_bodies[&body].value)
+        } else {
+            Ok(())
+        }
+    }
+}
 
+fn print_inlined_const(cx: &DocContext, did: DefId) -> String {
+    let body = cx.tcx.sess.cstore.maybe_get_item_body(cx.tcx, did).unwrap();
+    let inlined = InlinedConst {
+        nested_bodies: cx.tcx.sess.cstore.item_body_nested_bodies(did)
+    };
+    hir::print::to_string(&inlined, |s| s.print_expr(&body.value))
+}
+
+fn build_const(cx: &DocContext, did: DefId) -> clean::Constant {
     clean::Constant {
-        type_: ty.map(|t| t.clean(cx)).unwrap_or_else(|| cx.tcx.item_type(did).clean(cx)),
-        expr: sn
+        type_: cx.tcx.item_type(did).clean(cx),
+        expr: print_inlined_const(cx, did)
     }
 }
 
index 123516dc89d746fcad14b912ca96e3328c2230d3..3b8281980696d74db037d65b52d3238ec444a7c0 100644 (file)
@@ -32,7 +32,6 @@
 use rustc::middle::lang_items;
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc::hir::print as pprust;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, AdtKind};
 use rustc::middle::stability;
@@ -1030,22 +1029,14 @@ pub struct Method {
     pub abi: Abi,
 }
 
-impl Clean<Method> for hir::MethodSig {
+impl<'a> Clean<Method> for (&'a hir::MethodSig, hir::BodyId) {
     fn clean(&self, cx: &DocContext) -> Method {
-        let decl = FnDecl {
-            inputs: Arguments {
-                values: self.decl.inputs.clean(cx),
-            },
-            output: self.decl.output.clean(cx),
-            variadic: false,
-            attrs: Attributes::default()
-        };
         Method {
-            generics: self.generics.clean(cx),
-            unsafety: self.unsafety,
-            constness: self.constness,
-            decl: decl,
-            abi: self.abi
+            generics: self.0.generics.clean(cx),
+            unsafety: self.0.unsafety,
+            constness: self.0.constness,
+            decl: (&*self.0.decl, self.1).clean(cx),
+            abi: self.0.abi
         }
     }
 }
@@ -1058,25 +1049,6 @@ pub struct TyMethod {
     pub abi: Abi,
 }
 
-impl Clean<TyMethod> for hir::MethodSig {
-    fn clean(&self, cx: &DocContext) -> TyMethod {
-        let decl = FnDecl {
-            inputs: Arguments {
-                values: self.decl.inputs.clean(cx),
-            },
-            output: self.decl.output.clean(cx),
-            variadic: false,
-            attrs: Attributes::default()
-        };
-        TyMethod {
-            unsafety: self.unsafety.clone(),
-            decl: decl,
-            generics: self.generics.clean(cx),
-            abi: self.abi
-        }
-    }
-}
-
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Function {
     pub decl: FnDecl,
@@ -1097,7 +1069,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             deprecation: self.depr.clean(cx),
             def_id: cx.tcx.map.local_def_id(self.id),
             inner: FunctionItem(Function {
-                decl: self.decl.clean(cx),
+                decl: (&self.decl, self.body).clean(cx),
                 generics: self.generics.clean(cx),
                 unsafety: self.unsafety,
                 constness: self.constness,
@@ -1130,14 +1102,47 @@ pub struct Arguments {
     pub values: Vec<Argument>,
 }
 
-impl Clean<FnDecl> for hir::FnDecl {
+impl<'a> Clean<Arguments> for (&'a [P<hir::Ty>], &'a [Spanned<ast::Name>]) {
+    fn clean(&self, cx: &DocContext) -> Arguments {
+        Arguments {
+            values: self.0.iter().enumerate().map(|(i, ty)| {
+                let mut name = self.1.get(i).map(|n| n.node.to_string())
+                                            .unwrap_or(String::new());
+                if name.is_empty() {
+                    name = "_".to_string();
+                }
+                Argument {
+                    name: name,
+                    type_: ty.clean(cx),
+                }
+            }).collect()
+        }
+    }
+}
+
+impl<'a> Clean<Arguments> for (&'a [P<hir::Ty>], hir::BodyId) {
+    fn clean(&self, cx: &DocContext) -> Arguments {
+        let body = cx.tcx.map.body(self.1);
+
+        Arguments {
+            values: self.0.iter().enumerate().map(|(i, ty)| {
+                Argument {
+                    name: name_from_pat(&body.arguments[i].pat),
+                    type_: ty.clean(cx),
+                }
+            }).collect()
+        }
+    }
+}
+
+impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl, A)
+    where (&'a [P<hir::Ty>], A): Clean<Arguments>
+{
     fn clean(&self, cx: &DocContext) -> FnDecl {
         FnDecl {
-            inputs: Arguments {
-                values: self.inputs.clean(cx),
-            },
-            output: self.output.clean(cx),
-            variadic: self.variadic,
+            inputs: (&self.0.inputs[..], self.1).clean(cx),
+            output: self.0.output.clean(cx),
+            variadic: self.0.variadic,
             attrs: Attributes::default()
         }
     }
@@ -1159,7 +1164,6 @@ fn clean(&self, cx: &DocContext) -> FnDecl {
                 values: sig.skip_binder().inputs().iter().map(|t| {
                     Argument {
                         type_: t.clean(cx),
-                        id: ast::CRATE_NODE_ID,
                         name: names.next().map_or("".to_string(), |name| name.to_string()),
                     }
                 }).collect(),
@@ -1172,7 +1176,6 @@ fn clean(&self, cx: &DocContext) -> FnDecl {
 pub struct Argument {
     pub type_: Type,
     pub name: String,
-    pub id: ast::NodeId,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
@@ -1184,26 +1187,17 @@ pub enum SelfTy {
 
 impl Argument {
     pub fn to_self(&self) -> Option<SelfTy> {
-        if self.name == "self" {
-            match self.type_ {
-                Infer => Some(SelfValue),
-                BorrowedRef{ref lifetime, mutability, ref type_} if **type_ == Infer => {
-                    Some(SelfBorrowed(lifetime.clone(), mutability))
-                }
-                _ => Some(SelfExplicit(self.type_.clone()))
-            }
-        } else {
-            None
+        if self.name != "self" {
+            return None;
         }
-    }
-}
-
-impl Clean<Argument> for hir::Arg {
-    fn clean(&self, cx: &DocContext) -> Argument {
-        Argument {
-            name: name_from_pat(&*self.pat),
-            type_: (self.ty.clean(cx)),
-            id: self.id
+        if self.type_.is_self_type() {
+            return Some(SelfValue);
+        }
+        match self.type_ {
+            BorrowedRef{ref lifetime, mutability, ref type_} if type_.is_self_type() => {
+                Some(SelfBorrowed(lifetime.clone(), mutability))
+            }
+            _ => Some(SelfExplicit(self.type_.clone()))
         }
     }
 }
@@ -1269,17 +1263,22 @@ fn clean(&self, cx: &DocContext) -> PolyTrait {
 impl Clean<Item> for hir::TraitItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
-            hir::ConstTraitItem(ref ty, ref default) => {
+            hir::TraitItemKind::Const(ref ty, default) => {
                 AssociatedConstItem(ty.clean(cx),
-                                    default.as_ref().map(|e| pprust::expr_to_string(&e)))
+                                    default.map(|e| print_const_expr(cx, e)))
             }
-            hir::MethodTraitItem(ref sig, Some(_)) => {
-                MethodItem(sig.clean(cx))
+            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
+                MethodItem((sig, body).clean(cx))
             }
-            hir::MethodTraitItem(ref sig, None) => {
-                TyMethodItem(sig.clean(cx))
+            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => {
+                TyMethodItem(TyMethod {
+                    unsafety: sig.unsafety.clone(),
+                    decl: (&*sig.decl, &names[..]).clean(cx),
+                    generics: sig.generics.clean(cx),
+                    abi: sig.abi
+                })
             }
-            hir::TypeTraitItem(ref bounds, ref default) => {
+            hir::TraitItemKind::Type(ref bounds, ref default) => {
                 AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
             }
         };
@@ -1299,12 +1298,12 @@ fn clean(&self, cx: &DocContext) -> Item {
 impl Clean<Item> for hir::ImplItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
-            hir::ImplItemKind::Const(ref ty, ref expr) => {
+            hir::ImplItemKind::Const(ref ty, expr) => {
                 AssociatedConstItem(ty.clean(cx),
-                                    Some(pprust::expr_to_string(expr)))
+                                    Some(print_const_expr(cx, expr)))
             }
-            hir::ImplItemKind::Method(ref sig, _) => {
-                MethodItem(sig.clean(cx))
+            hir::ImplItemKind::Method(ref sig, body) => {
+                MethodItem((sig, body).clean(cx))
             }
             hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef {
                 type_: ty.clean(cx),
@@ -1353,11 +1352,13 @@ fn clean(&self, cx: &DocContext) -> Item {
                     };
                     let self_arg_ty = *fty.sig.input(0).skip_binder();
                     if self_arg_ty == self_ty {
-                        decl.inputs.values[0].type_ = Infer;
+                        decl.inputs.values[0].type_ = Generic(String::from("Self"));
                     } else if let ty::TyRef(_, mt) = self_arg_ty.sty {
                         if mt.ty == self_ty {
                             match decl.inputs.values[0].type_ {
-                                BorrowedRef{ref mut type_, ..} => **type_ = Infer,
+                                BorrowedRef{ref mut type_, ..} => {
+                                    **type_ = Generic(String::from("Self"))
+                                }
                                 _ => unreachable!(),
                             }
                         }
@@ -1568,6 +1569,13 @@ pub fn is_generic(&self) -> bool {
             _ => false,
         }
     }
+
+    pub fn is_self_type(&self) -> bool {
+        match *self {
+            Generic(ref name) => name == "Self",
+            _ => false
+        }
+    }
 }
 
 impl GetDefId for Type {
@@ -1677,11 +1685,12 @@ fn clean(&self, cx: &DocContext) -> Type {
                 BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx),
                              type_: box m.ty.clean(cx)},
             TySlice(ref ty) => Vector(box ty.clean(cx)),
-            TyArray(ref ty, ref e) => {
+            TyArray(ref ty, e) => {
                 use rustc_const_math::{ConstInt, ConstUsize};
                 use rustc_const_eval::eval_const_expr;
                 use rustc::middle::const_val::ConstVal;
 
+                let e = &cx.tcx.map.body(e).value;
                 let n = match eval_const_expr(cx.tcx, e) {
                     ConstVal::Integral(ConstInt::Usize(u)) => match u {
                         ConstUsize::Us16(u) => u.to_string(),
@@ -1737,7 +1746,6 @@ fn clean(&self, cx: &DocContext) -> Type {
                 segments.pop();
                 let trait_path = hir::Path {
                     span: p.span,
-                    global: p.global,
                     def: Def::Trait(cx.tcx.associated_item(p.def.def_id()).container.id()),
                     segments: segments.into(),
                 };
@@ -1756,7 +1764,6 @@ fn clean(&self, cx: &DocContext) -> Type {
                 }
                 let trait_path = hir::Path {
                     span: self.span,
-                    global: false,
                     def: def,
                     segments: vec![].into(),
                 };
@@ -2213,9 +2220,9 @@ pub fn last_name(&self) -> String {
 impl Clean<Path> for hir::Path {
     fn clean(&self, cx: &DocContext) -> Path {
         Path {
-            global: self.global,
+            global: self.is_global(),
             def: self.def,
-            segments: self.segments.clean(cx),
+            segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx),
         }
     }
 }
@@ -2270,24 +2277,19 @@ fn clean(&self, cx: &DocContext) -> PathSegment {
 }
 
 fn qpath_to_string(p: &hir::QPath) -> String {
-    let (segments, global) = match *p {
-        hir::QPath::Resolved(_, ref path) => {
-            (&path.segments, path.global)
-        }
-        hir::QPath::TypeRelative(_, ref segment) => {
-            return segment.name.to_string()
-        }
+    let segments = match *p {
+        hir::QPath::Resolved(_, ref path) => &path.segments,
+        hir::QPath::TypeRelative(_, ref segment) => return segment.name.to_string(),
     };
 
     let mut s = String::new();
-    let mut first = true;
-    for i in segments.iter().map(|x| x.name.as_str()) {
-        if !first || global {
+    for (i, seg) in segments.iter().enumerate() {
+        if i > 0 {
             s.push_str("::");
-        } else {
-            first = false;
         }
-        s.push_str(&i);
+        if seg.name != keywords::CrateRoot.name() {
+            s.push_str(&*seg.name.as_str());
+        }
     }
     s
 }
@@ -2339,7 +2341,7 @@ fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
                 type_params: Vec::new(),
                 where_predicates: Vec::new()
             },
-            decl: self.decl.clean(cx),
+            decl: (&*self.decl, &[][..]).clean(cx),
             abi: self.abi,
         }
     }
@@ -2369,7 +2371,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             inner: StaticItem(Static {
                 type_: self.type_.clean(cx),
                 mutability: self.mutability.clean(cx),
-                expr: pprust::expr_to_string(&self.expr),
+                expr: print_const_expr(cx, self.expr),
             }),
         }
     }
@@ -2393,7 +2395,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             deprecation: self.depr.clean(cx),
             inner: ConstantItem(Constant {
                 type_: self.type_.clean(cx),
-                expr: pprust::expr_to_string(&self.expr),
+                expr: print_const_expr(cx, self.expr),
             }),
         }
     }
@@ -2637,9 +2639,9 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
 impl Clean<Item> for hir::ForeignItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
-            hir::ForeignItemFn(ref decl, ref generics) => {
+            hir::ForeignItemFn(ref decl, ref names, ref generics) => {
                 ForeignFunctionItem(Function {
-                    decl: decl.clean(cx),
+                    decl: (&**decl, &names[..]).clean(cx),
                     generics: generics.clean(cx),
                     unsafety: hir::Unsafety::Unsafe,
                     abi: Abi::Rust,
@@ -2721,6 +2723,10 @@ fn name_from_pat(p: &hir::Pat) -> String {
     }
 }
 
+fn print_const_expr(cx: &DocContext, body: hir::BodyId) -> String {
+    cx.tcx.map.node_to_pretty_string(body.node_id)
+}
+
 /// Given a type Path, resolve it to a Type using the TyCtxt
 fn resolve_type(cx: &DocContext,
                 path: Path,
index 31e10fbd3b7d3e16ca57628798caceba41d79661..d819268240badca941579c315ac882df1194bcd0 100644 (file)
@@ -156,6 +156,7 @@ pub struct Function {
     pub whence: Span,
     pub generics: hir::Generics,
     pub abi: abi::Abi,
+    pub body: hir::BodyId,
 }
 
 pub struct Typedef {
@@ -174,7 +175,7 @@ pub struct Typedef {
 pub struct Static {
     pub type_: P<hir::Ty>,
     pub mutability: hir::Mutability,
-    pub expr: P<hir::Expr>,
+    pub expr: hir::BodyId,
     pub name: Name,
     pub attrs: hir::HirVec<ast::Attribute>,
     pub vis: hir::Visibility,
@@ -186,7 +187,7 @@ pub struct Static {
 
 pub struct Constant {
     pub type_: P<hir::Ty>,
-    pub expr: P<hir::Expr>,
+    pub expr: hir::BodyId,
     pub name: Name,
     pub attrs: hir::HirVec<ast::Attribute>,
     pub vis: hir::Visibility,
index 6dc6e80dae0b81fb926e5238e145fedcb07704ce..796a3a93068c8a5d8886a39b83057594ffdce949 100644 (file)
@@ -207,7 +207,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if !f.alternate() {
             clause.push_str("</span>");
             let plain = format!("{:#}", self);
-            if plain.len() > 80 {
+            if plain.len() + pad > 80 {
                 //break it onto its own line regardless, but make sure method impls and trait
                 //blocks keep their fixed padding (2 and 9, respectively)
                 let padding = if pad > 10 {
index 5353642e294251e6438a843c5a9f38a068f4ccb8..06a816412969bfc7eff9475db1fa481cf7688aff 100644 (file)
@@ -46,6 +46,7 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
 
     <title>{title}</title>
 
+    <link rel="stylesheet" type="text/css" href="{root_path}normalize.css">
     <link rel="stylesheet" type="text/css" href="{root_path}rustdoc.css">
     <link rel="stylesheet" type="text/css" href="{root_path}main.css">
     {css_extension}
index ac336fe45e54a2621a46ef8b2044b845c3369a4f..d66adb5ecfa35afc70bebcea83e3dc0d8fc76464 100644 (file)
@@ -591,7 +591,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
                 ty: item.type_(),
                 name: item.name.clone().unwrap(),
                 path: fqp[..fqp.len() - 1].join("::"),
-                desc: Escape(&shorter(item.doc_value())).to_string(),
+                desc: plain_summary_line(item.doc_value()),
                 parent: Some(did),
                 parent_idx: None,
                 search_type: get_index_search_type(&item),
@@ -629,7 +629,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
     }
 
     let crate_doc = krate.module.as_ref().map(|module| {
-        Escape(&shorter(module.doc_value())).to_string()
+        plain_summary_line(module.doc_value())
     }).unwrap_or(String::new());
 
     let mut crate_data = BTreeMap::new();
@@ -1064,7 +1064,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                             ty: item.type_(),
                             name: s.to_string(),
                             path: path.join("::").to_string(),
-                            desc: Escape(&shorter(item.doc_value())).to_string(),
+                            desc: plain_summary_line(item.doc_value()),
                             parent: parent,
                             parent_idx: None,
                             search_type: get_index_search_type(&item),
@@ -1662,8 +1662,13 @@ fn document_full(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result {
 }
 
 fn document_stability(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Result {
-    for stability in short_stability(item, cx, true) {
-        write!(w, "<div class='stability'>{}</div>", stability)?;
+    let stabilities = short_stability(item, cx, true);
+    if !stabilities.is_empty() {
+        write!(w, "<div class='stability'>")?;
+        for stability in stabilities {
+            write!(w, "{}", stability)?;
+        }
+        write!(w, "</div>")?;
     }
     Ok(())
 }
@@ -1862,7 +1867,7 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
                 String::new()
             };
             let text = format!("Deprecated{}{}", since, Markdown(&deprecated_reason));
-            stability.push(format!("<em class='stab deprecated'>{}</em>", text))
+            stability.push(format!("<div class='stab deprecated'>{}</div>", text))
         };
 
         if stab.level == stability::Unstable {
@@ -1887,7 +1892,7 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
                 String::new()
             };
             let text = format!("Unstable{}{}", unstable_extra, Markdown(&unstable_reason));
-            stability.push(format!("<em class='stab unstable'>{}</em>", text))
+            stability.push(format!("<div class='stab unstable'>{}</div>", text))
         };
     } else if let Some(depr) = item.deprecation.as_ref() {
         let note = if show_reason && !depr.note.is_empty() {
@@ -1902,7 +1907,7 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
         };
 
         let text = format!("Deprecated{}{}", since, Markdown(&note));
-        stability.push(format!("<em class='stab deprecated'>{}</em>", text))
+        stability.push(format!("<div class='stab deprecated'>{}</div>", text))
     }
 
     stability
index 6ea25fa1241f8c447c9e845f87dab6a1de786672..c12e1e7d6080db8739e07db05e9744fd57aa745b 100644 (file)
                               displayPath + '<span class="' + type + '">' +
                               name + '</span></a></td><td>' +
                               '<a href="' + href + '">' +
-                              '<span class="desc">' + item.desc +
+                              '<span class="desc">' + escape(item.desc) +
                               '&nbsp;</span></a></td></tr>';
                 });
             } else {
             search();
         }
 
-        function plainSummaryLine(markdown) {
-            markdown.replace(/\n/g, ' ')
-            .replace(/'/g, "\'")
-            .replace(/^#+? (.+?)/, "$1")
-            .replace(/\[(.*?)\]\(.*?\)/g, "$1")
-            .replace(/\[(.*?)\]\[.*?\]/g, "$1");
-        }
-
         index = buildIndex(rawSearchIndex);
         startSearch();
 
                 if (crates[i] === window.currentCrate) {
                     klass += ' current';
                 }
-                if (rawSearchIndex[crates[i]].items[0]) {
-                    var desc = rawSearchIndex[crates[i]].items[0][3];
-                    var link = $('<a>', {'href': '../' + crates[i] + '/index.html',
-                                         'title': plainSummaryLine(desc),
-                                         'class': klass}).text(crates[i]);
-                    ul.append($('<li>').append(link));
-                }
+                var link = $('<a>', {'href': '../' + crates[i] + '/index.html',
+                                     'title': rawSearchIndex[crates[i]].doc,
+                                     'class': klass}).text(crates[i]);
+                ul.append($('<li>').append(link));
             }
             sidebar.append(div);
         }
index 15912b41d59c061d9db61318a0ad1e486ec7c50c..0ca4f7ea36f1be8cbdf78b7e9edca337174c4c10 100644 (file)
@@ -1,5 +1,3 @@
-@import "normalize.css";
-
 /**
  * Copyright 2013 The Rust Project Developers. See the COPYRIGHT
  * file at the top-level directory of this distribution and at
@@ -525,20 +523,20 @@ body.blur > :not(#help) {
        padding: 20px;
 }
 
-em.stab {
-       display: inline-block;
+.stab {
+       display: table;
        border-width: 1px;
        border-style: solid;
        padding: 3px;
        margin-bottom: 5px;
        font-size: 90%;
-       font-style: normal;
 }
-em.stab p {
+.stab p {
        display: inline;
 }
 
 .module-item .stab {
+       display: inline;
        border-width: 0;
        padding: 0;
        margin: 0;
index 6a9a24f69960a32c0750318e0318389132643a72..862d6d12b9ad99f28489d34bdda597a430fb477e 100644 (file)
@@ -30,10 +30,6 @@ h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.t
     background-color: white;
 }
 
-div.stability > em > code {
-    background-color: initial;
-}
-
 .docblock code, .docblock-short code {
     background-color: #F5F5F5;
 }
@@ -129,5 +125,5 @@ a.test-arrow {
     background-color: white;
 }
 
-em.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
-em.stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
+.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
+.stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
index 835825d31eec98f46e954707fdf3dea03a2e7ff1..47616044879cd0df8396712cb5157048c8654daa 100644 (file)
@@ -267,13 +267,14 @@ pub fn main_args(args: &[String]) -> isize {
     };
     let crate_name = matches.opt_str("crate-name");
     let playground_url = matches.opt_str("playground-url");
+    let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
 
     match (should_test, markdown_input) {
         (true, true) => {
-            return markdown::test(input, cfgs, libs, externs, test_args)
+            return markdown::test(input, cfgs, libs, externs, test_args, maybe_sysroot)
         }
         (true, false) => {
-            return test::run(input, cfgs, libs, externs, test_args, crate_name)
+            return test::run(input, cfgs, libs, externs, test_args, crate_name, maybe_sysroot)
         }
         (false, true) => return markdown::render(input,
                                                  output.unwrap_or(PathBuf::from("doc")),
index 9dbc9d30e606b48851c59384b1d3ff93b5fc2bb9..369e18948ad5b44dbd18e4ad1c0ff8bd8a31b456 100644 (file)
@@ -144,7 +144,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
 
 /// Run any tests/code examples in the markdown file `input`.
 pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
-            mut test_args: Vec<String>) -> isize {
+            mut test_args: Vec<String>, maybe_sysroot: Option<PathBuf>) -> isize {
     let input_str = match load_string(input) {
         Ok(s) => s,
         Err(LoadStringError::ReadFail) => return 1,
@@ -154,7 +154,7 @@ pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
     let mut opts = TestOptions::default();
     opts.no_crate_inject = true;
     let mut collector = Collector::new(input.to_string(), cfgs, libs, externs,
-                                       true, opts);
+                                       true, opts, maybe_sysroot);
     find_testable_code(&input_str, &mut collector);
     test_args.insert(0, "rustdoctest".to_string());
     testing::test_main(&test_args, collector.tests);
index b96a737ed000748706375018180400470455950f..c242eea2362170206e7e33efeb84e2367d184e09 100644 (file)
@@ -54,14 +54,15 @@ pub fn run(input: &str,
            libs: SearchPaths,
            externs: Externs,
            mut test_args: Vec<String>,
-           crate_name: Option<String>)
+           crate_name: Option<String>,
+           maybe_sysroot: Option<PathBuf>)
            -> isize {
     let input_path = PathBuf::from(input);
     let input = config::Input::File(input_path.clone());
 
     let sessopts = config::Options {
-        maybe_sysroot: Some(env::current_exe().unwrap().parent().unwrap()
-                                              .parent().unwrap().to_path_buf()),
+        maybe_sysroot: maybe_sysroot.clone().or_else(
+            || Some(env::current_exe().unwrap().parent().unwrap().parent().unwrap().to_path_buf())),
         search_paths: libs.clone(),
         crate_types: vec![config::CrateTypeDylib],
         externs: externs.clone(),
@@ -99,7 +100,8 @@ pub fn run(input: &str,
                                        libs,
                                        externs,
                                        false,
-                                       opts);
+                                       opts,
+                                       maybe_sysroot);
 
     {
         let dep_graph = DepGraph::new(false);
@@ -157,7 +159,8 @@ fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions {
 fn runtest(test: &str, cratename: &str, cfgs: Vec<String>, libs: SearchPaths,
            externs: Externs,
            should_panic: bool, no_run: bool, as_test_harness: bool,
-           compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions) {
+           compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions,
+           maybe_sysroot: Option<PathBuf>) {
     // the test harness wants its own `main` & top level functions, so
     // never wrap the test in `fn main() { ... }`
     let test = maketest(test, Some(cratename), as_test_harness, opts);
@@ -168,8 +171,8 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec<String>, libs: SearchPaths,
     let outputs = OutputTypes::new(&[(OutputType::Exe, None)]);
 
     let sessopts = config::Options {
-        maybe_sysroot: Some(env::current_exe().unwrap().parent().unwrap()
-                                              .parent().unwrap().to_path_buf()),
+        maybe_sysroot: maybe_sysroot.or_else(
+            || Some(env::current_exe().unwrap().parent().unwrap().parent().unwrap().to_path_buf())),
         search_paths: libs,
         crate_types: vec![config::CrateTypeExecutable],
         output_types: outputs,
@@ -379,11 +382,12 @@ pub struct Collector {
     current_header: Option<String>,
     cratename: String,
     opts: TestOptions,
+    maybe_sysroot: Option<PathBuf>,
 }
 
 impl Collector {
     pub fn new(cratename: String, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
-               use_headers: bool, opts: TestOptions) -> Collector {
+               use_headers: bool, opts: TestOptions, maybe_sysroot: Option<PathBuf>) -> Collector {
         Collector {
             tests: Vec::new(),
             names: Vec::new(),
@@ -395,6 +399,7 @@ pub fn new(cratename: String, cfgs: Vec<String>, libs: SearchPaths, externs: Ext
             current_header: None,
             cratename: cratename,
             opts: opts,
+            maybe_sysroot: maybe_sysroot,
         }
     }
 
@@ -413,6 +418,7 @@ pub fn add_test(&mut self, test: String,
         let externs = self.externs.clone();
         let cratename = self.cratename.to_string();
         let opts = self.opts.clone();
+        let maybe_sysroot = self.maybe_sysroot.clone();
         debug!("Creating test {}: {}", name, test);
         self.tests.push(testing::TestDescAndFn {
             desc: testing::TestDesc {
@@ -432,7 +438,8 @@ pub fn add_test(&mut self, test: String,
                         as_test_harness,
                         compile_fail,
                         error_codes,
-                        &opts);
+                        &opts,
+                        maybe_sysroot);
             })
         });
     }
@@ -495,7 +502,7 @@ fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'thi
 
     fn visit_item(&mut self, item: &'hir hir::Item) {
         let name = if let hir::ItemImpl(.., ref ty, _) = item.node {
-            hir::print::ty_to_string(ty)
+            self.map.node_to_pretty_string(ty.id)
         } else {
             item.name.to_string()
         };
index c93112657b96db239e9b9528f53754f50108919e..b0afc3d63f47932a0bc805092e48eff4ab3af833 100644 (file)
@@ -157,7 +157,8 @@ pub fn visit_fn(&mut self, item: &hir::Item,
                     unsafety: &hir::Unsafety,
                     constness: hir::Constness,
                     abi: &abi::Abi,
-                    gen: &hir::Generics) -> Function {
+                    gen: &hir::Generics,
+                    body: hir::BodyId) -> Function {
         debug!("Visiting fn");
         Function {
             id: item.id,
@@ -172,6 +173,7 @@ pub fn visit_fn(&mut self, item: &hir::Item,
             unsafety: *unsafety,
             constness: constness,
             abi: *abi,
+            body: body,
         }
     }
 
@@ -410,9 +412,9 @@ pub fn visit_item(&mut self, item: &hir::Item,
                 om.structs.push(self.visit_variant_data(item, name, sd, gen)),
             hir::ItemUnion(ref sd, ref gen) =>
                 om.unions.push(self.visit_union_data(item, name, sd, gen)),
-            hir::ItemFn(ref fd, ref unsafety, constness, ref abi, ref gen, _) =>
+            hir::ItemFn(ref fd, ref unsafety, constness, ref abi, ref gen, body) =>
                 om.fns.push(self.visit_fn(item, name, &**fd, unsafety,
-                                          constness, abi, gen)),
+                                          constness, abi, gen, body)),
             hir::ItemTy(ref ty, ref gen) => {
                 let t = Typedef {
                     ty: ty.clone(),
@@ -456,11 +458,14 @@ pub fn visit_item(&mut self, item: &hir::Item,
                 };
                 om.constants.push(s);
             },
-            hir::ItemTrait(unsafety, ref gen, ref b, ref items) => {
+            hir::ItemTrait(unsafety, ref gen, ref b, ref item_ids) => {
+                let items = item_ids.iter()
+                                    .map(|ti| self.cx.tcx.map.trait_item(ti.id).clone())
+                                    .collect();
                 let t = Trait {
                     unsafety: unsafety,
                     name: name,
-                    items: items.clone(),
+                    items: items,
                     generics: gen.clone(),
                     bounds: b.iter().cloned().collect(),
                     id: item.id,
index b3eba508316981682638773827c3e04d9e5d7a82..5e1c3a2851568aef8c15caf46f19488375fa9893 100644 (file)
@@ -26,7 +26,7 @@ fn main() {
     let target = env::var("TARGET").expect("TARGET was not set");
     let host = env::var("HOST").expect("HOST was not set");
     if cfg!(feature = "backtrace") && !target.contains("apple") && !target.contains("msvc") &&
-        !target.contains("emscripten") && !target.contains("fuchsia") {
+        !target.contains("emscripten") && !target.contains("fuchsia") && !target.contains("redox") {
         build_libbacktrace(&host, &target);
     }
 
index 176b5f66fc4e8500ff4d9a8eaf8b740bfeddd13f..41934dc057e37eff774143b916e3924ade13a38a 100644 (file)
 ///
 /// # Examples
 ///
+/// Create a new file and write bytes to it:
+///
 /// ```no_run
+/// use std::fs::File;
 /// use std::io::prelude::*;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// let mut file = try!(File::create("foo.txt"));
+/// try!(file.write_all(b"Hello, world!"));
+/// # Ok(())
+/// # }
+/// ```
+///
+/// Read the contents of a file into a `String`:
+///
+/// ```no_run
 /// use std::fs::File;
+/// use std::io::prelude::*;
 ///
 /// # fn foo() -> std::io::Result<()> {
-/// let mut f = try!(File::create("foo.txt"));
-/// try!(f.write_all(b"Hello, world!"));
+/// let mut file = try!(File::open("foo.txt"));
+/// let mut contents = String::new();
+/// try!(file.read_to_string(&mut contents));
+/// assert_eq!(contents, "Hello, world!");
+/// # Ok(())
+/// # }
+/// ```
+///
+/// It can be more efficient to read the contents of a file with a buffered
+/// [`Read`]er. This can be accomplished with [`BufReader<R>`]:
+///
+/// ```no_run
+/// use std::fs::File;
+/// use std::io::BufReader;
+/// use std::io::prelude::*;
 ///
-/// let mut f = try!(File::open("foo.txt"));
-/// let mut s = String::new();
-/// try!(f.read_to_string(&mut s));
-/// assert_eq!(s, "Hello, world!");
+/// # fn foo() -> std::io::Result<()> {
+/// let file = try!(File::open("foo.txt"));
+/// let mut buf_reader = BufReader::new(file);
+/// let mut contents = String::new();
+/// try!(buf_reader.read_to_string(&mut contents));
+/// assert_eq!(contents, "Hello, world!");
 /// # Ok(())
 /// # }
 /// ```
+///
+/// [`BufReader`]: ../io/struct.BufReader.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct File {
     inner: fs_imp::File,
@@ -1767,6 +1799,16 @@ macro_rules! check { ($e:expr) => (
         }
     ) }
 
+    #[cfg(windows)]
+    macro_rules! error { ($e:expr, $s:expr) => (
+        match $e {
+            Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s),
+            Err(ref err) => assert!(err.raw_os_error() == Some($s),
+                                    format!("`{}` did not have a code of `{}`", err, $s))
+        }
+    ) }
+
+    #[cfg(unix)]
     macro_rules! error { ($e:expr, $s:expr) => (
         match $e {
             Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s),
@@ -1787,12 +1829,9 @@ pub fn got_symlink_permission(tmpdir: &TempDir) -> bool {
 
         match symlink_file(r"nonexisting_target", link) {
             Ok(_) => true,
-            Err(ref err) =>
-                if err.to_string().contains("A required privilege is not held by the client.") {
-                    false
-                } else {
-                    true
-                }
+            // ERROR_PRIVILEGE_NOT_HELD = 1314
+            Err(ref err) if err.raw_os_error() == Some(1314) => false,
+            Err(_) => true,
         }
     }
 
@@ -1823,12 +1862,10 @@ fn invalid_path_raises() {
         let filename = &tmpdir.join("file_that_does_not_exist.txt");
         let result = File::open(filename);
 
-        if cfg!(unix) {
-            error!(result, "No such file or directory");
-        }
-        if cfg!(windows) {
-            error!(result, "The system cannot find the file specified");
-        }
+        #[cfg(unix)]
+        error!(result, "No such file or directory");
+        #[cfg(windows)]
+        error!(result, 2); // ERROR_FILE_NOT_FOUND
     }
 
     #[test]
@@ -1838,12 +1875,10 @@ fn file_test_iounlinking_invalid_path_should_raise_condition() {
 
         let result = fs::remove_file(filename);
 
-        if cfg!(unix) {
-            error!(result, "No such file or directory");
-        }
-        if cfg!(windows) {
-            error!(result, "The system cannot find the file specified");
-        }
+        #[cfg(unix)]
+        error!(result, "No such file or directory");
+        #[cfg(windows)]
+        error!(result, 2); // ERROR_FILE_NOT_FOUND
     }
 
     #[test]
@@ -2598,8 +2633,10 @@ fn c<T: Clone>(t: &T) -> T { t.clone() }
         let mut a = OO::new(); a.append(true);
         let mut ra = OO::new(); ra.read(true).append(true);
 
-        let invalid_options = if cfg!(windows) { "The parameter is incorrect" }
-                              else { "Invalid argument" };
+        #[cfg(windows)]
+        let invalid_options = 87; // ERROR_INVALID_PARAMETER
+        #[cfg(unix)]
+        let invalid_options = "Invalid argument";
 
         // Test various combinations of creation modes and access modes.
         //
index cd7a50d07e268e4ec03d5e882b2b7f846ccc8542..c15a1c8328c03608a64344e0444201cab314dcda 100644 (file)
@@ -652,6 +652,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct LineWriter<W: Write> {
     inner: BufWriter<W>,
+    need_flush: bool,
 }
 
 impl<W: Write> LineWriter<W> {
@@ -692,7 +693,10 @@ pub fn new(inner: W) -> LineWriter<W> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(cap: usize, inner: W) -> LineWriter<W> {
-        LineWriter { inner: BufWriter::with_capacity(cap, inner) }
+        LineWriter {
+            inner: BufWriter::with_capacity(cap, inner),
+            need_flush: false,
+        }
     }
 
     /// Gets a reference to the underlying writer.
@@ -759,7 +763,10 @@ pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() }
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> {
         self.inner.into_inner().map_err(|IntoInnerError(buf, e)| {
-            IntoInnerError(LineWriter { inner: buf }, e)
+            IntoInnerError(LineWriter {
+                inner: buf,
+                need_flush: false,
+            }, e)
         })
     }
 }
@@ -767,20 +774,46 @@ pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<W: Write> Write for LineWriter<W> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        match memchr::memrchr(b'\n', buf) {
-            Some(i) => {
-                let n = self.inner.write(&buf[..i + 1])?;
-                if n != i + 1 || self.inner.flush().is_err() {
-                    // Do not return errors on partial writes.
-                    return Ok(n);
-                }
-                self.inner.write(&buf[i + 1..]).map(|i| n + i)
-            }
-            None => self.inner.write(buf),
+        if self.need_flush {
+            self.flush()?;
+        }
+
+        // Find the last newline character in the buffer provided. If found then
+        // we're going to write all the data up to that point and then flush,
+        // otherewise we just write the whole block to the underlying writer.
+        let i = match memchr::memrchr(b'\n', buf) {
+            Some(i) => i,
+            None => return self.inner.write(buf),
+        };
+
+
+        // Ok, we're going to write a partial amount of the data given first
+        // followed by flushing the newline. After we've successfully written
+        // some data then we *must* report that we wrote that data, so future
+        // errors are ignored. We set our internal `need_flush` flag, though, in
+        // case flushing fails and we need to try it first next time.
+        let n = self.inner.write(&buf[..i + 1])?;
+        self.need_flush = true;
+        if self.flush().is_err() || n != i + 1 {
+            return Ok(n)
+        }
+
+        // At this point we successfully wrote `i + 1` bytes and flushed it out,
+        // meaning that the entire line is now flushed out on the screen. While
+        // we can attempt to finish writing the rest of the data provided.
+        // Remember though that we ignore errors here as we've successfully
+        // written data, so we need to report that.
+        match self.inner.write(&buf[i + 1..]) {
+            Ok(i) => Ok(n + i),
+            Err(_) => Ok(n),
         }
     }
 
-    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
+    fn flush(&mut self) -> io::Result<()> {
+        self.inner.flush()?;
+        self.need_flush = false;
+        Ok(())
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1153,4 +1186,44 @@ fn bench_buffered_writer(b: &mut test::Bencher) {
             BufWriter::new(io::sink())
         });
     }
+
+    struct AcceptOneThenFail {
+        written: bool,
+        flushed: bool,
+    }
+
+    impl Write for AcceptOneThenFail {
+        fn write(&mut self, data: &[u8]) -> io::Result<usize> {
+            if !self.written {
+                assert_eq!(data, b"a\nb\n");
+                self.written = true;
+                Ok(data.len())
+            } else {
+                Err(io::Error::new(io::ErrorKind::NotFound, "test"))
+            }
+        }
+
+        fn flush(&mut self) -> io::Result<()> {
+            assert!(self.written);
+            assert!(!self.flushed);
+            self.flushed = true;
+            Err(io::Error::new(io::ErrorKind::Other, "test"))
+        }
+    }
+
+    #[test]
+    fn erroneous_flush_retried() {
+        let a = AcceptOneThenFail {
+            written: false,
+            flushed: false,
+        };
+
+        let mut l = LineWriter::new(a);
+        assert_eq!(l.write(b"a\nb\na").unwrap(), 4);
+        assert!(l.get_ref().written);
+        assert!(l.get_ref().flushed);
+        l.get_mut().flushed = false;
+
+        assert_eq!(l.write(b"a").unwrap_err().kind(), io::ErrorKind::Other)
+    }
 }
index 143a85ae321846c6c8b4342c32a54f9fe93b5489..5450a10c9bd9f1111763c171d7781d7e55dc415f 100644 (file)
@@ -1425,6 +1425,12 @@ fn split(self, byte: u8) -> Split<Self> where Self: Sized {
     ///     println!("{}", line.unwrap());
     /// }
     /// ```
+    ///
+    /// # Errors
+    ///
+    /// Each line of the iterator has the same error semantics as [`BufRead::read_line()`].
+    ///
+    /// [`BufRead::read_line()`]: trait.BufRead.html#method.read_line
     #[stable(feature = "rust1", since = "1.0.0")]
     fn lines(self) -> Lines<Self> where Self: Sized {
         Lines { buf: self }
index f6fea2f10761b0b423e3ac716d15a365a40077c0..212895d7b76fc661e2db49144288813d0ccffb5c 100644 (file)
@@ -52,10 +52,9 @@ fn next_back(&mut self) -> Option<OsString> { self.iter.next_back() }
 mod imp {
     use os::unix::prelude::*;
     use mem;
-    use ffi::OsString;
+    use ffi::{CStr, OsString};
     use marker::PhantomData;
-    use slice;
-    use str;
+    use libc;
     use super::Args;
 
     use sys_common::mutex::Mutex;
@@ -64,12 +63,9 @@ mod imp {
     static LOCK: Mutex = Mutex::new();
 
     pub unsafe fn init(argc: isize, argv: *const *const u8) {
-        let mut args: Vec<Vec<u8>> = Vec::new();
-        for i in 0..argc {
-            let len = *(argv.offset(i * 2)) as usize;
-            let ptr = *(argv.offset(i * 2 + 1));
-            args.push(slice::from_raw_parts(ptr, len).to_vec());
-        }
+        let args = (0..argc).map(|i| {
+            CStr::from_ptr(*argv.offset(i) as *const libc::c_char).to_bytes().to_vec()
+        }).collect();
 
         LOCK.lock();
         let ptr = get_global_ptr();
index 135e31fae1e687eb9062d3dfb3c823f290d57132..8e7cc593dbdeddea4426fe3162724ab56bdde7b2 100644 (file)
@@ -13,8 +13,9 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use fs;
+use net;
 use sys;
-use sys_common::{AsInner, FromInner, IntoInner};
+use sys_common::{self, AsInner, FromInner, IntoInner};
 
 /// Raw file descriptors.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -89,58 +90,62 @@ fn into_raw_fd(self) -> RawFd {
     }
 }
 
-/*
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRawFd for net::TcpStream {
-    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().as_inner().fd().raw()
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRawFd for net::TcpListener {
-    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().as_inner().fd().raw()
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRawFd for net::UdpSocket {
-    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().as_inner().fd().raw()
+    }
 }
 
 #[stable(feature = "from_raw_os", since = "1.1.0")]
 impl FromRawFd for net::TcpStream {
     unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
-        let socket = sys::net::Socket::from_inner(fd);
-        net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket))
+        let file = sys::fs::File::from_inner(fd);
+        net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(file))
     }
 }
 #[stable(feature = "from_raw_os", since = "1.1.0")]
 impl FromRawFd for net::TcpListener {
     unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
-        let socket = sys::net::Socket::from_inner(fd);
-        net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket))
+        let file = sys::fs::File::from_inner(fd);
+        net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(file))
     }
 }
 #[stable(feature = "from_raw_os", since = "1.1.0")]
 impl FromRawFd for net::UdpSocket {
     unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
-        let socket = sys::net::Socket::from_inner(fd);
-        net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket))
+        let file = sys::fs::File::from_inner(fd);
+        net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(file))
     }
 }
 
 #[stable(feature = "into_raw_os", since = "1.4.0")]
 impl IntoRawFd for net::TcpStream {
     fn into_raw_fd(self) -> RawFd {
-        self.into_inner().into_socket().into_inner()
+        self.into_inner().into_inner().into_fd().into_raw()
     }
 }
 #[stable(feature = "into_raw_os", since = "1.4.0")]
 impl IntoRawFd for net::TcpListener {
     fn into_raw_fd(self) -> RawFd {
-        self.into_inner().into_socket().into_inner()
+        self.into_inner().into_inner().into_fd().into_raw()
     }
 }
 #[stable(feature = "into_raw_os", since = "1.4.0")]
 impl IntoRawFd for net::UdpSocket {
     fn into_raw_fd(self) -> RawFd {
-        self.into_inner().into_socket().into_inner()
+        self.into_inner().into_inner().into_fd().into_raw()
     }
 }
-*/
index e3bd77f40099821ff6ece363b7f7ea5001e3a13f..a8391d2b8982f23de0b79337a4f8ddd92e602d8b 100644 (file)
@@ -43,7 +43,7 @@ pub struct DirEntry {
     name: Box<[u8]>
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct OpenOptions {
     // generic
     read: bool,
@@ -63,6 +63,7 @@ pub struct FilePermissions { mode: u16 }
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct FileType { mode: u16 }
 
+#[derive(Debug)]
 pub struct DirBuilder { mode: u16 }
 
 impl FileAttr {
@@ -336,7 +337,7 @@ pub fn new() -> DirBuilder {
     }
 
     pub fn mkdir(&self, p: &Path) -> io::Result<()> {
-        let flags = syscall::O_CREAT | syscall::O_DIRECTORY | syscall::O_EXCL;
+        let flags = syscall::O_CREAT | syscall::O_CLOEXEC | syscall::O_DIRECTORY | syscall::O_EXCL;
         let fd = cvt(syscall::open(p.to_str().unwrap(), flags | (self.mode as usize & 0o777)))?;
         let _ = syscall::close(fd);
         Ok(())
index 96efa27c0d34b120ef7316835fd3d59624583355..5982bdd6549ca46a131810c60a4305851bc9a493 100644 (file)
 
 #![allow(dead_code, missing_docs, bad_style)]
 
-pub extern crate syscall;
-
 use io::{self, ErrorKind};
 
 pub mod args;
+#[cfg(any(not(cargobuild), feature = "backtrace"))]
 pub mod backtrace;
 pub mod condvar;
 pub mod env;
@@ -34,6 +33,7 @@
 pub mod rwlock;
 pub mod stack_overflow;
 pub mod stdio;
+pub mod syscall;
 pub mod thread;
 pub mod thread_local;
 pub mod time;
index 334c5e51c39b4d3b9267520ac7906665772a712e..3fdf61cfed83c22cfd24c77f9d0b2109e4fd1c49 100644 (file)
 
 use self::dns::{Dns, DnsQuery};
 
-pub extern crate libc as netc;
 pub use self::tcp::{TcpStream, TcpListener};
 pub use self::udp::UdpSocket;
 
+pub mod netc;
+
 mod dns;
 mod tcp;
 mod udp;
diff --git a/src/libstd/sys/redox/net/netc.rs b/src/libstd/sys/redox/net/netc.rs
new file mode 100644 (file)
index 0000000..03e1c9f
--- /dev/null
@@ -0,0 +1,57 @@
+// 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 type in_addr_t = u32;
+pub type in_port_t = u16;
+
+pub type socklen_t = u32;
+pub type sa_family_t = u16;
+
+pub const AF_INET: sa_family_t = 1;
+pub const AF_INET6: sa_family_t = 2;
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub struct in_addr {
+    pub s_addr: in_addr_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub struct in6_addr {
+    pub s6_addr: [u8; 16],
+    __align: [u32; 0],
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub struct sockaddr {
+    pub sa_family: sa_family_t,
+    pub sa_data: [u8; 14],
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub struct sockaddr_in {
+    pub sin_family: sa_family_t,
+    pub sin_port: in_port_t,
+    pub sin_addr: in_addr,
+    pub sin_zero: [u8; 8],
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub struct sockaddr_in6 {
+    pub sin6_family: sa_family_t,
+    pub sin6_port: in_port_t,
+    pub sin6_flowinfo: u32,
+    pub sin6_addr: in6_addr,
+    pub sin6_scope_id: u32,
+}
index 1bfec2e861a68295140c9b33f4b24292cae4ffe5..d5362c9f131f6b8149ec330f4cdcf69c920930fb 100644 (file)
@@ -12,6 +12,7 @@
 use net::{SocketAddr, Shutdown};
 use path::Path;
 use sys::fs::{File, OpenOptions};
+use sys_common::{AsInner, FromInner, IntoInner};
 use time::Duration;
 use vec::Vec;
 
@@ -112,6 +113,20 @@ pub fn set_write_timeout(&self, _dur: Option<Duration>) -> Result<()> {
     }
 }
 
+impl AsInner<File> for TcpStream {
+    fn as_inner(&self) -> &File { &self.0 }
+}
+
+impl FromInner<File> for TcpStream {
+    fn from_inner(file: File) -> TcpStream {
+        TcpStream(file)
+    }
+}
+
+impl IntoInner<File> for TcpStream {
+    fn into_inner(self) -> File { self.0 }
+}
+
 #[derive(Debug)]
 pub struct TcpListener(File);
 
@@ -168,3 +183,17 @@ pub fn set_ttl(&self, _ttl: u32) -> Result<()> {
         Err(Error::new(ErrorKind::Other, "TcpListener::set_ttl not implemented"))
     }
 }
+
+impl AsInner<File> for TcpListener {
+    fn as_inner(&self) -> &File { &self.0 }
+}
+
+impl FromInner<File> for TcpListener {
+    fn from_inner(file: File) -> TcpListener {
+        TcpListener(file)
+    }
+}
+
+impl IntoInner<File> for TcpListener {
+    fn into_inner(self) -> File { self.0 }
+}
index b81508e8f0de129a23945641d3951ac52c8a8f4f..607c66c2ba70e3bf54023e631d921b8b471cf784 100644 (file)
@@ -13,6 +13,7 @@
 use net::{SocketAddr, Ipv4Addr, Ipv6Addr};
 use path::Path;
 use sys::fs::{File, OpenOptions};
+use sys_common::{AsInner, FromInner, IntoInner};
 use time::Duration;
 
 use super::{path_to_peer_addr, path_to_local_addr};
@@ -171,3 +172,17 @@ pub fn leave_multicast_v6(&self, _multiaddr: &Ipv6Addr, _interface: u32) -> Resu
         Err(Error::new(ErrorKind::Other, "UdpSocket::leave_multicast_v6 not implemented"))
     }
 }
+
+impl AsInner<File> for UdpSocket {
+    fn as_inner(&self) -> &File { &self.0 }
+}
+
+impl FromInner<File> for UdpSocket {
+    fn from_inner(file: File) -> UdpSocket {
+        UdpSocket(file, UnsafeCell::new(None))
+    }
+}
+
+impl IntoInner<File> for UdpSocket {
+    fn into_inner(self) -> File { self.0 }
+}
index d7e4d09a9d636bba8c77ee1ed0b6fb37b52f1efd..eb28eca38bcd94a51015d281553d63d75f3b440f 100644 (file)
@@ -9,15 +9,19 @@
 // except according to those terms.
 
 use io;
-use libc;
 use rand::Rng;
 
-pub struct OsRng;
+// FIXME: Use rand:
+pub struct OsRng {
+    state: [u64; 2]
+}
 
 impl OsRng {
     /// Create a new `OsRng`.
     pub fn new() -> io::Result<OsRng> {
-        Ok(OsRng)
+        Ok(OsRng {
+            state: [0xBADF00D1, 0xDEADBEEF]
+        })
     }
 }
 
@@ -26,7 +30,20 @@ fn next_u32(&mut self) -> u32 {
         self.next_u64() as u32
     }
     fn next_u64(&mut self) -> u64 {
-        unsafe { libc::random() }
+        // Store the first and second part.
+        let mut x = self.state[0];
+        let y = self.state[1];
+
+        // Put the second part into the first slot.
+        self.state[0] = y;
+        // Twist the first slot.
+        x ^= x << 23;
+        // Update the second slot.
+        self.state[1] = x ^ y ^ (x >> 17) ^ (y >> 26);
+
+        // Generate the final integer.
+        self.state[1].wrapping_add(y)
+
     }
     fn fill_bytes(&mut self, buf: &mut [u8]) {
         for chunk in buf.chunks_mut(8) {
diff --git a/src/libstd/sys/redox/syscall/arch/arm.rs b/src/libstd/sys/redox/syscall/arch/arm.rs
new file mode 100644 (file)
index 0000000..9fb3961
--- /dev/null
@@ -0,0 +1,83 @@
+// 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.
+
+use super::error::{Error, Result};
+
+pub unsafe fn syscall0(mut a: usize) -> Result<usize> {
+    asm!("swi $$0"
+        : "={r0}"(a)
+        : "{r7}"(a)
+        : "memory"
+        : "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall1(mut a: usize, b: usize) -> Result<usize> {
+    asm!("swi $$0"
+        : "={r0}"(a)
+        : "{r7}"(a), "{r0}"(b)
+        : "memory"
+        : "volatile");
+
+    Error::demux(a)
+}
+
+// Clobbers all registers - special for clone
+pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result<usize> {
+    asm!("swi $$0"
+        : "={r0}"(a)
+        : "{r7}"(a), "{r0}"(b)
+        : "memory", "r0", "r1", "r2", "r3", "r4"
+        : "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result<usize> {
+    asm!("swi $$0"
+        : "={r0}"(a)
+        : "{r7}"(a), "{r0}"(b), "{r1}"(c)
+        : "memory"
+        : "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
+    asm!("swi $$0"
+        : "={r0}"(a)
+        : "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d)
+        : "memory"
+        : "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
+    asm!("swi $$0"
+        : "={r0}"(a)
+        : "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d), "{r3}"(e)
+        : "memory"
+        : "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize)
+                       -> Result<usize> {
+    asm!("swi $$0"
+        : "={r0}"(a)
+        : "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d), "{r3}"(e), "{r4}"(f)
+        : "memory"
+        : "volatile");
+
+    Error::demux(a)
+}
diff --git a/src/libstd/sys/redox/syscall/arch/x86.rs b/src/libstd/sys/redox/syscall/arch/x86.rs
new file mode 100644 (file)
index 0000000..724a6b9
--- /dev/null
@@ -0,0 +1,83 @@
+// 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.
+
+use super::error::{Error, Result};
+
+pub unsafe fn syscall0(mut a: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={eax}"(a)
+        : "{eax}"(a)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall1(mut a: usize, b: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={eax}"(a)
+        : "{eax}"(a), "{ebx}"(b)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+// Clobbers all registers - special for clone
+pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={eax}"(a)
+        : "{eax}"(a), "{ebx}"(b)
+        : "memory", "ebx", "ecx", "edx", "esi", "edi"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={eax}"(a)
+        : "{eax}"(a), "{ebx}"(b), "{ecx}"(c)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={eax}"(a)
+        : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={eax}"(a)
+        : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize)
+                       -> Result<usize> {
+    asm!("int 0x80"
+        : "={eax}"(a)
+        : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e), "{edi}"(f)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
diff --git a/src/libstd/sys/redox/syscall/arch/x86_64.rs b/src/libstd/sys/redox/syscall/arch/x86_64.rs
new file mode 100644 (file)
index 0000000..a321c31
--- /dev/null
@@ -0,0 +1,84 @@
+// 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.
+
+use super::error::{Error, Result};
+
+pub unsafe fn syscall0(mut a: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={rax}"(a)
+        : "{rax}"(a)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall1(mut a: usize, b: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={rax}"(a)
+        : "{rax}"(a), "{rbx}"(b)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+// Clobbers all registers - special for clone
+pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={rax}"(a)
+        : "{rax}"(a), "{rbx}"(b)
+        : "memory", "rbx", "rcx", "rdx", "rsi", "rdi", "r8",
+          "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={rax}"(a)
+        : "{rax}"(a), "{rbx}"(b), "{rcx}"(c)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={rax}"(a)
+        : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={rax}"(a)
+        : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d), "{rsi}"(e)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize)
+                       -> Result<usize> {
+    asm!("int 0x80"
+        : "={rax}"(a)
+        : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d), "{rsi}"(e), "{rdi}"(f)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
diff --git a/src/libstd/sys/redox/syscall/call.rs b/src/libstd/sys/redox/syscall/call.rs
new file mode 100644 (file)
index 0000000..f58c240
--- /dev/null
@@ -0,0 +1,300 @@
+// 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.
+
+use super::arch::*;
+use super::data::{Stat, StatVfs, TimeSpec};
+use super::error::Result;
+use super::number::*;
+
+use core::mem;
+
+/// Set the end of the process's heap
+///
+/// When `addr` is `0`, this function will return the current break.
+///
+/// When `addr` is nonzero, this function will attempt to set the end of the process's
+/// heap to `addr` and return the new program break. The new program break should be
+/// checked by the allocator, it may not be exactly `addr`, as it may be aligned to a page
+/// boundary.
+///
+/// On error, `Err(ENOMEM)` will be returned indicating that no memory is available
+pub unsafe fn brk(addr: usize) -> Result<usize> {
+    syscall1(SYS_BRK, addr)
+}
+
+/// Change the process's working directory
+///
+/// This function will attempt to set the process's working directory to `path`, which can be
+/// either a relative, scheme relative, or absolute path.
+///
+/// On success, `Ok(0)` will be returned. On error, one of the following errors will be returned.
+///
+/// # Errors
+///
+/// * `EACCES` - permission is denied for one of the components of `path`, or `path`
+/// * `EFAULT` - `path` does not point to the process's addressible memory
+/// * `EIO` - an I/O error occured
+/// * `ENOENT` - `path` does not exit
+/// * `ENOTDIR` - `path` is not a directory
+pub fn chdir(path: &str) -> Result<usize> {
+    unsafe { syscall2(SYS_CHDIR, path.as_ptr() as usize, path.len()) }
+}
+
+pub fn chmod(path: &str, mode: usize) -> Result<usize> {
+    unsafe { syscall3(SYS_CHMOD, path.as_ptr() as usize, path.len(), mode) }
+}
+
+/// Produce a fork of the current process, or a new process thread
+pub unsafe fn clone(flags: usize) -> Result<usize> {
+    syscall1_clobber(SYS_CLONE, flags)
+}
+
+/// Close a file
+pub fn close(fd: usize) -> Result<usize> {
+    unsafe { syscall1(SYS_CLOSE, fd) }
+}
+
+/// Get the current system time
+pub fn clock_gettime(clock: usize, tp: &mut TimeSpec) -> Result<usize> {
+    unsafe { syscall2(SYS_CLOCK_GETTIME, clock, tp as *mut TimeSpec as usize) }
+}
+
+/// Copy and transform a file descriptor
+pub fn dup(fd: usize, buf: &[u8]) -> Result<usize> {
+    unsafe { syscall3(SYS_DUP, fd, buf.as_ptr() as usize, buf.len()) }
+}
+
+/// Replace the current process with a new executable
+pub fn execve(path: &str, args: &[[usize; 2]]) -> Result<usize> {
+    unsafe { syscall4(SYS_EXECVE, path.as_ptr() as usize, path.len(),
+                                  args.as_ptr() as usize, args.len()) }
+}
+
+/// Exit the current process
+pub fn exit(status: usize) -> Result<usize> {
+    unsafe { syscall1(SYS_EXIT, status) }
+}
+
+/// Register a file for event-based I/O
+pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result<usize> {
+    unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) }
+}
+
+/// Register a file for event-based I/O
+pub fn fevent(fd: usize, flags: usize) -> Result<usize> {
+    unsafe { syscall2(SYS_FEVENT, fd, flags) }
+}
+
+/// Map a file into memory
+pub unsafe fn fmap(fd: usize, offset: usize, size: usize) -> Result<usize> {
+    syscall3(SYS_FMAP, fd, offset, size)
+}
+
+/// Unmap a memory-mapped file
+pub unsafe fn funmap(addr: usize) -> Result<usize> {
+    syscall1(SYS_FUNMAP, addr)
+}
+
+/// Retrieve the canonical path of a file
+pub fn fpath(fd: usize, buf: &mut [u8]) -> Result<usize> {
+    unsafe { syscall3(SYS_FPATH, fd, buf.as_mut_ptr() as usize, buf.len()) }
+}
+
+/// Get metadata about a file
+pub fn fstat(fd: usize, stat: &mut Stat) -> Result<usize> {
+    unsafe { syscall3(SYS_FSTAT, fd, stat as *mut Stat as usize, mem::size_of::<Stat>()) }
+}
+
+/// Get metadata about a filesystem
+pub fn fstatvfs(fd: usize, stat: &mut StatVfs) -> Result<usize> {
+    unsafe { syscall3(SYS_FSTATVFS, fd, stat as *mut StatVfs as usize, mem::size_of::<StatVfs>()) }
+}
+
+/// Sync a file descriptor to its underlying medium
+pub fn fsync(fd: usize) -> Result<usize> {
+    unsafe { syscall1(SYS_FSYNC, fd) }
+}
+
+/// Truncate or extend a file to a specified length
+pub fn ftruncate(fd: usize, len: usize) -> Result<usize> {
+    unsafe { syscall2(SYS_FTRUNCATE, fd, len) }
+}
+
+/// Fast userspace mutex
+pub unsafe fn futex(addr: *mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32)
+                    -> Result<usize> {
+    syscall5(SYS_FUTEX, addr as usize, op, (val as isize) as usize, val2, addr2 as usize)
+}
+
+/// Get the current working directory
+pub fn getcwd(buf: &mut [u8]) -> Result<usize> {
+    unsafe { syscall2(SYS_GETCWD, buf.as_mut_ptr() as usize, buf.len()) }
+}
+
+/// Get the effective group ID
+pub fn getegid() -> Result<usize> {
+    unsafe { syscall0(SYS_GETEGID) }
+}
+
+/// Get the effective namespace
+pub fn getens() -> Result<usize> {
+    unsafe { syscall0(SYS_GETENS) }
+}
+
+/// Get the effective user ID
+pub fn geteuid() -> Result<usize> {
+    unsafe { syscall0(SYS_GETEUID) }
+}
+
+/// Get the current group ID
+pub fn getgid() -> Result<usize> {
+    unsafe { syscall0(SYS_GETGID) }
+}
+
+/// Get the current namespace
+pub fn getns() -> Result<usize> {
+    unsafe { syscall0(SYS_GETNS) }
+}
+
+/// Get the current process ID
+pub fn getpid() -> Result<usize> {
+    unsafe { syscall0(SYS_GETPID) }
+}
+
+/// Get the current user ID
+pub fn getuid() -> Result<usize> {
+    unsafe { syscall0(SYS_GETUID) }
+}
+
+/// Set the I/O privilege level
+pub unsafe fn iopl(level: usize) -> Result<usize> {
+    syscall1(SYS_IOPL, level)
+}
+
+/// Send a signal `sig` to the process identified by `pid`
+pub fn kill(pid: usize, sig: usize) -> Result<usize> {
+    unsafe { syscall2(SYS_KILL, pid, sig) }
+}
+
+/// Create a link to a file
+pub unsafe fn link(old: *const u8, new: *const u8) -> Result<usize> {
+    syscall2(SYS_LINK, old as usize, new as usize)
+}
+
+/// Seek to `offset` bytes in a file descriptor
+pub fn lseek(fd: usize, offset: isize, whence: usize) -> Result<usize> {
+    unsafe { syscall3(SYS_LSEEK, fd, offset as usize, whence) }
+}
+
+/// Make a new scheme namespace
+pub fn mkns(schemes: &[[usize; 2]]) -> Result<usize> {
+    unsafe { syscall2(SYS_MKNS, schemes.as_ptr() as usize, schemes.len()) }
+}
+
+/// Sleep for the time specified in `req`
+pub fn nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result<usize> {
+    unsafe { syscall2(SYS_NANOSLEEP, req as *const TimeSpec as usize,
+                                     rem as *mut TimeSpec as usize) }
+}
+
+/// Open a file
+pub fn open(path: &str, flags: usize) -> Result<usize> {
+    unsafe { syscall3(SYS_OPEN, path.as_ptr() as usize, path.len(), flags) }
+}
+
+/// Allocate pages, linearly in physical memory
+pub unsafe fn physalloc(size: usize) -> Result<usize> {
+    syscall1(SYS_PHYSALLOC, size)
+}
+
+/// Free physically allocated pages
+pub unsafe fn physfree(physical_address: usize, size: usize) -> Result<usize> {
+    syscall2(SYS_PHYSFREE, physical_address, size)
+}
+
+/// Map physical memory to virtual memory
+pub unsafe fn physmap(physical_address: usize, size: usize, flags: usize) -> Result<usize> {
+    syscall3(SYS_PHYSMAP, physical_address, size, flags)
+}
+
+/// Unmap previously mapped physical memory
+pub unsafe fn physunmap(virtual_address: usize) -> Result<usize> {
+    syscall1(SYS_PHYSUNMAP, virtual_address)
+}
+
+/// Create a pair of file descriptors referencing the read and write ends of a pipe
+pub fn pipe2(fds: &mut [usize; 2], flags: usize) -> Result<usize> {
+    unsafe { syscall2(SYS_PIPE2, fds.as_ptr() as usize, flags) }
+}
+
+/// Read from a file descriptor into a buffer
+pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> {
+    unsafe { syscall3(SYS_READ, fd, buf.as_mut_ptr() as usize, buf.len()) }
+}
+
+/// Remove a directory
+pub fn rmdir(path: &str) -> Result<usize> {
+    unsafe { syscall2(SYS_RMDIR, path.as_ptr() as usize, path.len()) }
+}
+
+/// Set the current process group IDs
+pub fn setregid(rgid: usize, egid: usize) -> Result<usize> {
+    unsafe { syscall2(SYS_SETREGID, rgid, egid) }
+}
+
+/// Make a new scheme namespace
+pub fn setrens(rns: usize, ens: usize) -> Result<usize> {
+    unsafe { syscall2(SYS_SETRENS, rns, ens) }
+}
+
+/// Set the current process user IDs
+pub fn setreuid(ruid: usize, euid: usize) -> Result<usize> {
+    unsafe { syscall2(SYS_SETREUID, ruid, euid) }
+}
+
+/// Remove a file
+pub fn unlink(path: &str) -> Result<usize> {
+    unsafe { syscall2(SYS_UNLINK, path.as_ptr() as usize, path.len()) }
+}
+
+/// Convert a virtual address to a physical one
+pub unsafe fn virttophys(virtual_address: usize) -> Result<usize> {
+    syscall1(SYS_VIRTTOPHYS, virtual_address)
+}
+
+/// Check if a child process has exited or received a signal
+pub fn waitpid(pid: usize, status: &mut usize, options: usize) -> Result<usize> {
+    unsafe { syscall3(SYS_WAITPID, pid, status as *mut usize as usize, options) }
+}
+
+/// Write a buffer to a file descriptor
+///
+/// The kernel will attempt to write the bytes in `buf` to the file descriptor `fd`, returning
+/// either an `Err`, explained below, or `Ok(count)` where `count` is the number of bytes which
+/// were written.
+///
+/// # Errors
+///
+/// * `EAGAIN` - the file descriptor was opened with `O_NONBLOCK` and writing would block
+/// * `EBADF` - the file descriptor is not valid or is not open for writing
+/// * `EFAULT` - `buf` does not point to the process's addressible memory
+/// * `EIO` - an I/O error occured
+/// * `ENOSPC` - the device containing the file descriptor has no room for data
+/// * `EPIPE` - the file descriptor refers to a pipe or socket whose reading end is closed
+pub fn write(fd: usize, buf: &[u8]) -> Result<usize> {
+    unsafe { syscall3(SYS_WRITE, fd, buf.as_ptr() as usize, buf.len()) }
+}
+
+/// Yield the process's time slice to the kernel
+///
+/// This function will return Ok(0) on success
+pub fn sched_yield() -> Result<usize> {
+    unsafe { syscall0(SYS_YIELD) }
+}
diff --git a/src/libstd/sys/redox/syscall/data.rs b/src/libstd/sys/redox/syscall/data.rs
new file mode 100644 (file)
index 0000000..ac39466
--- /dev/null
@@ -0,0 +1,86 @@
+// 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.
+
+use core::ops::{Deref, DerefMut};
+use core::{mem, slice};
+
+#[derive(Copy, Clone, Debug, Default)]
+#[repr(packed)]
+pub struct Stat {
+    pub st_dev: u64,
+    pub st_ino: u64,
+    pub st_mode: u16,
+    pub st_nlink: u32,
+    pub st_uid: u32,
+    pub st_gid: u32,
+    pub st_size: u64,
+    pub st_blksize: u32,
+    pub st_blocks: u64,
+    pub st_mtime: u64,
+    pub st_mtime_nsec: u32,
+    pub st_atime: u64,
+    pub st_atime_nsec: u32,
+    pub st_ctime: u64,
+    pub st_ctime_nsec: u32,
+}
+
+impl Deref for Stat {
+    type Target = [u8];
+    fn deref(&self) -> &[u8] {
+        unsafe {
+            slice::from_raw_parts(self as *const Stat as *const u8,
+                                  mem::size_of::<Stat>()) as &[u8]
+        }
+    }
+}
+
+impl DerefMut for Stat {
+    fn deref_mut(&mut self) -> &mut [u8] {
+        unsafe {
+            slice::from_raw_parts_mut(self as *mut Stat as *mut u8,
+                                      mem::size_of::<Stat>()) as &mut [u8]
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug, Default)]
+#[repr(packed)]
+pub struct StatVfs {
+    pub f_bsize: u32,
+    pub f_blocks: u64,
+    pub f_bfree: u64,
+    pub f_bavail: u64,
+}
+
+impl Deref for StatVfs {
+    type Target = [u8];
+    fn deref(&self) -> &[u8] {
+        unsafe {
+            slice::from_raw_parts(self as *const StatVfs as *const u8,
+                                  mem::size_of::<StatVfs>()) as &[u8]
+        }
+    }
+}
+
+impl DerefMut for StatVfs {
+    fn deref_mut(&mut self) -> &mut [u8] {
+        unsafe {
+            slice::from_raw_parts_mut(self as *mut StatVfs as *mut u8,
+                                      mem::size_of::<StatVfs>()) as &mut [u8]
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug, Default)]
+#[repr(packed)]
+pub struct TimeSpec {
+    pub tv_sec: i64,
+    pub tv_nsec: i32,
+}
diff --git a/src/libstd/sys/redox/syscall/error.rs b/src/libstd/sys/redox/syscall/error.rs
new file mode 100644 (file)
index 0000000..d8d78d5
--- /dev/null
@@ -0,0 +1,325 @@
+// 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.
+
+use core::{fmt, result};
+
+#[derive(Eq, PartialEq)]
+pub struct Error {
+    pub errno: i32,
+}
+
+pub type Result<T> = result::Result<T, Error>;
+
+impl Error {
+    pub fn new(errno: i32) -> Error {
+        Error { errno: errno }
+    }
+
+    pub fn mux(result: Result<usize>) -> usize {
+        match result {
+            Ok(value) => value,
+            Err(error) => -error.errno as usize,
+        }
+    }
+
+    pub fn demux(value: usize) -> Result<usize> {
+        let errno = -(value as i32);
+        if errno >= 1 && errno < STR_ERROR.len() as i32 {
+            Err(Error::new(errno))
+        } else {
+            Ok(value)
+        }
+    }
+
+    pub fn text(&self) -> &str {
+        if let Some(description) = STR_ERROR.get(self.errno as usize) {
+            description
+        } else {
+            "Unknown Error"
+        }
+    }
+}
+
+impl fmt::Debug for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+        f.write_str(self.text())
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+        f.write_str(self.text())
+    }
+}
+
+pub const EPERM: i32 = 1;  /* Operation not permitted */
+pub const ENOENT: i32 = 2;  /* No such file or directory */
+pub const ESRCH: i32 = 3;  /* No such process */
+pub const EINTR: i32 = 4;  /* Interrupted system call */
+pub const EIO: i32 = 5;  /* I/O error */
+pub const ENXIO: i32 = 6;  /* No such device or address */
+pub const E2BIG: i32 = 7;  /* Argument list too long */
+pub const ENOEXEC: i32 = 8;  /* Exec format error */
+pub const EBADF: i32 = 9;  /* Bad file number */
+pub const ECHILD: i32 = 10;  /* No child processes */
+pub const EAGAIN: i32 = 11;  /* Try again */
+pub const ENOMEM: i32 = 12;  /* Out of memory */
+pub const EACCES: i32 = 13;  /* Permission denied */
+pub const EFAULT: i32 = 14;  /* Bad address */
+pub const ENOTBLK: i32 = 15;  /* Block device required */
+pub const EBUSY: i32 = 16;  /* Device or resource busy */
+pub const EEXIST: i32 = 17;  /* File exists */
+pub const EXDEV: i32 = 18;  /* Cross-device link */
+pub const ENODEV: i32 = 19;  /* No such device */
+pub const ENOTDIR: i32 = 20;  /* Not a directory */
+pub const EISDIR: i32 = 21;  /* Is a directory */
+pub const EINVAL: i32 = 22;  /* Invalid argument */
+pub const ENFILE: i32 = 23;  /* File table overflow */
+pub const EMFILE: i32 = 24;  /* Too many open files */
+pub const ENOTTY: i32 = 25;  /* Not a typewriter */
+pub const ETXTBSY: i32 = 26;  /* Text file busy */
+pub const EFBIG: i32 = 27;  /* File too large */
+pub const ENOSPC: i32 = 28;  /* No space left on device */
+pub const ESPIPE: i32 = 29;  /* Illegal seek */
+pub const EROFS: i32 = 30;  /* Read-only file system */
+pub const EMLINK: i32 = 31;  /* Too many links */
+pub const EPIPE: i32 = 32;  /* Broken pipe */
+pub const EDOM: i32 = 33;  /* Math argument out of domain of func */
+pub const ERANGE: i32 = 34;  /* Math result not representable */
+pub const EDEADLK: i32 = 35;  /* Resource deadlock would occur */
+pub const ENAMETOOLONG: i32 = 36;  /* File name too long */
+pub const ENOLCK: i32 = 37;  /* No record locks available */
+pub const ENOSYS: i32 = 38;  /* Function not implemented */
+pub const ENOTEMPTY: i32 = 39;  /* Directory not empty */
+pub const ELOOP: i32 = 40;  /* Too many symbolic links encountered */
+pub const EWOULDBLOCK: i32 = 41;  /* Operation would block */
+pub const ENOMSG: i32 = 42;  /* No message of desired type */
+pub const EIDRM: i32 = 43;  /* Identifier removed */
+pub const ECHRNG: i32 = 44;  /* Channel number out of range */
+pub const EL2NSYNC: i32 = 45;  /* Level 2 not synchronized */
+pub const EL3HLT: i32 = 46;  /* Level 3 halted */
+pub const EL3RST: i32 = 47;  /* Level 3 reset */
+pub const ELNRNG: i32 = 48;  /* Link number out of range */
+pub const EUNATCH: i32 = 49;  /* Protocol driver not attached */
+pub const ENOCSI: i32 = 50;  /* No CSI structure available */
+pub const EL2HLT: i32 = 51;  /* Level 2 halted */
+pub const EBADE: i32 = 52;  /* Invalid exchange */
+pub const EBADR: i32 = 53;  /* Invalid request descriptor */
+pub const EXFULL: i32 = 54;  /* Exchange full */
+pub const ENOANO: i32 = 55;  /* No anode */
+pub const EBADRQC: i32 = 56;  /* Invalid request code */
+pub const EBADSLT: i32 = 57;  /* Invalid slot */
+pub const EDEADLOCK: i32 = 58; /* Resource deadlock would occur */
+pub const EBFONT: i32 = 59;  /* Bad font file format */
+pub const ENOSTR: i32 = 60;  /* Device not a stream */
+pub const ENODATA: i32 = 61;  /* No data available */
+pub const ETIME: i32 = 62;  /* Timer expired */
+pub const ENOSR: i32 = 63;  /* Out of streams resources */
+pub const ENONET: i32 = 64;  /* Machine is not on the network */
+pub const ENOPKG: i32 = 65;  /* Package not installed */
+pub const EREMOTE: i32 = 66;  /* Object is remote */
+pub const ENOLINK: i32 = 67;  /* Link has been severed */
+pub const EADV: i32 = 68;  /* Advertise error */
+pub const ESRMNT: i32 = 69;  /* Srmount error */
+pub const ECOMM: i32 = 70;  /* Communication error on send */
+pub const EPROTO: i32 = 71;  /* Protocol error */
+pub const EMULTIHOP: i32 = 72;  /* Multihop attempted */
+pub const EDOTDOT: i32 = 73;  /* RFS specific error */
+pub const EBADMSG: i32 = 74;  /* Not a data message */
+pub const EOVERFLOW: i32 = 75;  /* Value too large for defined data type */
+pub const ENOTUNIQ: i32 = 76;  /* Name not unique on network */
+pub const EBADFD: i32 = 77;  /* File descriptor in bad state */
+pub const EREMCHG: i32 = 78;  /* Remote address changed */
+pub const ELIBACC: i32 = 79;  /* Can not access a needed shared library */
+pub const ELIBBAD: i32 = 80;  /* Accessing a corrupted shared library */
+pub const ELIBSCN: i32 = 81;  /* .lib section in a.out corrupted */
+pub const ELIBMAX: i32 = 82;  /* Attempting to link in too many shared libraries */
+pub const ELIBEXEC: i32 = 83;  /* Cannot exec a shared library directly */
+pub const EILSEQ: i32 = 84;  /* Illegal byte sequence */
+pub const ERESTART: i32 = 85;  /* Interrupted system call should be restarted */
+pub const ESTRPIPE: i32 = 86;  /* Streams pipe error */
+pub const EUSERS: i32 = 87;  /* Too many users */
+pub const ENOTSOCK: i32 = 88;  /* Socket operation on non-socket */
+pub const EDESTADDRREQ: i32 = 89;  /* Destination address required */
+pub const EMSGSIZE: i32 = 90;  /* Message too long */
+pub const EPROTOTYPE: i32 = 91;  /* Protocol wrong type for socket */
+pub const ENOPROTOOPT: i32 = 92;  /* Protocol not available */
+pub const EPROTONOSUPPORT: i32 = 93;  /* Protocol not supported */
+pub const ESOCKTNOSUPPORT: i32 = 94;  /* Socket type not supported */
+pub const EOPNOTSUPP: i32 = 95;  /* Operation not supported on transport endpoint */
+pub const EPFNOSUPPORT: i32 = 96;  /* Protocol family not supported */
+pub const EAFNOSUPPORT: i32 = 97;  /* Address family not supported by protocol */
+pub const EADDRINUSE: i32 = 98;  /* Address already in use */
+pub const EADDRNOTAVAIL: i32 = 99;  /* Cannot assign requested address */
+pub const ENETDOWN: i32 = 100; /* Network is down */
+pub const ENETUNREACH: i32 = 101; /* Network is unreachable */
+pub const ENETRESET: i32 = 102; /* Network dropped connection because of reset */
+pub const ECONNABORTED: i32 = 103; /* Software caused connection abort */
+pub const ECONNRESET: i32 = 104; /* Connection reset by peer */
+pub const ENOBUFS: i32 = 105; /* No buffer space available */
+pub const EISCONN: i32 = 106; /* Transport endpoint is already connected */
+pub const ENOTCONN: i32 = 107; /* Transport endpoint is not connected */
+pub const ESHUTDOWN: i32 = 108; /* Cannot send after transport endpoint shutdown */
+pub const ETOOMANYREFS: i32 = 109; /* Too many references: cannot splice */
+pub const ETIMEDOUT: i32 = 110; /* Connection timed out */
+pub const ECONNREFUSED: i32 = 111; /* Connection refused */
+pub const EHOSTDOWN: i32 = 112; /* Host is down */
+pub const EHOSTUNREACH: i32 = 113; /* No route to host */
+pub const EALREADY: i32 = 114; /* Operation already in progress */
+pub const EINPROGRESS: i32 = 115; /* Operation now in progress */
+pub const ESTALE: i32 = 116; /* Stale NFS file handle */
+pub const EUCLEAN: i32 = 117; /* Structure needs cleaning */
+pub const ENOTNAM: i32 = 118; /* Not a XENIX named type file */
+pub const ENAVAIL: i32 = 119; /* No XENIX semaphores available */
+pub const EISNAM: i32 = 120; /* Is a named type file */
+pub const EREMOTEIO: i32 = 121; /* Remote I/O error */
+pub const EDQUOT: i32 = 122; /* Quota exceeded */
+pub const ENOMEDIUM: i32 = 123; /* No medium found */
+pub const EMEDIUMTYPE: i32 = 124; /* Wrong medium type */
+pub const ECANCELED: i32 = 125; /* Operation Canceled */
+pub const ENOKEY: i32 = 126; /* Required key not available */
+pub const EKEYEXPIRED: i32 = 127; /* Key has expired */
+pub const EKEYREVOKED: i32 = 128; /* Key has been revoked */
+pub const EKEYREJECTED: i32 = 129; /* Key was rejected by service */
+pub const EOWNERDEAD: i32 = 130; /* Owner died */
+pub const ENOTRECOVERABLE: i32 = 131; /* State not recoverable */
+
+pub static STR_ERROR: [&'static str; 132] = ["Success",
+                                             "Operation not permitted",
+                                             "No such file or directory",
+                                             "No such process",
+                                             "Interrupted system call",
+                                             "I/O error",
+                                             "No such device or address",
+                                             "Argument list too long",
+                                             "Exec format error",
+                                             "Bad file number",
+                                             "No child processes",
+                                             "Try again",
+                                             "Out of memory",
+                                             "Permission denied",
+                                             "Bad address",
+                                             "Block device required",
+                                             "Device or resource busy",
+                                             "File exists",
+                                             "Cross-device link",
+                                             "No such device",
+                                             "Not a directory",
+                                             "Is a directory",
+                                             "Invalid argument",
+                                             "File table overflow",
+                                             "Too many open files",
+                                             "Not a typewriter",
+                                             "Text file busy",
+                                             "File too large",
+                                             "No space left on device",
+                                             "Illegal seek",
+                                             "Read-only file system",
+                                             "Too many links",
+                                             "Broken pipe",
+                                             "Math argument out of domain of func",
+                                             "Math result not representable",
+                                             "Resource deadlock would occur",
+                                             "File name too long",
+                                             "No record locks available",
+                                             "Function not implemented",
+                                             "Directory not empty",
+                                             "Too many symbolic links encountered",
+                                             "Operation would block",
+                                             "No message of desired type",
+                                             "Identifier removed",
+                                             "Channel number out of range",
+                                             "Level 2 not synchronized",
+                                             "Level 3 halted",
+                                             "Level 3 reset",
+                                             "Link number out of range",
+                                             "Protocol driver not attached",
+                                             "No CSI structure available",
+                                             "Level 2 halted",
+                                             "Invalid exchange",
+                                             "Invalid request descriptor",
+                                             "Exchange full",
+                                             "No anode",
+                                             "Invalid request code",
+                                             "Invalid slot",
+                                             "Resource deadlock would occur",
+                                             "Bad font file format",
+                                             "Device not a stream",
+                                             "No data available",
+                                             "Timer expired",
+                                             "Out of streams resources",
+                                             "Machine is not on the network",
+                                             "Package not installed",
+                                             "Object is remote",
+                                             "Link has been severed",
+                                             "Advertise error",
+                                             "Srmount error",
+                                             "Communication error on send",
+                                             "Protocol error",
+                                             "Multihop attempted",
+                                             "RFS specific error",
+                                             "Not a data message",
+                                             "Value too large for defined data type",
+                                             "Name not unique on network",
+                                             "File descriptor in bad state",
+                                             "Remote address changed",
+                                             "Can not access a needed shared library",
+                                             "Accessing a corrupted shared library",
+                                             ".lib section in a.out corrupted",
+                                             "Attempting to link in too many shared libraries",
+                                             "Cannot exec a shared library directly",
+                                             "Illegal byte sequence",
+                                             "Interrupted system call should be restarted",
+                                             "Streams pipe error",
+                                             "Too many users",
+                                             "Socket operation on non-socket",
+                                             "Destination address required",
+                                             "Message too long",
+                                             "Protocol wrong type for socket",
+                                             "Protocol not available",
+                                             "Protocol not supported",
+                                             "Socket type not supported",
+                                             "Operation not supported on transport endpoint",
+                                             "Protocol family not supported",
+                                             "Address family not supported by protocol",
+                                             "Address already in use",
+                                             "Cannot assign requested address",
+                                             "Network is down",
+                                             "Network is unreachable",
+                                             "Network dropped connection because of reset",
+                                             "Software caused connection abort",
+                                             "Connection reset by peer",
+                                             "No buffer space available",
+                                             "Transport endpoint is already connected",
+                                             "Transport endpoint is not connected",
+                                             "Cannot send after transport endpoint shutdown",
+                                             "Too many references: cannot splice",
+                                             "Connection timed out",
+                                             "Connection refused",
+                                             "Host is down",
+                                             "No route to host",
+                                             "Operation already in progress",
+                                             "Operation now in progress",
+                                             "Stale NFS file handle",
+                                             "Structure needs cleaning",
+                                             "Not a XENIX named type file",
+                                             "No XENIX semaphores available",
+                                             "Is a named type file",
+                                             "Remote I/O error",
+                                             "Quota exceeded",
+                                             "No medium found",
+                                             "Wrong medium type",
+                                             "Operation Canceled",
+                                             "Required key not available",
+                                             "Key has expired",
+                                             "Key has been revoked",
+                                             "Key was rejected by service",
+                                             "Owner died",
+                                             "State not recoverable"];
diff --git a/src/libstd/sys/redox/syscall/flag.rs b/src/libstd/sys/redox/syscall/flag.rs
new file mode 100644 (file)
index 0000000..9f0d3e6
--- /dev/null
@@ -0,0 +1,94 @@
+// 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 const CLONE_VM: usize = 0x100;
+pub const CLONE_FS: usize = 0x200;
+pub const CLONE_FILES: usize = 0x400;
+pub const CLONE_VFORK: usize = 0x4000;
+
+pub const CLOCK_REALTIME: usize = 1;
+pub const CLOCK_MONOTONIC: usize = 4;
+
+pub const EVENT_NONE: usize = 0;
+pub const EVENT_READ: usize = 1;
+pub const EVENT_WRITE: usize = 2;
+
+pub const F_GETFL: usize = 1;
+pub const F_SETFL: usize = 2;
+
+pub const FUTEX_WAIT: usize = 0;
+pub const FUTEX_WAKE: usize = 1;
+pub const FUTEX_REQUEUE: usize = 2;
+
+pub const MAP_WRITE: usize = 1;
+pub const MAP_WRITE_COMBINE: usize = 2;
+
+pub const MODE_TYPE: u16 = 0xF000;
+pub const MODE_DIR: u16 = 0x4000;
+pub const MODE_FILE: u16 = 0x8000;
+
+pub const MODE_PERM: u16 = 0x0FFF;
+pub const MODE_SETUID: u16 = 0o4000;
+pub const MODE_SETGID: u16 = 0o2000;
+
+pub const O_RDONLY: usize =     0x0001_0000;
+pub const O_WRONLY: usize =     0x0002_0000;
+pub const O_RDWR: usize =       0x0003_0000;
+pub const O_NONBLOCK: usize =   0x0004_0000;
+pub const O_APPEND: usize =     0x0008_0000;
+pub const O_SHLOCK: usize =     0x0010_0000;
+pub const O_EXLOCK: usize =     0x0020_0000;
+pub const O_ASYNC: usize =      0x0040_0000;
+pub const O_FSYNC: usize =      0x0080_0000;
+pub const O_CLOEXEC: usize =    0x0100_0000;
+pub const O_CREAT: usize =      0x0200_0000;
+pub const O_TRUNC: usize =      0x0400_0000;
+pub const O_EXCL: usize =       0x0800_0000;
+pub const O_DIRECTORY: usize =  0x1000_0000;
+pub const O_STAT: usize =       0x2000_0000;
+pub const O_ACCMODE: usize =    O_RDONLY | O_WRONLY | O_RDWR;
+
+pub const SEEK_SET: usize = 0;
+pub const SEEK_CUR: usize = 1;
+pub const SEEK_END: usize = 2;
+
+pub const SIGHUP: usize =   1;
+pub const SIGINT: usize =   2;
+pub const SIGQUIT: usize =  3;
+pub const SIGILL: usize =   4;
+pub const SIGTRAP: usize =  5;
+pub const SIGABRT: usize =  6;
+pub const SIGBUS: usize =   7;
+pub const SIGFPE: usize =   8;
+pub const SIGKILL: usize =  9;
+pub const SIGUSR1: usize =  10;
+pub const SIGSEGV: usize =  11;
+pub const SIGUSR2: usize =  12;
+pub const SIGPIPE: usize =  13;
+pub const SIGALRM: usize =  14;
+pub const SIGTERM: usize =  15;
+pub const SIGSTKFLT: usize= 16;
+pub const SIGCHLD: usize =  17;
+pub const SIGCONT: usize =  18;
+pub const SIGSTOP: usize =  19;
+pub const SIGTSTP: usize =  20;
+pub const SIGTTIN: usize =  21;
+pub const SIGTTOU: usize =  22;
+pub const SIGURG: usize =   23;
+pub const SIGXCPU: usize =  24;
+pub const SIGXFSZ: usize =  25;
+pub const SIGVTALRM: usize= 26;
+pub const SIGPROF: usize =  27;
+pub const SIGWINCH: usize = 28;
+pub const SIGIO: usize =    29;
+pub const SIGPWR: usize =   30;
+pub const SIGSYS: usize =   31;
+
+pub const WNOHANG: usize = 1;
diff --git a/src/libstd/sys/redox/syscall/mod.rs b/src/libstd/sys/redox/syscall/mod.rs
new file mode 100644 (file)
index 0000000..ce789c2
--- /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.
+
+pub use self::arch::*;
+pub use self::call::*;
+pub use self::data::*;
+pub use self::error::*;
+pub use self::flag::*;
+pub use self::number::*;
+
+#[cfg(target_arch = "arm")]
+#[path="arch/arm.rs"]
+mod arch;
+
+#[cfg(target_arch = "x86")]
+#[path="arch/x86.rs"]
+mod arch;
+
+#[cfg(target_arch = "x86_64")]
+#[path="arch/x86_64.rs"]
+mod arch;
+
+/// Function definitions
+pub mod call;
+
+/// Complex structures that are used for some system calls
+pub mod data;
+
+/// All errors that can be generated by a system call
+pub mod error;
+
+/// Flags used as an argument to many system calls
+pub mod flag;
+
+/// Call numbers used by each system call
+pub mod number;
diff --git a/src/libstd/sys/redox/syscall/number.rs b/src/libstd/sys/redox/syscall/number.rs
new file mode 100644 (file)
index 0000000..358746c
--- /dev/null
@@ -0,0 +1,73 @@
+// 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 const SYS_CLASS: usize =    0xF000_0000;
+pub const SYS_CLASS_PATH: usize=0x1000_0000;
+pub const SYS_CLASS_FILE: usize=0x2000_0000;
+
+pub const SYS_ARG: usize =      0x0F00_0000;
+pub const SYS_ARG_SLICE: usize =0x0100_0000;
+pub const SYS_ARG_MSLICE: usize=0x0200_0000;
+pub const SYS_ARG_PATH: usize = 0x0300_0000;
+
+pub const SYS_RET: usize =      0x00F0_0000;
+pub const SYS_RET_FILE: usize = 0x0010_0000;
+
+pub const SYS_LINK: usize =     SYS_CLASS_PATH | SYS_ARG_PATH | 9;
+pub const SYS_OPEN: usize =     SYS_CLASS_PATH | SYS_RET_FILE | 5;
+pub const SYS_CHMOD: usize =    SYS_CLASS_PATH | 15;
+pub const SYS_RMDIR: usize =    SYS_CLASS_PATH | 84;
+pub const SYS_UNLINK: usize =   SYS_CLASS_PATH | 10;
+
+pub const SYS_CLOSE: usize =    SYS_CLASS_FILE | 6;
+pub const SYS_DUP: usize =      SYS_CLASS_FILE | SYS_RET_FILE | 41;
+pub const SYS_READ: usize =     SYS_CLASS_FILE | SYS_ARG_MSLICE | 3;
+pub const SYS_WRITE: usize =    SYS_CLASS_FILE | SYS_ARG_SLICE | 4;
+pub const SYS_LSEEK: usize =    SYS_CLASS_FILE | 19;
+pub const SYS_FCNTL: usize =    SYS_CLASS_FILE | 55;
+pub const SYS_FEVENT: usize =   SYS_CLASS_FILE | 927;
+pub const SYS_FMAP: usize =     SYS_CLASS_FILE | 90;
+pub const SYS_FUNMAP: usize =   SYS_CLASS_FILE | 91;
+pub const SYS_FPATH: usize =    SYS_CLASS_FILE | SYS_ARG_MSLICE | 928;
+pub const SYS_FSTAT: usize =    SYS_CLASS_FILE | SYS_ARG_MSLICE | 28;
+pub const SYS_FSTATVFS: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 100;
+pub const SYS_FSYNC: usize =    SYS_CLASS_FILE | 118;
+pub const SYS_FTRUNCATE: usize =SYS_CLASS_FILE | 93;
+
+pub const SYS_BRK: usize =      45;
+pub const SYS_CHDIR: usize =    12;
+pub const SYS_CLOCK_GETTIME: usize = 265;
+pub const SYS_CLONE: usize =    120;
+pub const SYS_EXECVE: usize =   11;
+pub const SYS_EXIT: usize =     1;
+pub const SYS_FUTEX: usize =    240;
+pub const SYS_GETCWD: usize =   183;
+pub const SYS_GETEGID: usize =  202;
+pub const SYS_GETENS: usize =   951;
+pub const SYS_GETEUID: usize =  201;
+pub const SYS_GETGID: usize =   200;
+pub const SYS_GETNS: usize =    950;
+pub const SYS_GETPID: usize =   20;
+pub const SYS_GETUID: usize =   199;
+pub const SYS_IOPL: usize =     110;
+pub const SYS_KILL: usize =     37;
+pub const SYS_MKNS: usize =     984;
+pub const SYS_NANOSLEEP: usize =162;
+pub const SYS_PHYSALLOC: usize =945;
+pub const SYS_PHYSFREE: usize = 946;
+pub const SYS_PHYSMAP: usize =  947;
+pub const SYS_PHYSUNMAP: usize =948;
+pub const SYS_VIRTTOPHYS: usize=949;
+pub const SYS_PIPE2: usize =    331;
+pub const SYS_SETREGID: usize = 204;
+pub const SYS_SETRENS: usize =  952;
+pub const SYS_SETREUID: usize = 203;
+pub const SYS_WAITPID: usize =  7;
+pub const SYS_YIELD: usize =    158;
index 2384d959881a238662648ceb50b59e935844174f..dcab30aad8385b9c9ed38929c3531007a1740b6d 100644 (file)
@@ -10,8 +10,9 @@
 
 #![unstable(reason = "not public", issue = "0", feature = "fd")]
 
+use cmp;
 use io::{self, Read};
-use libc::{self, c_int, c_void};
+use libc::{self, c_int, c_void, ssize_t};
 use mem;
 use sync::atomic::{AtomicBool, Ordering};
 use sys::cvt;
@@ -23,6 +24,22 @@ pub struct FileDesc {
     fd: c_int,
 }
 
+fn max_len() -> usize {
+    // The maximum read limit on most posix-like systems is `SSIZE_MAX`,
+    // with the man page quoting that if the count of bytes to read is
+    // greater than `SSIZE_MAX` the result is "unspecified".
+    //
+    // On OSX, however, apparently the 64-bit libc is either buggy or
+    // intentionally showing odd behavior by rejecting any read with a size
+    // larger than or equal to INT_MAX. To handle both of these the read
+    // size is capped on both platforms.
+    if cfg!(target_os = "macos") {
+        <c_int>::max_value() as usize - 1
+    } else {
+        <ssize_t>::max_value() as usize
+    }
+}
+
 impl FileDesc {
     pub fn new(fd: c_int) -> FileDesc {
         FileDesc { fd: fd }
@@ -41,7 +58,7 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         let ret = cvt(unsafe {
             libc::read(self.fd,
                        buf.as_mut_ptr() as *mut c_void,
-                       buf.len())
+                       cmp::min(buf.len(), max_len()))
         })?;
         Ok(ret as usize)
     }
@@ -69,7 +86,7 @@ unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: usize, offset: i64)
         unsafe {
             cvt_pread64(self.fd,
                         buf.as_mut_ptr() as *mut c_void,
-                        buf.len(),
+                        cmp::min(buf.len(), max_len()),
                         offset as i64)
                 .map(|n| n as usize)
         }
@@ -79,7 +96,7 @@ pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         let ret = cvt(unsafe {
             libc::write(self.fd,
                         buf.as_ptr() as *const c_void,
-                        buf.len())
+                        cmp::min(buf.len(), max_len()))
         })?;
         Ok(ret as usize)
     }
@@ -102,7 +119,7 @@ unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: usize, offset: i64)
         unsafe {
             cvt_pwrite64(self.fd,
                          buf.as_ptr() as *const c_void,
-                         buf.len(),
+                         cmp::min(buf.len(), max_len()),
                          offset as i64)
                 .map(|n| n as usize)
         }
index 319fbce35cd7b26da6110c2c9eb9cb5b257f66c0..2bb005be4ec93421675a9ab2d5189e7bc0a8e1d0 100644 (file)
@@ -23,7 +23,6 @@
 pub type mx_status_t = i32;
 
 pub type mx_size_t = usize;
-pub type mx_ssize_t = isize;
 
 pub const MX_HANDLE_INVALID: mx_handle_t = 0;
 
index 5384ef46e9ae3ce91816c577332c701b1f8e1317..d1c404195bc68d5bde33a61f08cb9765694c2394 100644 (file)
@@ -818,6 +818,16 @@ pub enum EXCEPTION_DISPOSITION {
     ExceptionCollidedUnwind
 }
 
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct CONSOLE_READCONSOLE_CONTROL {
+    pub nLength: ULONG,
+    pub nInitialChars: ULONG,
+    pub dwCtrlWakeupMask: ULONG,
+    pub dwControlKeyState: ULONG,
+}
+pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL;
+
 #[link(name = "ws2_32")]
 #[link(name = "userenv")]
 #[link(name = "shell32")]
@@ -848,12 +858,11 @@ pub fn WSASocketW(af: c_int,
     pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
     pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
 
-    // FIXME - pInputControl should be PCONSOLE_READCONSOLE_CONTROL
     pub fn ReadConsoleW(hConsoleInput: HANDLE,
                         lpBuffer: LPVOID,
                         nNumberOfCharsToRead: DWORD,
                         lpNumberOfCharsRead: LPDWORD,
-                        pInputControl: LPVOID) -> BOOL;
+                        pInputControl: PCONSOLE_READCONSOLE_CONTROL) -> BOOL;
 
     pub fn WriteConsoleW(hConsoleOutput: HANDLE,
                          lpBuffer: LPCVOID,
index 10b86ba44bc793a734e4131e323fd09c261a46e3..fdb9483fe1c8b0ed0aab3d708b194460591486ca 100644 (file)
@@ -19,7 +19,6 @@
 use sys::c;
 use sys::cvt;
 use sys_common::io::read_to_end_uninitialized;
-use u32;
 
 /// An owned container for `HANDLE` object, closing them on Drop.
 ///
@@ -83,9 +82,7 @@ pub fn raw(&self) -> c::HANDLE { self.0 }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         let mut read = 0;
-        // ReadFile takes a DWORD (u32) for the length so it only supports
-        // reading u32::MAX bytes at a time.
-        let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD;
+        let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
         let res = cvt(unsafe {
             c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID,
                         len, &mut read, ptr::null_mut())
@@ -181,9 +178,7 @@ pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         let mut amt = 0;
-        // WriteFile takes a DWORD (u32) for the length so it only supports
-        // writing u32::MAX bytes at a time.
-        let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD;
+        let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
         cvt(unsafe {
             c::WriteFile(self.0, buf.as_ptr() as c::LPVOID,
                          len, &mut amt, ptr::null_mut())
index a74e7699ba0fd6421911fce216ce83647d2657ba..b1a57c349fbb909e942fc854571ed57967e708ee 100644 (file)
@@ -111,19 +111,27 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         if utf8.position() as usize == utf8.get_ref().len() {
             let mut utf16 = vec![0u16; 0x1000];
             let mut num = 0;
+            let mut input_control = readconsole_input_control(CTRL_Z_MASK);
             cvt(unsafe {
                 c::ReadConsoleW(handle,
                                 utf16.as_mut_ptr() as c::LPVOID,
                                 utf16.len() as u32,
                                 &mut num,
-                                ptr::null_mut())
+                                &mut input_control as c::PCONSOLE_READCONSOLE_CONTROL)
             })?;
             utf16.truncate(num as usize);
             // FIXME: what to do about this data that has already been read?
-            let data = match String::from_utf16(&utf16) {
+            let mut data = match String::from_utf16(&utf16) {
                 Ok(utf8) => utf8.into_bytes(),
                 Err(..) => return Err(invalid_encoding()),
             };
+            if let Output::Console(_) = self.handle {
+                if let Some(&last_byte) = data.last() {
+                    if last_byte == CTRL_Z {
+                        data.pop();
+                    }
+                }
+            }
             *utf8 = Cursor::new(data);
         }
 
@@ -217,6 +225,18 @@ fn invalid_encoding() -> io::Error {
     io::Error::new(io::ErrorKind::InvalidData, "text was not valid unicode")
 }
 
+fn readconsole_input_control(wakeup_mask: c::ULONG) -> c::CONSOLE_READCONSOLE_CONTROL {
+    c::CONSOLE_READCONSOLE_CONTROL {
+        nLength: ::mem::size_of::<c::CONSOLE_READCONSOLE_CONTROL>() as c::ULONG,
+        nInitialChars: 0,
+        dwCtrlWakeupMask: wakeup_mask,
+        dwControlKeyState: 0,
+    }
+}
+
+const CTRL_Z: u8 = 0x1A;
+const CTRL_Z_MASK: c::ULONG = 0x4000000; //1 << 0x1A
+
 pub const EBADF_ERR: i32 = ::sys::c::ERROR_INVALID_HANDLE as i32;
 // The default buffer capacity is 64k, but apparently windows
 // doesn't like 64k reads on stdin. See #13304 for details, but the
index 2a3fb5ec43f2abeb8a33df697a94e382217d7f65..81979fd41a6bf6f16ed820eb705973831b46328c 100644 (file)
 
 /// Thread configuration. Provides detailed control over the properties
 /// and behavior of new threads.
+///
+/// # Examples
+///
+/// ```
+/// use std::thread;
+///
+/// let builder = thread::Builder::new();
+///
+/// let handler = builder.spawn(|| {
+///     // thread code
+/// }).unwrap();
+///
+/// handler.join().unwrap();
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Builder {
@@ -228,6 +242,22 @@ pub struct Builder {
 impl Builder {
     /// Generates the base configuration for spawning a thread, from which
     /// configuration methods can be chained.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    ///
+    /// let builder = thread::Builder::new()
+    ///                               .name("foo".into())
+    ///                               .stack_size(10);
+    ///
+    /// let handler = builder.spawn(|| {
+    ///     // thread code
+    /// }).unwrap();
+    ///
+    /// handler.join().unwrap();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> Builder {
         Builder {
@@ -241,7 +271,7 @@ pub fn new() -> Builder {
     ///
     /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// use std::thread;
     ///
     /// let builder = thread::Builder::new()
@@ -260,6 +290,14 @@ pub fn name(mut self, name: String) -> Builder {
     }
 
     /// Sets the size of the stack for the new thread.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    ///
+    /// let builder = thread::Builder::new().stack_size(10);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn stack_size(mut self, size: usize) -> Builder {
         self.stack_size = Some(size);
@@ -275,9 +313,26 @@ pub fn stack_size(mut self, size: usize) -> Builder {
     ///
     /// # Errors
     ///
-    /// Unlike the `spawn` free function, this method yields an
-    /// `io::Result` to capture any failure to create the thread at
+    /// Unlike the [`spawn`] free function, this method yields an
+    /// [`io::Result`] to capture any failure to create the thread at
     /// the OS level.
+    ///
+    /// [`spawn`]: ../../std/thread/fn.spawn.html
+    /// [`io::Result`]: ../../std/io/type.Result.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    ///
+    /// let builder = thread::Builder::new();
+    ///
+    /// let handler = builder.spawn(|| {
+    ///     // thread code
+    /// }).unwrap();
+    ///
+    /// handler.join().unwrap();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
         F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
@@ -318,20 +373,38 @@ pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
 // Free functions
 ////////////////////////////////////////////////////////////////////////////////
 
-/// Spawns a new thread, returning a `JoinHandle` for it.
+/// Spawns a new thread, returning a [`JoinHandle`] for it.
 ///
 /// The join handle will implicitly *detach* the child thread upon being
 /// dropped. In this case, the child thread may outlive the parent (unless
 /// the parent thread is the main thread; the whole process is terminated when
-/// the main thread finishes.) Additionally, the join handle provides a `join`
+/// the main thread finishes). Additionally, the join handle provides a [`join`]
 /// method that can be used to join the child thread. If the child thread
-/// panics, `join` will return an `Err` containing the argument given to
-/// `panic`.
+/// panics, [`join`] will return an [`Err`] containing the argument given to
+/// [`panic`].
 ///
 /// # Panics
 ///
-/// Panics if the OS fails to create a thread; use `Builder::spawn`
+/// 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
+///
+/// ```
+/// use std::thread;
+///
+/// let handler = thread::spawn(|| {
+///     // thread code
+/// });
+///
+/// handler.join().unwrap();
+/// ```
 #[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
@@ -341,7 +414,7 @@ pub fn spawn<F, T>(f: F) -> JoinHandle<T> where
 
 /// Gets a handle to the thread that invokes it.
 ///
-/// #Examples
+/// # Examples
 ///
 /// Getting a handle to the current thread with `thread::current()`:
 ///
@@ -366,6 +439,14 @@ pub fn current() -> Thread {
 }
 
 /// Cooperatively gives up a timeslice to the OS scheduler.
+///
+/// # Examples
+///
+/// ```
+/// use std::thread;
+///
+/// thread::yield_now();
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn yield_now() {
     imp::Thread::yield_now()
@@ -375,7 +456,7 @@ pub fn yield_now() {
 ///
 /// # Examples
 ///
-/// ```rust,should_panic
+/// ```should_panic
 /// use std::thread;
 ///
 /// struct SomeStruct;
@@ -413,6 +494,15 @@ pub fn panicking() -> bool {
 /// specifics or platform-dependent functionality. Note that on unix platforms
 /// this function will not return early due to a signal being received or a
 /// spurious wakeup.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::thread;
+///
+/// // Let's sleep for 2 seconds:
+/// thread::sleep_ms(2000);
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_deprecated(since = "1.6.0", reason = "replaced by `std::thread::sleep`")]
 pub fn sleep_ms(ms: u32) {
@@ -433,7 +523,7 @@ pub fn sleep_ms(ms: u32) {
 ///
 /// # Examples
 ///
-/// ```rust,no_run
+/// ```no_run
 /// use std::{thread, time};
 ///
 /// let ten_millis = time::Duration::from_millis(10);
@@ -749,7 +839,7 @@ fn join(&mut self) -> Result<T> {
 ///
 /// A `JoinHandle` *detaches* the child thread when it is dropped.
 ///
-/// Due to platform restrictions, it is not possible to `Clone` this
+/// Due to platform restrictions, it is not possible to [`Clone`] this
 /// handle: the ability to join a child thread is a uniquely-owned
 /// permission.
 ///
@@ -760,7 +850,7 @@ fn join(&mut self) -> Result<T> {
 ///
 /// Creation from [`thread::spawn`]:
 ///
-/// ```rust
+/// ```
 /// use std::thread;
 ///
 /// let join_handle: thread::JoinHandle<_> = thread::spawn(|| {
@@ -770,7 +860,7 @@ fn join(&mut self) -> Result<T> {
 ///
 /// Creation from [`thread::Builder::spawn`]:
 ///
-/// ```rust
+/// ```
 /// use std::thread;
 ///
 /// let builder = thread::Builder::new();
@@ -780,13 +870,31 @@ fn join(&mut self) -> Result<T> {
 /// }).unwrap();
 /// ```
 ///
+/// [`Clone`]: ../../std/clone/trait.Clone.html
 /// [`thread::spawn`]: fn.spawn.html
 /// [`thread::Builder::spawn`]: struct.Builder.html#method.spawn
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct JoinHandle<T>(JoinInner<T>);
 
 impl<T> JoinHandle<T> {
-    /// Extracts a handle to the underlying thread
+    /// Extracts a handle to the underlying thread.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(thread_id)]
+    ///
+    /// use std::thread;
+    ///
+    /// let builder = thread::Builder::new();
+    ///
+    /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| {
+    ///     // some work here
+    /// }).unwrap();
+    ///
+    /// let thread = join_handle.thread();
+    /// println!("thread id: {:?}", thread.id());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn thread(&self) -> &Thread {
         &self.0.thread
@@ -794,8 +902,24 @@ pub fn thread(&self) -> &Thread {
 
     /// Waits for the associated thread to finish.
     ///
-    /// If the child thread panics, `Err` is returned with the parameter given
-    /// to `panic`.
+    /// If the child thread panics, [`Err`] is returned with the parameter given
+    /// to [`panic`].
+    ///
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+    /// [`panic!`]: ../../std/macro.panic.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    ///
+    /// let builder = thread::Builder::new();
+    ///
+    /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| {
+    ///     // some work here
+    /// }).unwrap();
+    /// join_handle.join().expect("Couldn't join on the associated thread");
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn join(mut self) -> Result<T> {
         self.0.join()
index a39cac8db99171a26b08a163461d387d774d94dc..0cc62fb43a54d270cbf287167944c44782fd41f1 100644 (file)
@@ -41,6 +41,7 @@ pub enum Abi {
     Aapcs,
     Win64,
     SysV64,
+    PtxKernel,
 
     // Multiplatform / generic ABIs
     Rust,
@@ -82,6 +83,7 @@ pub struct AbiData {
     AbiData {abi: Abi::Aapcs, name: "aapcs", generic: false },
     AbiData {abi: Abi::Win64, name: "win64", generic: false },
     AbiData {abi: Abi::SysV64, name: "sysv64", generic: false },
+    AbiData {abi: Abi::PtxKernel, name: "ptx-kernel", generic: false },
 
     // Cross-platform ABIs
     AbiData {abi: Abi::Rust, name: "Rust", generic: true },
index fdd82225b974747990adb31c6a9d8067499011d2..f72985fd91a3ea1702e42221ccb864433522fc49 100644 (file)
@@ -111,10 +111,8 @@ pub struct LifetimeDef {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
 pub struct Path {
     pub span: Span,
-    /// A `::foo` path, is relative to the crate root rather than current
-    /// module (like paths in an import).
-    pub global: bool,
     /// The segments in the path: the things separated by `::`.
+    /// Global paths begin with `keywords::CrateRoot`.
     pub segments: Vec<PathSegment>,
 }
 
@@ -136,10 +134,22 @@ impl Path {
     pub fn from_ident(s: Span, identifier: Ident) -> Path {
         Path {
             span: s,
-            global: false,
             segments: vec![identifier.into()],
         }
     }
+
+    pub fn default_to_global(mut self) -> Path {
+        let name = self.segments[0].identifier.name;
+        if !self.is_global() && name != "$crate" &&
+           name != keywords::SelfValue.name() && name != keywords::Super.name() {
+            self.segments.insert(0, PathSegment::crate_root());
+        }
+        self
+    }
+
+    pub fn is_global(&self) -> bool {
+        !self.segments.is_empty() && self.segments[0].identifier.name == keywords::CrateRoot.name()
+    }
 }
 
 /// A segment of a path: an identifier, an optional lifetime, and a set of types.
@@ -166,6 +176,15 @@ fn from(id: Ident) -> Self {
     }
 }
 
+impl PathSegment {
+    pub fn crate_root() -> Self {
+        PathSegment {
+            identifier: keywords::CrateRoot.ident(),
+            parameters: None,
+        }
+    }
+}
+
 /// Parameters of a path segment.
 ///
 /// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
@@ -1452,12 +1471,13 @@ pub fn is_self(&self) -> bool {
     }
 
     pub fn from_self(eself: ExplicitSelf, eself_ident: SpannedIdent) -> Arg {
+        let span = mk_sp(eself.span.lo, eself_ident.span.hi);
         let infer_ty = P(Ty {
             id: DUMMY_NODE_ID,
             node: TyKind::ImplicitSelf,
-            span: DUMMY_SP,
+            span: span,
         });
-        let arg = |mutbl, ty, span| Arg {
+        let arg = |mutbl, ty| Arg {
             pat: P(Pat {
                 id: DUMMY_NODE_ID,
                 node: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
@@ -1467,15 +1487,13 @@ pub fn from_self(eself: ExplicitSelf, eself_ident: SpannedIdent) -> Arg {
             id: DUMMY_NODE_ID,
         };
         match eself.node {
-            SelfKind::Explicit(ty, mutbl) => {
-                arg(mutbl, ty, mk_sp(eself.span.lo, eself_ident.span.hi))
-            }
-            SelfKind::Value(mutbl) => arg(mutbl, infer_ty, eself.span),
+            SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty),
+            SelfKind::Value(mutbl) => arg(mutbl, infer_ty),
             SelfKind::Region(lt, mutbl) => arg(Mutability::Immutable, P(Ty {
                 id: DUMMY_NODE_ID,
                 node: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl: mutbl }),
-                span: DUMMY_SP,
-            }), eself.span),
+                span: span,
+            })),
         }
     }
 }
@@ -1759,10 +1777,6 @@ pub fn is_unit(&self) -> bool {
     }
 }
 
-/*
-  FIXME (#3300): Should allow items to be anonymous. Right now
-  we just use dummy names for anon items.
- */
 /// An item
 ///
 /// The name might be a dummy name in case of anonymous items
index 8e63f73fdaa7a1f7c6df130338a472fdcbbf6fe8..68d261c64f83cfd9180eb036a7fcb8f92bb2b1f1 100644 (file)
@@ -516,6 +516,7 @@ pub trait Resolver {
     fn next_node_id(&mut self) -> ast::NodeId;
     fn get_module_scope(&mut self, id: ast::NodeId) -> Mark;
     fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>;
+    fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool;
 
     fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion);
     fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>);
@@ -539,6 +540,7 @@ impl Resolver for DummyResolver {
     fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID }
     fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }
     fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
+    fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false }
 
     fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
     fn add_ext(&mut self, _ident: ast::Ident, _ext: Rc<SyntaxExtension>) {}
index c3dc64f91247bed799f59ed813dff72b423217f9..7584fa3916de01d77c9398c2b5e459c83d3d95fb 100644 (file)
@@ -322,7 +322,12 @@ fn path_all(&self,
                 bindings: Vec<ast::TypeBinding> )
                 -> ast::Path {
         let last_identifier = idents.pop().unwrap();
-        let mut segments: Vec<ast::PathSegment> = idents.into_iter().map(Into::into).collect();
+        let mut segments: Vec<ast::PathSegment> = Vec::new();
+        if global {
+            segments.push(ast::PathSegment::crate_root());
+        }
+
+        segments.extend(idents.into_iter().map(Into::into));
         let parameters = if lifetimes.is_empty() && types.is_empty() && bindings.is_empty() {
             None
         } else {
@@ -335,7 +340,6 @@ fn path_all(&self,
         segments.push(ast::PathSegment { identifier: last_identifier, parameters: parameters });
         ast::Path {
             span: sp,
-            global: global,
             segments: segments,
         }
     }
index eb4b6144c8d28ad989d2044710ed2cda42b3f49f..66555d7d95dce03c0ca9b0bda7dfbf18ba857473 100644 (file)
@@ -25,7 +25,7 @@
 pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
     fn mac_placeholder() -> ast::Mac {
         dummy_spanned(ast::Mac_ {
-            path: ast::Path { span: DUMMY_SP, global: false, segments: Vec::new() },
+            path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
             tts: Vec::new(),
         })
     }
index e04cc11f15e14dc2deba84907cadc8a7b3b49942..625af803458b5bd939782b4a4dafb698342b9e78 100644 (file)
@@ -318,6 +318,9 @@ pub fn new() -> Features {
 
     // Allow safe suggestions for potential type conversions.
     (active, safe_suggestion, "1.0.0", Some(37384)),
+
+    // `extern "ptx-*" fn()`
+    (active, abi_ptx, "1.15.0", None),
 );
 
 declare_features! (
@@ -986,7 +989,19 @@ fn check_abi(&self, abi: Abi, span: Span) {
                 gate_feature_post!(&self, abi_sysv64, span,
                                    "sysv64 ABI is experimental and subject to change");
             },
-            _ => {}
+            Abi::PtxKernel => {
+                gate_feature_post!(&self, abi_ptx, span,
+                                   "PTX ABIs are experimental and subject to change");
+            }
+            // Stable
+            Abi::Cdecl |
+            Abi::Stdcall |
+            Abi::Fastcall |
+            Abi::Aapcs |
+            Abi::Win64 |
+            Abi::Rust |
+            Abi::C |
+            Abi::System => {}
         }
     }
 }
index b3753e3e977e331cf424d382694f2bcd28ff0c34..9797e0003fc55865321d22a8ea6c453ee8d491f9 100644 (file)
@@ -302,23 +302,22 @@ pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<
     view_path.map(|Spanned {node, span}| Spanned {
         node: match node {
             ViewPathSimple(ident, path) => {
-                ViewPathSimple(ident, fld.fold_path(path))
+                ViewPathSimple(fld.fold_ident(ident), fld.fold_path(path))
             }
             ViewPathGlob(path) => {
                 ViewPathGlob(fld.fold_path(path))
             }
             ViewPathList(path, path_list_idents) => {
-                ViewPathList(fld.fold_path(path),
-                             path_list_idents.move_map(|path_list_ident| {
-                                Spanned {
-                                    node: PathListItem_ {
-                                        id: fld.new_id(path_list_ident.node.id),
-                                        rename: path_list_ident.node.rename,
-                                        name: path_list_ident.node.name,
-                                    },
-                                    span: fld.new_span(path_list_ident.span)
-                                }
-                             }))
+                let path = fld.fold_path(path);
+                let path_list_idents = path_list_idents.move_map(|path_list_ident| Spanned {
+                    node: PathListItem_ {
+                        id: fld.new_id(path_list_ident.node.id),
+                        rename: path_list_ident.node.rename.map(|ident| fld.fold_ident(ident)),
+                        name: fld.fold_ident(path_list_ident.node.name),
+                    },
+                    span: fld.new_span(path_list_ident.span)
+                });
+                ViewPathList(path, path_list_idents)
             }
         },
         span: fld.new_span(span)
@@ -345,7 +344,7 @@ pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm, fld: &mut T
 pub fn noop_fold_ty_binding<T: Folder>(b: TypeBinding, fld: &mut T) -> TypeBinding {
     TypeBinding {
         id: fld.new_id(b.id),
-        ident: b.ident,
+        ident: fld.fold_ident(b.ident),
         ty: fld.fold_ty(b.ty),
         span: fld.new_span(b.span),
     }
@@ -433,9 +432,8 @@ pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize {
     i
 }
 
-pub fn noop_fold_path<T: Folder>(Path {global, segments, span}: Path, fld: &mut T) -> Path {
+pub fn noop_fold_path<T: Folder>(Path { segments, span }: Path, fld: &mut T) -> Path {
     Path {
-        global: global,
         segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment {
             identifier: fld.fold_ident(identifier),
             parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))),
@@ -673,7 +671,7 @@ pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
             .collect::<Vec<_>>()
             .into(),
         id: fld.new_id(id),
-        ident: ident,
+        ident: fld.fold_ident(ident),
         bounds: fld.fold_bounds(bounds),
         default: default.map(|x| fld.fold_ty(x)),
         span: span
@@ -1088,7 +1086,7 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
                 let fs = fields.move_map(|f| {
                     Spanned { span: folder.new_span(f.span),
                               node: ast::FieldPat {
-                                  ident: f.node.ident,
+                                  ident: folder.fold_ident(f.node.ident),
                                   pat: folder.fold_pat(f.node.pat),
                                   is_shorthand: f.node.is_shorthand,
                               }}
index b9e6605639ead2c8ff0f8ee61cd0814c5df31738..24178e1f675b5197d218017aa558a5013b537932 100644 (file)
@@ -633,7 +633,6 @@ fn sp(a: u32, b: u32) -> Span {
                     id: ast::DUMMY_NODE_ID,
                     node: ast::ExprKind::Path(None, ast::Path {
                         span: sp(0, 1),
-                        global: false,
                         segments: vec![Ident::from_str("a").into()],
                     }),
                     span: sp(0, 1),
@@ -647,8 +646,9 @@ fn sp(a: u32, b: u32) -> Span {
                     id: ast::DUMMY_NODE_ID,
                     node: ast::ExprKind::Path(None, ast::Path {
                         span: sp(0, 6),
-                        global: true,
-                        segments: vec![Ident::from_str("a").into(), Ident::from_str("b").into()],
+                        segments: vec![ast::PathSegment::crate_root(),
+                                       Ident::from_str("a").into(),
+                                       Ident::from_str("b").into()]
                     }),
                     span: sp(0, 6),
                     attrs: ThinVec::new(),
@@ -757,7 +757,6 @@ fn string_to_tts_1() {
                         id: ast::DUMMY_NODE_ID,
                         node:ast::ExprKind::Path(None, ast::Path{
                             span: sp(7, 8),
-                            global: false,
                             segments: vec![Ident::from_str("d").into()],
                         }),
                         span:sp(7,8),
@@ -775,7 +774,6 @@ fn string_to_tts_1() {
                            id: ast::DUMMY_NODE_ID,
                            node: ast::ExprKind::Path(None, ast::Path {
                                span:sp(0,1),
-                               global:false,
                                segments: vec![Ident::from_str("b").into()],
                             }),
                            span: sp(0,1),
@@ -817,7 +815,6 @@ fn parser_done(p: Parser){
                                     ty: P(ast::Ty{id: ast::DUMMY_NODE_ID,
                                                   node: ast::TyKind::Path(None, ast::Path{
                                         span:sp(10,13),
-                                        global:false,
                                         segments: vec![Ident::from_str("i32").into()],
                                         }),
                                         span:sp(10,13)
@@ -860,7 +857,6 @@ fn parser_done(p: Parser){
                                                 node: ast::ExprKind::Path(None,
                                                       ast::Path{
                                                         span:sp(17,18),
-                                                        global:false,
                                                         segments: vec![Ident::from_str("b").into()],
                                                       }),
                                                 span: sp(17,18),
index 72462b74e686ca60b1f002f220738dd7e55b162f..a0ed50b33a46c8709e18c9dc9ec5c55c8e850233 100644 (file)
@@ -1614,7 +1614,6 @@ pub fn parse_qualified_path(&mut self, mode: PathStyle)
         } else {
             ast::Path {
                 span: span,
-                global: false,
                 segments: vec![]
             }
         };
@@ -1658,7 +1657,7 @@ pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> {
         // Parse any number of segments and bound sets. A segment is an
         // identifier followed by an optional lifetime and a set of types.
         // A bound set is a set of type parameter bounds.
-        let segments = match mode {
+        let mut segments = match mode {
             PathStyle::Type => {
                 self.parse_path_segments_without_colons()?
             }
@@ -1670,13 +1669,16 @@ pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> {
             }
         };
 
+        if is_global {
+            segments.insert(0, ast::PathSegment::crate_root());
+        }
+
         // Assemble the span.
         let span = mk_sp(lo, self.prev_span.hi);
 
         // Assemble the result.
         Ok(ast::Path {
             span: span,
-            global: is_global,
             segments: segments,
         })
     }
@@ -4366,6 +4368,23 @@ pub fn parse_where_clause(&mut self) -> PResult<'a, ast::WhereClause> {
             return Ok(where_clause);
         }
 
+        // This is a temporary hack.
+        //
+        // We are considering adding generics to the `where` keyword as an alternative higher-rank
+        // parameter syntax (as in `where<'a>` or `where<T>`. To avoid that being a breaking
+        // change, for now we refuse to parse `where < (ident | lifetime) (> | , | :)`.
+        if token::Lt == self.token {
+            let ident_or_lifetime = self.look_ahead(1, |t| t.is_ident() || t.is_lifetime());
+            if ident_or_lifetime {
+                let gt_comma_or_colon = self.look_ahead(2, |t| {
+                    *t == token::Gt || *t == token::Comma || *t == token::Colon
+                });
+                if gt_comma_or_colon {
+                    self.span_err(self.span, "syntax `where<T>` is reserved for future use");
+                }
+            }
+        }
+
         let mut parsed_something = false;
         loop {
             let lo = self.span.lo;
@@ -5180,7 +5199,7 @@ fn parse_visibility(&mut self, allow_path: bool) -> PResult<'a, Visibility> {
         } else if self.eat_keyword(keywords::Crate) {
             pub_crate(self)
         } else {
-            let path = self.parse_path(PathStyle::Mod)?;
+            let path = self.parse_path(PathStyle::Mod)?.default_to_global();
             self.expect(&token::CloseDelim(token::Paren))?;
             Ok(Visibility::Restricted { path: P(path), id: ast::DUMMY_NODE_ID })
         }
@@ -6068,9 +6087,9 @@ fn parse_view_path(&mut self) -> PResult<'a, P<ViewPath>> {
         if self.check(&token::OpenDelim(token::Brace)) || self.check(&token::BinOp(token::Star)) ||
            self.is_import_coupler() {
             // `{foo, bar}`, `::{foo, bar}`, `*`, or `::*`.
+            self.eat(&token::ModSep);
             let prefix = ast::Path {
-                global: self.eat(&token::ModSep),
-                segments: Vec::new(),
+                segments: vec![ast::PathSegment::crate_root()],
                 span: mk_sp(lo, self.span.hi),
             };
             let view_path_kind = if self.eat(&token::BinOp(token::Star)) {
@@ -6080,7 +6099,7 @@ fn parse_view_path(&mut self) -> PResult<'a, P<ViewPath>> {
             };
             Ok(P(spanned(lo, self.span.hi, view_path_kind)))
         } else {
-            let prefix = self.parse_path(PathStyle::Mod)?;
+            let prefix = self.parse_path(PathStyle::Mod)?.default_to_global();
             if self.is_import_coupler() {
                 // `foo::bar::{a, b}` or `foo::bar::*`
                 self.bump();
index 22e8391de93ed4910d9fbf988db6e3093392c844..7558f0256da18986c1897fa021431e15fe90af79 100644 (file)
@@ -371,7 +371,7 @@ pub fn fn_block_to_string(p: &ast::FnDecl) -> String {
 }
 
 pub fn path_to_string(p: &ast::Path) -> String {
-    to_string(|s| s.print_path(p, false, 0))
+    to_string(|s| s.print_path(p, false, 0, false))
 }
 
 pub fn ident_to_string(id: ast::Ident) -> String {
@@ -435,7 +435,8 @@ pub fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String {
     match *vis {
         ast::Visibility::Public => format!("pub {}", s),
         ast::Visibility::Crate(_) => format!("pub(crate) {}", s),
-        ast::Visibility::Restricted { ref path, .. } => format!("pub({}) {}", path, s),
+        ast::Visibility::Restricted { ref path, .. } =>
+            format!("pub({}) {}", to_string(|s| s.print_path(path, false, 0, true)), s),
         ast::Visibility::Inherited => s.to_string()
     }
 }
@@ -1021,7 +1022,7 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
                                  &generics));
             }
             ast::TyKind::Path(None, ref path) => {
-                try!(self.print_path(path, false, 0));
+                try!(self.print_path(path, false, 0, false));
             }
             ast::TyKind::Path(Some(ref qself), ref path) => {
                 try!(self.print_qpath(path, qself, false))
@@ -1332,7 +1333,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
             }
             ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => {
                 try!(self.print_visibility(&item.vis));
-                try!(self.print_path(&node.path, false, 0));
+                try!(self.print_path(&node.path, false, 0, false));
                 try!(word(&mut self.s, "! "));
                 try!(self.print_ident(item.ident));
                 try!(self.cbox(INDENT_UNIT));
@@ -1347,7 +1348,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
     }
 
     fn print_trait_ref(&mut self, t: &ast::TraitRef) -> io::Result<()> {
-        self.print_path(&t.path, false, 0)
+        self.print_path(&t.path, false, 0, false)
     }
 
     fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> io::Result<()> {
@@ -1405,8 +1406,10 @@ pub fn print_visibility(&mut self, vis: &ast::Visibility) -> io::Result<()> {
         match *vis {
             ast::Visibility::Public => self.word_nbsp("pub"),
             ast::Visibility::Crate(_) => self.word_nbsp("pub(crate)"),
-            ast::Visibility::Restricted { ref path, .. } =>
-                self.word_nbsp(&format!("pub({})", path)),
+            ast::Visibility::Restricted { ref path, .. } => {
+                let path = to_string(|s| s.print_path(path, false, 0, true));
+                self.word_nbsp(&format!("pub({})", path))
+            }
             ast::Visibility::Inherited => Ok(())
         }
     }
@@ -1571,7 +1574,7 @@ pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
             }
             ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => {
                 // code copied from ItemKind::Mac:
-                self.print_path(&node.path, false, 0)?;
+                self.print_path(&node.path, false, 0, false)?;
                 word(&mut self.s, "! ")?;
                 self.cbox(INDENT_UNIT)?;
                 self.popen()?;
@@ -1607,7 +1610,7 @@ pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
             }
             ast::ImplItemKind::Macro(codemap::Spanned { ref node, .. }) => {
                 // code copied from ItemKind::Mac:
-                try!(self.print_path(&node.path, false, 0));
+                try!(self.print_path(&node.path, false, 0, false));
                 try!(word(&mut self.s, "! "));
                 try!(self.cbox(INDENT_UNIT));
                 try!(self.popen());
@@ -1793,7 +1796,7 @@ pub fn print_if_let(&mut self, pat: &ast::Pat, expr: &ast::Expr, blk: &ast::Bloc
 
     pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken)
                      -> io::Result<()> {
-        try!(self.print_path(&m.node.path, false, 0));
+        try!(self.print_path(&m.node.path, false, 0, false));
         try!(word(&mut self.s, "!"));
         match delim {
             token::Paren => try!(self.popen()),
@@ -1885,7 +1888,7 @@ fn print_expr_struct(&mut self,
                          fields: &[ast::Field],
                          wth: &Option<P<ast::Expr>>,
                          attrs: &[Attribute]) -> io::Result<()> {
-        try!(self.print_path(path, true, 0));
+        try!(self.print_path(path, true, 0, false));
         try!(word(&mut self.s, "{"));
         try!(self.print_inner_attributes_inline(attrs));
         try!(self.commasep_cmnt(
@@ -2186,7 +2189,7 @@ fn print_expr_outer_attr_style(&mut self,
                 }
             }
             ast::ExprKind::Path(None, ref path) => {
-                try!(self.print_path(path, true, 0))
+                try!(self.print_path(path, true, 0, false))
             }
             ast::ExprKind::Path(Some(ref qself), ref path) => {
                 try!(self.print_qpath(path, qself, true))
@@ -2334,23 +2337,26 @@ pub fn print_for_decl(&mut self, loc: &ast::Local,
     fn print_path(&mut self,
                   path: &ast::Path,
                   colons_before_params: bool,
-                  depth: usize)
+                  depth: usize,
+                  defaults_to_global: bool)
                   -> io::Result<()>
     {
         try!(self.maybe_print_comment(path.span.lo));
 
-        let mut first = !path.global;
-        for segment in &path.segments[..path.segments.len()-depth] {
-            if first {
-                first = false
-            } else {
+        let mut segments = path.segments[..path.segments.len()-depth].iter();
+        if defaults_to_global && path.is_global() {
+            segments.next();
+        }
+        for (i, segment) in segments.enumerate() {
+            if i > 0 {
                 try!(word(&mut self.s, "::"))
             }
-
-            try!(self.print_ident(segment.identifier));
-
-            if let Some(ref parameters) = segment.parameters {
-                try!(self.print_path_parameters(parameters, colons_before_params))
+            if segment.identifier.name != keywords::CrateRoot.name() &&
+               segment.identifier.name != "$crate" {
+                try!(self.print_ident(segment.identifier));
+                if let Some(ref parameters) = segment.parameters {
+                    try!(self.print_path_parameters(parameters, colons_before_params));
+                }
             }
         }
 
@@ -2369,7 +2375,7 @@ fn print_qpath(&mut self,
             try!(space(&mut self.s));
             try!(self.word_space("as"));
             let depth = path.segments.len() - qself.position;
-            try!(self.print_path(&path, false, depth));
+            try!(self.print_path(&path, false, depth, false));
         }
         try!(word(&mut self.s, ">"));
         try!(word(&mut self.s, "::"));
@@ -2472,7 +2478,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
                 }
             }
             PatKind::TupleStruct(ref path, ref elts, ddpos) => {
-                try!(self.print_path(path, true, 0));
+                try!(self.print_path(path, true, 0, false));
                 try!(self.popen());
                 if let Some(ddpos) = ddpos {
                     try!(self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p)));
@@ -2490,13 +2496,13 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
                 try!(self.pclose());
             }
             PatKind::Path(None, ref path) => {
-                try!(self.print_path(path, true, 0));
+                try!(self.print_path(path, true, 0, false));
             }
             PatKind::Path(Some(ref qself), ref path) => {
                 try!(self.print_qpath(path, qself, false));
             }
             PatKind::Struct(ref path, ref fields, etc) => {
-                try!(self.print_path(path, true, 0));
+                try!(self.print_path(path, true, 0, false));
                 try!(self.nbsp());
                 try!(self.word_space("{"));
                 try!(self.commasep_cmnt(
@@ -2843,7 +2849,7 @@ pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause)
                     try!(self.print_lifetime_bounds(lifetime, bounds));
                 }
                 ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
-                    try!(self.print_path(path, false, 0));
+                    try!(self.print_path(path, false, 0, false));
                     try!(space(&mut self.s));
                     try!(self.word_space("="));
                     try!(self.print_type(&ty));
@@ -2857,7 +2863,7 @@ pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause)
     pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> io::Result<()> {
         match vp.node {
             ast::ViewPathSimple(ident, ref path) => {
-                try!(self.print_path(path, false, 0));
+                try!(self.print_path(path, false, 0, true));
 
                 if path.segments.last().unwrap().identifier.name !=
                         ident.name {
@@ -2870,7 +2876,7 @@ pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> io::Result<()> {
             }
 
             ast::ViewPathGlob(ref path) => {
-                try!(self.print_path(path, false, 0));
+                try!(self.print_path(path, false, 0, true));
                 word(&mut self.s, "::*")
             }
 
@@ -2878,7 +2884,7 @@ pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> io::Result<()> {
                 if path.segments.is_empty() {
                     try!(word(&mut self.s, "{"));
                 } else {
-                    try!(self.print_path(path, false, 0));
+                    try!(self.print_path(path, false, 0, true));
                     try!(word(&mut self.s, "::{"));
                 }
                 try!(self.commasep(Inconsistent, &idents[..], |s, w| {
index 4ad760a3cafe4194ca60be1ec28fb9e5c5c12168..68d807b24a788547bc8516c68dbffd496e4ce353 100644 (file)
@@ -80,8 +80,7 @@ pub fn maybe_inject_crates_ref(sess: &ParseSess,
         }],
         vis: ast::Visibility::Inherited,
         node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path {
-            global: false,
-            segments: vec![name, "prelude", "v1"].into_iter().map(|name| {
+            segments: ["{{root}}", name, "prelude", "v1"].into_iter().map(|name| {
                 ast::Ident::from_str(name).into()
             }).collect(),
             span: span,
index fe9a176179ce67aebc42f13398c418b104c7f4cd..c2123ea5a079803a3897053afefec54656df786e 100644 (file)
@@ -221,6 +221,9 @@ fn fresh() -> Self {
     (53, Default,        "default")
     (54, StaticLifetime, "'static")
     (55, Union,          "union")
+
+    // A virtual keyword that resolves to the crate root when used in a lexical scope.
+    (56, CrateRoot, "{{root}}")
 }
 
 // If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
index 7709d3bd1cf1ce27e5bcd1492ac54a34a7ad08b8..b8e0b938814a76605dc24226e8c726c97cb30589 100644 (file)
@@ -579,7 +579,6 @@ fn nospan<T>(t: T) -> codemap::Spanned<T> {
 fn path_node(ids: Vec<Ident>) -> ast::Path {
     ast::Path {
         span: DUMMY_SP,
-        global: false,
         segments: ids.into_iter().map(Into::into).collect(),
     }
 }
index 1381490efa194b3bd7a1e7850aa35c394bae9a30..1fc1bdff593c2766fa16ab94bad998451f82e0ee 100644 (file)
@@ -61,7 +61,6 @@ impl Result {
         fn path(&self) -> ast::Path {
             ast::Path {
                 span: self.span,
-                global: false,
                 segments: vec![self.ident.into()],
             }
         }
index 51199819dfcd7dec64c15568222460ae7703e47b..7f187d8d1c1195a472d8a749ace01da3a892fa63 100644 (file)
@@ -363,15 +363,12 @@ struct Visitor<'a, 'b: 'a> {
 
     impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> {
         fn visit_ty(&mut self, ty: &'a ast::Ty) {
-            match ty.node {
-                ast::TyKind::Path(_, ref path) if !path.global => {
-                    if let Some(segment) = path.segments.first() {
-                        if self.ty_param_names.contains(&segment.identifier.name) {
-                            self.types.push(P(ty.clone()));
-                        }
+            if let ast::TyKind::Path(_, ref path) = ty.node {
+                if let Some(segment) = path.segments.first() {
+                    if self.ty_param_names.contains(&segment.identifier.name) {
+                        self.types.push(P(ty.clone()));
                     }
                 }
-                _ => {}
             }
 
             visit::walk_ty(self, ty)
index 535d7de19e341aa5432f89d3a57512cd21f19f08..0511b0d252b60b9fa2c0b4b6873ac0343a76a77c 100644 (file)
@@ -175,8 +175,10 @@ pub fn expand_derive(cx: &mut ExtCtxt,
                                            feature_gate::GateIssue::Language,
                                            feature_gate::EXPLAIN_CUSTOM_DERIVE);
         } else {
-            cx.span_warn(titem.span, feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE);
             let name = Symbol::intern(&format!("derive_{}", tname));
+            if !cx.resolver.is_whitelisted_legacy_custom_derive(name) {
+                cx.span_warn(titem.span, feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE);
+            }
             let mitem = cx.meta_word(titem.span, name);
             new_attributes.push(cx.attribute(mitem.span, mitem));
         }
index f5546b6aac4f5bfe54699d3c21c7fb2d09a3b4a4..82acbf934881dc1048dd98a151d15b900b170d22 100644 (file)
@@ -914,6 +914,11 @@ fn use_color(opts: &TestOpts) -> bool {
     }
 }
 
+#[cfg(target_os = "redox")]
+fn stdout_isatty() -> bool {
+    // FIXME: Implement isatty on Redox
+    false
+}
 #[cfg(unix)]
 fn stdout_isatty() -> bool {
     unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 }
@@ -1103,6 +1108,12 @@ struct SYSTEM_INFO {
         }
     }
 
+    #[cfg(target_os = "redox")]
+    fn num_cpus() -> usize {
+        // FIXME: Implement num_cpus on Redox
+        1
+    }
+
     #[cfg(any(target_os = "linux",
               target_os = "macos",
               target_os = "ios",
index f5fa66f1b0e5ae79ed948db604cca268696355a6..5d5845213e2301a7add72251249e2967416f9309 100644 (file)
@@ -150,6 +150,8 @@ from_rust(LLVMRustAttribute kind) {
       return Attribute::UWTable;
     case ZExt:
       return Attribute::ZExt;
+    case InReg:
+      return Attribute::InReg;
     default:
       llvm_unreachable("bad AttributeKind");
   }
index 73c8bb97a1435d2d05163a15a7f57df6187099a2..b74f491385820051170dfecf3b9c3b0acb880396 100644 (file)
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be forcibly 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.
-2016-12-16
+2016-12-19
index b8c4076f4ce45d3208c0766d4142c73eb925e7ec..8f7e0e3d918758281100c7ee17bf33dc2299084e 100644 (file)
@@ -98,6 +98,7 @@ enum LLVMRustAttribute {
     StructRet       = 16,
     UWTable         = 17,
     ZExt            = 18,
+    InReg           = 19,
 };
 
 typedef struct OpaqueRustString *RustStringRef;
index 187c56d7889ea52a27eb3d424a872f37e0e6558c..4be9e3e57baacbacef2d76e5630fd9a2f238fdca 100644 (file)
@@ -12,5 +12,5 @@
 # tarball for a stable release you'll likely see `1.x.0-$date` where `1.x.0` was
 # released on `$date`
 
-rustc: beta-2016-12-16
-cargo: fbeea902d2c9a5be6d99cc35681565d8f7832592
+rustc: beta-2016-12-20
+cargo: bfee18f73287687c543bda8c35e4e33808792715
diff --git a/src/test/codegen/fastcall-inreg.rs b/src/test/codegen/fastcall-inreg.rs
new file mode 100644 (file)
index 0000000..e1dda4d
--- /dev/null
@@ -0,0 +1,85 @@
+// 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.
+
+// Checks if the "fastcall" calling convention marks function arguments
+// as "inreg" like the C/C++ compilers for the platforms.
+// x86 only.
+
+// ignore-aarch64
+// ignore-aarch64_be
+// ignore-arm
+// ignore-armeb
+// ignore-avr
+// ignore-bpfel
+// ignore-bpfeb
+// ignore-hexagon
+// ignore-mips
+// ignore-mipsel
+// ignore-mips64
+// ignore-mips64el
+// ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-powerpc
+// ignore-r600
+// ignore-amdgcn
+// ignore-sparc
+// ignore-sparcv9
+// ignore-sparcel
+// ignore-s390x
+// ignore-tce
+// ignore-thumb
+// ignore-thumbeb
+// ignore-x86_64 no-ignore-x86
+// ignore-xcore
+// ignore-nvptx
+// ignore-nvptx64
+// ignore-le32
+// ignore-le64
+// ignore-amdil
+// ignore-amdil64
+// ignore-hsail
+// ignore-hsail64
+// ignore-spir
+// ignore-spir64
+// ignore-kalimba
+// ignore-shave
+// ignore-wasm32
+// ignore-wasm64
+
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+mod tests {
+    // CHECK: @f1(i32 inreg, i32 inreg, i32)
+    #[no_mangle]
+    extern "fastcall" fn f1(_: i32, _: i32, _: i32) {}
+
+    // CHECK: @f2(i32* inreg, i32* inreg, i32*)
+    #[no_mangle]
+    extern "fastcall" fn f2(_: *const i32, _: *const i32, _: *const i32) {}
+
+    // CHECK: @f3(float, i32 inreg, i32 inreg, i32)
+    #[no_mangle]
+    extern "fastcall" fn f3(_: f32, _: i32, _: i32, _: i32) {}
+
+    // CHECK: @f4(i32 inreg, float, i32 inreg, i32)
+    #[no_mangle]
+    extern "fastcall" fn f4(_: i32, _: f32, _: i32, _: i32) {}
+
+    // CHECK: @f5(i64, i32)
+    #[no_mangle]
+    extern "fastcall" fn f5(_: i64, _: i32) {}
+
+    // CHECK: @f6(i1 inreg zeroext, i32 inreg, i32)
+    #[no_mangle]
+    extern "fastcall" fn f6(_: bool, _: i32, _: i32) {}
+}
index f563a1f88d000acdb8e534629d25935c92a8e951..b0a2859a5dacb0032e8ad4426a16fbf72517e0a1 100644 (file)
@@ -14,5 +14,5 @@
 extern crate macro_crate_test;
 
 fn main() {
-    macro_crate_test::foo(); //~ ERROR unresolved name
+    macro_crate_test::foo(); //~ ERROR unresolved function `macro_crate_test::foo`
 }
index 8acab3369e48fb3ef3ba71b3c45160eaf2750970..149985717c6e011c9c4306f9ff1b662c881ddd06 100644 (file)
@@ -39,6 +39,6 @@ fn main() {
 
     assert_eq!(pprust::expr_to_string(&*quote_expr!(&cx, 23)), "23");
 
-    let expr = quote_expr!(&cx, 2 - $abcd + 7); //~ ERROR unresolved name `abcd`
+    let expr = quote_expr!(&cx, 2 - $abcd + 7); //~ ERROR unresolved value `abcd`
     assert_eq!(pprust::expr_to_string(&*expr), "2 - $abcd + 7");
 }
index 44f73e10e25d3d93c39c93593cefa774231b3cd9..03d47472093924f22e9212d7a1186f6b7bb148d3 100644 (file)
@@ -14,8 +14,8 @@ trait SomeTrait {
 
 fn main() {
     let trait_obj: &SomeTrait = SomeTrait;
-    //~^ ERROR E0425
-    //~| NOTE unresolved name
+    //~^ ERROR expected value, found trait `SomeTrait`
+    //~| NOTE not a value
     //~| ERROR E0038
     //~| method `foo` has no receiver
     //~| NOTE the trait `SomeTrait` cannot be made into an object
diff --git a/src/test/compile-fail/E0248.rs b/src/test/compile-fail/E0248.rs
deleted file mode 100644 (file)
index 25568a3..0000000
+++ /dev/null
@@ -1,18 +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.
-
-enum Foo {
-    Bar(u32),
-}
-
-fn do_something(x: Foo::Bar) { } //~ ERROR E0248
-                //~| NOTE value used as a type
-fn main() {
-}
index 98b700984a707c5729a9fdeb6cb45266551a2426..f5fea77cf9639a001500ece7b31521280b88a88e 100644 (file)
@@ -12,5 +12,4 @@ fn main () {
     struct Foo { a: bool };
 
     let f = Foo(); //~ ERROR E0423
-                   //~^ struct called like a function
 }
index 911007113d3d64804a3c8ab51eb1fd4293ed4280..445d0c5f3edc0db383c7925cdc243d22b23eab57 100644 (file)
@@ -14,10 +14,7 @@ impl Foo {
     fn bar(self) {}
 
     fn foo() {
-        self.bar();
-        //~^ ERROR `self` is not available in a static method [E0424]
-        //~| NOTE not available in static method
-        //~| NOTE maybe a `self` argument is missing?
+        self.bar(); //~ ERROR E0424
     }
 }
 
index 70f4b1107ad4dfa30a9213d38daacecf61b18839..3786282031f25b306971b60c593cc4b0f1ff5562 100644 (file)
@@ -10,7 +10,7 @@
 
 trait Foo {
     fn bar() {
-        Self; //~ ERROR E0425
+        elf; //~ ERROR E0425
     }
 }
 
diff --git a/src/test/compile-fail/E0513.rs b/src/test/compile-fail/E0513.rs
deleted file mode 100644 (file)
index 726e232..0000000
+++ /dev/null
@@ -1,19 +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.
-
-use std::mem;
-
-fn main() {
-    unsafe {
-        let size = mem::size_of::<u32>();
-        mem::transmute_copy::<u32, [u8; size]>(&8_8); //~ ERROR E0513
-                                                      //~| NOTE no type for variable
-    }
-}
index c3fa39659b968217fb83481c75edea49d0855a37..7c3f7a1d574f99fea3df47f3b596ba8f4ad3a9e0 100644 (file)
@@ -25,8 +25,10 @@ impl Foo for Def {
 }
 
 pub fn test<A: Foo, B: Foo>() {
-    let _array = [4; <A as Foo>::Y]; //~ ERROR E0080
-                                     //~| non-constant path in constant
+    let _array = [4; <A as Foo>::Y];
+    //~^ ERROR cannot use an outer type parameter in this context [E0402]
+    //~| ERROR constant evaluation error [E0080]
+    //~| non-constant path in constant
 }
 
 fn main() {
index ddf16a2278e5bd140cca704c6992e27dafb09f8e..dcf87d5f0fc44b97585cd070cc9f54ceab7fa4e6 100644 (file)
@@ -26,7 +26,9 @@ impl Foo for Def {
 
 pub fn test<A: Foo, B: Foo>() {
     let _array: [u32; <A as Foo>::Y];
-    //~^ ERROR the trait bound `A: Foo` is not satisfied
+    //~^ ERROR cannot use an outer type parameter in this context [E0402]
+    //~| ERROR constant evaluation error [E0080]
+    //~| non-constant path in constant
 }
 
 fn main() {
index 6bc110239cdbf157c2191f1c72690bba4cb69edb..0295d4248e545c2fb31a8f32c496ef6513d38dd7 100644 (file)
 // Check that associated paths starting with `<<` are successfully parsed.
 
 fn main() {
-    let _: <<A>::B>::C; //~ ERROR type name `A` is undefined or not in scope
-    let _ = <<A>::B>::C; //~ ERROR type name `A` is undefined or not in scope
-    let <<A>::B>::C; //~ ERROR type name `A` is undefined or not in scope
-    let 0 ... <<A>::B>::C; //~ ERROR type name `A` is undefined or not in scope
+    let _: <<A>::B>::C; //~ ERROR unresolved type `A`
+    let _ = <<A>::B>::C; //~ ERROR unresolved type `A`
+    let <<A>::B>::C; //~ ERROR unresolved type `A`
+    let 0 ... <<A>::B>::C; //~ ERROR unresolved type `A`
                            //~^ ERROR only char and numeric types are allowed in range patterns
-    <<A>::B>::C; //~ ERROR type name `A` is undefined or not in scope
+    <<A>::B>::C; //~ ERROR unresolved type `A`
 }
index 59d871460978347496475de3e445c4d594e18e31..46d5633c8dd6132ec48d8d01ae1216dfdf8ad893 100644 (file)
@@ -17,7 +17,7 @@ pub trait Foo {
 }
 
 fn foo2<I: Foo>(x: I) {
-    let _: A = x.boo(); //~ERROR undefined or not in scope
+    let _: A = x.boo(); //~ ERROR unresolved type `A`
 }
 
 pub fn main() {}
diff --git a/src/test/compile-fail/auxiliary/issue-21221-3.rs b/src/test/compile-fail/auxiliary/issue-21221-3.rs
deleted file mode 100644 (file)
index fae0fe1..0000000
+++ /dev/null
@@ -1,29 +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.
-
-// testing whether the lookup mechanism picks up types
-// defined in the outside crate
-
-#![crate_type="lib"]
-
-pub mod outer {
-    // should suggest this
-    pub trait OuterTrait {}
-
-    // should not suggest this since the module is private
-    mod private_module {
-        pub trait OuterTrait {}
-    }
-
-    // should not suggest since the trait is private
-    pub mod public_module {
-        trait OuterTrait {}
-    }
-}
diff --git a/src/test/compile-fail/auxiliary/issue-21221-4.rs b/src/test/compile-fail/auxiliary/issue-21221-4.rs
deleted file mode 100644 (file)
index fffe060..0000000
+++ /dev/null
@@ -1,22 +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.
-
-// testing whether the lookup mechanism picks up types
-// defined in the outside crate
-
-#![crate_type="lib"]
-
-mod foo {
-    // should not be suggested => foo is private
-    pub trait T {}
-}
-
-// should be suggested
-pub use foo::T;
diff --git a/src/test/compile-fail/auxiliary/issue_19452_aux.rs b/src/test/compile-fail/auxiliary/issue_19452_aux.rs
deleted file mode 100644 (file)
index 205566e..0000000
+++ /dev/null
@@ -1,13 +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.
-
-pub enum Homura {
-    Madoka { age: u32 }
-}
diff --git a/src/test/compile-fail/auxiliary/issue_3907.rs b/src/test/compile-fail/auxiliary/issue_3907.rs
deleted file mode 100644 (file)
index 6472c08..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2013 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 Foo {
-    fn bar();
-}
index 1049bcd15644fcdd87d25ddec4475fb05263f94f..5e3cb606ce0371f258c77d2ec1576f398f29addd 100644 (file)
@@ -132,6 +132,10 @@ pub struct UnstableStruct {
 pub struct StableStruct {
     #[stable(feature = "test_feature", since = "1.0.0")] pub i: isize
 }
+#[unstable(feature = "test_feature", issue = "0")]
+pub enum UnstableEnum {}
+#[stable(feature = "rust1", since = "1.0.0")]
+pub enum StableEnum {}
 
 #[stable(feature = "test_feature", since = "1.0.0")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
index 7bd1a96f452d83a53c47aaeb4cbe7a397c08b466..4207fc2373b1749ad49c929fe83655c1778cf4a2 100644 (file)
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 // no-prefer-dynamic
+// compile-flags: --emit=metadata
 
-#![crate_type="metadata"]
+#![crate_type="rlib"]
 
 pub struct Foo {
     pub field: i32,
index c18a318347745600c237235760541766f8d37454..05400a0eb657798b5be62788c85f4c3c2e0f7fba 100644 (file)
@@ -8,8 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: unresolved name `m1::arguments`
-
 mod m1 {}
 
-fn main(arguments: Vec<String>) { log(debug, m1::arguments); }
+fn main(arguments: Vec<String>) { //~ ERROR main function has wrong type
+    log(debug, m1::arguments);
+    //~^ ERROR unresolved function `log`
+    //~| ERROR unresolved value `debug`
+    //~| ERROR unresolved value `m1::arguments`
+}
index e1c1afb0049d74d76286a70842848124448f4ddb..867166134b294f107178a845f677f882ddf11cec 100644 (file)
@@ -8,12 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: unresolved name `m1::arguments`
-
 mod m1 {
     pub mod arguments {}
 }
 
-fn main(arguments: Vec<String>) {
+fn main(arguments: Vec<String>) { //~ ERROR main function has wrong type
     log(debug, m1::arguments);
+    //~^ ERROR unresolved function `log`
+    //~| ERROR unresolved value `debug`
+    //~| ERROR expected value, found module `m1::arguments`
 }
index ab76af1cbe600d91168633f3b66f3b5db04d6ee7..cab46ec1fbf22e5359cebc23adaa64d65d96f828 100644 (file)
@@ -16,8 +16,8 @@ impl cat {
     fn sleep(&self) { loop{} }
     fn meow(&self) {
       println!("Meow");
-      meows += 1; //~ ERROR unresolved name
-      sleep();     //~ ERROR unresolved name
+      meows += 1; //~ ERROR unresolved value `meows`
+      sleep();     //~ ERROR unresolved function `sleep`
     }
 
 }
index b33f27fbc8a03f43180f720f46c46d8e8e82b6b1..7c7782b9b443f0733469429755753940dc34518f 100644 (file)
@@ -16,7 +16,7 @@ impl Foo for i8 {}
 impl Foo for i16 {}
 impl Foo for i32 {}
 impl Foo for i64 {}
-impl Foo for DoesNotExist {} //~ ERROR `DoesNotExist` is undefined
+impl Foo for DoesNotExist {} //~ ERROR unresolved type `DoesNotExist`
 impl Foo for u8 {}
 impl Foo for u16 {}
 impl Foo for u32 {}
index 235fc5051d780f78a50b91a8c06bfd8c063acbb8..36382e776ce281fe4f4182303e2f2e52e291270f 100644 (file)
@@ -34,9 +34,11 @@ struct WontChange {
 mod signatures {
     use WillChange;
 
-    #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
-    #[rustc_then_this_would_need(CollectItem)] //~ ERROR OK
+    #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path
+    #[rustc_then_this_would_need(CollectItem)] //~ ERROR no path
     trait Bar {
+        #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
+        #[rustc_then_this_would_need(CollectItem)] //~ ERROR OK
         fn do_something(x: WillChange);
     }
 
index 2e33f11c04b4595ba708d46944facab51093a6a6..4cc15e8b522ac7add81492663a36395c325d2c06 100644 (file)
@@ -35,8 +35,9 @@ enum Enum {
     Variant2(i32)
 }
 
-#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
+#[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path
 trait Trait {
+    #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
     fn method(&self, _: TypeAlias);
 }
 
index cf283f6d3e4b56bee48316b9663e34e73cfd1594..2a294a4e31f5e11f6977e7f86de60c554d0e8f08 100644 (file)
@@ -20,7 +20,7 @@ fn closure<F, T>(x: F) -> Result<T, ()>
 }
 
 fn foo() -> Result<(), ()> {
-    try!(closure(|| bar(0 as *mut _))); //~ ERROR unresolved name `bar`
+    try!(closure(|| bar(0 as *mut _))); //~ ERROR unresolved function `bar`
     Ok(())
 }
 
index c0cd406f062b3fbdaae273a61dd523c80f0ce028..96e14d2fb221b2ef884c938e41c976655802c894 100644 (file)
@@ -8,5 +8,5 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: unresolved name `this_does_nothing_what_the`
 fn main() { println!("doing"); this_does_nothing_what_the; println!("boing"); }
+//~^ ERROR unresolved value `this_does_nothing_what_the`
index 1c86af30c79fd1b66757ac4d78878c9b5dff5cd9..d4e85e9744d649b29bc50fd65f3630adfb3a90bd 100644 (file)
@@ -22,13 +22,13 @@ enum E {
 }
 
 fn main() {
-    let e1 = Empty1; //~ ERROR `Empty1` is the name of a struct or struct variant
-    let e1 = Empty1(); //~ ERROR `Empty1` is the name of a struct or struct variant
-    let e3 = E::Empty3; //~ ERROR `E::Empty3` is the name of a struct or struct variant
-    let e3 = E::Empty3(); //~ ERROR `E::Empty3` is the name of a struct or struct variant
+    let e1 = Empty1; //~ ERROR expected value, found struct `Empty1`
+    let e1 = Empty1(); //~ ERROR expected function, found struct `Empty1`
+    let e3 = E::Empty3; //~ ERROR expected value, found struct variant `E::Empty3`
+    let e3 = E::Empty3(); //~ ERROR expected function, found struct variant `E::Empty3`
 
-    let xe1 = XEmpty1; //~ ERROR `XEmpty1` is the name of a struct or struct variant
-    let xe1 = XEmpty1(); //~ ERROR `XEmpty1` is the name of a struct or struct variant
+    let xe1 = XEmpty1; //~ ERROR expected value, found struct `XEmpty1`
+    let xe1 = XEmpty1(); //~ ERROR expected function, found struct `XEmpty1`
     let xe3 = XE::Empty3; //~ ERROR no associated item named `Empty3` found for type
     let xe3 = XE::Empty3(); //~ ERROR no associated item named `Empty3` found for type
 }
index 4349e72c5d73be4af2d24c2a54ba9232bbbfd518..d3b13457dc62b878cc6bfef5255f621178442311 100644 (file)
@@ -22,15 +22,15 @@ fn main() {
     let xe1 = XEmpty1 {};
 
     match e1 {
-        Empty1() => () //~ ERROR unresolved tuple struct/variant `Empty1`
+        Empty1() => () //~ ERROR expected tuple struct/variant, found struct `Empty1`
     }
     match xe1 {
-        XEmpty1() => () //~ ERROR unresolved tuple struct/variant `XEmpty1`
+        XEmpty1() => () //~ ERROR expected tuple struct/variant, found struct `XEmpty1`
     }
     match e1 {
-        Empty1(..) => () //~ ERROR unresolved tuple struct/variant `Empty1`
+        Empty1(..) => () //~ ERROR expected tuple struct/variant, found struct `Empty1`
     }
     match xe1 {
-        XEmpty1(..) => () //~ ERROR unresolved tuple struct/variant `XEmpty1`
+        XEmpty1(..) => () //~ ERROR expected tuple struct/variant, found struct `XEmpty1`
     }
 }
index eef4bea1df11b6cb0987bbb64fae318d55918112..258bfd1e3ba9246412ec8eb92161d6353002bb3b 100644 (file)
@@ -14,6 +14,6 @@ enum Foo {
     Bar
 }
 
-fn foo(x: Foo::Bar) {} //~ERROR found value `Foo::Bar` used as a type
+fn foo(x: Foo::Bar) {} //~ ERROR expected type, found variant `Foo::Bar`
 
 fn main() {}
diff --git a/src/test/compile-fail/enums-are-namespaced-xc.rs b/src/test/compile-fail/enums-are-namespaced-xc.rs
deleted file mode 100644 (file)
index 0293956..0000000
+++ /dev/null
@@ -1,19 +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.
-
-// aux-build:namespaced_enums.rs
-extern crate namespaced_enums;
-
-fn main() {
-    let _ = namespaced_enums::A; //~ ERROR unresolved name
-    let _ = namespaced_enums::B(10); //~ ERROR unresolved name
-    let _ = namespaced_enums::C { a: 10 };
-    //~^ ERROR unresolved struct, variant or union type `namespaced_enums::C`
-}
index f8aa1ea95f0f66d51039d8bb09d1c11502bf1ec2..eac134ff3cc7d6b287cf83a34ca4c67862897d20 100644 (file)
@@ -14,8 +14,8 @@ struct Foo<'a,'b> {
 }
 
 impl<'a,'b> Foo<'a,'b> {
-    fn bar(
-        self
+    fn bar(self:
+           Foo<'b,'a>
     //~^ ERROR mismatched method receiver
     //~| expected type `Foo<'a, 'b>`
     //~| found type `Foo<'b, 'a>`
@@ -24,7 +24,7 @@ fn bar(
     //~| expected type `Foo<'a, 'b>`
     //~| found type `Foo<'b, 'a>`
     //~| lifetime mismatch
-            : Foo<'b,'a>) {}
+           ) {}
 }
 
 fn main() {}
index 166ef7ab87fcd1d2297dc0eda5e21f4c16424c48..19fa13f8377dbc81845d1913eb7522964db26457 100644 (file)
@@ -8,14 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: failed to resolve. Use of undeclared type or module `foo`
-
 // In this test baz isn't resolved when called as foo.baz even though
 // it's called from inside foo. This is somewhat surprising and may
 // want to change eventually.
 
 mod foo {
-    pub fn bar() { foo::baz(); }
+    pub fn bar() { foo::baz(); } //~ ERROR failed to resolve. Use of undeclared type or module `foo`
 
     fn baz() { }
 }
index 3a391e7c609ff35dd72d07d254e6bb9b65334366..a412cac699f628081890083911278ee09113be31 100644 (file)
@@ -8,10 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: unresolved name
 mod foo {
     pub fn x(y: isize) { log(debug, y); }
+    //~^ ERROR unresolved function `log`
+    //~| ERROR unresolved value `debug`
     fn z(y: isize) { log(debug, y); }
+    //~^ ERROR unresolved function `log`
+    //~| ERROR unresolved value `debug`
 }
 
-fn main() { foo::z(10); }
+fn main() { foo::z(10); } //~ ERROR function `z` is private
index f7b1400aa45acf87e7c8a60bea566b0d75527013..dc96ce7f504964b14ceab88bd1ee73ffac39d4d1 100644 (file)
@@ -8,10 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: failed to resolve. Use of undeclared type or module `bar`
-
 mod foo {
-    pub fn x() { bar::x(); }
+    pub fn x() { bar::x(); } //~ ERROR failed to resolve. Use of undeclared type or module `bar`
 }
 
 mod bar {
index d8bdd5974c7e1e098039ca404161876de040a21d..0f8ad8d53882297bff9e3407be25c186e16b0463 100644 (file)
@@ -24,7 +24,7 @@
 
     // Unresolved bounds should still error.
     fn align_of<T: NoSuchTrait>() -> usize;
-    //~^ ERROR trait `NoSuchTrait` is not in scope
+    //~^ ERROR unresolved trait `NoSuchTrait`
 }
 
 fn main() {}
index 43776d75a47f4aba186fe1364ae62de428146465..a051789ec9842bc0d4ab9f0924c10affdd0e9fd0 100644 (file)
@@ -13,7 +13,7 @@
 fn main() {
     // Odd formatting to make sure we get the right span.
     for t in &
-      foo //~ ERROR unresolved name `foo`
+      foo //~ ERROR unresolved value `foo`
     {
     }
 }
index f06882875fd9b4650d29f17b0caf019a30cd7153..2135ad6e73c49b9f915d2df0125ebc8812305a2d 100644 (file)
@@ -13,6 +13,6 @@
 
 fn main() {
     for _ in 0..10 {
-        iter.next();  //~ error: unresolved name `iter`
+        iter.next();  //~ ERROR unresolved value `iter`
     }
 }
index 1e5662aa1721ffc44d88d79e6d3cb3315f95ea8d..58e677965867bd8ac2cb3dc6f26cc08d3645a964 100644 (file)
@@ -29,13 +29,13 @@ pub enum B { B1 }
 fn foo<T>() {}
 
 fn main() {
-    fpriv(); //~ ERROR: unresolved
-    epriv(); //~ ERROR: unresolved
-    B; //~ ERROR: unresolved
-    C; //~ ERROR: unresolved
-    import(); //~ ERROR: unresolved
-
-    foo::<A>(); //~ ERROR: not in scope
-    foo::<C>(); //~ ERROR: not in scope
-    foo::<D>(); //~ ERROR: not in scope
+    fpriv(); //~ ERROR unresolved function `fpriv`
+    epriv(); //~ ERROR unresolved function `epriv`
+    B; //~ ERROR expected value, found enum `B`
+    C; //~ ERROR unresolved value `C`
+    import(); //~ ERROR: unresolved function `import`
+
+    foo::<A>(); //~ ERROR: unresolved type `A`
+    foo::<C>(); //~ ERROR: unresolved type `C`
+    foo::<D>(); //~ ERROR: unresolved type `D`
 }
index 21aa811ea718869f6350e1686e6565936f66c318..12e45cfa2cbef3f380d8e74e4aae560a745d7d19 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: unresolved name
-
 use module_of_many_things::*;
 
 mod module_of_many_things {
@@ -23,6 +21,6 @@ mod module_of_many_things {
 fn main() {
     f1();
     f2();
-    f999(); // 'export' currently doesn't work?
+    f999(); //~ ERROR unresolved function `f999`
     f4();
 }
diff --git a/src/test/compile-fail/issue-14254.rs b/src/test/compile-fail/issue-14254.rs
deleted file mode 100644 (file)
index c7bd343..0000000
+++ /dev/null
@@ -1,137 +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.
-
-trait Foo {
-    fn bar(&self);
-    fn baz(&self) { }
-    fn bah(_: Option<&Self>) { }
-}
-
-struct BarTy {
-    x : isize,
-    y : f64,
-}
-
-impl BarTy {
-    fn a() {}
-    fn b(&self) {}
-}
-
-impl Foo for *const BarTy {
-    fn bar(&self) {
-        baz();
-        //~^ ERROR: unresolved name `baz`
-        //~| NOTE did you mean to call `self.baz`?
-        a;
-        //~^ ERROR: unresolved name `a`
-        //~| NOTE unresolved name
-    }
-}
-
-impl<'a> Foo for &'a BarTy {
-    fn bar(&self) {
-        baz();
-        //~^ ERROR: unresolved name `baz`
-        //~| NOTE did you mean to call `self.baz`?
-        x;
-        //~^ ERROR: unresolved name `x`
-        //~| NOTE did you mean `self.x`?
-        y;
-        //~^ ERROR: unresolved name `y`
-        //~| NOTE did you mean `self.y`?
-        a;
-        //~^ ERROR: unresolved name `a`
-        //~| NOTE unresolved name
-        bah;
-        //~^ ERROR: unresolved name `bah`
-        //~| NOTE did you mean to call `Foo::bah`?
-        b;
-        //~^ ERROR: unresolved name `b`
-        //~| NOTE unresolved name
-    }
-}
-
-impl<'a> Foo for &'a mut BarTy {
-    fn bar(&self) {
-        baz();
-        //~^ ERROR: unresolved name `baz`
-        //~| NOTE did you mean to call `self.baz`?
-        x;
-        //~^ ERROR: unresolved name `x`
-        //~| NOTE did you mean `self.x`?
-        y;
-        //~^ ERROR: unresolved name `y`
-        //~| NOTE did you mean `self.y`?
-        a;
-        //~^ ERROR: unresolved name `a`
-        //~| NOTE unresolved name
-        bah;
-        //~^ ERROR: unresolved name `bah`
-        //~| NOTE did you mean to call `Foo::bah`?
-        b;
-        //~^ ERROR: unresolved name `b`
-        //~| NOTE unresolved name
-    }
-}
-
-impl Foo for Box<BarTy> {
-    fn bar(&self) {
-        baz();
-        //~^ ERROR: unresolved name `baz`
-        //~| NOTE did you mean to call `self.baz`?
-        bah;
-        //~^ ERROR: unresolved name `bah`
-        //~| NOTE did you mean to call `Foo::bah`?
-    }
-}
-
-impl Foo for *const isize {
-    fn bar(&self) {
-        baz();
-        //~^ ERROR: unresolved name `baz`
-        //~| NOTE did you mean to call `self.baz`?
-        bah;
-        //~^ ERROR: unresolved name `bah`
-        //~| NOTE did you mean to call `Foo::bah`?
-    }
-}
-
-impl<'a> Foo for &'a isize {
-    fn bar(&self) {
-        baz();
-        //~^ ERROR: unresolved name `baz`
-        //~| NOTE did you mean to call `self.baz`?
-        bah;
-        //~^ ERROR: unresolved name `bah`
-        //~| NOTE did you mean to call `Foo::bah`?
-    }
-}
-
-impl<'a> Foo for &'a mut isize {
-    fn bar(&self) {
-        baz();
-        //~^ ERROR: unresolved name `baz`
-        //~| NOTE did you mean to call `self.baz`?
-        bah;
-        //~^ ERROR: unresolved name `bah`
-        //~| NOTE did you mean to call `Foo::bah`?
-    }
-}
-
-impl Foo for Box<isize> {
-    fn bar(&self) {
-        baz();
-        //~^ ERROR: unresolved name `baz`
-        //~| NOTE did you mean to call `self.baz`?
-        bah;
-        //~^ ERROR: unresolved name `bah`
-        //~| NOTE did you mean to call `Foo::bah`?
-    }
-}
index 73a0e0c0775eef21db08174248fcd5ca20524260..b7797cf5b367ae9899ce818ee26a1aa24e767819 100644 (file)
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    println!("{}", x); //~ ERROR unresolved name `x`
+    println!("{}", x); //~ ERROR unresolved value `x`
 }
index 2bd7da91d2c5832012544e85d3bb70824f07bf1f..4e77636b3797bd23a1ac975bfa78f96a2e72d62f 100644 (file)
 // macro f should not be able to inject a reference to 'n'.
 
 macro_rules! f { () => (n) }
-//~^ ERROR unresolved name `n`
-//~| ERROR unresolved name `n`
-//~| ERROR unresolved name `n`
-//~| ERROR unresolved name `n`
+//~^ ERROR unresolved value `n`
+//~| ERROR unresolved value `n`
+//~| ERROR unresolved value `n`
+//~| ERROR unresolved value `n`
 
 fn main() -> (){
     for n in 0..1 {
diff --git a/src/test/compile-fail/issue-16058.rs b/src/test/compile-fail/issue-16058.rs
deleted file mode 100644 (file)
index 92c1e4b..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-
-pub struct GslResult {
-    pub val: f64,
-    pub err: f64
-}
-
-impl GslResult {
-    pub fn new() -> GslResult {
-        Result { //~ ERROR: expected struct, variant or union type, found enum `Result`
-            val: 0f64,
-            err: 0f64
-        }
-    }
-}
-
-fn main() {}
diff --git a/src/test/compile-fail/issue-17518.rs b/src/test/compile-fail/issue-17518.rs
deleted file mode 100644 (file)
index 2113e38..0000000
+++ /dev/null
@@ -1,17 +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.
-
-enum SomeEnum {
-    E
-}
-
-fn main() {
-    E { name: "foobar" }; //~ ERROR unresolved struct, variant or union type `E`
-}
index e640ba3f00fb6d7d2faf69b529d1ab62d439c0fd..fe125b973d9bd72de187129c9716ad3610972e38 100644 (file)
@@ -20,7 +20,7 @@ pub enum MyEnum {
     }
 
     fn new() -> NoResult<MyEnum, String> {
-        //~^ ERROR: found value `foo::MyEnum::NoResult` used as a type
+        //~^ ERROR expected type, found variant `NoResult`
         unimplemented!()
     }
 }
@@ -30,18 +30,18 @@ mod bar {
     use foo;
 
     fn new() -> Result<foo::MyEnum, String> {
-        //~^ ERROR: found value `foo::MyEnum::Result` used as a type
+        //~^ ERROR expected type, found variant `Result`
         unimplemented!()
     }
 }
 
 fn new() -> Result<foo::MyEnum, String> {
-    //~^ ERROR: found value `foo::MyEnum::Result` used as a type
+    //~^ ERROR expected type, found variant `Result`
     unimplemented!()
 }
 
 fn newer() -> NoResult<foo::MyEnum, String> {
-    //~^ ERROR: found value `foo::MyEnum::NoResult` used as a type
+    //~^ ERROR expected type, found variant `NoResult`
     unimplemented!()
 }
 
index 0447cf781ff95c81da07ceff1485a2c510b2b688..1611cc418fb11d59e9ac4050dcb518ef66b48a75 100644 (file)
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 impl Undefined {}
-//~^ ERROR type name `Undefined` is undefined or not in scope
+//~^ ERROR unresolved type `Undefined`
 
 fn main() {}
index f06496463e4c1d015e2415b888b2c19faae837dc..412f7566f472be63fddb7e1c59101f486043eb4a 100644 (file)
 fn foo() {}
 
 impl X {}
-//~^ ERROR type name `X` is undefined or not in scope
+//~^ ERROR expected type, found constant `X`
 impl Y {}
-//~^ ERROR type name `Y` is undefined or not in scope
+//~^ ERROR expected type, found static `Y`
 impl foo {}
-//~^ ERROR type name `foo` is undefined or not in scope
+//~^ ERROR expected type, found function `foo`
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-18252.rs b/src/test/compile-fail/issue-18252.rs
deleted file mode 100644 (file)
index 8e3faca..0000000
+++ /dev/null
@@ -1,19 +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.
-
-enum Foo {
-    Variant { x: usize }
-}
-
-fn main() {
-    let f = Foo::Variant(42);
-    //~^ ERROR uses it like a function
-    //~| struct called like a function
-}
diff --git a/src/test/compile-fail/issue-19452.rs b/src/test/compile-fail/issue-19452.rs
deleted file mode 100644 (file)
index 34872b7..0000000
+++ /dev/null
@@ -1,26 +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.
-
-// aux-build:issue_19452_aux.rs
-extern crate issue_19452_aux;
-
-enum Homura {
-    Madoka { age: u32 }
-}
-
-fn main() {
-    let homura = Homura::Madoka;
-    //~^ ERROR uses it like a function
-    //~| struct called like a function
-
-    let homura = issue_19452_aux::Homura::Madoka;
-    //~^ ERROR uses it like a function
-    //~| struct called like a function
-}
index 3a7a1692f38cf8b1e3bf01f313a474c6e2427511..6fc5fa03c58c2681811e68e67897f1998618b246 100644 (file)
@@ -17,7 +17,7 @@ trait From<Src> {
 trait To: Sized {
     fn to<Dst: From<Self>>(self) ->
         <Dst as From<Self>>::Dst
-        //~^ ERROR associated type `From::Dst` is undefined or not in scope
+        //~^ ERROR unresolved associated type `From::Dst`
     {
         From::from(self)
     }
diff --git a/src/test/compile-fail/issue-21221-1.rs b/src/test/compile-fail/issue-21221-1.rs
deleted file mode 100644 (file)
index 2bc9ec3..0000000
+++ /dev/null
@@ -1,97 +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.
-
-mod mul1 {
-    pub trait Mul {}
-}
-
-mod mul2 {
-    pub trait Mul {}
-}
-
-mod mul3 {
-    enum Mul {
-      Yes,
-      No
-    }
-}
-
-mod mul4 {
-    type Mul = String;
-}
-
-mod mul5 {
-    struct Mul{
-        left_term: u32,
-        right_term: u32
-    }
-}
-
-#[derive(Debug)]
-struct Foo;
-
-// When we comment the next line:
-//use mul1::Mul;
-
-// BEFORE, we got the following error for the `impl` below:
-//   error: use of undeclared trait name `Mul` [E0405]
-// AFTER, we get this message:
-//   error: trait `Mul` is not in scope.
-//   help: ...
-//   help: you can import several candidates into scope (`use ...;`):
-//   help:   `mul1::Mul`
-//   help:   `mul2::Mul`
-//   help:   `std::ops::Mul`
-
-impl Mul for Foo {
-//~^ ERROR trait `Mul` is not in scope
-//~| HELP `mul1::Mul`
-//~| HELP `mul2::Mul`
-//~| HELP `std::ops::Mul`
-//~| HELP you can import several candidates into scope (`use ...;`):
-}
-
-// BEFORE, we got:
-//   error: use of undeclared type name `Mul` [E0412]
-// AFTER, we get:
-//   error: type name `Mul` is not in scope. Maybe you meant:
-//   help: ...
-//   help: you can import several candidates into scope (`use ...;`):
-//   help:   `mul1::Mul`
-//   help:   `mul2::Mul`
-//   help:   `mul3::Mul`
-//   help:   `mul4::Mul`
-//   help:   and 2 other candidates
-fn getMul() -> Mul {
-//~^ ERROR type name `Mul` is undefined or not in scope
-//~| HELP `mul1::Mul`
-//~| HELP `mul2::Mul`
-//~| HELP `mul3::Mul`
-//~| HELP `mul4::Mul`
-//~| HELP and 2 other candidates
-//~| HELP you can import several candidates into scope (`use ...;`):
-}
-
-// Let's also test what happens if the trait doesn't exist:
-impl ThisTraitReallyDoesntExistInAnyModuleReally for Foo {
-//~^ ERROR trait `ThisTraitReallyDoesntExistInAnyModuleReally` is not in scope
-//~| HELP no candidates by the name of `ThisTraitReallyDoesntExistInAnyModuleReally` found
-}
-
-// Let's also test what happens if there's just one alternative:
-impl Div for Foo {
-//~^ ERROR trait `Div` is not in scope
-//~| HELP `use std::ops::Div;`
-}
-
-fn main() {
-    let foo = Foo();
-    println!("Hello, {:?}!", foo);
-}
diff --git a/src/test/compile-fail/issue-21221-2.rs b/src/test/compile-fail/issue-21221-2.rs
deleted file mode 100644 (file)
index 861acf6..0000000
+++ /dev/null
@@ -1,30 +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.
-
-pub mod foo {
-    pub mod bar {
-        // note: trait T is not public, but being in the current
-        // crate, it's fine to show it, since the programmer can
-        // decide to make it public based on the suggestion ...
-        pub trait T {}
-    }
-    // imports should be ignored:
-    use self::bar::T;
-}
-
-pub mod baz {
-    pub use foo;
-    pub use std::ops::{Mul as T};
-}
-
-struct Foo;
-impl T for Foo { }
-//~^ ERROR trait `T` is not in scope
-//~| HELP you can import it into scope: `use foo::bar::T;`.
diff --git a/src/test/compile-fail/issue-21221-3.rs b/src/test/compile-fail/issue-21221-3.rs
deleted file mode 100644 (file)
index 05786e6..0000000
+++ /dev/null
@@ -1,30 +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.
-
-// testing whether the lookup mechanism picks up types
-// defined in the outside crate
-
-// aux-build:issue-21221-3.rs
-
-extern crate issue_21221_3;
-
-struct Foo;
-
-// NOTE: This shows only traits accessible from the current
-// crate, thus the two private entities:
-//   `issue_21221_3::outer::private_module::OuterTrait` and
-//   `issue_21221_3::outer::public_module::OuterTrait`
-// are hidden from the view.
-impl OuterTrait for Foo {}
-//~^ ERROR trait `OuterTrait` is not in scope
-//~| HELP you can import it into scope: `use issue_21221_3::outer::OuterTrait;`.
-fn main() {
-    println!("Hello, world!");
-}
diff --git a/src/test/compile-fail/issue-21221-4.rs b/src/test/compile-fail/issue-21221-4.rs
deleted file mode 100644 (file)
index bcbee16..0000000
+++ /dev/null
@@ -1,26 +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.
-
-// testing whether the lookup mechanism picks up types
-// defined in the outside crate
-
-// aux-build:issue-21221-4.rs
-
-extern crate issue_21221_4;
-
-struct Foo;
-
-impl T for Foo {}
-//~^ ERROR trait `T` is not in scope
-//~| HELP you can import it into scope: `use issue_21221_4::T;`.
-
-fn main() {
-    println!("Hello, world!");
-}
index 74f1be95420bd8ed247906f74a0ae8c88bbe62f3..2a81b55dc7be87e995efc8e98e40a581c2334f03 100644 (file)
@@ -11,7 +11,7 @@
 trait A {
     type Output;
     fn a(&self) -> <Self as A>::X;
-//~^ ERROR: associated type `A::X` is undefined or not in scope
+    //~^ ERROR unresolved associated type `A::X`
 }
 
 impl A for u32 {
index 46a43bdfcb8d6108b9e9c11d9413a35975c88585..ad42a7e4a97458f132d6edcf48019221b362e2e2 100644 (file)
@@ -14,5 +14,5 @@ trait Trait {
 
 fn main() {
     <<i32 as Copy>::foobar as Trait>::foo();
-    //~^ ERROR associated type `Copy::foobar` is undefined or not in scope
+    //~^ ERROR unresolved associated type `Copy::foobar`
 }
index f59252dd3154b7e766baf7bdfcfe422b2339194a..8d21650ed6f33d0c370ce2fd3cc8dd78166af68c 100644 (file)
@@ -8,6 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: unresolved name `foobar`
-
-fn main() { println!("{}", foobar); }
+fn main() { println!("{}", foobar); } //~ ERROR unresolved value `foobar`
index 63f146a21d925a73b616b0519e054923d4d8893f..f1a282695ac11f70c2985edeb788835b161808a8 100644 (file)
@@ -15,7 +15,7 @@ trait channel<T> {
 }
 
 // `chan` is not a trait, it's an enum
-impl chan for isize { //~ ERROR `chan` is not a trait
+impl chan for isize { //~ ERROR expected trait, found enum `chan`
     fn send(&self, v: isize) { panic!() }
 }
 
diff --git a/src/test/compile-fail/issue-23305.rs b/src/test/compile-fail/issue-23305.rs
deleted file mode 100644 (file)
index 4acb1f7..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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.
-
-pub trait ToNbt<T> {
-    fn new(val: T) -> Self;
-}
-
-impl ToNbt<Self> {} //~ ERROR use of `Self` outside of an impl or trait
-//~^ ERROR the trait `ToNbt` cannot be made into an object
-
-fn main() {}
diff --git a/src/test/compile-fail/issue-2356.rs b/src/test/compile-fail/issue-2356.rs
deleted file mode 100644 (file)
index d7635d7..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait Groom {
-    fn shave(other: usize);
-}
-
-pub struct cat {
-  whiskers: isize,
-}
-
-pub enum MaybeDog {
-    Dog,
-    NoDog
-}
-
-impl MaybeDog {
-  fn bark() {
-    // If this provides a suggestion, it's a bug as MaybeDog doesn't impl Groom
-    shave();
-    //~^ ERROR: unresolved name `shave`
-    //~| NOTE unresolved name
-  }
-}
-
-impl Groom for cat {
-  fn shave(other: usize) {
-    whiskers -= other;
-    //~^ ERROR: unresolved name `whiskers`
-    //~| NOTE unresolved name
-    //~| HELP this is an associated function
-    shave(4);
-    //~^ ERROR: unresolved name `shave`
-    //~| NOTE did you mean to call `Groom::shave`?
-    purr();
-    //~^ ERROR: unresolved name `purr`
-    //~| NOTE unresolved name
-  }
-}
-
-impl cat {
-    fn static_method() {}
-
-    fn purr_louder() {
-        static_method();
-        //~^ ERROR: unresolved name `static_method`
-        //~| NOTE unresolved name
-        purr();
-        //~^ ERROR: unresolved name `purr`
-        //~| NOTE unresolved name
-        purr();
-        //~^ ERROR: unresolved name `purr`
-        //~| NOTE unresolved name
-        purr();
-        //~^ ERROR: unresolved name `purr`
-        //~| NOTE unresolved name
-    }
-}
-
-impl cat {
-  fn meow() {
-    if self.whiskers > 3 {
-        //~^ ERROR `self` is not available in a static method [E0424]
-        //~| NOTE not available in static method
-        //~| NOTE maybe a `self` argument is missing?
-        println!("MEOW");
-    }
-  }
-
-  fn purr(&self) {
-    grow_older();
-    //~^ ERROR: unresolved name `grow_older`
-    //~| NOTE unresolved name
-    shave();
-    //~^ ERROR: unresolved name `shave`
-    //~| NOTE unresolved name
-  }
-
-  fn burn_whiskers(&mut self) {
-    whiskers = 0;
-    //~^ ERROR: unresolved name `whiskers`
-    //~| NOTE did you mean `self.whiskers`?
-  }
-
-  pub fn grow_older(other:usize) {
-    whiskers = 4;
-    //~^ ERROR: unresolved name `whiskers`
-    //~| NOTE unresolved name
-    //~| HELP this is an associated function
-    purr_louder();
-    //~^ ERROR: unresolved name `purr_louder`
-    //~| NOTE unresolved name
-  }
-}
-
-fn main() {
-    self += 1;
-    //~^ ERROR: unresolved name `self`
-    //~| NOTE unresolved name
-    //~| HELP: module `self`
-    // it's a bug if this suggests a missing `self` as we're not in a method
-}
diff --git a/src/test/compile-fail/issue-24968.rs b/src/test/compile-fail/issue-24968.rs
deleted file mode 100644 (file)
index f51b77b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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.
-
-fn foo(_: Self) {
-    //~^ ERROR use of `Self` outside of an impl or trait
-}
-
-fn main() {}
index e89bff025e006bf6fed83b4939302027ecadf66f..f80135848e0c10fe4f8de3139b715a58fd4f82c3 100644 (file)
@@ -16,6 +16,4 @@ fn main() {
     //~| expected type `usize`
     //~| found type `S`
     //~| expected usize, found struct `S`
-    //~| ERROR expected `usize` for repeat count, found struct [E0306]
-    //~| expected `usize`
 }
index ed7851ec0f15700bb63b91f7b16ae2bc08e9a6c7..334fdee00a0e72883a9000a569007dd40faf85f8 100644 (file)
@@ -10,8 +10,6 @@
 
 // Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
 
-use foo::{};
-//~^ ERROR failed to resolve. Maybe a missing `extern crate foo;`?
-//~| NOTE foo
+use foo::{}; //~ ERROR unresolved module or enum `foo`
 
 fn main() {}
index 4baaa16e772da82726737bfb79697a117b22fa23..12357779b5171e3b7ae5e5a144f0621edf43dcdf 100644 (file)
@@ -14,8 +14,7 @@
 
 extern crate lint_stability;
 
-use lint_stability::UnstableStruct::{};
-//~^ ERROR use of unstable library feature 'test_feature'
-use lint_stability::StableStruct::{}; // OK
+use lint_stability::UnstableEnum::{}; //~ ERROR use of unstable library feature 'test_feature'
+use lint_stability::StableEnum::{}; // OK
 
 fn main() {}
index 93f3086d05771980741232610f1008ee9c8c98bc..90f5220a623af856d8c14b33634906abdc9f55ca 100644 (file)
@@ -13,7 +13,7 @@
 extern crate issue_30535 as foo;
 
 fn bar(
-    _: foo::Foo::FooV //~ ERROR value `foo::Foo::FooV` used as a type
+    _: foo::Foo::FooV //~ ERROR expected type, found variant `foo::Foo::FooV`
 ) {}
 
 fn main() {}
index 32765d5acb4fefbb5d93f8daa1932fc51fc62916..dd5fac9bed13c8292b5018f2864254f768fe34ba 100644 (file)
@@ -10,7 +10,7 @@
 
 use std::fmt;
 
-impl fmt::Display for DecoderError { //~ ERROR E0412
+impl fmt::Display for DecoderError { //~ ERROR unresolved type `DecoderError`
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "Missing data: {}", self.0)
     }
index 344a1117254601a9ba4d545710e2f62076c901ff..32e004af1f3d7a4e13adc5abd9c3b1f3cedc5d39 100644 (file)
@@ -14,7 +14,7 @@ fn f() {
     fn g() {}
     mod foo {
         fn h() {
-           g(); //~ ERROR unresolved name
+           g(); //~ ERROR unresolved function `g`
         }
     }
 }
diff --git a/src/test/compile-fail/issue-33876.rs b/src/test/compile-fail/issue-33876.rs
deleted file mode 100644 (file)
index 87747d2..0000000
+++ /dev/null
@@ -1,23 +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.
-
-use std::any::Any;
-
-struct Foo;
-
-trait Bar {}
-
-impl Bar for Foo {}
-
-fn main() {
-    let any: &Any = &Bar; //~ ERROR E0425
-                          //~| HELP trait `Bar`
-    if any.is::<u32>() { println!("u32"); }
-}
index ffcd052369d297725d55bbf0f6b12c83cb5d4475..fa672557c5ed033b53dd822969c36cb8e75740fb 100644 (file)
@@ -11,5 +11,5 @@
 fn main () {
     let sr: Vec<(u32, _, _) = vec![]; //~ ERROR expected one of `+`, `,`, or `>`, found `=`
     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
-    //~^ ERROR unresolved name `sr`
+    //~^ ERROR unresolved value `sr`
 }
index a70452dcbd09a6fe1ac0594a3752ac16da9985b6..39d06312aa791611fb311319a68437dc84640fc7 100644 (file)
@@ -9,11 +9,11 @@
 // except according to those terms.
 
 struct Bar<T> {
-    inner: Foo<T> //~ ERROR type name `Foo` is undefined or not in scope
+    inner: Foo<T> //~ ERROR unresolved type `Foo`
 }
 
 enum Baz<T> {
-    Foo(Foo<T>) //~ ERROR type name `Foo` is undefined or not in scope
+    Foo(Foo<T>) //~ ERROR unresolved type `Foo`
 }
 
 fn main() {}
index eb676601e89ce2b77abc9b139808b53e3a58595b..1a6d92166d7c0769df03b446b822537520c71593 100644 (file)
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 struct Foo<T: ?Hash> { }
-//~^ ERROR trait `Hash` is not in scope [E0405]
-//~^^ ERROR parameter `T` is never used [E0392]
+//~^ ERROR unresolved trait `Hash`
+//~^^ ERROR parameter `T` is never used
 //~^^^ WARN default bound relaxed for a type parameter, but this does nothing
 
 fn main() { }
diff --git a/src/test/compile-fail/issue-3907-2.rs b/src/test/compile-fail/issue-3907-2.rs
deleted file mode 100644 (file)
index 1306479..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2013-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.
-
-// aux-build:issue_3907.rs
-extern crate issue_3907;
-
-type Foo = issue_3907::Foo+'static;
-
-struct S {
-    name: isize
-}
-
-fn bar(_x: Foo) {}
-//~^ ERROR E0038
-
-fn main() {}
diff --git a/src/test/compile-fail/issue-3907.rs b/src/test/compile-fail/issue-3907.rs
deleted file mode 100644 (file)
index 86906ed..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013-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.
-
-// aux-build:issue_3907.rs
-extern crate issue_3907;
-
-type Foo = issue_3907::Foo;
-
-struct S {
-    name: isize
-}
-
-impl Foo for S { //~ ERROR: `Foo` is not a trait
-                 //~| NOTE: expected trait, found type alias
-                 //~| NOTE: type aliases cannot be used for traits
-    fn bar() { }
-}
-
-fn main() {
-    let s = S {
-        name: 0
-    };
-    s.bar();
-}
index a6fe719509c9d5aa8a8efe0a95ef74b9f4a176a1..687720a130c9977edfc9c754618960ce26ca4a3a 100644 (file)
@@ -23,7 +23,7 @@ pub mod b {
     pub mod sub {
         use a::b::*;
         fn sub() -> bar { 1 }
-        //~^ ERROR: type name `bar` is undefined or not in scope
+        //~^ ERROR unresolved type `bar`
     }
 }
 
@@ -32,5 +32,5 @@ fn foo() {}
 }
 
 fn main() {
-    foo(); //~ ERROR: unresolved name
+    foo(); //~ ERROR expected function, found module `foo`
 }
index 5625ac00c85d74831d11f5d66f45e9897635d256..18e55ee3c2a6278059e47ff1533ab657d86a8374 100644 (file)
@@ -25,7 +25,7 @@ pub mod b {
     }
     pub mod sub {
         use a::b::*;
-        fn sub() -> isize { foo(); 1 } //~ ERROR: unresolved name `foo`
+        fn sub() -> isize { foo(); 1 } //~ ERROR unresolved function `foo`
     }
 }
 
diff --git a/src/test/compile-fail/issue-5035-2.rs b/src/test/compile-fail/issue-5035-2.rs
deleted file mode 100644 (file)
index 83ff95c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2013-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.
-
-trait I {}
-type K = I+'static;
-
-fn foo(_x: K) {} //~ ERROR: `I + 'static: std::marker::Sized` is not satisfied
-
-fn main() {}
diff --git a/src/test/compile-fail/issue-5035.rs b/src/test/compile-fail/issue-5035.rs
deleted file mode 100644 (file)
index 8ebcba4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2013-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.
-
-trait I {}
-type K = I;
-impl K for isize {} //~ ERROR: `K` is not a trait
-                    //~| NOTE: expected trait, found type alias
-                    //~| NOTE: aliases cannot be used for traits
-
-use ImportError; //~ ERROR unresolved import `ImportError` [E0432]
-                 //~^ no `ImportError` in the root
-impl ImportError for () {} // check that this is not an additional error (c.f. #35142)
-
-fn main() {}
index c2e1fc615cca3c29b43b9d73d4563c70273dd0d5..e78b54bd411fb1bff3bf067e1bbf66e8276f421e 100644 (file)
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 
-trait B < A > { fn a() -> A { this.a } } //~ ERROR unresolved name
+trait B < A > { fn a() -> A { this.a } } //~ ERROR unresolved value `this`
 
 fn main() {}
index 7668a2117a26592b3b72edf183b76de5e8bccf8e..c421dbd1eb3c8b7e8748d9e1d642cfefef05f71d 100644 (file)
@@ -12,7 +12,7 @@
 fn main() {
     let z = match 3 {
         x(1) => x(1) //~ ERROR unresolved tuple struct/variant `x`
-        //~^ ERROR unresolved name `x`
+        //~^ ERROR unresolved function `x`
     };
     assert!(z == 3);
 }
diff --git a/src/test/compile-fail/issue-6702.rs b/src/test/compile-fail/issue-6702.rs
deleted file mode 100644 (file)
index 66ed817..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2013 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 Monster {
-    damage: isize
-}
-
-
-fn main() {
-    let _m = Monster(); //~ ERROR `Monster` is the name of a struct or
-    //~^ HELP did you mean to write: `Monster { /* fields */ }`?
-}
index 96ac2de17628504c22ad540bf7860b60217550e8..e7b7decbdb073b6752c312ed12c1cd5e77cf92cd 100644 (file)
@@ -12,7 +12,7 @@ struct Foo {
     x: isize
 }
 
-impl Fo { //~ ERROR type name `Fo` is undefined or not in scope
+impl Fo { //~ ERROR unresolved type `Fo`
     fn foo() {}
 }
 
index 1c97c0c886da28bc9df2330c3bdfa17e9c6b72e6..318eab92252859c1b34ef0130249a24866d19f37 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-impl B { //~ ERROR type name `B` is undefined or not in scope
+impl B { //~ ERROR unresolved type `B`
 }
 
 fn main() {
index 531705563e2e070ccfaacb82e5d01963d400a1f8..62649ba8a0fe1e364cdca2e26c02939d9ea5d687 100644 (file)
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    let super = "foo"; //~ ERROR unresolved unit struct/variant or constant `super`
+    let super = "foo"; //~ ERROR failed to resolve. There are too many initial `super`s
 }
index 9ac9e800c843bb4218cf601c41f09046b7f8a970..02047bd639ff919df011aba842d568ebdbd2fedf 100644 (file)
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    let super: isize; //~ ERROR unresolved unit struct/variant or constant `super`
+    let super: isize; //~ ERROR failed to resolve. There are too many initial `super`s
 }
index 0469a9d1cc859fd57c89674df4b50007a4d403b2..70a50d83904d7af6e997cd98092c0da54a8b4153 100644 (file)
@@ -25,6 +25,6 @@ macro_rules! test { ($nm:ident,
 // test1!(#[bar])
 #[qux]
 fn main() {
-    a::bar(); //~ ERROR unresolved name `a::bar`
+    a::bar(); //~ ERROR unresolved function `a::bar`
     b::bar();
 }
index 2ef697591284dc2ddbabd227de841355840bde61..dc5a2deab42b251483e090662599194884d3f1a3 100644 (file)
@@ -18,6 +18,6 @@ macro_rules! foo {
 // not to the macro variable '$id'
 fn main() {
     foo!(
-        x //~ ERROR unresolved name `x`
+        x //~ ERROR unresolved value `x`
         );
 }
index 4ec426fd3aa8b9f3f4af9babde301be0df9d776f..3f6304db957bf6805231c48e2504dd3d2f2cecc8 100644 (file)
@@ -16,6 +16,6 @@
 fn main() {
     match true { false => { my_panic(); } true => { } }
 
-    println!("{}", x); //~ ERROR unresolved name `x`
+    println!("{}", x); //~ ERROR unresolved value `x`
     let x: isize;
 }
index 596cec167c218ac2ce674d1c7366c571143f2ce2..4cf8eea78cfa7dce62af1d1cd5fdc6ec1fc12937 100644 (file)
@@ -34,7 +34,7 @@ fn main() {
         [0, 1, 2, 3, x..] => {} //~ ERROR pattern requires
     };
 
-    match does_not_exist { //~ ERROR unresolved name
+    match does_not_exist { //~ ERROR unresolved value `does_not_exist`
         [] => {}
     };
 }
index f8ea5dda183366df38ecfa9544f08d21d4406a97..c64b22a7f415a50eba24d8f70ec0b5ae844adff6 100644 (file)
@@ -13,5 +13,5 @@
 mod mod_file_aux;
 
 fn main() {
-    assert!(mod_file_aux::bar() == 10); //~ ERROR unresolved name
+    assert!(mod_file_aux::bar() == 10); //~ ERROR unresolved function `mod_file_aux::bar`
 }
index 4c76c4b8b0265662e236c3024bb58d395af6e117..359417aee52797c992a2d8c93c52a2b6025f9b4d 100644 (file)
@@ -13,6 +13,6 @@
 fn main() {
   let None: isize = 42; //~ ERROR let bindings cannot shadow unit variants
   log(debug, None);
-  //~^ ERROR unresolved name `debug`
-  //~| ERROR unresolved name `log`
+  //~^ ERROR unresolved function `log`
+  //~| ERROR unresolved value `debug`
 }
index cb7894b726f46f597e60d1a102302a6c8ec375c2..c1c724fc431c7c30e497b3daf456b9731bdf97cf 100644 (file)
@@ -41,13 +41,13 @@ mod m2 {
 
 fn f12() {
     check(m1::S{}); //~ ERROR c::Item
-    check(m1::S); //~ ERROR unresolved name
+    check(m1::S); //~ ERROR expected value, found type alias `m1::S`
     check(m2::S{}); //~ ERROR c::S
     check(m2::S); //~ ERROR c::Item
 }
 fn xf12() {
     check(xm1::S{}); //~ ERROR c::Item
-    check(xm1::S); //~ ERROR unresolved name
+    check(xm1::S); //~ ERROR expected value, found type alias `xm1::S`
     check(xm2::S{}); //~ ERROR c::S
     check(xm2::S); //~ ERROR c::Item
 }
@@ -107,13 +107,13 @@ mod m8 {
 
 fn f78() {
     check(m7::V{}); //~ ERROR c::Item
-    check(m7::V); //~ ERROR name of a struct or struct variant
+    check(m7::V); //~ ERROR expected value, found struct variant `m7::V`
     check(m8::V{}); //~ ERROR c::E
     check(m8::V); //~ ERROR c::Item
 }
 fn xf78() {
     check(xm7::V{}); //~ ERROR c::Item
-    check(xm7::V); //~ ERROR name of a struct or struct variant
+    check(xm7::V); //~ ERROR expected value, found struct variant `xm7::V`
     check(xm8::V{}); //~ ERROR c::E
     check(xm8::V); //~ ERROR c::Item
 }
index 4fcb31d36865aa55793ad1d2bdf537a2fff63111..d92323e290b42f6096318b645ee40e2adf1b1315 100644 (file)
@@ -18,8 +18,8 @@ mod m {
 pub fn main() {
     use namespaced_enums::Foo::*;
 
-    foo(); //~ ERROR unresolved name `foo`
-    m::foo(); //~ ERROR unresolved name `m::foo`
-    bar(); //~ ERROR unresolved name `bar`
-    m::bar(); //~ ERROR unresolved name `m::bar`
+    foo(); //~ ERROR unresolved function `foo`
+    m::foo(); //~ ERROR unresolved function `m::foo`
+    bar(); //~ ERROR unresolved function `bar`
+    m::bar(); //~ ERROR unresolved function `m::bar`
 }
index 4437482fb67cc2fa1180b58564f8e390fcbb9e02..b7c7397ee989c1cf230f873fdf53b730e3a3a54a 100644 (file)
@@ -28,8 +28,8 @@ mod m {
 pub fn main() {
     use m2::Foo::*;
 
-    foo(); //~ ERROR unresolved name `foo`
-    m::foo(); //~ ERROR unresolved name `m::foo`
-    bar(); //~ ERROR unresolved name `bar`
-    m::bar(); //~ ERROR unresolved name `m::bar`
+    foo(); //~ ERROR unresolved function `foo`
+    m::foo(); //~ ERROR unresolved function `m::foo`
+    bar(); //~ ERROR unresolved function `bar`
+    m::bar(); //~ ERROR unresolved function `m::bar`
 }
index 6010b1e695e9bd5dc7a35b8bb95e74b6a7c7e267..f3e20f4f614663cb8cf180742a4f6c8481d6263f 100644 (file)
@@ -11,4 +11,4 @@
 #[cfg_attr(all(), cfg_attr(all(), cfg(foo)))]
 fn f() {}
 
-fn main() { f() } //~ ERROR unresolved name `f`
+fn main() { f() } //~ ERROR unresolved function `f`
index af1046bcd5d97b02d7668b531923e47e4a500d0f..49e2e9f34fa3e796787ebfe8279f4172297917be 100644 (file)
 mod foo {
     mod baz {
         struct Test;
-        impl Add for Test {} //~ ERROR: not in scope
-        impl Clone for Test {} //~ ERROR: not in scope
-        impl Iterator for Test {} //~ ERROR: not in scope
-        impl ToString for Test {} //~ ERROR: not in scope
-        impl Writer for Test {} //~ ERROR: not in scope
+        impl Add for Test {} //~ ERROR unresolved trait `Add`
+        impl Clone for Test {} //~ ERROR unresolved trait `Clone`
+        impl Iterator for Test {} //~ ERROR unresolved trait `Iterator`
+        impl ToString for Test {} //~ ERROR unresolved trait `ToString`
+        impl Writer for Test {} //~ ERROR unresolved trait `Writer`
 
         fn foo() {
-            drop(2) //~ ERROR: unresolved name
+            drop(2) //~ ERROR unresolved function `drop`
         }
     }
 
     struct Test;
-    impl Add for Test {} //~ ERROR: not in scope
-    impl Clone for Test {} //~ ERROR: not in scope
-    impl Iterator for Test {} //~ ERROR: not in scope
-    impl ToString for Test {} //~ ERROR: not in scope
-    impl Writer for Test {} //~ ERROR: not in scope
+    impl Add for Test {} //~ ERROR unresolved trait `Add`
+    impl Clone for Test {} //~ ERROR unresolved trait `Clone`
+    impl Iterator for Test {} //~ ERROR unresolved trait `Iterator`
+    impl ToString for Test {} //~ ERROR unresolved trait `ToString`
+    impl Writer for Test {} //~ ERROR unresolved trait `Writer`
 
     fn foo() {
-        drop(2) //~ ERROR: unresolved name
+        drop(2) //~ ERROR unresolved function `drop`
     }
 }
 
@@ -45,14 +45,14 @@ fn qux() {
     #[no_implicit_prelude]
     mod qux_inner {
         struct Test;
-        impl Add for Test {} //~ ERROR: not in scope
-        impl Clone for Test {} //~ ERROR: not in scope
-        impl Iterator for Test {} //~ ERROR: not in scope
-        impl ToString for Test {} //~ ERROR: not in scope
-        impl Writer for Test {} //~ ERROR: not in scope
+        impl Add for Test {} //~ ERROR unresolved trait `Add`
+        impl Clone for Test {} //~ ERROR unresolved trait `Clone`
+        impl Iterator for Test {} //~ ERROR unresolved trait `Iterator`
+        impl ToString for Test {} //~ ERROR unresolved trait `ToString`
+        impl Writer for Test {} //~ ERROR unresolved trait `Writer`
 
         fn foo() {
-            drop(2) //~ ERROR: unresolved name
+            drop(2) //~ ERROR unresolved function `drop`
         }
     }
 }
index 4693fd14e7de756f4d1246ec08abc6023a55e17a..b830a64fa8188d2f01a92f5f15f498cea944f8b3 100644 (file)
 // fail with the same error message).
 
 struct Test;
-impl Add for Test {} //~ ERROR: not in scope
-impl Clone for Test {} //~ ERROR: not in scope
-impl Iterator for Test {} //~ ERROR: not in scope
-impl ToString for Test {} //~ ERROR: not in scope
-impl Writer for Test {} //~ ERROR: not in scope
+impl Add for Test {} //~ ERROR unresolved trait `Add`
+impl Clone for Test {} //~ ERROR unresolved trait `Clone`
+impl Iterator for Test {} //~ ERROR unresolved trait `Iterator`
+impl ToString for Test {} //~ ERROR unresolved trait `ToString`
+impl Writer for Test {} //~ ERROR unresolved trait `Writer`
 
 fn main() {
-    drop(2) //~ ERROR: unresolved name
+    drop(2) //~ ERROR unresolved function `drop`
 }
index c4737a373992d5658c455303ac703780bdf0fe48..7e4e55543cd222d1a316ff8d265f873f8b3fb5fc 100644 (file)
@@ -15,5 +15,5 @@
 //~^ WARN custom derive crates and `#[no_link]` crates have no effect without `#[macro_use]`
 
 fn main() {
-    empty_struct::XEmpty1; //~ ERROR unresolved name
+    empty_struct::XEmpty1; //~ ERROR unresolved value `empty_struct::XEmpty1`
 }
index b5401f7d124e24e1d2c29aea4a44fdeef9dd386d..691d8d31b412d1c3934d8cbf2f7da2cff49b1788 100644 (file)
@@ -12,8 +12,8 @@
 
 fn main() {
     fn bar(n: isize) {
-        // FIXME (#24414): This error message needs improvement.
         let _x: [isize; n];
-        //~^ ERROR no type for local variable
+        //~^ ERROR attempt to use a non-constant value in a constant [E0435]
+        //~| ERROR constant evaluation error [E0080]
     }
 }
index a6f88a57b9125846a8f5ba8b52a91b18f7157736..f4769a78587280494ea4bab4f91ca3784317f148 100644 (file)
@@ -13,8 +13,9 @@
 fn main() {
     fn bar(n: usize) {
         let _x = [0; n];
-        //~^ ERROR constant evaluation error
-        //~| non-constant path in constant expression
-        //~| NOTE `n` is a variable
+        //~^ ERROR attempt to use a non-constant value in a constant [E0435]
+        //~| NOTE non-constant used with constant
+        //~| NOTE unresolved path in constant expression
+        //~| ERROR constant evaluation error [E0080]
     }
 }
index 85b62461238336b5e8bb90c286132d7bbe7e5b72..373b33c3e4985d56a08bec4311bc6e2292e7501a 100644 (file)
 
 trait Foo {
     fn bar() {
-        let x = foo(); //~ ERROR unresolved name `foo`
+        let x = foo(); //~ ERROR unresolved function `foo`
 
 }
 
 fn main() {
     let x = y.;  //~ ERROR unexpected token
-                 //~^ ERROR unresolved name `y`
+                 //~^ ERROR unresolved value `y`
 } //~ ERROR this file contains an un-closed delimiter
index 109da6251e37d436d1e3ead96c65b46794e43681..c2bbbda4011e9b42ad7eb45aa170efdc841ca106 100644 (file)
 
 trait Foo {
     fn bar() {
-        let x = foo(); //~ ERROR unresolved name `foo`
+        let x = foo(); //~ ERROR unresolved function `foo`
     ) //~ ERROR incorrect close delimiter: `)`
 }
 
 fn main() {
     let x = y.;  //~ ERROR unexpected token
-                 //~^ ERROR unresolved name `y`
+                 //~^ ERROR unresolved value `y`
 }
index 1c79c9a2293a0f03bfbe9a63d151a265ab6bdb34..24f296661725a00885a87935c7f040731a3217e5 100644 (file)
@@ -12,5 +12,5 @@ macro_rules! foo { () => ( x ) }
 
 fn main() {
     let foo!() = 2;
-    x + 1; //~ ERROR unresolved name `x`
+    x + 1; //~ ERROR unresolved value `x`
 }
index dcab3a46b0a5945c86d27a626ded7dd8e4482d18..9c1e8250dbc6df0466ba8d824612af9c888d3ded 100644 (file)
@@ -27,7 +27,7 @@ fn Bar() { }
 fn test_glob1() {
     use foo1::*;
 
-    Bar();  //~ ERROR unresolved name `Bar`
+    Bar();  //~ ERROR expected function, found trait `Bar`
 }
 
 // private type, public value
@@ -42,7 +42,7 @@ pub fn Bar() { }
 fn test_glob2() {
     use foo2::*;
 
-    let _x: Box<Bar>;  //~ ERROR type name `Bar` is undefined or not in scope
+    let _x: Box<Bar>;  //~ ERROR expected type, found function `Bar`
 }
 
 // neither public
@@ -57,8 +57,8 @@ fn Bar() { }
 fn test_glob3() {
     use foo3::*;
 
-    Bar();  //~ ERROR unresolved name `Bar`
-    let _x: Box<Bar>;  //~ ERROR  type name `Bar` is undefined or not in scope
+    Bar();  //~ ERROR unresolved function `Bar`
+    let _x: Box<Bar>;  //~ ERROR unresolved type `Bar`
 }
 
 fn main() {
index 7accf0ca8201c27da5c21be4463c7fe765572dac..ec9396b5e7bcbad193d7f2a087486e77dd6de2c2 100644 (file)
@@ -27,13 +27,13 @@ fn Bar() { }
 fn test_single1() {
     use foo1::Bar;
 
-    Bar(); //~ ERROR unresolved name `Bar`
+    Bar(); //~ ERROR expected function, found trait `Bar`
 }
 
 fn test_list1() {
     use foo1::{Bar,Baz};
 
-    Bar(); //~ ERROR unresolved name `Bar`
+    Bar(); //~ ERROR expected function, found trait `Bar`
 }
 
 // private type, public value
@@ -48,13 +48,13 @@ pub fn Bar() { }
 fn test_single2() {
     use foo2::Bar;
 
-    let _x : Box<Bar>; //~ ERROR type name `Bar` is undefined
+    let _x : Box<Bar>; //~ ERROR expected type, found function `Bar`
 }
 
 fn test_list2() {
     use foo2::{Bar,Baz};
 
-    let _x: Box<Bar>; //~ ERROR type name `Bar` is undefined
+    let _x: Box<Bar>; //~ ERROR expected type, found function `Bar`
 }
 
 // neither public
index 3e1bb7666229c60fbedea94abd1b0b7f5f2eb04c..01e2c6cd7e8288b40a99fc27d9e42bbb9802e6cf 100644 (file)
@@ -57,6 +57,6 @@ fn main() {
 }
 
 mod pathological {
-    pub(bad::path) mod m1 {} //~ ERROR failed to resolve module path
+    pub(bad::path) mod m1 {} //~ ERROR failed to resolve. Maybe a missing `extern crate bad;`?
     pub(foo) mod m2 {} //~ ERROR visibilities can only be restricted to ancestor modules
 }
index ae60c4366ee33521583cac84de334014064e3e92..593713a6e059fa0dfa22583e29b2b9308820a876 100644 (file)
@@ -16,11 +16,11 @@ macro_rules! m {
 
 struct S<T>(T);
 m!{ S<u8> } //~ ERROR type or lifetime parameters in visibility path
-//~^ ERROR failed to resolve module path. Not a module `S`
+//~^ ERROR expected module, found struct `S`
 
 mod foo {
     struct S(pub(foo<T>) ()); //~ ERROR type or lifetime parameters in visibility path
-    //~^ ERROR type name `T` is undefined or not in scope
+    //~^ ERROR unresolved type `T`
 }
 
 fn main() {}
index 6fd52beeec62c444243a402978169da346c07c39..48ec16a7610b7fc2afbda0674d46bb4987ee6ba2 100644 (file)
@@ -10,6 +10,8 @@
 
 // aux-build:recursive_reexports.rs
 
-fn f() -> recursive_reexports::S {} //~ ERROR undeclared
+extern crate recursive_reexports;
+
+fn f() -> recursive_reexports::S {} //~ ERROR unresolved type `recursive_reexports::S`
 
 fn main() {}
index 5d5113ce07c719f66c2cf622d259cb7498f3e845..a716f3e29d488ce62adf8503f769b5deb70f6361 100644 (file)
 fn main() {
     let n = 1;
     let a = [0; n];
-    //~^ ERROR constant evaluation error
-    //~| non-constant path in constant expression
+    //~^ ERROR attempt to use a non-constant value in a constant [E0435]
     let b = [0; ()];
     //~^ ERROR mismatched types
     //~| expected type `usize`
     //~| found type `()`
     //~| expected usize, found ()
-    //~| ERROR expected `usize` for repeat count, found tuple [E0306]
-    //~| expected `usize`
     let c = [0; true];
     //~^ ERROR mismatched types
     //~| expected usize, found bool
-    //~| ERROR expected `usize` for repeat count, found boolean [E0306]
-    //~| expected `usize`
     let d = [0; 0.5];
     //~^ ERROR mismatched types
     //~| expected type `usize`
     //~| found type `{float}`
     //~| expected usize, found floating-point variable
-    //~| ERROR expected `usize` for repeat count, found float [E0306]
-    //~| expected `usize`
     let e = [0; "foo"];
     //~^ ERROR mismatched types
     //~| expected type `usize`
     //~| found type `&'static str`
     //~| expected usize, found reference
-    //~| ERROR expected `usize` for repeat count, found string literal [E0306]
-    //~| expected `usize`
     let f = [0; -4_isize];
-    //~^ ERROR constant evaluation error
-    //~| expected usize, found isize
-    //~| ERROR mismatched types
+    //~^ ERROR mismatched types
     //~| expected usize, found isize
     let f = [0_usize; -1_isize];
-    //~^ ERROR constant evaluation error
-    //~| expected usize, found isize
-    //~| ERROR mismatched types
+    //~^ ERROR mismatched types
     //~| expected usize, found isize
     struct G {
         g: (),
@@ -59,6 +46,4 @@ struct G {
     //~| expected type `usize`
     //~| found type `main::G`
     //~| expected usize, found struct `main::G`
-    //~| ERROR expected `usize` for repeat count, found struct [E0306]
-    //~| expected `usize`
 }
diff --git a/src/test/compile-fail/resolve-bad-import-prefix.rs b/src/test/compile-fail/resolve-bad-import-prefix.rs
new file mode 100644 (file)
index 0000000..6b4a512
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.
+
+mod m {}
+enum E {}
+struct S;
+trait Tr {}
+
+use {}; // OK
+use ::{}; // OK
+use m::{}; // OK
+use E::{}; // OK
+use S::{}; //~ ERROR expected module or enum, found struct `S`
+use Tr::{}; //~ ERROR expected module or enum, found trait `Tr`
+use Nonexistent::{}; //~ ERROR unresolved module or enum `Nonexistent`
+
+fn main () {}
diff --git a/src/test/compile-fail/resolve-bad-visibility.rs b/src/test/compile-fail/resolve-bad-visibility.rs
new file mode 100644 (file)
index 0000000..088a4e6
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(pub_restricted)]
+
+enum E {}
+trait Tr {}
+
+pub(E) struct S; //~ ERROR expected module, found enum `E`
+pub(Tr) struct Z; //~ ERROR expected module, found trait `Tr`
+pub(std::vec) struct F; //~ ERROR visibilities can only be restricted to ancestor modules
+pub(nonexistent) struct G; //~ ERROR unresolved module `nonexistent`
+pub(too_soon) struct H; //~ ERROR unresolved module `too_soon`
+
+// Visibilities are resolved eagerly without waiting for modules becoming fully populated.
+// Visibilities can only use ancestor modules legally which are always available in time,
+// so the worst thing that can happen due to eager resolution is a suboptimal error message.
+mod too_soon {}
+
+fn main () {}
diff --git a/src/test/compile-fail/resolve-hint-macro.rs b/src/test/compile-fail/resolve-hint-macro.rs
deleted file mode 100644 (file)
index edaab01..0000000
+++ /dev/null
@@ -1,15 +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() {
-    assert(true);
-    //~^ ERROR unresolved name `assert`
-    //~| NOTE did you mean the macro `assert!`?
-}
index 1e43933ad0ab4356ccfd93746d9a99d6aa857669..de463cd9e6af6dc1ee10ee34b3ac49613cdd849f 100644 (file)
 fn main() {
     // Make sure primitive type fallback doesn't work in value namespace
     std::mem::size_of(u16);
-    //~^ ERROR unresolved name `u16`
+    //~^ ERROR expected value, found builtin type `u16`
     //~| ERROR this function takes 0 parameters but 1 parameter was supplied
 
     // Make sure primitive type fallback doesn't work with global paths
     let _: ::u8;
-    //~^ ERROR type name `u8` is undefined or not in scope
+    //~^ ERROR unresolved type `u8`
 }
index dae3a79832b10ddf847cde152cc2bfec77fc32ba..affafbfadcf274171e514d039f98ea0b2ec5d7da 100644 (file)
 
 
 trait NewTrait : SomeNonExistentTrait {}
-//~^ ERROR trait `SomeNonExistentTrait` is not in scope
+//~^ ERROR unresolved trait `SomeNonExistentTrait`
 
 impl SomeNonExistentTrait for isize {}
-//~^ ERROR trait `SomeNonExistentTrait` is not in scope
+//~^ ERROR unresolved trait `SomeNonExistentTrait`
 
 fn f<T:SomeNonExistentTrait>() {}
-//~^ ERROR trait `SomeNonExistentTrait` is not in scope
+//~^ ERROR unresolved trait `SomeNonExistentTrait`
index f2ac37a2ce9f597925d07daa1bde884abc3ca770..dde559b018cde55ecbc1f7fdac6f8cefc68e5262 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: --emit=metadata
 // aux-build:rmeta_rlib.rs
 // no-prefer-dynamic
 // must-compile-successfully
@@ -15,8 +16,6 @@
 // Check that building a metadata crate works with a dependent, rlib crate.
 // This is a cfail test since there is no executable to run.
 
-#![crate_type="metadata"]
-
 extern crate rmeta_rlib;
 use rmeta_rlib::Foo;
 
index 2c0b6f77c1e08114d0239f36fac1192e5f71d86f..5b24da79a7e63a953d6eebadc9f997e3319a962a 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: --emit=metadata
 // aux-build:rmeta_meta.rs
 // no-prefer-dynamic
 // must-compile-successfully
@@ -16,8 +17,6 @@
 // crate.
 // This is a cfail test since there is no executable to run.
 
-#![crate_type="metadata"]
-
 extern crate rmeta_meta;
 use rmeta_meta::Foo;
 
diff --git a/src/test/compile-fail/rmeta-priv-warn.rs b/src/test/compile-fail/rmeta-priv-warn.rs
new file mode 100644 (file)
index 0000000..3e7019e
--- /dev/null
@@ -0,0 +1,21 @@
+// 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: --emit=metadata
+// no-prefer-dynamic
+// must-compile-successfully
+
+#[deny(warnings)]
+
+// Test that we don't get warnings for non-pub main when only emitting metadata.
+// (#38273)
+
+fn main() {
+}
index e81e0541096d62c9bca728ef0101907600fcd8ac..edcf98d99647654b66eb4d6c47f7b82e5b8d8ef3 100644 (file)
@@ -9,11 +9,10 @@
 // except according to those terms.
 
 // no-prefer-dynamic
+// compile-flags: --emit=metadata
 
 // Check that building a metadata crate finds an error.
 
-#![crate_type="metadata"]
-
 fn main() {
-    let _ = Foo; //~ ERROR unresolved name `Foo`
+    let _ = Foo; //~ ERROR unresolved value `Foo`
 }
index 1c922c281397a8f45102c2d64a909a2819b05000..ffeb5bc3b858f26261364c70dc2059af9f25349f 100644 (file)
@@ -8,13 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: --emit=metadata
 // aux-build:rmeta_meta.rs
 // no-prefer-dynamic
 
 // Check that building a metadata crate finds an error with a dependent,
 // metadata-only crate.
 
-#![crate_type="metadata"]
 
 extern crate rmeta_meta;
 use rmeta_meta::Foo;
index 50a43f4a276daa5fe036c2b8f1abac90a81106ba..d15553730159a3d375f4f8800566338d7ce0657b 100644 (file)
@@ -19,6 +19,6 @@ fn main() {
     let x = 0;
     let foo = Foo {
         x,
-        y //~ ERROR unresolved name `y`
+        y //~ ERROR unresolved value `y`
     };
 }
diff --git a/src/test/compile-fail/suggest-path-instead-of-mod-dot-item.rs b/src/test/compile-fail/suggest-path-instead-of-mod-dot-item.rs
deleted file mode 100644 (file)
index 4a816ea..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-// 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.
-
-// Beginners write `mod.item` when they should write `mod::item`.
-// This tests that we suggest the latter when we encounter the former.
-
-pub mod a {
-    pub const I: i32 = 1;
-
-    pub fn f() -> i32 { 2 }
-
-    pub mod b {
-        pub const J: i32 = 3;
-
-        pub fn g() -> i32 { 4 }
-    }
-}
-
-fn h1() -> i32 {
-    a.I
-        //~^ ERROR E0425
-        //~| HELP to reference an item from the `a` module, use `a::I`
-}
-
-fn h2() -> i32 {
-    a.g()
-        //~^ ERROR E0425
-        //~| HELP to call a function from the `a` module, use `a::g(..)`
-}
-
-fn h3() -> i32 {
-    a.b.J
-        //~^ ERROR E0425
-        //~| HELP to reference an item from the `a` module, use `a::b`
-}
-
-fn h4() -> i32 {
-    a::b.J
-        //~^ ERROR E0425
-        //~| HELP to reference an item from the `a::b` module, use `a::b::J`
-}
-
-fn h5() {
-    a.b.f();
-        //~^ ERROR E0425
-        //~| HELP to reference an item from the `a` module, use `a::b`
-    let v = Vec::new();
-    v.push(a::b);
-        //~^ ERROR E0425
-        //~| HELP module `a::b` cannot be used as an expression
-}
-
-fn h6() -> i32 {
-    a::b.f()
-        //~^ ERROR E0425
-        //~| HELP to call a function from the `a::b` module, use `a::b::f(..)`
-}
-
-fn h7() {
-    a::b
-        //~^ ERROR E0425
-        //~| HELP module `a::b` cannot be used as an expression
-}
-
-fn h8() -> i32 {
-    a::b()
-        //~^ ERROR E0425
-        //~| HELP module `a::b` cannot be used as an expression
-}
index f06e3544e575dec1874a39eb9dc1eeb2b735aae0..0beb4f084c8babd1da0feec5431c415226b4b023 100644 (file)
@@ -18,7 +18,7 @@ pub fn main() {
     // this now fails (correctly, I claim) because hygiene prevents
     // the assembled identifier from being a reference to the binding.
     assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string());
-    //~^ ERROR: unresolved name `asdf_fdsa`
+    //~^ ERROR unresolved value `asdf_fdsa`
 
     assert_eq!(stringify!(use_mention_distinction), "use_mention_distinction");
 }
index 0709d9095124eb695142b4a0b6426b6ffd3f48bf..28c69e8df222fd350056e78db0d669711259a4a6 100644 (file)
@@ -14,5 +14,5 @@
 fn foo() {}
 
 fn main() {
-    foo(); //~ ERROR unresolved name `foo`
+    foo(); //~ ERROR unresolved function `foo`
 }
diff --git a/src/test/compile-fail/token-error-correct-2.rs b/src/test/compile-fail/token-error-correct-2.rs
deleted file mode 100644 (file)
index 151c1d4..0000000
+++ /dev/null
@@ -1,18 +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.
-
-// Test that we do some basic error correcton in the tokeniser (and don't ICE).
-
-fn main() {
-    if foo { //~ NOTE: unclosed delimiter
-    //~^ ERROR: unresolved name `foo`
-    //~| NOTE unresolved name
-    ) //~ ERROR: incorrect close delimiter: `)`
-}
diff --git a/src/test/compile-fail/token-error-correct-3.rs b/src/test/compile-fail/token-error-correct-3.rs
deleted file mode 100644 (file)
index 5f21bf1..0000000
+++ /dev/null
@@ -1,38 +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.
-
-// Test that we do some basic error correcton in the tokeniser (and don't spew
-// too many bogus errors).
-
-pub mod raw {
-    use std::{io, fs};
-    use std::path::Path;
-
-    pub fn ensure_dir_exists<P: AsRef<Path>, F: FnOnce(&Path)>(path: P,
-                                                               callback: F)
-                                                               -> io::Result<bool> {
-        if !is_directory(path.as_ref()) { //~ ERROR: unresolved name `is_directory`
-                                          //~| NOTE unresolved name
-            callback(path.as_ref();  //~ NOTE: unclosed delimiter
-                     //~^ ERROR: expected one of
-            fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types
-            //~^ expected (), found enum `std::result::Result`
-            //~| expected type `()`
-            //~| found type `std::result::Result<bool, std::io::Error>`
-        } else { //~ ERROR: incorrect close delimiter: `}`
-            //~^ ERROR: expected one of
-            Ok(false);
-        }
-
-        panic!();
-    }
-}
-
-fn main() {}
diff --git a/src/test/compile-fail/token-error-correct.rs b/src/test/compile-fail/token-error-correct.rs
deleted file mode 100644 (file)
index 3ba9edd..0000000
+++ /dev/null
@@ -1,24 +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.
-
-// Test that we do some basic error correcton in the tokeniser.
-
-fn main() {
-    foo(bar(; //~ NOTE: unclosed delimiter
-    //~^ NOTE: unclosed delimiter
-    //~^^ ERROR: expected expression, found `;`
-    //~^^^ ERROR: unresolved name `bar`
-    //~^^^^ ERROR: unresolved name `foo`
-    //~^^^^^ ERROR: expected one of `)`, `,`, `.`, `<`, `?`
-    //~| NOTE unresolved name
-    //~| NOTE unresolved name
-} //~ ERROR: incorrect close delimiter: `}`
-//~^ ERROR: incorrect close delimiter: `}`
-//~^^ ERROR: expected expression, found `)`
diff --git a/src/test/compile-fail/ufcs-partially-resolved.rs b/src/test/compile-fail/ufcs-partially-resolved.rs
new file mode 100644 (file)
index 0000000..5337272
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(associated_type_defaults)]
+
+trait Tr {
+    type Y = u16;
+    fn Y() {}
+}
+impl Tr for u8 {}
+
+trait Dr {
+    type X = u16;
+    fn Z() {}
+}
+impl Dr for u8 {}
+
+enum E { Y }
+type A = u32;
+
+fn main() {
+    let _: <u8 as Tr>::N; //~ ERROR unresolved associated type `Tr::N`
+    let _: <u8 as E>::N; //~ ERROR unresolved associated type `E::N`
+    let _: <u8 as A>::N; //~ ERROR unresolved associated type `A::N`
+    <u8 as Tr>::N; //~ ERROR unresolved method or associated constant `Tr::N`
+    <u8 as E>::N; //~ ERROR unresolved method or associated constant `E::N`
+    <u8 as A>::N; //~ ERROR unresolved method or associated constant `A::N`
+    let _: <u8 as Tr>::Y; // OK
+    let _: <u8 as E>::Y; //~ ERROR expected associated type, found variant `E::Y`
+    <u8 as Tr>::Y; // OK
+    <u8 as E>::Y; //~ ERROR expected method or associated constant, found unit variant `E::Y`
+
+    let _: <u8 as Tr>::N::NN; //~ ERROR unresolved associated type `Tr::N`
+    let _: <u8 as E>::N::NN; //~ ERROR unresolved associated type `E::N`
+    let _: <u8 as A>::N::NN; //~ ERROR unresolved associated type `A::N`
+    <u8 as Tr>::N::NN; //~ ERROR unresolved associated type `Tr::N`
+    <u8 as E>::N::NN; //~ ERROR unresolved associated type `E::N`
+    <u8 as A>::N::NN; //~ ERROR unresolved associated type `A::N`
+    let _: <u8 as Tr>::Y::NN; //~ ERROR ambiguous associated type
+    let _: <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
+    <u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found for type `<u8 as Tr>::Y`
+    <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
+
+    let _: <u8 as Tr::N>::NN; //~ ERROR unresolved associated type `Tr::N::NN`
+    let _: <u8 as E::N>::NN; //~ ERROR unresolved associated type `E::N::NN`
+    let _: <u8 as A::N>::NN; //~ ERROR unresolved associated type `A::N::NN`
+    <u8 as Tr::N>::NN; //~ ERROR unresolved method or associated constant `Tr::N::NN`
+    <u8 as E::N>::NN; //~ ERROR unresolved method or associated constant `E::N::NN`
+    <u8 as A::N>::NN; //~ ERROR unresolved method or associated constant `A::N::NN`
+    let _: <u8 as Tr::Y>::NN; //~ ERROR unresolved associated type `Tr::Y::NN`
+    let _: <u8 as E::Y>::NN; //~ ERROR unresolved associated type `E::Y::NN`
+    <u8 as Tr::Y>::NN; //~ ERROR unresolved method or associated constant `Tr::Y::NN`
+    <u8 as E::Y>::NN; //~ ERROR unresolved method or associated constant `E::Y::NN`
+
+    let _: <u8 as Dr>::Z; //~ ERROR expected associated type, found method `Dr::Z`
+    <u8 as Dr>::X; //~ ERROR expected method or associated constant, found associated type `Dr::X`
+    let _: <u8 as Dr>::Z::N; //~ ERROR expected associated type, found method `Dr::Z`
+    <u8 as Dr>::X::N; //~ ERROR no associated item named `N` found for type `<u8 as Dr>::X`
+}
diff --git a/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs b/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs
deleted file mode 100644 (file)
index 465bddd..0000000
+++ /dev/null
@@ -1,17 +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 f<F:Nonexist(isize) -> isize>(x: F) {} //~ ERROR trait `Nonexist` is not in scope
-
-type Typedef = isize;
-
-fn g<F:Typedef(isize) -> isize>(x: F) {} //~ ERROR `Typedef` is not a trait
-
-fn main() {}
diff --git a/src/test/compile-fail/unresolved_static_type_field.rs b/src/test/compile-fail/unresolved_static_type_field.rs
deleted file mode 100644 (file)
index 80f6108..0000000
+++ /dev/null
@@ -1,24 +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.
-
-fn f(_: bool) {}
-
-struct Foo {
-    cx: bool,
-}
-
-impl Foo {
-    fn bar() {
-        f(cx); //~ ERROR E0425
-               //~| HELP this is an associated function
-    }
-}
-
-fn main() {}
index 73defa6eef991045c3cf234c101c8a852d9881cd..c889b7d28f8c2a8568ace30ce068822f39e987ac 100644 (file)
@@ -15,7 +15,7 @@
 enum Ty {
     A,
     B(Ty::A),
-    //~^ ERROR: found value `Ty::A` used as a type
+    //~^ ERROR expected type, found variant `Ty::A`
 }
 
 
@@ -25,6 +25,6 @@ enum E {
 }
 
 impl E::A {}
-//~^ ERROR: found value `E::A` used as a type
+//~^ ERROR expected type, found variant `E::A`
 
 fn main() {}
index 214a2a371baaf63d882403b03dc8b588e511d5e4..04af71330007593f0b4f15989652cc67a438eda6 100644 (file)
@@ -17,6 +17,6 @@
 
 fn main() {
     let _ = xcrate_unit_struct::StructWithFields;
-    //~^ ERROR: `xcrate_unit_struct::StructWithFields` is the name of a struct or struct variant
+    //~^ ERROR expected value, found struct `xcrate_unit_struct::StructWithFields`
     let _ = xcrate_unit_struct::Struct;
 }
index 26e73a08ea137ce9c905776182d98fc04517afdd..ada9e0b30ccae1cc61010da8c3b819e4211e6dfe 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // min-lldb-version: 310
+// ignore-macos FIXME(#37479)
 
 // compile-flags:-g
 
index 10c02d84b385e7105723652a177694a4c6700e13..28e85c94b664ce47882d2559402eeea53f64f259 100644 (file)
 const CONST_CHANGE_VALUE_1: i16 = 1;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_1: i16 = 2;
 const CONST_CHANGE_VALUE_2: i16 = 1 + 1;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_2: i16 = 1 + 2;
 const CONST_CHANGE_VALUE_3: i16 = 2 + 3;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_3: i16 = 2 * 3;
 const CONST_CHANGE_VALUE_4: i16 = 1 + 2 * 3;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_4: i16 = 1 + 2 * 4;
index aa17a24be23b6fab6027ea981dce126de9e41b99..da3a953d11eaa883367ebcdedcca038947c44a7f 100644 (file)
@@ -108,8 +108,10 @@ enum EnumChangeValueCStyleVariant0 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumChangeValueCStyleVariant0 {
@@ -126,6 +128,8 @@ enum EnumChangeValueCStyleVariant1 {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumChangeValueCStyleVariant1 {
diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs
new file mode 100644 (file)
index 0000000..03e621f
--- /dev/null
@@ -0,0 +1,272 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+// This test case tests the incremental compilation hash (ICH) implementation
+// for `extern` modules.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// must-compile-successfully
+// revisions: cfail1 cfail2 cfail3
+// compile-flags: -Z query-dep-graph
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![feature(unboxed_closures)]
+#![feature(link_args)]
+#![crate_type="rlib"]
+
+
+// Change function name --------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    pub fn change_function_name1(c: i64) -> i32;
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+extern {
+    pub fn change_function_name2(c: i64) -> i32;
+}
+
+
+
+// Change parameter name -------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    pub fn change_parameter_name(c: i64) -> i32;
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+extern {
+    pub fn change_parameter_name(d: i64) -> i32;
+}
+
+
+
+// Change parameter type -------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    pub fn change_parameter_type(c: i64) -> i32;
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+extern {
+    pub fn change_parameter_type(c: i32) -> i32;
+}
+
+
+
+// Change return type ----------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    pub fn change_return_type(c: i32) -> i32;
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+extern {
+    pub fn change_return_type(c: i32) -> i8;
+}
+
+
+
+// Add parameter ---------------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    pub fn add_parameter(c: i32) -> i32;
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+extern {
+    pub fn add_parameter(c: i32, d: i32) -> i32;
+}
+
+
+
+// Add return type -------------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    pub fn add_return_type(c: i32);
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+extern {
+    pub fn add_return_type(c: i32) -> i32;
+}
+
+
+
+// Make function variadic ------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    pub fn make_function_variadic(c: i32);
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+extern {
+    pub fn make_function_variadic(c: i32, ...);
+}
+
+
+
+// Change calling convention ---------------------------------------------------
+#[cfg(cfail1)]
+extern "C" {
+    pub fn change_calling_convention(c: i32);
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+extern "rust-call" {
+    pub fn change_calling_convention(c: i32);
+}
+
+
+
+// Make function public --------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    fn make_function_public(c: i32);
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+extern {
+    pub fn make_function_public(c: i32);
+}
+
+
+
+// Add function ----------------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    pub fn add_function1(c: i32);
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+extern {
+    pub fn add_function1(c: i32);
+    pub fn add_function2();
+}
+
+
+
+// Change link-args ------------------------------------------------------------
+#[cfg(cfail1)]
+#[link_args = "-foo -bar"]
+extern {
+    pub fn change_link_args(c: i32);
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+#[link_args = "-foo -bar -baz"]
+extern {
+    pub fn change_link_args(c: i32);
+}
+
+
+
+// Change link-name ------------------------------------------------------------
+#[cfg(cfail1)]
+#[link(name = "foo")]
+extern {
+    pub fn change_link_name(c: i32);
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+#[link(name = "bar")]
+extern {
+    pub fn change_link_name(c: i32);
+}
+
+type c_i32 = i32;
+type c_i64 = i64;
+
+// Indirectly change parameter type --------------------------------------------
+mod indirectly_change_parameter_type {
+    #[cfg(cfail1)]
+    use super::c_i32 as c_int;
+    #[cfg(not(cfail1))]
+    use super::c_i64 as c_int;
+
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    extern {
+        pub fn indirectly_change_parameter_type(c: c_int);
+    }
+}
+
+
+
+// Indirectly change return type --------------------------------------------
+mod indirectly_change_return_type {
+    #[cfg(cfail1)]
+    use super::c_i32 as c_int;
+    #[cfg(not(cfail1))]
+    use super::c_i64 as c_int;
+
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    extern {
+        pub fn indirectly_change_return_type() -> c_int;
+    }
+}
index f7a390e874509312e6c01c0c5817e32f2651270b..5c37bc133596dd02cf8e369c396a50aee8a7eb55 100644 (file)
@@ -107,7 +107,7 @@ impl Foo {
     pub fn method_selfness(&self) { }
 }
 
-// Change Method Selfmutness -----------------------------------------------------------
+// Change Method Selfmutness ---------------------------------------------------
 #[cfg(cfail1)]
 impl Foo {
     pub fn method_selfmutness(&self) { }
@@ -126,3 +126,411 @@ impl Foo {
     pub fn method_selfmutness(&mut self) { }
 }
 
+
+
+// Add Method To Impl ----------------------------------------------------------
+#[cfg(cfail1)]
+impl Foo {
+    pub fn add_method_to_impl1(&self) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+    #[rustc_clean(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub fn add_method_to_impl1(&self) { }
+
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub fn add_method_to_impl2(&self) { }
+}
+
+
+
+// Add Method Parameter --------------------------------------------------------
+#[cfg(cfail1)]
+impl Foo {
+    pub fn add_method_parameter(&self) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub fn add_method_parameter(&self, _: i32) { }
+}
+
+
+
+// Change Method Parameter Name ------------------------------------------------
+#[cfg(cfail1)]
+impl Foo {
+    pub fn change_method_parameter_name(&self, a: i64) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub fn change_method_parameter_name(&self, b: i64) { }
+}
+
+
+
+// Change Method Return Type ---------------------------------------------------
+#[cfg(cfail1)]
+impl Foo {
+    pub fn change_method_return_type(&self) -> u16 { 0 }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub fn change_method_return_type(&self) -> u8 { 0 }
+}
+
+
+
+// Make Method #[inline] -------------------------------------------------------
+#[cfg(cfail1)]
+impl Foo {
+    pub fn make_method_inline(&self) -> u8 { 0 }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    #[inline]
+    pub fn make_method_inline(&self) -> u8 { 0 }
+}
+
+
+
+//  Change order of parameters -------------------------------------------------
+#[cfg(cfail1)]
+impl Foo {
+    pub fn change_method_parameter_order(&self, a: i64, b: i64) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub fn change_method_parameter_order(&self, b: i64, a: i64) { }
+}
+
+
+
+// Make method unsafe ----------------------------------------------------------
+#[cfg(cfail1)]
+impl Foo {
+    pub fn make_method_unsafe(&self) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub unsafe fn make_method_unsafe(&self) { }
+}
+
+
+
+// Make method extern ----------------------------------------------------------
+#[cfg(cfail1)]
+impl Foo {
+    pub fn make_method_extern(&self) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub extern fn make_method_extern(&self) { }
+}
+
+
+
+// Change method calling convention --------------------------------------------
+#[cfg(cfail1)]
+impl Foo {
+    pub extern "C" fn change_method_calling_convention(&self) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub extern "system" fn change_method_calling_convention(&self) { }
+}
+
+
+
+// Add Lifetime Parameter to Method --------------------------------------------
+#[cfg(cfail1)]
+impl Foo {
+    pub fn add_lifetime_parameter_to_method(&self) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub fn add_lifetime_parameter_to_method<'a>(&self) { }
+}
+
+
+
+// Add Type Parameter To Method ------------------------------------------------
+#[cfg(cfail1)]
+impl Foo {
+    pub fn add_type_parameter_to_method(&self) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub fn add_type_parameter_to_method<T>(&self) { }
+}
+
+
+
+// Add Lifetime Bound to Lifetime Parameter of Method --------------------------
+#[cfg(cfail1)]
+impl Foo {
+    pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b>(&self) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { }
+}
+
+
+
+// Add Lifetime Bound to Type Parameter of Method ------------------------------
+#[cfg(cfail1)]
+impl Foo {
+    pub fn add_lifetime_bound_to_type_param_of_method<'a, T>(&self) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { }
+}
+
+
+
+// Add Trait Bound to Type Parameter of Method ------------------------------
+#[cfg(cfail1)]
+impl Foo {
+    pub fn add_trait_bound_to_type_param_of_method<T>(&self) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub fn add_trait_bound_to_type_param_of_method<T: Clone>(&self) { }
+}
+
+
+
+// Add #[no_mangle] to Method --------------------------------------------------
+#[cfg(cfail1)]
+impl Foo {
+    pub fn add_no_mangle_to_method(&self) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    #[no_mangle]
+    pub fn add_no_mangle_to_method(&self) { }
+}
+
+
+
+struct Bar<T>(T);
+
+// Add Type Parameter To Impl --------------------------------------------------
+#[cfg(cfail1)]
+impl Bar<u32> {
+    pub fn add_type_parameter_to_impl(&self) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl<T> Bar<T> {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub fn add_type_parameter_to_impl(&self) { }
+}
+
+
+
+// Change Self Type of Impl ----------------------------------------------------
+#[cfg(cfail1)]
+impl Bar<u32> {
+    pub fn change_impl_self_type(&self) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Bar<u64> {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub fn change_impl_self_type(&self) { }
+}
+
+
+
+// Add Lifetime Bound to Impl --------------------------------------------------
+#[cfg(cfail1)]
+impl<T> Bar<T> {
+    pub fn add_lifetime_bound_to_impl_parameter(&self) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl<T: 'static> Bar<T> {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub fn add_lifetime_bound_to_impl_parameter(&self) { }
+}
+
+
+
+// Add Trait Bound to Impl Parameter -------------------------------------------
+#[cfg(cfail1)]
+impl<T> Bar<T> {
+    pub fn add_trait_bound_to_impl_parameter(&self) { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl<T: Clone> Bar<T> {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub fn add_trait_bound_to_impl_parameter(&self) { }
+}
diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs
new file mode 100644 (file)
index 0000000..a1057c0
--- /dev/null
@@ -0,0 +1,265 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+// This test case tests the incremental compilation hash (ICH) implementation
+// for inline asm.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// must-compile-successfully
+// revisions: cfail1 cfail2 cfail3
+// compile-flags: -Z query-dep-graph
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![feature(asm)]
+#![crate_type="rlib"]
+
+
+
+// Change template -------------------------------------------------------------
+#[cfg(cfail1)]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn change_template(a: i32) -> i32 {
+    let c: i32;
+    unsafe {
+        asm!("add 1, $0"
+             : "=r"(c)
+             : "0"(a)
+             :
+             :
+             );
+    }
+    c
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn change_template(a: i32) -> i32 {
+    let c: i32;
+    unsafe {
+        asm!("add 2, $0"
+             : "=r"(c)
+             : "0"(a)
+             :
+             :
+             );
+    }
+    c
+}
+
+
+
+// Change output -------------------------------------------------------------
+#[cfg(cfail1)]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn change_output(a: i32) -> i32 {
+    let mut _out1: i32 = 0;
+    let mut _out2: i32 = 0;
+    unsafe {
+        asm!("add 1, $0"
+             : "=r"(_out1)
+             : "0"(a)
+             :
+             :
+             );
+    }
+    _out1
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn change_output(a: i32) -> i32 {
+    let mut _out1: i32 = 0;
+    let mut _out2: i32 = 0;
+    unsafe {
+        asm!("add 1, $0"
+             : "=r"(_out2)
+             : "0"(a)
+             :
+             :
+             );
+    }
+    _out1
+}
+
+
+
+// Change input -------------------------------------------------------------
+#[cfg(cfail1)]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn change_input(_a: i32, _b: i32) -> i32 {
+    let _out;
+    unsafe {
+        asm!("add 1, $0"
+             : "=r"(_out)
+             : "0"(_a)
+             :
+             :
+             );
+    }
+    _out
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn change_input(_a: i32, _b: i32) -> i32 {
+    let _out;
+    unsafe {
+        asm!("add 1, $0"
+             : "=r"(_out)
+             : "0"(_b)
+             :
+             :
+             );
+    }
+    _out
+}
+
+
+
+// Change input constraint -----------------------------------------------------
+#[cfg(cfail1)]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn change_input_constraint(_a: i32, _b: i32) -> i32 {
+    let _out;
+    unsafe {
+        asm!("add 1, $0"
+             : "=r"(_out)
+             : "0"(_a), "r"(_b)
+             :
+             :
+             );
+    }
+    _out
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn change_input_constraint(_a: i32, _b: i32) -> i32 {
+    let _out;
+    unsafe {
+        asm!("add 1, $0"
+             : "=r"(_out)
+             : "r"(_a), "0"(_b)
+             :
+             :
+             );
+    }
+    _out
+}
+
+
+
+// Change clobber --------------------------------------------------------------
+#[cfg(cfail1)]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn change_clobber(_a: i32) -> i32 {
+    let _out;
+    unsafe {
+        asm!("add 1, $0"
+             : "=r"(_out)
+             : "0"(_a)
+             :
+             :
+             );
+    }
+    _out
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn change_clobber(_a: i32) -> i32 {
+    let _out;
+    unsafe {
+        asm!("add 1, $0"
+             : "=r"(_out)
+             : "0"(_a)
+             : "eax"
+             :
+             );
+    }
+    _out
+}
+
+
+
+// Change options --------------------------------------------------------------
+#[cfg(cfail1)]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn change_options(_a: i32) -> i32 {
+    let _out;
+    unsafe {
+        asm!("add 1, $0"
+             : "=r"(_out)
+             : "0"(_a)
+             :
+             :
+             );
+    }
+    _out
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn change_options(_a: i32) -> i32 {
+    let _out;
+    unsafe {
+        asm!("add 1, $0"
+             : "=r"(_out)
+             : "0"(_a)
+             :
+             : "volatile"
+             );
+    }
+    _out
+}
+
+
+
index ac67e4349013a8cad20e453dceaaee3ea1673572..7c6da3ba9fea6030f7d88d0628862c3f3c1be10e 100644 (file)
 static STATIC_CHANGE_VALUE_1: i16 = 1;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_1: i16 = 2;
 
 static STATIC_CHANGE_VALUE_2: i16 = 1 + 1;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_2: i16 = 1 + 2;
 
 static STATIC_CHANGE_VALUE_3: i16 = 2 + 3;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_3: i16 = 2 * 3;
 
 static STATIC_CHANGE_VALUE_4: i16 = 1 + 2 * 3;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_4: i16 = 1 + 2 * 4;
 
index 391c2e75ba4d5770dbd81840130fe2708043ab5e..bc401ae93404f0a45e099b022e781654715d5e2b 100644 (file)
@@ -98,11 +98,15 @@ trait TraitAddReturnType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddReturnType {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method() -> u32;
 }
 
@@ -115,11 +119,15 @@ trait TraitChangeReturnType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeReturnType {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method() -> u64;
 }
 
@@ -132,11 +140,15 @@ trait TraitAddParameterToMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddParameterToMethod {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(a: u32);
 }
 
@@ -146,15 +158,29 @@ trait TraitAddParameterToMethod {
 #[cfg(cfail1)]
 trait TraitChangeMethodParameterName {
     fn method(a: u32);
+    fn with_default(x: i32) {}
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParameterName {
+    // FIXME(#38501) This should preferably always be clean.
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(b: u32);
+
+    #[rustc_clean(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="HirBody", cfg="cfail2")]
+    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    fn with_default(y: i32) {}
 }
 
 
@@ -166,11 +192,15 @@ trait TraitChangeMethodParameterType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParameterType {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(a: i64);
 }
 
@@ -183,11 +213,15 @@ trait TraitChangeMethodParameterTypeRef {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParameterTypeRef {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(a: &mut i32);
 }
 
@@ -200,11 +234,15 @@ trait TraitChangeMethodParametersOrder {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParametersOrder {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(b: i64, a: i32);
 }
 
@@ -253,11 +291,15 @@ trait TraitChangeModeSelfRefToMut {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeModeSelfRefToMut {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(&mut self);
 }
 
@@ -269,11 +311,15 @@ fn method(self) {}
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeModeSelfOwnToMut: Sized {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(mut self) {}
 }
 
@@ -285,11 +331,15 @@ trait TraitChangeModeSelfOwnToRef {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeModeSelfOwnToRef {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(&self);
 }
 
@@ -302,11 +352,15 @@ trait TraitAddUnsafeModifier {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddUnsafeModifier {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     unsafe fn method();
 }
 
@@ -319,11 +373,15 @@ trait TraitAddExternModifier {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddExternModifier {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     extern fn method();
 }
 
@@ -336,11 +394,15 @@ trait TraitChangeExternCToRustIntrinsic {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeExternCToRustIntrinsic {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     extern "rust-intrinsic" fn method();
 }
 
@@ -353,11 +415,15 @@ trait TraitAddTypeParameterToMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddTypeParameterToMethod {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method<T>();
 }
 
@@ -370,11 +436,15 @@ trait TraitAddLifetimeParameterToMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddLifetimeParameterToMethod {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method<'a>();
 }
 
@@ -391,11 +461,15 @@ trait TraitAddTraitBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddTraitBoundToMethodTypeParameter {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method<T: ReferencedTrait0>();
 }
 
@@ -408,11 +482,15 @@ trait TraitAddBuiltinBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddBuiltinBoundToMethodTypeParameter {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method<T: Sized>();
 }
 
@@ -425,11 +503,15 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddLifetimeBoundToMethodLifetimeParameter {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method<'a, 'b: 'a>(a: &'a u32, b: &'b u32);
 }
 
@@ -442,11 +524,15 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddSecondTraitBoundToMethodTypeParameter {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method<T: ReferencedTrait0 + ReferencedTrait1>();
 }
 
@@ -459,11 +545,15 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method<T: Sized + Sync>();
 }
 
@@ -476,11 +566,15 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method<'a, 'b, 'c: 'a + 'b>(a: &'a u32, b: &'b u32, c: &'c u32);
 }
 
@@ -514,11 +608,15 @@ trait TraitAddTraitBoundToAssociatedType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddTraitBoundToAssociatedType {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     type Associated: ReferencedTrait0;
 
     fn mathod();
@@ -535,11 +633,15 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddLifetimeBoundToAssociatedType<'a> {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     type Associated: 'a;
 
     fn mathod();
@@ -617,11 +719,15 @@ trait TraitChangeTypeOfAssociatedConstant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeTypeOfAssociatedConstant {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     const Value: f64;
 
     fn mathod();
@@ -1013,11 +1119,15 @@ mod change_return_type_of_method_indirectly_use {
     #[cfg(not(cfail1))]
     use super::ReferenceType1 as ReturnType;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeReturnType {
+        #[rustc_dirty(label="Hir", cfg="cfail2")]
+        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
         fn method() -> ReturnType;
     }
 }
@@ -1031,11 +1141,15 @@ mod change_method_parameter_type_indirectly_by_use {
     #[cfg(not(cfail1))]
     use super::ReferenceType1 as ArgType;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeArgType {
+        #[rustc_dirty(label="Hir", cfg="cfail2")]
+        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
         fn method(a: ArgType);
     }
 }
@@ -1049,11 +1163,15 @@ mod change_method_parameter_type_bound_indirectly_by_use {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeBoundOfMethodTypeParameter {
+        #[rustc_dirty(label="Hir", cfg="cfail2")]
+        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
         fn method<T: Bound>(a: T);
     }
 }
@@ -1068,11 +1186,15 @@ mod change_method_parameter_type_bound_indirectly_by_use_where {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeBoundOfMethodTypeParameterWhere {
+        #[rustc_dirty(label="Hir", cfg="cfail2")]
+        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
         fn method<T>(a: T) where T: Bound;
     }
 }
index ba8d3cc934bfc253e6f23651c57ded089f5a66e4..8651a67bae221e88a5d4e9a3e24347b259b27d6a 100644 (file)
@@ -23,14 +23,14 @@ fn main() { }
 mod x {
     #[cfg(rpass1)]
     pub fn x() {
-        println!("1");
+        println!("{}", "1");
     }
 
     #[cfg(rpass2)]
     #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
     #[rustc_dirty(label="TransCrateItem", cfg="rpass2")]
     pub fn x() {
-        println!("2");
+        println!("{}", "2");
     }
 }
 
diff --git a/src/test/parse-fail/where_with_bound.rs b/src/test/parse-fail/where_with_bound.rs
new file mode 100644 (file)
index 0000000..cb57500
--- /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.
+
+// compile-flags: -Z parse-only
+
+fn foo<T>() where <T>::Item: ToString, T: Iterator { }
+               //~^ syntax `where<T>` is reserved for future use
+
+fn main() {}
index fdb7f9c68b99db54189764c305f92df4223d482e..6c74e7758c4ab113d63f5d1d4b691a3bba7f0c99 100644 (file)
@@ -39,7 +39,7 @@ pub fn bar() ({
 
 
 
-                  (($crate::fmt::format as
+                  ((::fmt::format as
                        fn(std::fmt::Arguments<'_>) -> std::string::String {std::fmt::format})(((<::std::fmt::Arguments>::new_v1
                                                                                                    as
                                                                                                    fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments<'_>::new_v1})(({
index c1d6e3023fbc163eb6954560c05fad3a5fdb0621..b0491fe6e27fd44e7a1e01950641dcdfeb96ebaf 100644 (file)
@@ -1,15 +1,15 @@
 digraph block {
     N0[label="entry"];
     N1[label="exit"];
-    N2[label="stmt "];
+    N2[label="stmt fn inner(x: isize) -> isize { x + x }"];
     N3[label="expr inner"];
     N4[label="expr inner"];
     N5[label="expr 18"];
     N6[label="expr inner(18)"];
     N7[label="expr inner(inner(18))"];
     N8[label="stmt inner(inner(18));"];
-    N9[label="block { inner(inner(18)); }"];
-    N10[label="expr { inner(inner(18)); }"];
+    N9[label="block {\l    fn inner(x: isize) -> isize { x + x }\l    inner(inner(18));\l}\l"];
+    N10[label="expr {\l    fn inner(x: isize) -> isize { x + x }\l    inner(inner(18));\l}\l"];
     N0 -> N2;
     N2 -> N3;
     N3 -> N4;
index d2f9f41f647beb48e6772f75f402e150abf6941d..223978c3d7634f7380960dc81d32f2c8eadda422 100644 (file)
@@ -1,8 +1,8 @@
 digraph block {
     N0[label="entry"];
     N1[label="exit"];
-    N2[label="stmt "];
-    N3[label="stmt "];
+    N2[label="stmt struct S19 {\l    x: isize,\l}\l"];
+    N3[label="stmt impl S19 {\l    fn inner(self: Self) -> S19 { S19{x: self.x + self.x,} }\l}\l"];
     N4[label="expr 19"];
     N5[label="expr S19{x: 19,}"];
     N6[label="local s"];
@@ -11,8 +11,8 @@ digraph block {
     N9[label="expr s.inner()"];
     N10[label="expr s.inner().inner()"];
     N11[label="stmt s.inner().inner();"];
-    N12[label="block { let s = S19{x: 19,}; s.inner().inner(); }"];
-    N13[label="expr { let s = S19{x: 19,}; s.inner().inner(); }"];
+    N12[label="block {\l    struct S19 {\l        x: isize,\l    }\l    impl S19 {\l        fn inner(self: Self) -> S19 { S19{x: self.x + self.x,} }\l    }\l    let s = S19{x: 19,};\l    s.inner().inner();\l}\l"];
+    N13[label="expr {\l    struct S19 {\l        x: isize,\l    }\l    impl S19 {\l        fn inner(self: Self) -> S19 { S19{x: self.x + self.x,} }\l    }\l    let s = S19{x: 19,};\l    s.inner().inner();\l}\l"];
     N0 -> N2;
     N2 -> N3;
     N3 -> N4;
diff --git a/src/test/run-make/issue-38237/Makefile b/src/test/run-make/issue-38237/Makefile
new file mode 100644 (file)
index 0000000..0a68140
--- /dev/null
@@ -0,0 +1,5 @@
+-include ../tools.mk
+
+all:
+       $(RUSTC) foo.rs; $(RUSTC) bar.rs
+       $(RUSTDOC) baz.rs -L $(TMPDIR) -o $(TMPDIR)
diff --git a/src/test/run-make/issue-38237/bar.rs b/src/test/run-make/issue-38237/bar.rs
new file mode 100644 (file)
index 0000000..794e08c
--- /dev/null
@@ -0,0 +1,14 @@
+// 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.
+
+#![crate_type = "lib"]
+
+#[derive(Debug)]
+pub struct S;
diff --git a/src/test/run-make/issue-38237/baz.rs b/src/test/run-make/issue-38237/baz.rs
new file mode 100644 (file)
index 0000000..c2a2c89
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+extern crate foo;
+extern crate bar;
+
+pub struct Bar;
+impl ::std::ops::Deref for Bar {
+    type Target = bar::S;
+    fn deref(&self) -> &Self::Target { unimplemented!() }
+}
diff --git a/src/test/run-make/issue-38237/foo.rs b/src/test/run-make/issue-38237/foo.rs
new file mode 100644 (file)
index 0000000..c291ffb
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro, proc_macro_lib)]
+
+extern crate proc_macro;
+
+#[proc_macro_derive(A)]
+pub fn derive(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { ts }
+
+#[derive(Debug)]
+struct S;
index 696e0544fdc5793003c11493f059864c632f9040..fae134986872e06cac70ff4f8d22f1fb05e6bb01 100644 (file)
@@ -12,5 +12,6 @@
 
 
 
-fn foo_method(&self) -> &'static str { return "i am very similar to foo."; }
-/* nest::{{impl}}::foo_method */
+fn foo_method(self: &Self)
+ -> &'static str { return "i am very similar to foo."; } /*
+nest::{{impl}}::foo_method */
index 07f7d6bad7bf2b40967b8830f4bdc380dafcd0cc..e46e4fb3766d31420f7ae1bf10bf4390b3b9f796 100644 (file)
@@ -31,7 +31,7 @@
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_syntax_extension(
+    reg.register_custom_derive(
         Symbol::intern("derive_TotalSum"),
         MultiDecorator(box expand));
 }
index c6892757c682f22cbc4d5d2c60b8d7ab9f69e71d..e1b1b441894b75eeeb087697d8e658a51b1a522c 100644 (file)
@@ -41,12 +41,12 @@ fn get_lints(&self) -> LintArray { lint_array!(REGION_HIERARCHY) }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
     fn check_fn(&mut self, cx: &LateContext,
-                              fk: FnKind, _: &hir::FnDecl, expr: &hir::Expr,
+                              fk: FnKind, _: &hir::FnDecl, body: &hir::Body,
                               span: Span, node: ast::NodeId)
     {
         if let FnKind::Closure(..) = fk { return }
 
-        let mut extent = cx.tcx.region_maps.node_extent(expr.id);
+        let mut extent = cx.tcx.region_maps.node_extent(body.value.id);
         while let Some(parent) = cx.tcx.region_maps.opt_encl_scope(extent) {
             extent = parent;
         }
index 394845b66f3d3a105694589464d879349d60096a..c3cfe89ee5c3e9cca6b80d7a3721a682bc9e301d 100644 (file)
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 // no-prefer-dynamic
+// compile-flags: --emit=metadata
 
-#![crate_type="metadata"]
+#![crate_type="rlib"]
 #![crate_name="rmeta_aux"]
 
 pub struct Foo {
diff --git a/src/test/run-pass/issue-38437.rs b/src/test/run-pass/issue-38437.rs
new file mode 100644 (file)
index 0000000..a6e7df1
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that drop elaboration clears the "master" discriminant
+// drop flag even if it protects no fields.
+
+struct Good(usize);
+impl Drop for Good {
+    #[inline(never)]
+    fn drop(&mut self) {
+        println!("dropping Good({})", self.0);
+    }
+}
+
+struct Void;
+impl Drop for Void {
+    #[inline(never)]
+    fn drop(&mut self) {
+        panic!("Suddenly, a Void appears.");
+    }
+}
+
+enum E {
+    Never(Void),
+    Fine(Good)
+}
+
+fn main() {
+    let mut go = true;
+
+    loop {
+        let next;
+        match go {
+            true => next = E::Fine(Good(123)),
+            false => return,
+        }
+
+        match next {
+            E::Never(_) => return,
+            E::Fine(_good) => go = false,
+        }
+
+        // `next` is dropped and StorageDead'd here. We must reset the
+        // discriminant's drop flag to avoid random variants being
+        // dropped.
+    }
+}
diff --git a/src/test/run-pass/issue-38556.rs b/src/test/run-pass/issue-38556.rs
new file mode 100644 (file)
index 0000000..f6f334f
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub struct Foo;
+
+macro_rules! reexport {
+    () => { use Foo as Bar; }
+}
+
+reexport!();
+
+fn main() {
+    use Bar;
+    fn f(_: Bar) {}
+}
index 6614a76107f8539cd7f3d261e8c165afcf9654b2..bbb01eaaf46b9b43afbdbf4bdbf4c7ebfbf4aa61 100644 (file)
@@ -31,10 +31,6 @@ enum e3 {
     a([u16; 0], u8), b
 }
 
-// Test struct field reordering to make sure it actually reorders.
-struct WillOptimize1(u8, u16, u8);
-struct WillOptimize2 { a: u8, b: u16, c: u8}
-
 pub fn main() {
     assert_eq!(size_of::<u8>(), 1 as usize);
     assert_eq!(size_of::<u32>(), 4 as usize);
@@ -58,7 +54,4 @@ pub fn main() {
     assert_eq!(size_of::<e1>(), 8 as usize);
     assert_eq!(size_of::<e2>(), 8 as usize);
     assert_eq!(size_of::<e3>(), 4 as usize);
-
-    assert_eq!(size_of::<WillOptimize1>(), 4);
-    assert_eq!(size_of::<WillOptimize2>(), 4);
 }
diff --git a/src/test/rustdoc/search-index-summaries.rs b/src/test/rustdoc/search-index-summaries.rs
new file mode 100644 (file)
index 0000000..dd195dc
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+#![crate_name = "foo"]
+
+// @has 'search-index.js' 'Foo short link.'
+// @!has - 'www.example.com'
+// @!has - 'More Foo.'
+
+/// Foo short [link](https://www.example.com/).
+///
+/// More Foo.
+pub struct Foo;
index f865f0a5f23cdc4427c610d74a8bd97ec548b5c9..73d548009dda1277d41a91ff6f3c6dbe27d80deb 100644 (file)
@@ -1,8 +1,8 @@
-error[E0425]: unresolved name `bar`
+error[E0425]: unresolved value `bar`
   --> $DIR/tab.rs:14:2
    |
 14 | \tbar;
-   | \t^^^ unresolved name
+   | \t^^^ no resolution found
 
 error: aborting due to previous error
 
index d05e6eb2bbe4da144b184bf1a3d8ddf5b8250ca7..9db43dde1ac7e1be6558212afea633f966011b71 100644 (file)
@@ -1,10 +1,8 @@
-error[E0404]: `Bar` is not a trait
+error[E0404]: expected trait, found type alias `Bar`
   --> $DIR/two_files.rs:15:6
    |
 15 | impl Bar for Baz { }
-   |      ^^^ expected trait, found type alias
-   |
-   = note: type aliases cannot be used for traits
+   |      ^^^ type aliases cannot be used for traits
 
 error: cannot continue compilation due to previous error
 
index a748e13ecf102bf9207afbb3f409938f5549f278..70fe17888e84d6a74fef8daee7ec9c03eeb941d7 100644 (file)
@@ -1,4 +1,4 @@
-error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, aapcs, win64, sysv64, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic], found `路濫狼á́́`
+error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, aapcs, win64, sysv64, ptx-kernel, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic], found `路濫狼á́́`
   --> $DIR/unicode.rs:11:8
    |
 11 | extern "路濫狼á́́" fn foo() {}
index 1c7fac894f976cf2468dbedf5e2aa9c147e1625d..27514093621583d1c327e71c8aa76c2fd534a7a1 100644 (file)
@@ -1,17 +1,17 @@
-error[E0425]: unresolved name `fake`
+error[E0425]: unresolved value `fake`
   --> $DIR/macro-backtrace-nested.rs:15:12
    |
 15 |     () => (fake)
-   |            ^^^^ unresolved name
+   |            ^^^^ no resolution found
 ...
 27 |     1 + call_nested_expr!();
    |         ------------------- in this macro invocation
 
-error[E0425]: unresolved name `fake`
+error[E0425]: unresolved value `fake`
   --> $DIR/macro-backtrace-nested.rs:15:12
    |
 15 |     () => (fake)
-   |            ^^^^ unresolved name
+   |            ^^^^ no resolution found
 ...
 28 |     call_nested_expr_sum!();
    |     ------------------------ in this macro invocation
index 830678f174f88cf38e0d76836bac2cc7c9a9ee96..dd999c4a5e4c779d1e30f105926d4a4ef4e07eda 100644 (file)
@@ -1,22 +1,25 @@
-print-type-size type: `IndirectNonZero<u32>`: 12 bytes, alignment: 4 bytes
-print-type-size     field `.nested`: 8 bytes
-print-type-size     field `.post`: 2 bytes
+print-type-size type: `IndirectNonZero<u32>`: 20 bytes, alignment: 4 bytes
 print-type-size     field `.pre`: 1 bytes
-print-type-size     end padding: 1 bytes
-print-type-size type: `MyOption<IndirectNonZero<u32>>`: 12 bytes, alignment: 4 bytes
-print-type-size     variant `Some`: 12 bytes
-print-type-size         field `.0`: 12 bytes
-print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes
-print-type-size     variant `Record`: 7 bytes
-print-type-size         field `.val`: 4 bytes
-print-type-size         field `.post`: 2 bytes
-print-type-size         field `.pre`: 1 bytes
-print-type-size     end padding: 1 bytes
-print-type-size type: `NestedNonZero<u32>`: 8 bytes, alignment: 4 bytes
-print-type-size     field `.val`: 4 bytes
+print-type-size     padding: 3 bytes
+print-type-size     field `.nested`: 12 bytes, alignment: 4 bytes
 print-type-size     field `.post`: 2 bytes
+print-type-size     end padding: 2 bytes
+print-type-size type: `MyOption<IndirectNonZero<u32>>`: 20 bytes, alignment: 4 bytes
+print-type-size     variant `Some`: 20 bytes
+print-type-size         field `.0`: 20 bytes
+print-type-size type: `EmbeddedDiscr`: 12 bytes, alignment: 4 bytes
+print-type-size     variant `Record`: 10 bytes
+print-type-size         field `.pre`: 1 bytes
+print-type-size         padding: 3 bytes
+print-type-size         field `.val`: 4 bytes, alignment: 4 bytes
+print-type-size         field `.post`: 2 bytes
+print-type-size     end padding: 2 bytes
+print-type-size type: `NestedNonZero<u32>`: 12 bytes, alignment: 4 bytes
 print-type-size     field `.pre`: 1 bytes
-print-type-size     end padding: 1 bytes
+print-type-size     padding: 3 bytes
+print-type-size     field `.val`: 4 bytes, alignment: 4 bytes
+print-type-size     field `.post`: 2 bytes
+print-type-size     end padding: 2 bytes
 print-type-size type: `MyOption<core::nonzero::NonZero<u32>>`: 4 bytes, alignment: 4 bytes
 print-type-size     variant `Some`: 4 bytes
 print-type-size         field `.0`: 4 bytes
index 83fd333c9c7fc45dba547de22add55c477521ef9..1278a7d7c92c67836d9e74db7eefd791ef4b3b23 100644 (file)
@@ -1,11 +1,13 @@
-print-type-size type: `Padded`: 12 bytes, alignment: 4 bytes
-print-type-size     field `.g`: 4 bytes
-print-type-size     field `.h`: 2 bytes
+print-type-size type: `Padded`: 16 bytes, alignment: 4 bytes
 print-type-size     field `.a`: 1 bytes
 print-type-size     field `.b`: 1 bytes
+print-type-size     padding: 2 bytes
+print-type-size     field `.g`: 4 bytes, alignment: 4 bytes
 print-type-size     field `.c`: 1 bytes
+print-type-size     padding: 1 bytes
+print-type-size     field `.h`: 2 bytes, alignment: 2 bytes
 print-type-size     field `.d`: 1 bytes
-print-type-size     end padding: 2 bytes
+print-type-size     end padding: 3 bytes
 print-type-size type: `Packed`: 10 bytes, alignment: 1 bytes
 print-type-size     field `.a`: 1 bytes
 print-type-size     field `.b`: 1 bytes
index 0eaff7118b35c38a528dab7052d2cd498acb15aa..bb95f790bd9e471bdd740e5f9817faf8af8d4f54 100644 (file)
@@ -1,12 +1,10 @@
 print-type-size type: `E1`: 12 bytes, alignment: 4 bytes
-print-type-size     discriminant: 1 bytes
-print-type-size     variant `A`: 7 bytes
+print-type-size     discriminant: 4 bytes
+print-type-size     variant `A`: 5 bytes
+print-type-size         field `.0`: 4 bytes
 print-type-size         field `.1`: 1 bytes
-print-type-size         padding: 2 bytes
-print-type-size         field `.0`: 4 bytes, alignment: 4 bytes
-print-type-size     variant `B`: 11 bytes
-print-type-size         padding: 3 bytes
-print-type-size         field `.0`: 8 bytes, alignment: 4 bytes
+print-type-size     variant `B`: 8 bytes
+print-type-size         field `.0`: 8 bytes
 print-type-size type: `E2`: 12 bytes, alignment: 4 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `A`: 7 bytes
@@ -17,7 +15,7 @@ print-type-size     variant `B`: 11 bytes
 print-type-size         padding: 3 bytes
 print-type-size         field `.0`: 8 bytes, alignment: 4 bytes
 print-type-size type: `S`: 8 bytes, alignment: 4 bytes
-print-type-size     field `.g`: 4 bytes
 print-type-size     field `.a`: 1 bytes
 print-type-size     field `.b`: 1 bytes
-print-type-size     end padding: 2 bytes
+print-type-size     padding: 2 bytes
+print-type-size     field `.g`: 4 bytes, alignment: 4 bytes
diff --git a/src/test/ui/resolve/auxiliary/issue-21221-3.rs b/src/test/ui/resolve/auxiliary/issue-21221-3.rs
new file mode 100644 (file)
index 0000000..fae0fe1
--- /dev/null
@@ -0,0 +1,29 @@
+// 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.
+
+// testing whether the lookup mechanism picks up types
+// defined in the outside crate
+
+#![crate_type="lib"]
+
+pub mod outer {
+    // should suggest this
+    pub trait OuterTrait {}
+
+    // should not suggest this since the module is private
+    mod private_module {
+        pub trait OuterTrait {}
+    }
+
+    // should not suggest since the trait is private
+    pub mod public_module {
+        trait OuterTrait {}
+    }
+}
diff --git a/src/test/ui/resolve/auxiliary/issue-21221-4.rs b/src/test/ui/resolve/auxiliary/issue-21221-4.rs
new file mode 100644 (file)
index 0000000..fffe060
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// testing whether the lookup mechanism picks up types
+// defined in the outside crate
+
+#![crate_type="lib"]
+
+mod foo {
+    // should not be suggested => foo is private
+    pub trait T {}
+}
+
+// should be suggested
+pub use foo::T;
diff --git a/src/test/ui/resolve/auxiliary/issue_19452_aux.rs b/src/test/ui/resolve/auxiliary/issue_19452_aux.rs
new file mode 100644 (file)
index 0000000..205566e
--- /dev/null
@@ -0,0 +1,13 @@
+// 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 enum Homura {
+    Madoka { age: u32 }
+}
diff --git a/src/test/ui/resolve/auxiliary/issue_3907.rs b/src/test/ui/resolve/auxiliary/issue_3907.rs
new file mode 100644 (file)
index 0000000..6472c08
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2013 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 Foo {
+    fn bar();
+}
diff --git a/src/test/ui/resolve/auxiliary/namespaced_enums.rs b/src/test/ui/resolve/auxiliary/namespaced_enums.rs
new file mode 100644 (file)
index 0000000..3bf39b7
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+pub enum Foo {
+    A,
+    B(isize),
+    C { a: isize },
+}
+
+impl Foo {
+    pub fn foo() {}
+    pub fn bar(&self) {}
+}
diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.rs b/src/test/ui/resolve/enums-are-namespaced-xc.rs
new file mode 100644 (file)
index 0000000..4f55f33
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.
+
+// aux-build:namespaced_enums.rs
+extern crate namespaced_enums;
+
+fn main() {
+    let _ = namespaced_enums::A;
+    //~^ ERROR unresolved value `namespaced_enums::A`
+    //~| HELP you can import it into scope: `use namespaced_enums::Foo::A;`
+    let _ = namespaced_enums::B(10);
+    //~^ ERROR unresolved function `namespaced_enums::B`
+    //~| HELP you can import it into scope: `use namespaced_enums::Foo::B;`
+    let _ = namespaced_enums::C { a: 10 };
+    //~^ ERROR unresolved struct, variant or union type `namespaced_enums::C`
+    //~| HELP you can import it into scope: `use namespaced_enums::Foo::C;`
+}
diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.stderr b/src/test/ui/resolve/enums-are-namespaced-xc.stderr
new file mode 100644 (file)
index 0000000..fda8023
--- /dev/null
@@ -0,0 +1,29 @@
+error[E0425]: unresolved value `namespaced_enums::A`
+  --> $DIR/enums-are-namespaced-xc.rs:15:13
+   |
+15 |     let _ = namespaced_enums::A;
+   |             ^^^^^^^^^^^^^^^^^^^ no resolution found
+   |
+   = help: possible candidate is found in another module, you can import it into scope:
+   = help:   `use namespaced_enums::Foo::A;`
+
+error[E0425]: unresolved function `namespaced_enums::B`
+  --> $DIR/enums-are-namespaced-xc.rs:18:13
+   |
+18 |     let _ = namespaced_enums::B(10);
+   |             ^^^^^^^^^^^^^^^^^^^ no resolution found
+   |
+   = help: possible candidate is found in another module, you can import it into scope:
+   = help:   `use namespaced_enums::Foo::B;`
+
+error[E0422]: unresolved struct, variant or union type `namespaced_enums::C`
+  --> $DIR/enums-are-namespaced-xc.rs:21:13
+   |
+21 |     let _ = namespaced_enums::C { a: 10 };
+   |             ^^^^^^^^^^^^^^^^^^^ no resolution found
+   |
+   = help: possible candidate is found in another module, you can import it into scope:
+   = help:   `use namespaced_enums::Foo::C;`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/resolve/issue-14254.rs b/src/test/ui/resolve/issue-14254.rs
new file mode 100644 (file)
index 0000000..b1fc6c4
--- /dev/null
@@ -0,0 +1,137 @@
+// 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.
+
+trait Foo {
+    fn bar(&self);
+    fn baz(&self) { }
+    fn bah(_: Option<&Self>) { }
+}
+
+struct BarTy {
+    x : isize,
+    y : f64,
+}
+
+impl BarTy {
+    fn a() {}
+    fn b(&self) {}
+}
+
+impl Foo for *const BarTy {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR unresolved function `baz`
+        //~| NOTE did you mean `self.baz(...)`?
+        a;
+        //~^ ERROR unresolved value `a`
+        //~| NOTE no resolution found
+    }
+}
+
+impl<'a> Foo for &'a BarTy {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR unresolved function `baz`
+        //~| NOTE did you mean `self.baz(...)`?
+        x;
+        //~^ ERROR unresolved value `x`
+        //~| NOTE did you mean `self.x`?
+        y;
+        //~^ ERROR unresolved value `y`
+        //~| NOTE did you mean `self.y`?
+        a;
+        //~^ ERROR unresolved value `a`
+        //~| NOTE no resolution found
+        bah;
+        //~^ ERROR unresolved value `bah`
+        //~| NOTE did you mean `Self::bah`?
+        b;
+        //~^ ERROR unresolved value `b`
+        //~| NOTE no resolution found
+    }
+}
+
+impl<'a> Foo for &'a mut BarTy {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR unresolved function `baz`
+        //~| NOTE did you mean `self.baz(...)`?
+        x;
+        //~^ ERROR unresolved value `x`
+        //~| NOTE did you mean `self.x`?
+        y;
+        //~^ ERROR unresolved value `y`
+        //~| NOTE did you mean `self.y`?
+        a;
+        //~^ ERROR unresolved value `a`
+        //~| NOTE no resolution found
+        bah;
+        //~^ ERROR unresolved value `bah`
+        //~| NOTE did you mean `Self::bah`?
+        b;
+        //~^ ERROR unresolved value `b`
+        //~| NOTE no resolution found
+    }
+}
+
+impl Foo for Box<BarTy> {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR unresolved function `baz`
+        //~| NOTE did you mean `self.baz(...)`?
+        bah;
+        //~^ ERROR unresolved value `bah`
+        //~| NOTE did you mean `Self::bah`?
+    }
+}
+
+impl Foo for *const isize {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR unresolved function `baz`
+        //~| NOTE did you mean `self.baz(...)`?
+        bah;
+        //~^ ERROR unresolved value `bah`
+        //~| NOTE did you mean `Self::bah`?
+    }
+}
+
+impl<'a> Foo for &'a isize {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR unresolved function `baz`
+        //~| NOTE did you mean `self.baz(...)`?
+        bah;
+        //~^ ERROR unresolved value `bah`
+        //~| NOTE did you mean `Self::bah`?
+    }
+}
+
+impl<'a> Foo for &'a mut isize {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR unresolved function `baz`
+        //~| NOTE did you mean `self.baz(...)`?
+        bah;
+        //~^ ERROR unresolved value `bah`
+        //~| NOTE did you mean `Self::bah`?
+    }
+}
+
+impl Foo for Box<isize> {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR unresolved function `baz`
+        //~| NOTE did you mean `self.baz(...)`?
+        bah;
+        //~^ ERROR unresolved value `bah`
+        //~| NOTE did you mean `Self::bah`?
+    }
+}
diff --git a/src/test/ui/resolve/issue-14254.stderr b/src/test/ui/resolve/issue-14254.stderr
new file mode 100644 (file)
index 0000000..2780c1c
--- /dev/null
@@ -0,0 +1,148 @@
+error[E0425]: unresolved function `baz`
+  --> $DIR/issue-14254.rs:29:9
+   |
+29 |         baz();
+   |         ^^^ did you mean `self.baz(...)`?
+
+error[E0425]: unresolved value `a`
+  --> $DIR/issue-14254.rs:32:9
+   |
+32 |         a;
+   |         ^ no resolution found
+
+error[E0425]: unresolved function `baz`
+  --> $DIR/issue-14254.rs:40:9
+   |
+40 |         baz();
+   |         ^^^ did you mean `self.baz(...)`?
+
+error[E0425]: unresolved value `x`
+  --> $DIR/issue-14254.rs:43:9
+   |
+43 |         x;
+   |         ^ did you mean `self.x`?
+
+error[E0425]: unresolved value `y`
+  --> $DIR/issue-14254.rs:46:9
+   |
+46 |         y;
+   |         ^ did you mean `self.y`?
+
+error[E0425]: unresolved value `a`
+  --> $DIR/issue-14254.rs:49:9
+   |
+49 |         a;
+   |         ^ no resolution found
+
+error[E0425]: unresolved value `bah`
+  --> $DIR/issue-14254.rs:52:9
+   |
+52 |         bah;
+   |         ^^^ did you mean `Self::bah`?
+
+error[E0425]: unresolved value `b`
+  --> $DIR/issue-14254.rs:55:9
+   |
+55 |         b;
+   |         ^ no resolution found
+
+error[E0425]: unresolved function `baz`
+  --> $DIR/issue-14254.rs:63:9
+   |
+63 |         baz();
+   |         ^^^ did you mean `self.baz(...)`?
+
+error[E0425]: unresolved value `x`
+  --> $DIR/issue-14254.rs:66:9
+   |
+66 |         x;
+   |         ^ did you mean `self.x`?
+
+error[E0425]: unresolved value `y`
+  --> $DIR/issue-14254.rs:69:9
+   |
+69 |         y;
+   |         ^ did you mean `self.y`?
+
+error[E0425]: unresolved value `a`
+  --> $DIR/issue-14254.rs:72:9
+   |
+72 |         a;
+   |         ^ no resolution found
+
+error[E0425]: unresolved value `bah`
+  --> $DIR/issue-14254.rs:75:9
+   |
+75 |         bah;
+   |         ^^^ did you mean `Self::bah`?
+
+error[E0425]: unresolved value `b`
+  --> $DIR/issue-14254.rs:78:9
+   |
+78 |         b;
+   |         ^ no resolution found
+
+error[E0425]: unresolved function `baz`
+  --> $DIR/issue-14254.rs:86:9
+   |
+86 |         baz();
+   |         ^^^ did you mean `self.baz(...)`?
+
+error[E0425]: unresolved value `bah`
+  --> $DIR/issue-14254.rs:89:9
+   |
+89 |         bah;
+   |         ^^^ did you mean `Self::bah`?
+
+error[E0425]: unresolved function `baz`
+  --> $DIR/issue-14254.rs:97:9
+   |
+97 |         baz();
+   |         ^^^ did you mean `self.baz(...)`?
+
+error[E0425]: unresolved value `bah`
+   --> $DIR/issue-14254.rs:100:9
+    |
+100 |         bah;
+    |         ^^^ did you mean `Self::bah`?
+
+error[E0425]: unresolved function `baz`
+   --> $DIR/issue-14254.rs:108:9
+    |
+108 |         baz();
+    |         ^^^ did you mean `self.baz(...)`?
+
+error[E0425]: unresolved value `bah`
+   --> $DIR/issue-14254.rs:111:9
+    |
+111 |         bah;
+    |         ^^^ did you mean `Self::bah`?
+
+error[E0425]: unresolved function `baz`
+   --> $DIR/issue-14254.rs:119:9
+    |
+119 |         baz();
+    |         ^^^ did you mean `self.baz(...)`?
+
+error[E0425]: unresolved value `bah`
+   --> $DIR/issue-14254.rs:122:9
+    |
+122 |         bah;
+    |         ^^^ did you mean `Self::bah`?
+
+error[E0425]: unresolved function `baz`
+   --> $DIR/issue-14254.rs:130:9
+    |
+130 |         baz();
+    |         ^^^ did you mean `self.baz(...)`?
+
+error[E0425]: unresolved value `bah`
+   --> $DIR/issue-14254.rs:133:9
+    |
+133 |         bah;
+    |         ^^^ did you mean `Self::bah`?
+
+error: main function not found
+
+error: aborting due to 25 previous errors
+
diff --git a/src/test/ui/resolve/issue-16058.rs b/src/test/ui/resolve/issue-16058.rs
new file mode 100644 (file)
index 0000000..1f777e5
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+pub struct GslResult {
+    pub val: f64,
+    pub err: f64
+}
+
+impl GslResult {
+    pub fn new() -> GslResult {
+        Result {
+//~^ ERROR expected struct, variant or union type, found enum `Result`
+//~| HELP possible better candidates are found in other modules, you can import them into scope
+//~| HELP std::fmt::Result
+//~| HELP std::io::Result
+//~| HELP std::thread::Result
+            val: 0f64,
+            err: 0f64
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-16058.stderr b/src/test/ui/resolve/issue-16058.stderr
new file mode 100644 (file)
index 0000000..6b00cfb
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0574]: expected struct, variant or union type, found enum `Result`
+  --> $DIR/issue-16058.rs:19:9
+   |
+19 |         Result {
+   |         ^^^^^^ not a struct, variant or union type
+   |
+   = help: possible better candidates are found in other modules, you can import them into scope:
+   = help:   `use std::fmt::Result;`
+   = help:   `use std::io::Result;`
+   = help:   `use std::thread::Result;`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/resolve/issue-17518.rs b/src/test/ui/resolve/issue-17518.rs
new file mode 100644 (file)
index 0000000..3ac9b37
--- /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.
+
+enum SomeEnum {
+    E
+}
+
+fn main() {
+    E { name: "foobar" }; //~ ERROR unresolved struct, variant or union type `E`
+                          //~^ HELP you can import it into scope: `use SomeEnum::E;`
+}
diff --git a/src/test/ui/resolve/issue-17518.stderr b/src/test/ui/resolve/issue-17518.stderr
new file mode 100644 (file)
index 0000000..9de4372
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0422]: unresolved struct, variant or union type `E`
+  --> $DIR/issue-17518.rs:16:5
+   |
+16 |     E { name: "foobar" }; //~ ERROR unresolved struct, variant or union type `E`
+   |     ^ no resolution found
+   |
+   = help: possible candidate is found in another module, you can import it into scope:
+   = help:   `use SomeEnum::E;`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/resolve/issue-18252.rs b/src/test/ui/resolve/issue-18252.rs
new file mode 100644 (file)
index 0000000..02c6643
--- /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.
+
+enum Foo {
+    Variant { x: usize }
+}
+
+fn main() {
+    let f = Foo::Variant(42);
+    //~^ ERROR expected function, found struct variant `Foo::Variant`
+}
diff --git a/src/test/ui/resolve/issue-18252.stderr b/src/test/ui/resolve/issue-18252.stderr
new file mode 100644 (file)
index 0000000..edc7196
--- /dev/null
@@ -0,0 +1,8 @@
+error[E0423]: expected function, found struct variant `Foo::Variant`
+  --> $DIR/issue-18252.rs:16:13
+   |
+16 |     let f = Foo::Variant(42);
+   |             ^^^^^^^^^^^^ did you mean `Foo::Variant { /* fields */ }`?
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/resolve/issue-19452.rs b/src/test/ui/resolve/issue-19452.rs
new file mode 100644 (file)
index 0000000..080fb06
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.
+
+// aux-build:issue_19452_aux.rs
+extern crate issue_19452_aux;
+
+enum Homura {
+    Madoka { age: u32 }
+}
+
+fn main() {
+    let homura = Homura::Madoka;
+    //~^ ERROR expected value, found struct variant `Homura::Madoka`
+
+    let homura = issue_19452_aux::Homura::Madoka;
+    //~^ ERROR expected value, found struct variant `issue_19452_aux::Homura::Madoka`
+}
diff --git a/src/test/ui/resolve/issue-19452.stderr b/src/test/ui/resolve/issue-19452.stderr
new file mode 100644 (file)
index 0000000..7b14d49
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0423]: expected value, found struct variant `Homura::Madoka`
+  --> $DIR/issue-19452.rs:19:18
+   |
+19 |     let homura = Homura::Madoka;
+   |                  ^^^^^^^^^^^^^^ did you mean `Homura::Madoka { /* fields */ }`?
+
+error[E0423]: expected value, found struct variant `issue_19452_aux::Homura::Madoka`
+  --> $DIR/issue-19452.rs:22:18
+   |
+22 |     let homura = issue_19452_aux::Homura::Madoka;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `issue_19452_aux::Homura::Madoka { /* fields */ }`?
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/resolve/issue-21221-1.rs b/src/test/ui/resolve/issue-21221-1.rs
new file mode 100644 (file)
index 0000000..b1266a5
--- /dev/null
@@ -0,0 +1,96 @@
+// 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.
+
+mod mul1 {
+    pub trait Mul {}
+}
+
+mod mul2 {
+    pub trait Mul {}
+}
+
+mod mul3 {
+    enum Mul {
+      Yes,
+      No
+    }
+}
+
+mod mul4 {
+    type Mul = String;
+}
+
+mod mul5 {
+    struct Mul{
+        left_term: u32,
+        right_term: u32
+    }
+}
+
+#[derive(Debug)]
+struct Foo;
+
+// When we comment the next line:
+//use mul1::Mul;
+
+// BEFORE, we got the following error for the `impl` below:
+//   error: use of undeclared trait name `Mul` [E0405]
+// AFTER, we get this message:
+//   error: trait `Mul` is not in scope.
+//   help: ...
+//   help: you can import several candidates into scope (`use ...;`):
+//   help:   `mul1::Mul`
+//   help:   `mul2::Mul`
+//   help:   `std::ops::Mul`
+
+impl Mul for Foo {
+//~^ ERROR unresolved trait `Mul`
+//~| HELP possible candidates are found in other modules, you can import them into scope
+//~| HELP `mul1::Mul`
+//~| HELP `mul2::Mul`
+//~| HELP `std::ops::Mul`
+}
+
+// BEFORE, we got:
+//   error: use of undeclared type name `Mul` [E0412]
+// AFTER, we get:
+//   error: type name `Mul` is not in scope. Maybe you meant:
+//   help: ...
+//   help: you can import several candidates into scope (`use ...;`):
+//   help:   `mul1::Mul`
+//   help:   `mul2::Mul`
+//   help:   `mul3::Mul`
+//   help:   `mul4::Mul`
+//   help:   and 2 other candidates
+fn getMul() -> Mul {
+//~^ ERROR unresolved type `Mul`
+//~| HELP possible candidates are found in other modules, you can import them into scope
+//~| HELP `mul1::Mul`
+//~| HELP `mul2::Mul`
+//~| HELP `mul3::Mul`
+//~| HELP `mul4::Mul`
+//~| HELP and 2 other candidates
+}
+
+// Let's also test what happens if the trait doesn't exist:
+impl ThisTraitReallyDoesntExistInAnyModuleReally for Foo {
+//~^ ERROR unresolved trait `ThisTraitReallyDoesntExistInAnyModuleReally`
+}
+
+// Let's also test what happens if there's just one alternative:
+impl Div for Foo {
+//~^ ERROR unresolved trait `Div`
+//~| HELP `use std::ops::Div;`
+}
+
+fn main() {
+    let foo = Foo();
+    println!("Hello, {:?}!", foo);
+}
diff --git a/src/test/ui/resolve/issue-21221-1.stderr b/src/test/ui/resolve/issue-21221-1.stderr
new file mode 100644 (file)
index 0000000..17b70d2
--- /dev/null
@@ -0,0 +1,41 @@
+error[E0405]: unresolved trait `Mul`
+  --> $DIR/issue-21221-1.rs:53:6
+   |
+53 | impl Mul for Foo {
+   |      ^^^ no resolution found
+   |
+   = help: possible candidates are found in other modules, you can import them into scope:
+   = help:   `use mul1::Mul;`
+   = help:   `use mul2::Mul;`
+   = help:   `use std::ops::Mul;`
+
+error[E0412]: unresolved type `Mul`
+  --> $DIR/issue-21221-1.rs:72:16
+   |
+72 | fn getMul() -> Mul {
+   |                ^^^ no resolution found
+   |
+   = help: possible candidates are found in other modules, you can import them into scope:
+   = help:   `use mul1::Mul;`
+   = help:   `use mul2::Mul;`
+   = help:   `use mul3::Mul;`
+   = help:   `use mul4::Mul;`
+   = help:   and 2 other candidates
+
+error[E0405]: unresolved trait `ThisTraitReallyDoesntExistInAnyModuleReally`
+  --> $DIR/issue-21221-1.rs:83:6
+   |
+83 | impl ThisTraitReallyDoesntExistInAnyModuleReally for Foo {
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no resolution found
+
+error[E0405]: unresolved trait `Div`
+  --> $DIR/issue-21221-1.rs:88:6
+   |
+88 | impl Div for Foo {
+   |      ^^^ no resolution found
+   |
+   = help: possible candidate is found in another module, you can import it into scope:
+   = help:   `use std::ops::Div;`
+
+error: cannot continue compilation due to previous error
+
diff --git a/src/test/ui/resolve/issue-21221-2.rs b/src/test/ui/resolve/issue-21221-2.rs
new file mode 100644 (file)
index 0000000..15e8593
--- /dev/null
@@ -0,0 +1,30 @@
+// 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 mod foo {
+    pub mod bar {
+        // note: trait T is not public, but being in the current
+        // crate, it's fine to show it, since the programmer can
+        // decide to make it public based on the suggestion ...
+        pub trait T {}
+    }
+    // imports should be ignored:
+    use self::bar::T;
+}
+
+pub mod baz {
+    pub use foo;
+    pub use std::ops::{Mul as T};
+}
+
+struct Foo;
+impl T for Foo { }
+//~^ ERROR unresolved trait `T`
+//~| HELP you can import it into scope: `use foo::bar::T;`
diff --git a/src/test/ui/resolve/issue-21221-2.stderr b/src/test/ui/resolve/issue-21221-2.stderr
new file mode 100644 (file)
index 0000000..342fe12
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0405]: unresolved trait `T`
+  --> $DIR/issue-21221-2.rs:28:6
+   |
+28 | impl T for Foo { }
+   |      ^ no resolution found
+   |
+   = help: possible candidate is found in another module, you can import it into scope:
+   = help:   `use foo::bar::T;`
+
+error: main function not found
+
+error: cannot continue compilation due to previous error
+
diff --git a/src/test/ui/resolve/issue-21221-3.rs b/src/test/ui/resolve/issue-21221-3.rs
new file mode 100644 (file)
index 0000000..5d62cb8
--- /dev/null
@@ -0,0 +1,30 @@
+// 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.
+
+// testing whether the lookup mechanism picks up types
+// defined in the outside crate
+
+// aux-build:issue-21221-3.rs
+
+extern crate issue_21221_3;
+
+struct Foo;
+
+// NOTE: This shows only traits accessible from the current
+// crate, thus the two private entities:
+//   `issue_21221_3::outer::private_module::OuterTrait` and
+//   `issue_21221_3::outer::public_module::OuterTrait`
+// are hidden from the view.
+impl OuterTrait for Foo {}
+//~^ ERROR unresolved trait `OuterTrait`
+//~| HELP you can import it into scope: `use issue_21221_3::outer::OuterTrait;`
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/resolve/issue-21221-3.stderr b/src/test/ui/resolve/issue-21221-3.stderr
new file mode 100644 (file)
index 0000000..25f57f3
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0405]: unresolved trait `OuterTrait`
+  --> $DIR/issue-21221-3.rs:25:6
+   |
+25 | impl OuterTrait for Foo {}
+   |      ^^^^^^^^^^ no resolution found
+   |
+   = help: possible candidate is found in another module, you can import it into scope:
+   = help:   `use issue_21221_3::outer::OuterTrait;`
+
+error: cannot continue compilation due to previous error
+
diff --git a/src/test/ui/resolve/issue-21221-4.rs b/src/test/ui/resolve/issue-21221-4.rs
new file mode 100644 (file)
index 0000000..ff6698f
--- /dev/null
@@ -0,0 +1,26 @@
+// 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.
+
+// testing whether the lookup mechanism picks up types
+// defined in the outside crate
+
+// aux-build:issue-21221-4.rs
+
+extern crate issue_21221_4;
+
+struct Foo;
+
+impl T for Foo {}
+//~^ ERROR unresolved trait `T`
+//~| HELP you can import it into scope: `use issue_21221_4::T;`
+
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/resolve/issue-21221-4.stderr b/src/test/ui/resolve/issue-21221-4.stderr
new file mode 100644 (file)
index 0000000..7ddbeeb
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0405]: unresolved trait `T`
+  --> $DIR/issue-21221-4.rs:20:6
+   |
+20 | impl T for Foo {}
+   |      ^ no resolution found
+   |
+   = help: possible candidate is found in another module, you can import it into scope:
+   = help:   `use issue_21221_4::T;`
+
+error: cannot continue compilation due to previous error
+
diff --git a/src/test/ui/resolve/issue-23305.rs b/src/test/ui/resolve/issue-23305.rs
new file mode 100644 (file)
index 0000000..19069f4
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+pub trait ToNbt<T> {
+    fn new(val: T) -> Self;
+}
+
+impl ToNbt<Self> {}
+//~^ ERROR unresolved type `Self`
+//~| NOTE `Self` is only available in traits and impls
+//~| ERROR the trait `ToNbt` cannot be made into an object
+//~| NOTE the trait `ToNbt` cannot be made into an object
+//~| NOTE method `new` has no receiver
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr
new file mode 100644 (file)
index 0000000..cd0d7d3
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0411]: unresolved type `Self`
+  --> $DIR/issue-23305.rs:15:12
+   |
+15 | impl ToNbt<Self> {}
+   |            ^^^^ `Self` is only available in traits and impls
+
+error[E0038]: the trait `ToNbt` cannot be made into an object
+  --> $DIR/issue-23305.rs:15:6
+   |
+15 | impl ToNbt<Self> {}
+   |      ^^^^^^^^^^^ the trait `ToNbt` cannot be made into an object
+   |
+   = note: method `new` has no receiver
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/resolve/issue-2356.rs b/src/test/ui/resolve/issue-2356.rs
new file mode 100644 (file)
index 0000000..6deb598
--- /dev/null
@@ -0,0 +1,125 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Groom {
+    fn shave(other: usize);
+}
+
+pub struct cat {
+  whiskers: isize,
+}
+
+pub enum MaybeDog {
+    Dog,
+    NoDog
+}
+
+impl MaybeDog {
+  fn bark() {
+    // If this provides a suggestion, it's a bug as MaybeDog doesn't impl Groom
+    shave();
+    //~^ ERROR unresolved function `shave`
+    //~| NOTE no resolution found
+  }
+}
+
+impl Clone for cat {
+  fn clone(&self) -> Self {
+    clone();
+    //~^ ERROR unresolved function `clone`
+    //~| NOTE did you mean `self.clone(...)`?
+    loop {}
+  }
+}
+impl Default for cat {
+  fn default() -> Self {
+    default();
+    //~^ ERROR unresolved function `default`
+    //~| NOTE did you mean `Self::default`?
+    loop {}
+  }
+}
+
+impl Groom for cat {
+  fn shave(other: usize) {
+    whiskers -= other;
+    //~^ ERROR unresolved value `whiskers`
+    //~| ERROR unresolved value `whiskers`
+    //~| NOTE did you mean `self.whiskers`?
+    //~| NOTE `self` value is only available in methods with `self` parameter
+    shave(4);
+    //~^ ERROR unresolved function `shave`
+    //~| NOTE did you mean `Self::shave`?
+    purr();
+    //~^ ERROR unresolved function `purr`
+    //~| NOTE no resolution found
+  }
+}
+
+impl cat {
+    fn static_method() {}
+
+    fn purr_louder() {
+        static_method();
+        //~^ ERROR unresolved function `static_method`
+        //~| NOTE no resolution found
+        purr();
+        //~^ ERROR unresolved function `purr`
+        //~| NOTE no resolution found
+        purr();
+        //~^ ERROR unresolved function `purr`
+        //~| NOTE no resolution found
+        purr();
+        //~^ ERROR unresolved function `purr`
+        //~| NOTE no resolution found
+    }
+}
+
+impl cat {
+  fn meow() {
+    if self.whiskers > 3 {
+        //~^ ERROR expected value, found module `self`
+        //~| NOTE `self` value is only available in methods with `self` parameter
+        println!("MEOW");
+    }
+  }
+
+  fn purr(&self) {
+    grow_older();
+    //~^ ERROR unresolved function `grow_older`
+    //~| NOTE no resolution found
+    shave();
+    //~^ ERROR unresolved function `shave`
+    //~| NOTE no resolution found
+  }
+
+  fn burn_whiskers(&mut self) {
+    whiskers = 0;
+    //~^ ERROR unresolved value `whiskers`
+    //~| NOTE did you mean `self.whiskers`?
+  }
+
+  pub fn grow_older(other:usize) {
+    whiskers = 4;
+    //~^ ERROR unresolved value `whiskers`
+    //~| ERROR unresolved value `whiskers`
+    //~| NOTE did you mean `self.whiskers`?
+    //~| NOTE `self` value is only available in methods with `self` parameter
+    purr_louder();
+    //~^ ERROR unresolved function `purr_louder`
+    //~| NOTE no resolution found
+  }
+}
+
+fn main() {
+    self += 1;
+    //~^ ERROR expected value, found module `self`
+    //~| NOTE `self` value is only available in methods with `self` parameter
+}
diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr
new file mode 100644 (file)
index 0000000..32c1a36
--- /dev/null
@@ -0,0 +1,110 @@
+error[E0425]: unresolved function `shave`
+  --> $DIR/issue-2356.rs:27:5
+   |
+27 |     shave();
+   |     ^^^^^ no resolution found
+
+error[E0425]: unresolved function `clone`
+  --> $DIR/issue-2356.rs:35:5
+   |
+35 |     clone();
+   |     ^^^^^ did you mean `self.clone(...)`?
+
+error[E0425]: unresolved function `default`
+  --> $DIR/issue-2356.rs:43:5
+   |
+43 |     default();
+   |     ^^^^^^^ did you mean `Self::default`?
+
+error[E0425]: unresolved value `whiskers`
+  --> $DIR/issue-2356.rs:52:5
+   |
+52 |     whiskers -= other;
+   |     ^^^^^^^^
+   |     |
+   |     did you mean `self.whiskers`?
+   |     `self` value is only available in methods with `self` parameter
+
+error[E0425]: unresolved function `shave`
+  --> $DIR/issue-2356.rs:57:5
+   |
+57 |     shave(4);
+   |     ^^^^^ did you mean `Self::shave`?
+
+error[E0425]: unresolved function `purr`
+  --> $DIR/issue-2356.rs:60:5
+   |
+60 |     purr();
+   |     ^^^^ no resolution found
+
+error[E0425]: unresolved function `static_method`
+  --> $DIR/issue-2356.rs:70:9
+   |
+70 |         static_method();
+   |         ^^^^^^^^^^^^^ no resolution found
+
+error[E0425]: unresolved function `purr`
+  --> $DIR/issue-2356.rs:73:9
+   |
+73 |         purr();
+   |         ^^^^ no resolution found
+
+error[E0425]: unresolved function `purr`
+  --> $DIR/issue-2356.rs:76:9
+   |
+76 |         purr();
+   |         ^^^^ no resolution found
+
+error[E0425]: unresolved function `purr`
+  --> $DIR/issue-2356.rs:79:9
+   |
+79 |         purr();
+   |         ^^^^ no resolution found
+
+error[E0424]: expected value, found module `self`
+  --> $DIR/issue-2356.rs:87:8
+   |
+87 |     if self.whiskers > 3 {
+   |        ^^^^ `self` value is only available in methods with `self` parameter
+
+error[E0425]: unresolved function `grow_older`
+  --> $DIR/issue-2356.rs:95:5
+   |
+95 |     grow_older();
+   |     ^^^^^^^^^^ no resolution found
+
+error[E0425]: unresolved function `shave`
+  --> $DIR/issue-2356.rs:98:5
+   |
+98 |     shave();
+   |     ^^^^^ no resolution found
+
+error[E0425]: unresolved value `whiskers`
+   --> $DIR/issue-2356.rs:104:5
+    |
+104 |     whiskers = 0;
+    |     ^^^^^^^^ did you mean `self.whiskers`?
+
+error[E0425]: unresolved value `whiskers`
+   --> $DIR/issue-2356.rs:110:5
+    |
+110 |     whiskers = 4;
+    |     ^^^^^^^^
+    |     |
+    |     did you mean `self.whiskers`?
+    |     `self` value is only available in methods with `self` parameter
+
+error[E0425]: unresolved function `purr_louder`
+   --> $DIR/issue-2356.rs:115:5
+    |
+115 |     purr_louder();
+    |     ^^^^^^^^^^^ no resolution found
+
+error[E0424]: expected value, found module `self`
+   --> $DIR/issue-2356.rs:122:5
+    |
+122 |     self += 1;
+    |     ^^^^ `self` value is only available in methods with `self` parameter
+
+error: aborting due to 17 previous errors
+
diff --git a/src/test/ui/resolve/issue-24968.rs b/src/test/ui/resolve/issue-24968.rs
new file mode 100644 (file)
index 0000000..0d562ca
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+fn foo(_: Self) {
+//~^ ERROR unresolved type `Self`
+//~| NOTE `Self` is only available in traits and impls
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-24968.stderr b/src/test/ui/resolve/issue-24968.stderr
new file mode 100644 (file)
index 0000000..3050bc4
--- /dev/null
@@ -0,0 +1,8 @@
+error[E0411]: unresolved type `Self`
+  --> $DIR/issue-24968.rs:11:11
+   |
+11 | fn foo(_: Self) {
+   |           ^^^^ `Self` is only available in traits and impls
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/resolve/issue-33876.rs b/src/test/ui/resolve/issue-33876.rs
new file mode 100644 (file)
index 0000000..a97cc5e
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::any::Any;
+
+struct Foo;
+
+trait Bar {}
+
+impl Bar for Foo {}
+
+fn main() {
+    let any: &Any = &Bar; //~ ERROR expected value, found trait `Bar`
+    if any.is::<u32>() { println!("u32"); }
+}
diff --git a/src/test/ui/resolve/issue-33876.stderr b/src/test/ui/resolve/issue-33876.stderr
new file mode 100644 (file)
index 0000000..5dbecc4
--- /dev/null
@@ -0,0 +1,8 @@
+error[E0423]: expected value, found trait `Bar`
+  --> $DIR/issue-33876.rs:20:22
+   |
+20 |     let any: &Any = &Bar; //~ ERROR expected value, found trait `Bar`
+   |                      ^^^ not a value
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/resolve/issue-3907-2.rs b/src/test/ui/resolve/issue-3907-2.rs
new file mode 100644 (file)
index 0000000..1306479
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2013-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.
+
+// aux-build:issue_3907.rs
+extern crate issue_3907;
+
+type Foo = issue_3907::Foo+'static;
+
+struct S {
+    name: isize
+}
+
+fn bar(_x: Foo) {}
+//~^ ERROR E0038
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr
new file mode 100644 (file)
index 0000000..ef02250
--- /dev/null
@@ -0,0 +1,10 @@
+error[E0038]: the trait `issue_3907::Foo` cannot be made into an object
+  --> $DIR/issue-3907-2.rs:20:1
+   |
+20 | fn bar(_x: Foo) {}
+   | ^^^^^^^^^^^^^^^^^^ the trait `issue_3907::Foo` cannot be made into an object
+   |
+   = note: method `bar` has no receiver
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/resolve/issue-3907.rs b/src/test/ui/resolve/issue-3907.rs
new file mode 100644 (file)
index 0000000..0e54e68
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2013-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.
+
+// aux-build:issue_3907.rs
+extern crate issue_3907;
+
+type Foo = issue_3907::Foo;
+
+struct S {
+    name: isize
+}
+
+impl Foo for S { //~ ERROR expected trait, found type alias `Foo`
+    fn bar() { }
+}
+
+fn main() {
+    let s = S {
+        name: 0
+    };
+    s.bar();
+}
diff --git a/src/test/ui/resolve/issue-3907.stderr b/src/test/ui/resolve/issue-3907.stderr
new file mode 100644 (file)
index 0000000..0a40268
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0404]: expected trait, found type alias `Foo`
+  --> $DIR/issue-3907.rs:20:6
+   |
+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:
+   = help:   `use issue_3907::Foo;`
+
+error: cannot continue compilation due to previous error
+
diff --git a/src/test/ui/resolve/issue-5035-2.rs b/src/test/ui/resolve/issue-5035-2.rs
new file mode 100644 (file)
index 0000000..83ff95c
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2013-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.
+
+trait I {}
+type K = I+'static;
+
+fn foo(_x: K) {} //~ ERROR: `I + 'static: std::marker::Sized` is not satisfied
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-5035-2.stderr b/src/test/ui/resolve/issue-5035-2.stderr
new file mode 100644 (file)
index 0000000..72b1578
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `I + 'static: std::marker::Sized` is not satisfied
+  --> $DIR/issue-5035-2.rs:14:8
+   |
+14 | fn foo(_x: K) {} //~ ERROR: `I + 'static: std::marker::Sized` is not satisfied
+   |        ^^ the trait `std::marker::Sized` is not implemented for `I + 'static`
+   |
+   = note: `I + 'static` does not have a constant size known at compile-time
+   = note: all local variables must have a statically known size
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/resolve/issue-5035.rs b/src/test/ui/resolve/issue-5035.rs
new file mode 100644 (file)
index 0000000..6263e6f
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2013-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.
+
+trait I {}
+type K = I;
+impl K for isize {} //~ ERROR expected trait, found type alias `K`
+                    //~| NOTE type aliases cannot be used for traits
+
+use ImportError; //~ ERROR unresolved import `ImportError` [E0432]
+                 //~^ no `ImportError` in the root
+impl ImportError for () {} // check that this is not an additional error (c.f. #35142)
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-5035.stderr b/src/test/ui/resolve/issue-5035.stderr
new file mode 100644 (file)
index 0000000..6cb9a28
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0432]: unresolved import `ImportError`
+  --> $DIR/issue-5035.rs:16:5
+   |
+16 | use ImportError; //~ ERROR unresolved import `ImportError` [E0432]
+   |     ^^^^^^^^^^^ no `ImportError` in the root
+
+error[E0404]: expected trait, found type alias `K`
+  --> $DIR/issue-5035.rs:13:6
+   |
+13 | impl K for isize {} //~ ERROR expected trait, found type alias `K`
+   |      ^ type aliases cannot be used for traits
+
+error: cannot continue compilation due to previous error
+
diff --git a/src/test/ui/resolve/issue-6702.rs b/src/test/ui/resolve/issue-6702.rs
new file mode 100644 (file)
index 0000000..b391ddf
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2013 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 Monster {
+    damage: isize
+}
+
+
+fn main() {
+    let _m = Monster(); //~ ERROR expected function, found struct `Monster`
+                        //~^ NOTE did you mean `Monster { /* fields */ }`?
+}
diff --git a/src/test/ui/resolve/issue-6702.stderr b/src/test/ui/resolve/issue-6702.stderr
new file mode 100644 (file)
index 0000000..b502957
--- /dev/null
@@ -0,0 +1,8 @@
+error[E0423]: expected function, found struct `Monster`
+  --> $DIR/issue-6702.rs:17:14
+   |
+17 |     let _m = Monster(); //~ ERROR expected function, found struct `Monster`
+   |              ^^^^^^^ did you mean `Monster { /* fields */ }`?
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/resolve/resolve-assoc-suggestions.rs b/src/test/ui/resolve/resolve-assoc-suggestions.rs
new file mode 100644 (file)
index 0000000..53e26dd
--- /dev/null
@@ -0,0 +1,58 @@
+// 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.
+
+// Make sure associated items are recommended only in appropriate contexts.
+
+struct S {
+    field: u8,
+}
+
+trait Tr {
+    fn method(&self);
+    type Type;
+}
+
+impl Tr for S {
+    type Type = u8;
+
+    fn method(&self) {
+        let _: field;
+        //~^ ERROR unresolved type `field`
+        //~| NOTE no resolution found
+        let field(..);
+        //~^ ERROR unresolved tuple struct/variant `field`
+        //~| NOTE no resolution found
+        field;
+        //~^ ERROR unresolved value `field`
+        //~| NOTE did you mean `self.field`?
+
+        let _: Type;
+        //~^ ERROR unresolved type `Type`
+        //~| NOTE did you mean `Self::Type`?
+        let Type(..);
+        //~^ ERROR unresolved tuple struct/variant `Type`
+        //~| NOTE no resolution found
+        Type;
+        //~^ ERROR unresolved value `Type`
+        //~| NOTE no resolution found
+
+        let _: method;
+        //~^ ERROR unresolved type `method`
+        //~| NOTE no resolution found
+        let method(..);
+        //~^ ERROR unresolved tuple struct/variant `method`
+        //~| NOTE no resolution found
+        method;
+        //~^ ERROR unresolved value `method`
+        //~| NOTE did you mean `self.method(...)`?
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/resolve-assoc-suggestions.stderr b/src/test/ui/resolve/resolve-assoc-suggestions.stderr
new file mode 100644 (file)
index 0000000..98ead71
--- /dev/null
@@ -0,0 +1,56 @@
+error[E0412]: unresolved type `field`
+  --> $DIR/resolve-assoc-suggestions.rs:26:16
+   |
+26 |         let _: field;
+   |                ^^^^^ no resolution found
+
+error[E0531]: unresolved tuple struct/variant `field`
+  --> $DIR/resolve-assoc-suggestions.rs:29:13
+   |
+29 |         let field(..);
+   |             ^^^^^ no resolution found
+
+error[E0425]: unresolved value `field`
+  --> $DIR/resolve-assoc-suggestions.rs:32:9
+   |
+32 |         field;
+   |         ^^^^^ did you mean `self.field`?
+
+error[E0412]: unresolved type `Type`
+  --> $DIR/resolve-assoc-suggestions.rs:36:16
+   |
+36 |         let _: Type;
+   |                ^^^^ did you mean `Self::Type`?
+
+error[E0531]: unresolved tuple struct/variant `Type`
+  --> $DIR/resolve-assoc-suggestions.rs:39:13
+   |
+39 |         let Type(..);
+   |             ^^^^ no resolution found
+
+error[E0425]: unresolved value `Type`
+  --> $DIR/resolve-assoc-suggestions.rs:42:9
+   |
+42 |         Type;
+   |         ^^^^ no resolution found
+
+error[E0412]: unresolved type `method`
+  --> $DIR/resolve-assoc-suggestions.rs:46:16
+   |
+46 |         let _: method;
+   |                ^^^^^^ no resolution found
+
+error[E0531]: unresolved tuple struct/variant `method`
+  --> $DIR/resolve-assoc-suggestions.rs:49:13
+   |
+49 |         let method(..);
+   |             ^^^^^^ no resolution found
+
+error[E0425]: unresolved value `method`
+  --> $DIR/resolve-assoc-suggestions.rs:52:9
+   |
+52 |         method;
+   |         ^^^^^^ did you mean `self.method(...)`?
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/resolve/resolve-hint-macro.rs b/src/test/ui/resolve/resolve-hint-macro.rs
new file mode 100644 (file)
index 0000000..72fd9a7
--- /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.
+
+fn main() {
+    assert(true);
+    //~^ ERROR expected function, found macro `assert`
+    //~| NOTE did you mean `assert!(...)`?
+}
diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr
new file mode 100644 (file)
index 0000000..ffb3f84
--- /dev/null
@@ -0,0 +1,8 @@
+error[E0423]: expected function, found macro `assert`
+  --> $DIR/resolve-hint-macro.rs:12:5
+   |
+12 |     assert(true);
+   |     ^^^^^^ did you mean `assert!(...)`?
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/resolve/resolve-speculative-adjustment.rs b/src/test/ui/resolve/resolve-speculative-adjustment.rs
new file mode 100644 (file)
index 0000000..95289e2
--- /dev/null
@@ -0,0 +1,44 @@
+// 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.
+
+// Make sure speculative path resolution works properly when resolution
+// adjustment happens and no extra errors is reported.
+
+struct S {
+    field: u8,
+}
+
+trait Tr {
+    fn method(&self);
+}
+
+impl Tr for S {
+    fn method(&self) {
+        fn g() {
+            // Speculative resolution of `Self` and `self` silently fails,
+            // "did you mean" messages are not printed.
+            field;
+            //~^ ERROR unresolved value `field`
+            //~| NOTE no resolution found
+            method();
+            //~^ ERROR unresolved function `method`
+            //~| NOTE no resolution found
+        }
+
+        field;
+        //~^ ERROR unresolved value `field`
+        //~| NOTE did you mean `self.field`?
+        method();
+        //~^ ERROR unresolved function `method`
+        //~| NOTE did you mean `self.method(...)`?
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/resolve-speculative-adjustment.stderr b/src/test/ui/resolve/resolve-speculative-adjustment.stderr
new file mode 100644 (file)
index 0000000..173b690
--- /dev/null
@@ -0,0 +1,26 @@
+error[E0425]: unresolved value `field`
+  --> $DIR/resolve-speculative-adjustment.rs:27:13
+   |
+27 |             field;
+   |             ^^^^^ no resolution found
+
+error[E0425]: unresolved function `method`
+  --> $DIR/resolve-speculative-adjustment.rs:30:13
+   |
+30 |             method();
+   |             ^^^^^^ no resolution found
+
+error[E0425]: unresolved value `field`
+  --> $DIR/resolve-speculative-adjustment.rs:35:9
+   |
+35 |         field;
+   |         ^^^^^ did you mean `self.field`?
+
+error[E0425]: unresolved function `method`
+  --> $DIR/resolve-speculative-adjustment.rs:38:9
+   |
+38 |         method();
+   |         ^^^^^^ did you mean `self.method(...)`?
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs
new file mode 100644 (file)
index 0000000..789bdfb
--- /dev/null
@@ -0,0 +1,76 @@
+// 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.
+
+// Beginners write `mod.item` when they should write `mod::item`.
+// This tests that we suggest the latter when we encounter the former.
+
+pub mod a {
+    pub const I: i32 = 1;
+
+    pub fn f() -> i32 { 2 }
+
+    pub mod b {
+        pub const J: i32 = 3;
+
+        pub fn g() -> i32 { 4 }
+    }
+}
+
+fn h1() -> i32 {
+    a.I
+    //~^ ERROR expected value, found module `a`
+    //~| NOTE did you mean `a::I`?
+}
+
+fn h2() -> i32 {
+    a.g()
+    //~^ ERROR expected value, found module `a`
+    //~| NOTE did you mean `a::g(...)`?
+}
+
+fn h3() -> i32 {
+    a.b.J
+    //~^ ERROR expected value, found module `a`
+    //~| NOTE did you mean `a::b`?
+}
+
+fn h4() -> i32 {
+    a::b.J
+    //~^ ERROR expected value, found module `a::b`
+    //~| NOTE did you mean `a::b::J`?
+}
+
+fn h5() {
+    a.b.f();
+    //~^ ERROR expected value, found module `a`
+    //~| NOTE did you mean `a::b`?
+    let v = Vec::new();
+    v.push(a::b);
+    //~^ ERROR expected value, found module `a::b`
+    //~| NOTE not a value
+}
+
+fn h6() -> i32 {
+    a::b.f()
+    //~^ ERROR expected value, found module `a::b`
+    //~| NOTE did you mean `a::b::f(...)`?
+}
+
+fn h7() {
+    a::b
+    //~^ ERROR expected value, found module `a::b`
+    //~| NOTE not a value
+}
+
+fn h8() -> i32 {
+    a::b()
+    //~^ ERROR expected function, found module `a::b`
+    //~| NOTE not a function
+}
diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
new file mode 100644 (file)
index 0000000..8ace738
--- /dev/null
@@ -0,0 +1,58 @@
+error[E0423]: expected value, found module `a`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5
+   |
+27 |     a.I
+   |     ^ did you mean `a::I`?
+
+error[E0423]: expected value, found module `a`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:33:5
+   |
+33 |     a.g()
+   |     ^ did you mean `a::g(...)`?
+
+error[E0423]: expected value, found module `a`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:39:5
+   |
+39 |     a.b.J
+   |     ^ did you mean `a::b`?
+
+error[E0423]: expected value, found module `a::b`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5
+   |
+45 |     a::b.J
+   |     ^^^^ did you mean `a::b::J`?
+
+error[E0423]: expected value, found module `a`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:51:5
+   |
+51 |     a.b.f();
+   |     ^ did you mean `a::b`?
+
+error[E0423]: expected value, found module `a::b`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:55:12
+   |
+55 |     v.push(a::b);
+   |            ^^^^ not a value
+
+error[E0423]: expected value, found module `a::b`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:61:5
+   |
+61 |     a::b.f()
+   |     ^^^^ did you mean `a::b::f(...)`?
+
+error[E0423]: expected value, found module `a::b`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:67:5
+   |
+67 |     a::b
+   |     ^^^^ not a value
+
+error[E0423]: expected function, found module `a::b`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:73:5
+   |
+73 |     a::b()
+   |     ^^^^ not a function
+
+error: main function not found
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/resolve/token-error-correct-2.rs b/src/test/ui/resolve/token-error-correct-2.rs
new file mode 100644 (file)
index 0000000..6fa1260
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we do some basic error correcton in the tokeniser (and don't ICE).
+
+fn main() {
+    if foo {
+    //~^ NOTE: unclosed delimiter
+    //~| ERROR: unresolved value `foo`
+    //~| NOTE: no resolution found
+    ) //~ ERROR: incorrect close delimiter: `)`
+}
diff --git a/src/test/ui/resolve/token-error-correct-2.stderr b/src/test/ui/resolve/token-error-correct-2.stderr
new file mode 100644 (file)
index 0000000..7c42239
--- /dev/null
@@ -0,0 +1,20 @@
+error: incorrect close delimiter: `)`
+  --> $DIR/token-error-correct-2.rs:18:5
+   |
+18 |     ) //~ ERROR: incorrect close delimiter: `)`
+   |     ^
+   |
+note: unclosed delimiter
+  --> $DIR/token-error-correct-2.rs:14:12
+   |
+14 |     if foo {
+   |            ^
+
+error[E0425]: unresolved value `foo`
+  --> $DIR/token-error-correct-2.rs:14:8
+   |
+14 |     if foo {
+   |        ^^^ no resolution found
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/resolve/token-error-correct-3.rs b/src/test/ui/resolve/token-error-correct-3.rs
new file mode 100644 (file)
index 0000000..f72b7ad
--- /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.
+
+// Test that we do some basic error correcton in the tokeniser (and don't spew
+// too many bogus errors).
+
+pub mod raw {
+    use std::{io, fs};
+    use std::path::Path;
+
+    pub fn ensure_dir_exists<P: AsRef<Path>, F: FnOnce(&Path)>(path: P,
+                                                               callback: F)
+                                                               -> io::Result<bool> {
+        if !is_directory(path.as_ref()) { //~ ERROR: unresolved function `is_directory`
+                                          //~^ NOTE: no resolution found
+            callback(path.as_ref();  //~ NOTE: unclosed delimiter
+                     //~^ ERROR: expected one of
+            fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types
+            //~^ expected (), found enum `std::result::Result`
+            //~| expected type `()`
+            //~| found type `std::result::Result<bool, std::io::Error>`
+        } else { //~ ERROR: incorrect close delimiter: `}`
+            //~^ ERROR: expected one of
+            Ok(false);
+        }
+
+        panic!();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr
new file mode 100644 (file)
index 0000000..0b15c23
--- /dev/null
@@ -0,0 +1,45 @@
+error: incorrect close delimiter: `}`
+  --> $DIR/token-error-correct-3.rs:29:9
+   |
+29 |         } else { //~ ERROR: incorrect close delimiter: `}`
+   |         ^
+   |
+note: unclosed delimiter
+  --> $DIR/token-error-correct-3.rs:23:21
+   |
+23 |             callback(path.as_ref();  //~ NOTE: unclosed delimiter
+   |                     ^
+
+error: expected one of `,`, `.`, `?`, or an operator, found `;`
+  --> $DIR/token-error-correct-3.rs:23:35
+   |
+23 |             callback(path.as_ref();  //~ NOTE: unclosed delimiter
+   |                                   ^
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)`
+  --> $DIR/token-error-correct-3.rs:29:9
+   |
+29 |         } else { //~ ERROR: incorrect close delimiter: `}`
+   |         ^
+
+error[E0425]: unresolved function `is_directory`
+  --> $DIR/token-error-correct-3.rs:21:13
+   |
+21 |         if !is_directory(path.as_ref()) { //~ ERROR: unresolved function `is_directory`
+   |             ^^^^^^^^^^^^ no resolution found
+
+error[E0308]: mismatched types
+  --> $DIR/token-error-correct-3.rs:25:13
+   |
+25 |             fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `std::result::Result`
+   |
+   = note: expected type `()`
+   = note:    found type `std::result::Result<bool, std::io::Error>`
+   = help: here are some functions which might fulfill your needs:
+ - .unwrap()
+ - .unwrap_err()
+ - .unwrap_or_default()
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/resolve/token-error-correct.rs b/src/test/ui/resolve/token-error-correct.rs
new file mode 100644 (file)
index 0000000..5fd35e5
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we do some basic error correcton in the tokeniser.
+
+fn main() {
+    foo(bar(;
+    //~^ NOTE: unclosed delimiter
+    //~| NOTE: unclosed delimiter
+    //~| ERROR: expected expression, found `;`
+    //~| ERROR: unresolved function `foo`
+    //~| NOTE: no resolution found
+    //~| ERROR: unresolved function `bar`
+    //~| NOTE: no resolution found
+    //~| ERROR: expected one of `)`, `,`, `.`, `<`, `?`
+}
+//~^ ERROR: incorrect close delimiter: `}`
+//~| ERROR: incorrect close delimiter: `}`
+//~| ERROR: expected expression, found `)`
diff --git a/src/test/ui/resolve/token-error-correct.stderr b/src/test/ui/resolve/token-error-correct.stderr
new file mode 100644 (file)
index 0000000..38cd95a
--- /dev/null
@@ -0,0 +1,56 @@
+error: incorrect close delimiter: `}`
+  --> $DIR/token-error-correct.rs:23:1
+   |
+23 | }
+   | ^
+   |
+note: unclosed delimiter
+  --> $DIR/token-error-correct.rs:14:12
+   |
+14 |     foo(bar(;
+   |            ^
+
+error: incorrect close delimiter: `}`
+  --> $DIR/token-error-correct.rs:23:1
+   |
+23 | }
+   | ^
+   |
+note: unclosed delimiter
+  --> $DIR/token-error-correct.rs:14:8
+   |
+14 |     foo(bar(;
+   |        ^
+
+error: expected expression, found `;`
+  --> $DIR/token-error-correct.rs:14:13
+   |
+14 |     foo(bar(;
+   |             ^
+
+error: expected one of `)`, `,`, `.`, `<`, `?`, `break`, `continue`, `false`, `for`, `if`, `loop`, `match`, `move`, `return`, `true`, `unsafe`, `while`, or an operator, found `;`
+  --> $DIR/token-error-correct.rs:14:13
+   |
+14 |     foo(bar(;
+   |             ^
+
+error: expected expression, found `)`
+  --> $DIR/token-error-correct.rs:23:1
+   |
+23 | }
+   | ^
+
+error[E0425]: unresolved function `foo`
+  --> $DIR/token-error-correct.rs:14:5
+   |
+14 |     foo(bar(;
+   |     ^^^ no resolution found
+
+error[E0425]: unresolved function `bar`
+  --> $DIR/token-error-correct.rs:14:9
+   |
+14 |     foo(bar(;
+   |         ^^^ no resolution found
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/resolve/tuple-struct-alias.rs b/src/test/ui/resolve/tuple-struct-alias.rs
new file mode 100644 (file)
index 0000000..c9c0520
--- /dev/null
@@ -0,0 +1,28 @@
+// 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.
+
+struct S(u8, u16);
+type A = S;
+
+impl S {
+    fn f() {
+        let s = Self(0, 1);
+        match s {
+            Self(..) => {}
+        }
+    }
+}
+
+fn main() {
+    let s = A(0, 1);
+    match s {
+        A(..) => {}
+    }
+}
diff --git a/src/test/ui/resolve/tuple-struct-alias.stderr b/src/test/ui/resolve/tuple-struct-alias.stderr
new file mode 100644 (file)
index 0000000..485c8eb
--- /dev/null
@@ -0,0 +1,26 @@
+error[E0423]: expected function, found self type `Self`
+  --> $DIR/tuple-struct-alias.rs:16:17
+   |
+16 |         let s = Self(0, 1);
+   |                 ^^^^ did you mean `Self { /* fields */ }`?
+
+error[E0532]: expected tuple struct/variant, found self type `Self`
+  --> $DIR/tuple-struct-alias.rs:18:13
+   |
+18 |             Self(..) => {}
+   |             ^^^^ did you mean `Self { /* fields */ }`?
+
+error[E0423]: expected function, found type alias `A`
+  --> $DIR/tuple-struct-alias.rs:24:13
+   |
+24 |     let s = A(0, 1);
+   |             ^ did you mean `A { /* fields */ }`?
+
+error[E0532]: expected tuple struct/variant, found type alias `A`
+  --> $DIR/tuple-struct-alias.rs:26:9
+   |
+26 |         A(..) => {}
+   |         ^ did you mean `A { /* fields */ }`?
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.rs b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.rs
new file mode 100644 (file)
index 0000000..57f6ddd
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn f<F:Nonexist(isize) -> isize>(x: F) {}
+//~^ ERROR unresolved trait `Nonexist`
+//~| NOTE no resolution found
+
+type Typedef = isize;
+
+fn g<F:Typedef(isize) -> isize>(x: F) {}
+//~^ ERROR expected trait, found type alias `Typedef`
+//~| NOTE type aliases cannot be used for traits
+
+fn main() {}
diff --git a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr
new file mode 100644 (file)
index 0000000..ba90321
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0405]: unresolved trait `Nonexist`
+  --> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:11:8
+   |
+11 | fn f<F:Nonexist(isize) -> isize>(x: F) {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^ no resolution found
+
+error[E0404]: expected trait, found type alias `Typedef`
+  --> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:17:8
+   |
+17 | fn g<F:Typedef(isize) -> isize>(x: F) {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used for traits
+
+error: cannot continue compilation due to previous error
+
diff --git a/src/test/ui/resolve/unresolved_static_type_field.rs b/src/test/ui/resolve/unresolved_static_type_field.rs
new file mode 100644 (file)
index 0000000..19beabd
--- /dev/null
@@ -0,0 +1,27 @@
+// 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.
+
+fn f(_: bool) {}
+
+struct Foo {
+    cx: bool,
+}
+
+impl Foo {
+    fn bar() {
+        f(cx);
+        //~^ ERROR unresolved value `cx`
+        //~| ERROR unresolved value `cx`
+        //~| NOTE did you mean `self.cx`?
+        //~| NOTE `self` value is only available in methods with `self` parameter
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/unresolved_static_type_field.stderr b/src/test/ui/resolve/unresolved_static_type_field.stderr
new file mode 100644 (file)
index 0000000..1d0ee19
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0425]: unresolved value `cx`
+  --> $DIR/unresolved_static_type_field.rs:19:11
+   |
+19 |         f(cx);
+   |           ^^
+   |           |
+   |           did you mean `self.cx`?
+   |           `self` value is only available in methods with `self` parameter
+
+error: aborting due to previous error
+
index 815893e0c82d6a83ffb45d3d1c251a6379a23e84..717f5ee200c74041e5aea5c3509ea17ef7e5869d 100644 (file)
@@ -1,3 +1,9 @@
+error[E0437]: type `bar` is not a member of trait `Foo`
+  --> $DIR/impl-wrong-item-for-trait.rs:47:5
+   |
+47 |     type bar = u64;
+   |     ^^^^^^^^^^^^^^^ not a member of trait `Foo`
+
 error[E0323]: item `bar` is an associated const, which doesn't match its trait `Foo`
   --> $DIR/impl-wrong-item-for-trait.rs:25:5
    |
index 2370b3d6c612edea41f0011319bc476cf7993022..764f34cabde9ac85a8f93ce946506373d9f6204d 100644 (file)
@@ -1,10 +1,11 @@
-error[E0404]: `Add` is not a trait
+error[E0404]: expected trait, found type parameter `Add`
   --> $DIR/issue-35987.rs:15:21
    |
 15 | impl<T: Clone, Add> Add for Foo<T> {
-   |                ---  ^^^ expected trait, found type parameter
-   |                |
-   |                type parameter defined here
+   |                     ^^^ not a trait
+   |
+   = help: possible better candidate is found in another module, you can import it into scope:
+   = help:   `use std::ops::Add;`
 
 error: main function not found
 
index 5e9a0b915031e0a8c23a238fe860fc1f55d7659c..58f66c1358437132e9236fb7a0c6b3e677bcd297 100644 (file)
@@ -1,11 +1,3 @@
-error: cannot borrow immutable borrowed content `*a` as mutable
-  --> $DIR/mut-arg-hint.rs:13:9
-   |
-12 |     fn foo(mut a: &String) {
-   |                   ------- use `&mut String` here to make mutable
-13 |         a.push_str("bar");
-   |         ^
-
 error: cannot borrow immutable borrowed content `*a` as mutable
   --> $DIR/mut-arg-hint.rs:18:5
    |
@@ -14,6 +6,14 @@ error: cannot borrow immutable borrowed content `*a` as mutable
 18 |     a.push_str("foo");
    |     ^
 
+error: cannot borrow immutable borrowed content `*a` as mutable
+  --> $DIR/mut-arg-hint.rs:13:9
+   |
+12 |     fn foo(mut a: &String) {
+   |                   ------- use `&mut String` here to make mutable
+13 |         a.push_str("bar");
+   |         ^
+
 error: cannot borrow immutable borrowed content `*a` as mutable
   --> $DIR/mut-arg-hint.rs:25:9
    |
index 5446175aa250500bcd957c9de550862f1bcfd1ac..117c38e1db97149dc5fefdd418118034444232f6 100644 (file)
@@ -1,10 +1,10 @@
-error[E0425]: unresolved name `bar`
+error[E0425]: unresolved value `bar`
   --> $DIR/typo-suggestion.rs:15:26
    |
 15 |     println!("Hello {}", bar);
-   |                          ^^^ unresolved name
+   |                          ^^^ no resolution found
 
-error[E0425]: unresolved name `fob`
+error[E0425]: unresolved value `fob`
   --> $DIR/typo-suggestion.rs:18:26
    |
 18 |     println!("Hello {}", fob);
index 26a2e96f571081ef8b6fff2c7b289d0b11988937..8c8e426604e11aeee6ab29d62a53552f2a5d5323 100644 (file)
@@ -21,19 +21,44 @@ struct Test {
     lock: Option<&'static str>,
 }
 
-const TEST_REPOS: &'static [Test] = &[Test {
-                                          name: "cargo",
-                                          repo: "https://github.com/rust-lang/cargo",
-                                          sha: "b7be4f2ef2cf743492edc6dfb55d087ed88f2d76",
-                                          lock: None,
-                                      },
-                                      Test {
-                                          name: "iron",
-                                          repo: "https://github.com/iron/iron",
-                                          sha: "16c858ec2901e2992fe5e529780f59fa8ed12903",
-                                          lock: Some(include_str!("lockfiles/iron-Cargo.lock")),
-                                      }];
-
+const TEST_REPOS: &'static [Test] = &[
+    Test {
+        name: "cargo",
+        repo: "https://github.com/rust-lang/cargo",
+        sha: "b7be4f2ef2cf743492edc6dfb55d087ed88f2d76",
+        lock: None,
+    },
+    Test {
+        name: "iron",
+        repo: "https://github.com/iron/iron",
+        sha: "16c858ec2901e2992fe5e529780f59fa8ed12903",
+        lock: Some(include_str!("lockfiles/iron-Cargo.lock")),
+    },
+    Test {
+        name: "ripgrep",
+        repo: "https://github.com/BurntSushi/ripgrep",
+        sha: "b65bb37b14655e1a89c7cd19c8b011ef3e312791",
+        lock: None,
+    },
+    Test {
+        name: "tokei",
+        repo: "https://github.com/Aaronepower/tokei",
+        sha: "5e11c4852fe4aa086b0e4fe5885822fbe57ba928",
+        lock: None,
+    },
+    Test {
+        name: "treeify",
+        repo: "https://github.com/dzamlo/treeify",
+        sha: "999001b223152441198f117a68fb81f57bc086dd",
+        lock: None,
+    },
+    Test {
+        name: "xsv",
+        repo: "https://github.com/BurntSushi/xsv",
+        sha: "5ec4fff4a3f507eda887049469897f02c6fae036",
+        lock: None,
+    },
+];
 
 fn main() {
     // One of the projects being tested here is Cargo, and when being tested
index 956392ca540cd64c8efcd0c6b31b4af92cb2af40..e7690c03de5c3de88856a9b03c0d93405bdc8729 100644 (file)
@@ -2,6 +2,7 @@
 authors = ["The Rust Project Developers"]
 name = "rustbook"
 version = "0.0.0"
+build = false
 
 [[bin]]
 name = "rustbook"