]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #53815 - F001:if-let-guard, r=petrochenkov
authorbors <bors@rust-lang.org>
Sat, 1 Sep 2018 20:31:29 +0000 (20:31 +0000)
committerbors <bors@rust-lang.org>
Sat, 1 Sep 2018 20:31:29 +0000 (20:31 +0000)
refactor match guard

This is the first step to implement RFC 2294: if-let-guard. Tracking issue: https://github.com/rust-lang/rust/issues/51114

The second step should be introducing another variant `IfLet` in the Guard enum. I separated them into 2 PRs for the convenience of reviewers.

r? @petrochenkov

1203 files changed:
.gitignore
.travis.yml
CONTRIBUTING.md
RELEASES.md
config.toml.example
src/.gitignore [new file with mode: 0644]
src/Cargo.lock
src/bootstrap/bin/rustdoc.rs
src/bootstrap/builder.rs
src/bootstrap/check.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/flags.rs
src/bootstrap/job.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/tool.rs
src/bootstrap/util.rs
src/ci/docker/disabled/dist-armebv7r-none-eabihf/Dockerfile [deleted file]
src/ci/docker/dist-various-1/Dockerfile
src/ci/docker/dist-x86_64-linux/Dockerfile
src/ci/docker/dist-x86_64-linux/build-clang.sh
src/ci/docker/scripts/musl.sh
src/doc/book
src/doc/index.md
src/doc/nomicon
src/doc/rustc/src/codegen-options/index.md
src/doc/rustc/src/lints/listing/deny-by-default.md
src/doc/rustdoc/src/unstable-features.md
src/doc/unstable-book/src/language-features/attr-literals.md [deleted file]
src/doc/unstable-book/src/language-features/catch-expr.md [deleted file]
src/doc/unstable-book/src/language-features/doc-cfg.md
src/doc/unstable-book/src/language-features/infer-outlives-requirements.md
src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md
src/doc/unstable-book/src/language-features/macro-vis-matcher.md [deleted file]
src/doc/unstable-book/src/language-features/plugin.md
src/doc/unstable-book/src/language-features/tool-attributes.md [deleted file]
src/doc/unstable-book/src/language-features/try-blocks.md [new file with mode: 0644]
src/doc/unstable-book/src/language-features/used.md
src/etc/rust-gdb
src/etc/rust-gdbgui [new file with mode: 0755]
src/etc/rust-lldb
src/liballoc/alloc.rs
src/liballoc/borrow.rs
src/liballoc/boxed.rs
src/liballoc/collections/btree/node.rs
src/liballoc/collections/vec_deque.rs
src/liballoc/lib.rs
src/liballoc/pin.rs [new file with mode: 0644]
src/liballoc/raw_vec.rs
src/liballoc/rc.rs
src/liballoc/slice.rs
src/liballoc/str.rs
src/liballoc/string.rs
src/liballoc/sync.rs
src/liballoc/tests/lib.rs
src/liballoc/vec.rs
src/liballoc_jemalloc/lib.rs
src/liballoc_system/lib.rs
src/libarena/lib.rs
src/libcompiler_builtins
src/libcore/benches/any.rs
src/libcore/cmp.rs
src/libcore/fmt/mod.rs
src/libcore/future/future.rs
src/libcore/future/future_obj.rs
src/libcore/intrinsics.rs
src/libcore/iter/iterator.rs
src/libcore/iter/range.rs
src/libcore/lib.rs
src/libcore/macros.rs
src/libcore/marker.rs
src/libcore/mem.rs
src/libcore/num/mod.rs
src/libcore/ops/function.rs
src/libcore/option.rs
src/libcore/pin.rs [new file with mode: 0644]
src/libcore/ptr.rs
src/libcore/slice/memchr.rs
src/libcore/slice/mod.rs
src/libcore/slice/rotate.rs
src/libcore/slice/sort.rs
src/libcore/str/mod.rs
src/libcore/tests/lib.rs
src/libfmt_macros/lib.rs
src/libgraphviz/lib.rs
src/liblibc
src/libpanic_abort/lib.rs
src/libpanic_unwind/dwarf/mod.rs
src/libpanic_unwind/lib.rs
src/libpanic_unwind/seh.rs
src/libpanic_unwind/seh64_gnu.rs
src/libpanic_unwind/windows.rs
src/libproc_macro/lib.rs
src/libprofiler_builtins/lib.rs
src/librustc/Cargo.toml
src/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/graph.rs
src/librustc/hir/def.rs
src/librustc/hir/def_id.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/blocks.rs
src/librustc/hir/map/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/ich/hcx.rs
src/librustc/ich/impls_hir.rs
src/librustc/ich/impls_mir.rs
src/librustc/ich/impls_syntax.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/anon_types/mod.rs
src/librustc/infer/canonical/canonicalizer.rs
src/librustc/infer/canonical/mod.rs
src/librustc/infer/canonical/query_result.rs
src/librustc/infer/canonical/substitute.rs
src/librustc/infer/combine.rs
src/librustc/infer/equate.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/error_reporting/need_type_info.rs
src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs
src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs
src/librustc/infer/error_reporting/nice_region_error/util.rs
src/librustc/infer/freshen.rs
src/librustc/infer/fudge.rs
src/librustc/infer/higher_ranked/mod.rs
src/librustc/infer/lattice.rs
src/librustc/infer/mod.rs
src/librustc/infer/outlives/obligations.rs
src/librustc/infer/resolve.rs
src/librustc/infer/sub.rs
src/librustc/infer/type_variable.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/lint/context.rs
src/librustc/lint/levels.rs
src/librustc/lint/mod.rs
src/librustc/middle/cstore.rs
src/librustc/middle/dead.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/intrinsicck.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/lib_features.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/privacy.rs
src/librustc/middle/reachable.rs
src/librustc/middle/region.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc/middle/weak_lang_items.rs
src/librustc/mir/interpret/error.rs
src/librustc/mir/interpret/mod.rs
src/librustc/mir/interpret/value.rs
src/librustc/mir/mod.rs
src/librustc/mir/tcx.rs
src/librustc/mir/traversal.rs
src/librustc/mir/visit.rs
src/librustc/session/config.rs
src/librustc/session/filesearch.rs
src/librustc/session/mod.rs
src/librustc/traits/auto_trait.rs
src/librustc/traits/coherence.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/fulfill.rs
src/librustc/traits/mod.rs
src/librustc/traits/object_safety.rs
src/librustc/traits/project.rs
src/librustc/traits/query/dropck_outlives.rs
src/librustc/traits/query/evaluate_obligation.rs
src/librustc/traits/query/normalize.rs
src/librustc/traits/query/outlives_bounds.rs
src/librustc/traits/query/type_op/custom.rs
src/librustc/traits/query/type_op/implied_outlives_bounds.rs [new file with mode: 0644]
src/librustc/traits/query/type_op/mod.rs
src/librustc/traits/select.rs
src/librustc/traits/specialize/mod.rs
src/librustc/traits/structural_impls.rs
src/librustc/ty/_match.rs
src/librustc/ty/cast.rs
src/librustc/ty/codec.rs
src/librustc/ty/context.rs
src/librustc/ty/error.rs
src/librustc/ty/fast_reject.rs
src/librustc/ty/flags.rs
src/librustc/ty/fold.rs
src/librustc/ty/inhabitedness/def_id_forest.rs
src/librustc/ty/inhabitedness/mod.rs
src/librustc/ty/instance.rs
src/librustc/ty/item_path.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/outlives.rs
src/librustc/ty/query/config.rs
src/librustc/ty/query/job.rs
src/librustc/ty/query/mod.rs
src/librustc/ty/query/plumbing.rs
src/librustc/ty/relate.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc/ty/subst.rs
src/librustc/ty/util.rs
src/librustc/ty/walk.rs
src/librustc/ty/wf.rs
src/librustc/util/common.rs
src/librustc/util/ppaux.rs
src/librustc/util/profiling.rs
src/librustc/util/time_graph.rs
src/librustc_allocator/Cargo.toml
src/librustc_allocator/expand.rs
src/librustc_allocator/lib.rs
src/librustc_apfloat/lib.rs
src/librustc_asan/lib.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
src/librustc_borrowck/borrowck/gather_loans/move_error.rs
src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/borrowck/move_data.rs
src/librustc_borrowck/borrowck/unused.rs
src/librustc_borrowck/dataflow.rs
src/librustc_borrowck/graphviz.rs
src/librustc_borrowck/lib.rs
src/librustc_codegen_llvm/abi.rs
src/librustc_codegen_llvm/attributes.rs
src/librustc_codegen_llvm/back/link.rs
src/librustc_codegen_llvm/back/linker.rs
src/librustc_codegen_llvm/back/rpath.rs
src/librustc_codegen_llvm/back/symbol_export.rs
src/librustc_codegen_llvm/back/write.rs
src/librustc_codegen_llvm/base.rs
src/librustc_codegen_llvm/common.rs
src/librustc_codegen_llvm/consts.rs
src/librustc_codegen_llvm/context.rs
src/librustc_codegen_llvm/debuginfo/metadata.rs
src/librustc_codegen_llvm/debuginfo/mod.rs
src/librustc_codegen_llvm/debuginfo/type_names.rs
src/librustc_codegen_llvm/glue.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/lib.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/librustc_codegen_llvm/llvm_util.rs
src/librustc_codegen_llvm/mir/analyze.rs
src/librustc_codegen_llvm/mir/block.rs
src/librustc_codegen_llvm/mir/constant.rs
src/librustc_codegen_llvm/mir/mod.rs
src/librustc_codegen_llvm/mir/operand.rs
src/librustc_codegen_llvm/mir/place.rs
src/librustc_codegen_llvm/mir/rvalue.rs
src/librustc_codegen_llvm/type_of.rs
src/librustc_codegen_utils/codegen_backend.rs
src/librustc_codegen_utils/lib.rs
src/librustc_codegen_utils/link.rs
src/librustc_codegen_utils/symbol_names.rs
src/librustc_cratesio_shim/src/lib.rs
src/librustc_data_structures/Cargo.toml
src/librustc_data_structures/accumulate_vec.rs [deleted file]
src/librustc_data_structures/array_vec.rs
src/librustc_data_structures/bitvec.rs
src/librustc_data_structures/flock.rs
src/librustc_data_structures/graph/dominators/mod.rs
src/librustc_data_structures/graph/test.rs
src/librustc_data_structures/indexed_set.rs
src/librustc_data_structures/lib.rs
src/librustc_data_structures/small_c_str.rs
src/librustc_data_structures/small_vec.rs
src/librustc_data_structures/stable_hasher.rs
src/librustc_data_structures/sync.rs
src/librustc_data_structures/vec_linked_list.rs [new file with mode: 0644]
src/librustc_data_structures/work_queue.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_driver/profile/trace.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_errors/lock.rs
src/librustc_errors/registry.rs
src/librustc_incremental/lib.rs
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_lint/bad_style.rs [deleted file]
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_lint/nonstandard_style.rs [new file with mode: 0644]
src/librustc_lint/types.rs
src/librustc_lint/unused.rs
src/librustc_llvm/lib.rs
src/librustc_lsan/lib.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/lib.rs
src/librustc_metadata/locator.rs
src/librustc_metadata/native_libs.rs
src/librustc_mir/Cargo.toml
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/borrow_check/flows.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/move_errors.rs
src/librustc_mir/borrow_check/mutability_errors.rs
src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs
src/librustc_mir/borrow_check/nll/invalidation.rs
src/librustc_mir/borrow_check/nll/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/values.rs
src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs
src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs [new file with mode: 0644]
src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs [new file with mode: 0644]
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
src/librustc_mir/borrow_check/nll/universal_regions.rs
src/librustc_mir/borrow_check/place_ext.rs
src/librustc_mir/borrow_check/places_conflict.rs
src/librustc_mir/borrow_check/prefixes.rs
src/librustc_mir/build/expr/as_constant.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/build/expr/into.rs
src/librustc_mir/build/matches/test.rs
src/librustc_mir/build/misc.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/const_eval.rs [new file with mode: 0644]
src/librustc_mir/dataflow/at_location.rs
src/librustc_mir/dataflow/drop_flag_effects.rs
src/librustc_mir/dataflow/impls/mod.rs
src/librustc_mir/dataflow/mod.rs
src/librustc_mir/dataflow/move_paths/builder.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/mod.rs
src/librustc_mir/hair/pattern/_match.rs
src/librustc_mir/hair/pattern/check_match.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/interpret/cast.rs
src/librustc_mir/interpret/const_eval.rs [deleted file]
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/intrinsics.rs [new file with mode: 0644]
src/librustc_mir/interpret/machine.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/mod.rs
src/librustc_mir/interpret/operand.rs [new file with mode: 0644]
src/librustc_mir/interpret/operator.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/step.rs
src/librustc_mir/interpret/terminator.rs [new file with mode: 0644]
src/librustc_mir/interpret/terminator/drop.rs [deleted file]
src/librustc_mir/interpret/terminator/mod.rs [deleted file]
src/librustc_mir/interpret/traits.rs
src/librustc_mir/interpret/validity.rs [new file with mode: 0644]
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/item.rs
src/librustc_mir/monomorphize/partitioning.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/add_validation.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/deaggregator.rs
src/librustc_mir/transform/elaborate_drops.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/instcombine.rs
src/librustc_mir/transform/lower_128bit.rs
src/librustc_mir/transform/mod.rs
src/librustc_mir/transform/promote_consts.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/qualify_min_const_fn.rs [new file with mode: 0644]
src/librustc_mir/transform/rustc_peek.rs
src/librustc_mir/transform/uniform_array_move_out.rs
src/librustc_mir/util/alignment.rs
src/librustc_mir/util/borrowck_errors.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_mir/util/liveness.rs
src/librustc_mir/util/pretty.rs
src/librustc_msan/lib.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/lib.rs
src/librustc_passes/loops.rs
src/librustc_passes/rvalue_promotion.rs
src/librustc_platform_intrinsics/lib.rs
src/librustc_plugin/lib.rs
src/librustc_plugin/registry.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/Cargo.toml
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/lib.rs
src/librustc_target/lib.rs
src/librustc_target/spec/aarch64_apple_ios.rs
src/librustc_target/spec/aarch64_fuchsia.rs
src/librustc_target/spec/aarch64_linux_android.rs
src/librustc_target/spec/aarch64_unknown_cloudabi.rs
src/librustc_target/spec/aarch64_unknown_freebsd.rs
src/librustc_target/spec/aarch64_unknown_hermit.rs
src/librustc_target/spec/aarch64_unknown_netbsd.rs
src/librustc_target/spec/aarch64_unknown_none.rs
src/librustc_target/spec/aarch64_unknown_openbsd.rs
src/librustc_target/spec/arm_linux_androideabi.rs
src/librustc_target/spec/armebv7r_none_eabi.rs [new file with mode: 0644]
src/librustc_target/spec/armebv7r_none_eabihf.rs
src/librustc_target/spec/armv7_apple_ios.rs
src/librustc_target/spec/armv7_linux_androideabi.rs
src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs
src/librustc_target/spec/armv7r_none_eabi.rs [new file with mode: 0644]
src/librustc_target/spec/armv7r_none_eabihf.rs [new file with mode: 0644]
src/librustc_target/spec/armv7s_apple_ios.rs
src/librustc_target/spec/asmjs_unknown_emscripten.rs
src/librustc_target/spec/i386_apple_ios.rs
src/librustc_target/spec/i686_apple_darwin.rs
src/librustc_target/spec/i686_linux_android.rs
src/librustc_target/spec/i686_unknown_cloudabi.rs
src/librustc_target/spec/i686_unknown_dragonfly.rs
src/librustc_target/spec/i686_unknown_freebsd.rs
src/librustc_target/spec/i686_unknown_haiku.rs
src/librustc_target/spec/i686_unknown_netbsd.rs
src/librustc_target/spec/i686_unknown_openbsd.rs
src/librustc_target/spec/mod.rs
src/librustc_target/spec/msp430_none_elf.rs
src/librustc_target/spec/powerpc_unknown_netbsd.rs
src/librustc_target/spec/riscv32imac_unknown_none_elf.rs
src/librustc_target/spec/riscv32imc_unknown_none_elf.rs [new file with mode: 0644]
src/librustc_target/spec/riscv_base.rs [new file with mode: 0644]
src/librustc_target/spec/sparc64_unknown_netbsd.rs
src/librustc_target/spec/sparcv9_sun_solaris.rs
src/librustc_target/spec/thumb_base.rs
src/librustc_target/spec/thumbv6m_none_eabi.rs
src/librustc_target/spec/thumbv7em_none_eabi.rs
src/librustc_target/spec/thumbv7em_none_eabihf.rs
src/librustc_target/spec/thumbv7m_none_eabi.rs
src/librustc_target/spec/wasm32_experimental_emscripten.rs
src/librustc_target/spec/wasm32_unknown_emscripten.rs
src/librustc_target/spec/wasm32_unknown_unknown.rs
src/librustc_target/spec/windows_base.rs
src/librustc_target/spec/windows_msvc_base.rs
src/librustc_target/spec/x86_64_apple_darwin.rs
src/librustc_target/spec/x86_64_apple_ios.rs
src/librustc_target/spec/x86_64_fuchsia.rs
src/librustc_target/spec/x86_64_linux_android.rs
src/librustc_target/spec/x86_64_rumprun_netbsd.rs
src/librustc_target/spec/x86_64_sun_solaris.rs
src/librustc_target/spec/x86_64_unknown_bitrig.rs
src/librustc_target/spec/x86_64_unknown_cloudabi.rs
src/librustc_target/spec/x86_64_unknown_dragonfly.rs
src/librustc_target/spec/x86_64_unknown_freebsd.rs
src/librustc_target/spec/x86_64_unknown_haiku.rs
src/librustc_target/spec/x86_64_unknown_hermit.rs
src/librustc_target/spec/x86_64_unknown_netbsd.rs
src/librustc_target/spec/x86_64_unknown_openbsd.rs
src/librustc_target/spec/x86_64_unknown_redox.rs
src/librustc_traits/Cargo.toml
src/librustc_traits/chalk_context.rs
src/librustc_traits/dropck_outlives.rs
src/librustc_traits/lib.rs
src/librustc_traits/lowering.rs
src/librustc_tsan/lib.rs
src/librustc_typeck/Cargo.toml
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/autoderef.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/generator_interior.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/confirm.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/op.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/builtin.rs
src/librustc_typeck/coherence/inherent_impls.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/orphan.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/constrained_type_params.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/impl_wf_check.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/outlives/implicit_infer.rs
src/librustc_typeck/outlives/mod.rs
src/librustc_typeck/structured_errors.rs
src/librustc_typeck/variance/constraints.rs
src/librustc_typeck/variance/mod.rs
src/librustc_typeck/variance/solve.rs
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/blanket_impl.rs
src/librustdoc/clean/cfg.rs
src/librustdoc/clean/def_ctor.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/format.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/themes/dark.css
src/librustdoc/html/static/themes/light.css
src/librustdoc/lib.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/theme.rs
src/librustdoc/visit_ast.rs
src/libserialize/Cargo.toml
src/libserialize/collection_impls.rs
src/libserialize/leb128.rs
src/libserialize/lib.rs
src/libserialize/opaque.rs
src/libserialize/serialize.rs
src/libstd/alloc.rs
src/libstd/collections/hash/table.rs
src/libstd/error.rs
src/libstd/future.rs
src/libstd/io/buffered.rs
src/libstd/io/lazy.rs
src/libstd/io/stdio.rs
src/libstd/keyword_docs.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/memchr.rs
src/libstd/net/ip.rs
src/libstd/os/mod.rs
src/libstd/panic.rs
src/libstd/panicking.rs
src/libstd/process.rs
src/libstd/sync/once.rs
src/libstd/sys/cloudabi/condvar.rs
src/libstd/sys/cloudabi/rwlock.rs
src/libstd/sys/mod.rs
src/libstd/sys/redox/mod.rs
src/libstd/sys/unix/fd.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/net.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/wasm/net.rs
src/libstd/sys/windows/backtrace/mod.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/mod.rs
src/libstd/sys/windows/mutex.rs
src/libstd/sys/windows/os.rs
src/libstd/sys/windows/pipe.rs
src/libstd/sys_common/wtf8.rs
src/libstd/thread/mod.rs
src/libsyntax/Cargo.toml
src/libsyntax/ast.rs
src/libsyntax/attr/builtin.rs
src/libsyntax/attr/mod.rs
src/libsyntax/diagnostic_list.rs
src/libsyntax/diagnostics/plugin.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/derive.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/placeholders.rs
src/libsyntax/ext/source_util.rs
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/ext/tt/quoted.rs
src/libsyntax/ext/tt/transcribe.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/lib.rs
src/libsyntax/parse/classify.rs
src/libsyntax/parse/lexer/comments.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/lexer/unicode_chars.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/source_map.rs
src/libsyntax/test.rs
src/libsyntax/util/parser.rs
src/libsyntax/visit.rs
src/libsyntax_ext/Cargo.toml
src/libsyntax_ext/format.rs
src/libsyntax_ext/global_asm.rs
src/libsyntax_ext/lib.rs
src/libsyntax_pos/hygiene.rs
src/libsyntax_pos/lib.rs
src/libsyntax_pos/symbol.rs
src/libterm/lib.rs
src/libtest/formatters/json.rs
src/libtest/formatters/terse.rs
src/libtest/lib.rs
src/libunwind/lib.rs
src/libunwind/libunwind.rs
src/llvm
src/rustllvm/PassWrapper.cpp
src/rustllvm/llvm-rebuild-trigger
src/test/codegen-units/item-collection/cross-crate-trait-method.rs
src/test/codegen-units/item-collection/unreferenced-const-fn.rs
src/test/codegen/function-arguments.rs
src/test/codegen/link-dead-code.rs
src/test/compile-fail-fulldeps/auxiliary/lint_for_crate.rs
src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs
src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs
src/test/compile-fail-fulldeps/auxiliary/pub_and_stability.rs
src/test/compile-fail-fulldeps/proc-macro/auxiliary/more-gates.rs
src/test/compile-fail-fulldeps/proc-macro/more-gates.rs
src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs
src/test/compile-fail/auxiliary/some-panic-impl.rs
src/test/compile-fail/issue-43733-2.rs
src/test/compile-fail/panic-handler-missing.rs [new file with mode: 0644]
src/test/compile-fail/panic-handler-twice.rs [new file with mode: 0644]
src/test/compile-fail/panic-implementation-missing.rs [deleted file]
src/test/compile-fail/panic-implementation-twice.rs [deleted file]
src/test/compile-fail/weak-lang-item.rs
src/test/incremental-fulldeps/auxiliary/issue_49482_macro_def.rs [new file with mode: 0644]
src/test/incremental-fulldeps/auxiliary/issue_49482_reexport.rs [new file with mode: 0644]
src/test/incremental-fulldeps/issue-49482.rs [new file with mode: 0644]
src/test/mir-opt/lower_128bit_debug_test.rs
src/test/mir-opt/lower_128bit_test.rs
src/test/mir-opt/nll/named-lifetimes-basic.rs
src/test/parse-fail/do-catch-suggests-try.rs [new file with mode: 0644]
src/test/parse-fail/keyword-try-as-identifier-edition2018.rs [new file with mode: 0644]
src/test/pretty/attr-literals.rs
src/test/run-fail/issue-29798.rs
src/test/run-fail/run-unexported-tests.rs
src/test/run-make-fulldeps/hir-tree/Makefile
src/test/run-make-fulldeps/issue-51671/app.rs
src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs
src/test/run-make-fulldeps/rustdoc-error-lines/Makefile
src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile
src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile
src/test/run-make-fulldeps/target-cpu-native/Makefile
src/test/run-make-fulldeps/use-suggestions-rust-2018/Makefile [new file with mode: 0644]
src/test/run-make-fulldeps/use-suggestions-rust-2018/ep-nested-lib.rs [new file with mode: 0644]
src/test/run-make-fulldeps/use-suggestions-rust-2018/use-suggestions.rs [new file with mode: 0644]
src/test/run-make/wasm-symbols-not-exported/bar.rs
src/test/run-make/wasm-symbols-not-imported/Makefile [new file with mode: 0644]
src/test/run-make/wasm-symbols-not-imported/foo.rs [new file with mode: 0644]
src/test/run-make/wasm-symbols-not-imported/verify-no-imports.js [new file with mode: 0644]
src/test/run-pass-fulldeps/auxiliary/issue-16723.rs
src/test/run-pass-fulldeps/auxiliary/lint_for_crate.rs
src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs
src/test/run-pass-fulldeps/compiler-calls.rs
src/test/run-pass-fulldeps/macro-crate-multi-decorator-literals.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs
src/test/run-pass-fulldeps/proc-macro/derive-b.rs
src/test/run-pass-fulldeps/proc-macro/issue-42708.rs
src/test/run-pass-fulldeps/proc-macro/issue-50061.rs
src/test/run-pass/align-with-extern-c-fn.rs
src/test/run-pass/async-await.rs
src/test/run-pass/auxiliary/const_fn_lib.rs
src/test/run-pass/auxiliary/edition-kw-macro-2015.rs
src/test/run-pass/auxiliary/issue-36954.rs
src/test/run-pass/auxiliary/issue13507.rs
src/test/run-pass/catch-expr.rs [deleted file]
src/test/run-pass/command-before-exec.rs
src/test/run-pass/const-fn-const-eval.rs
src/test/run-pass/const-fn-method.rs
src/test/run-pass/const-fn-nested.rs
src/test/run-pass/const-meth-pattern.rs
src/test/run-pass/const-pattern-variant.rs
src/test/run-pass/const-size_of-align_of.rs
src/test/run-pass/const-unsafe-fn.rs
src/test/run-pass/consts-in-patterns.rs
src/test/run-pass/ctfe/ice-48279.rs
src/test/run-pass/ctfe/match-const-fn-structs.rs
src/test/run-pass/ctfe/promotion.rs
src/test/run-pass/ctfe/return-in-const-fn.rs
src/test/run-pass/ctfe/transmute-const.rs [new file with mode: 0644]
src/test/run-pass/dropck_legal_cycles.rs
src/test/run-pass/edition-keywords-2015-2015.rs
src/test/run-pass/edition-keywords-2015-2018.rs
src/test/run-pass/futures-api.rs
src/test/run-pass/ifmt.rs
src/test/run-pass/invalid_const_promotion.rs
src/test/run-pass/issue-15881-model-lexer-dotdotdot.rs
src/test/run-pass/issue-20616.rs
src/test/run-pass/issue-28822.rs
src/test/run-pass/issue-29927.rs
src/test/run-pass/issue-33537.rs
src/test/run-pass/issue-33903.rs
src/test/run-pass/issue-37991.rs
src/test/run-pass/issue-45124.rs
src/test/run-pass/issue-48006.rs [new file with mode: 0644]
src/test/run-pass/issue-48962.rs
src/test/run-pass/issue-50865-private-impl-trait/auxiliary/lib.rs [new file with mode: 0644]
src/test/run-pass/issue-50865-private-impl-trait/main.rs [new file with mode: 0644]
src/test/run-pass/issue-52705/auxiliary/png.rs [deleted file]
src/test/run-pass/issue-52705/auxiliary/png2.rs [new file with mode: 0644]
src/test/run-pass/issue-52705/main.rs
src/test/run-pass/issue29927-1.rs
src/test/run-pass/macro-first-set.rs
src/test/run-pass/macro-pub-matcher.rs
src/test/run-pass/match-range.rs
src/test/run-pass/match-reassign.rs
src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs
src/test/run-pass/packed-struct-optimized-enum.rs
src/test/run-pass/realloc-16687.rs
src/test/run-pass/rfc-2151-raw-identifiers/attr.rs
src/test/run-pass/rfc-2151-raw-identifiers/basic.rs
src/test/run-pass/rfc-2151-raw-identifiers/items.rs
src/test/run-pass/rfc-2151-raw-identifiers/macros.rs
src/test/run-pass/running-with-no-runtime.rs
src/test/run-pass/signal-alternate-stack-cleanup.rs
src/test/run-pass/simd-target-feature-mixup.rs
src/test/run-pass/tool_attributes.rs
src/test/run-pass/try-block.rs [new file with mode: 0644]
src/test/run-pass/try-from-int-error-partial-eq.rs [new file with mode: 0644]
src/test/run-pass/try-is-identifier-edition2015.rs [new file with mode: 0644]
src/test/run-pass/unboxed-closures-unique-type-id.rs
src/test/rustdoc-js/pinbox-new.js
src/test/rustdoc-js/substring.js [new file with mode: 0644]
src/test/rustdoc-js/vec-new.js
src/test/rustdoc/auxiliary/issue-27362.rs
src/test/rustdoc/blanket-reexport-item.rs [new file with mode: 0644]
src/test/rustdoc/const-fn.rs
src/test/rustdoc/const.rs
src/test/rustdoc/extern-html-root-url.rs [new file with mode: 0644]
src/test/rustdoc/impl-everywhere.rs [new file with mode: 0644]
src/test/rustdoc/inline_cross/auxiliary/macro-vis.rs
src/test/rustdoc/intra-links.rs
src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs
src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs
src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
src/test/ui-fulldeps/lint_tool_test.rs
src/test/ui-fulldeps/lint_tool_test.stderr
src/test/ui-fulldeps/proc-macro/generate-mod.rs
src/test/ui-fulldeps/proc-macro/generate-mod.stderr
src/test/ui-fulldeps/proc-macro/macro-namespace-reserved-2.stderr
src/test/ui/E0705.rs
src/test/ui/E0705.stderr
src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs
src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs
src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs
src/test/ui/anon-params-denied-2018.rs [new file with mode: 0644]
src/test/ui/anon-params-denied-2018.stderr [new file with mode: 0644]
src/test/ui/anon-params-deprecated.fixed [new file with mode: 0644]
src/test/ui/anon-params-deprecated.rs
src/test/ui/anon-params-deprecated.stderr
src/test/ui/associated-types/associated-types-incomplete-object.rs
src/test/ui/attr-usage-repr.rs
src/test/ui/attr-usage-repr.stderr
src/test/ui/bad/bad-mid-path-type-params.stderr
src/test/ui/bastion-of-the-turbofish.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-45983.rs
src/test/ui/borrowck/move-in-static-initializer-issue-38520.rs
src/test/ui/catch/catch-bad-lifetime.nll.stderr [deleted file]
src/test/ui/catch/catch-bad-lifetime.rs [deleted file]
src/test/ui/catch/catch-bad-lifetime.stderr [deleted file]
src/test/ui/catch/catch-bad-type.rs [deleted file]
src/test/ui/catch/catch-bad-type.stderr [deleted file]
src/test/ui/catch/catch-block-type-error.rs [deleted file]
src/test/ui/catch/catch-block-type-error.stderr [deleted file]
src/test/ui/catch/catch-in-match.rs [deleted file]
src/test/ui/catch/catch-in-match.stderr [deleted file]
src/test/ui/catch/catch-in-while.rs [deleted file]
src/test/ui/catch/catch-in-while.stderr [deleted file]
src/test/ui/catch/catch-maybe-bad-lifetime.nll.stderr [deleted file]
src/test/ui/catch/catch-maybe-bad-lifetime.rs [deleted file]
src/test/ui/catch/catch-maybe-bad-lifetime.stderr [deleted file]
src/test/ui/catch/catch-opt-init.nll.stderr [deleted file]
src/test/ui/catch/catch-opt-init.rs [deleted file]
src/test/ui/catch/catch-opt-init.stderr [deleted file]
src/test/ui/cfg-attr-unknown-attribute-macro-expansion.stderr
src/test/ui/chalkify/lower_trait.rs
src/test/ui/chalkify/lower_trait_higher_rank.rs
src/test/ui/chalkify/lower_trait_where_clause.rs
src/test/ui/closure-expected.rs [new file with mode: 0644]
src/test/ui/closure-expected.stderr [new file with mode: 0644]
src/test/ui/const-eval/issue-53157.rs [deleted file]
src/test/ui/constructor-lifetime-args.stderr
src/test/ui/consts/auxiliary/const_fn_lib.rs
src/test/ui/consts/const-eval/auxiliary/stability.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/const_panic.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/const_panic.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/const_panic_libcore.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/const_panic_libcore.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/const_panic_libcore_main.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/const_panic_libcore_main.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.nll.stderr
src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.rs
src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr
src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.nll.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/double_check2.stderr
src/test/ui/consts/const-eval/feature-gate-const_panic.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/feature-gate-const_panic.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/issue-43197.rs
src/test/ui/consts/const-eval/issue-47971.rs
src/test/ui/consts/const-eval/issue-53157.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/issue-53401.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/transmute-const-promotion.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/transmute-const-promotion.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/transmute-const.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/transmute-const.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/ub-enum-ptr.rs [deleted file]
src/test/ui/consts/const-eval/ub-enum-ptr.stderr [deleted file]
src/test/ui/consts/const-eval/ub-enum.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/ub-enum.stderr [new file with mode: 0644]
src/test/ui/consts/const-fn-not-safe-for-const.rs
src/test/ui/consts/const-fn-not-safe-for-const.stderr
src/test/ui/consts/const-pattern-not-const-evaluable.rs
src/test/ui/consts/const-size_of-cycle.rs
src/test/ui/consts/const-size_of-cycle.stderr
src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr [new file with mode: 0644]
src/test/ui/crate-in-paths.rs [new file with mode: 0644]
src/test/ui/crate-in-paths.stderr [new file with mode: 0644]
src/test/ui/custom-attribute-multisegment.rs
src/test/ui/custom_attribute.stderr
src/test/ui/defaulted-never-note.rs
src/test/ui/deref-suggestion.rs
src/test/ui/deref-suggestion.stderr
src/test/ui/editions/auxiliary/edition-kw-macro-2015.rs
src/test/ui/editions/auxiliary/edition-kw-macro-2018.rs
src/test/ui/editions/edition-keywords-2015-2015-expansion.rs
src/test/ui/editions/edition-keywords-2015-2015-parsing.rs
src/test/ui/editions/edition-keywords-2015-2015-parsing.stderr
src/test/ui/editions/edition-keywords-2015-2018-expansion.rs
src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr
src/test/ui/editions/edition-keywords-2015-2018-parsing.rs
src/test/ui/editions/edition-keywords-2015-2018-parsing.stderr
src/test/ui/editions/edition-keywords-2018-2015-expansion.rs
src/test/ui/enum/enum-discrim-autosizing.rs
src/test/ui/enum/enum-discrim-autosizing.stderr
src/test/ui/error-codes/E0087.rs [deleted file]
src/test/ui/error-codes/E0087.stderr [deleted file]
src/test/ui/error-codes/E0088.rs [deleted file]
src/test/ui/error-codes/E0088.stderr [deleted file]
src/test/ui/error-codes/E0089.rs [deleted file]
src/test/ui/error-codes/E0089.stderr [deleted file]
src/test/ui/error-codes/E0090.rs [deleted file]
src/test/ui/error-codes/E0090.stderr [deleted file]
src/test/ui/error-codes/E0243.rs [deleted file]
src/test/ui/error-codes/E0243.stderr [deleted file]
src/test/ui/error-codes/E0244.rs [deleted file]
src/test/ui/error-codes/E0244.stderr [deleted file]
src/test/ui/error-codes/E0308.stderr
src/test/ui/error-codes/E0401.stderr
src/test/ui/error-codes/E0565-1.rs
src/test/ui/error-codes/E0565-1.stderr
src/test/ui/error-codes/E0565.rs
src/test/ui/error-codes/E0565.stderr
src/test/ui/exhaustive_integer_patterns.rs [new file with mode: 0644]
src/test/ui/exhaustive_integer_patterns.stderr [new file with mode: 0644]
src/test/ui/existential_types/nested_existential_types.rs [new file with mode: 0644]
src/test/ui/existential_types/no_inferrable_concrete_type.stderr
src/test/ui/extern/extern-wrong-value-type.rs
src/test/ui/extern/extern-wrong-value-type.stderr
src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.rs [new file with mode: 0644]
src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.stderr [new file with mode: 0644]
src/test/ui/feature-gate-exhaustive_integer_patterns.rs [new file with mode: 0644]
src/test/ui/feature-gate-exhaustive_integer_patterns.stderr [new file with mode: 0644]
src/test/ui/feature-gate-rustc-attrs-1.rs [deleted file]
src/test/ui/feature-gate-rustc-attrs-1.stderr [deleted file]
src/test/ui/feature-gate-uniform-paths.rs [deleted file]
src/test/ui/feature-gate-uniform-paths.stderr [deleted file]
src/test/ui/feature-gate-unrestricted-attribute-tokens.rs [deleted file]
src/test/ui/feature-gate-unrestricted-attribute-tokens.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-catch_expr.rs [deleted file]
src/test/ui/feature-gates/feature-gate-catch_expr.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-const_fn.rs
src/test/ui/feature-gates/feature-gate-const_fn.stderr
src/test/ui/feature-gates/feature-gate-const_transmute.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-const_transmute.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-custom_attribute.rs
src/test/ui/feature-gates/feature-gate-custom_attribute.stderr
src/test/ui/feature-gates/feature-gate-custom_derive.stderr
src/test/ui/feature-gates/feature-gate-generic_associated_types.rs
src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr
src/test/ui/feature-gates/feature-gate-macro-vis-matcher.rs [deleted file]
src/test/ui/feature-gates/feature-gate-macro-vis-matcher.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-min_const_fn.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-min_const_fn.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-panic-handler.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-panic-handler.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-panic-implementation.rs
src/test/ui/feature-gates/feature-gate-panic-implementation.stderr
src/test/ui/feature-gates/feature-gate-raw-identifiers.rs [deleted file]
src/test/ui/feature-gates/feature-gate-raw-identifiers.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
src/test/ui/feature-gates/feature-gate-tool_attributes.rs [deleted file]
src/test/ui/feature-gates/feature-gate-tool_attributes.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-try_blocks.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-try_blocks.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-uniform-paths.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-uniform-paths.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-unrestricted-attribute-tokens.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-unrestricted-attribute-tokens.stderr [new file with mode: 0644]
src/test/ui/fn/fn-trait-formatting.rs
src/test/ui/fn/fn-trait-formatting.stderr
src/test/ui/future-incompatible-lint-group.stderr
src/test/ui/gated-attr-literals.rs [deleted file]
src/test/ui/gated-attr-literals.stderr [deleted file]
src/test/ui/gated-bad-feature.rs
src/test/ui/gated-bad-feature.stderr
src/test/ui/generic/generic-arg-mismatch-recover.stderr
src/test/ui/generic/generic-impl-less-params-with-defaults.stderr
src/test/ui/generic/generic-impl-more-params-with-defaults.stderr
src/test/ui/generic/generic-type-less-params-with-defaults.rs
src/test/ui/generic/generic-type-less-params-with-defaults.stderr
src/test/ui/generic/generic-type-more-params-with-defaults.rs
src/test/ui/generic/generic-type-more-params-with-defaults.stderr
src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr
src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr
src/test/ui/hygiene/expansion-info-reset.rs [new file with mode: 0644]
src/test/ui/hygiene/expansion-info-reset.stderr [new file with mode: 0644]
src/test/ui/hygiene/fields-move.nll.stderr
src/test/ui/hygiene/generate-mod.rs
src/test/ui/hygiene/generate-mod.stderr
src/test/ui/hygiene/no_implicit_prelude.rs
src/test/ui/hygiene/no_implicit_prelude.stderr
src/test/ui/impl-trait/impl-generic-mismatch.stderr
src/test/ui/impl-trait/where-allowed.rs
src/test/ui/imports/import-glob-circular.rs
src/test/ui/imports/import-glob-circular.stderr
src/test/ui/imports/import-loop-2.rs
src/test/ui/imports/import-loop-2.stderr
src/test/ui/imports/issue-53140.rs [new file with mode: 0644]
src/test/ui/imports/issue-53269.rs [new file with mode: 0644]
src/test/ui/imports/issue-53269.stderr [new file with mode: 0644]
src/test/ui/imports/issue-53512.rs [new file with mode: 0644]
src/test/ui/imports/issue-53512.stderr [new file with mode: 0644]
src/test/ui/imports/local-modularized-tricky-fail-2.rs
src/test/ui/imports/local-modularized-tricky-fail-3.rs
src/test/ui/imports/local-modularized-tricky-fail-3.stderr
src/test/ui/imports/macros.stderr
src/test/ui/imports/shadow_builtin_macros.rs
src/test/ui/imports/shadow_builtin_macros.stderr
src/test/ui/infinite/infinite-recursion-const-fn.rs
src/test/ui/invalid_crate_type_syntax.rs
src/test/ui/invalid_crate_type_syntax.stderr
src/test/ui/issue-52992.rs [new file with mode: 0644]
src/test/ui/issue-53251.stderr
src/test/ui/issue-53300.rs [new file with mode: 0644]
src/test/ui/issue-53300.stderr [new file with mode: 0644]
src/test/ui/issue-53419.rs [new file with mode: 0644]
src/test/ui/issue-53568.rs [new file with mode: 0644]
src/test/ui/issues/issue-14092.rs
src/test/ui/issues/issue-14092.stderr
src/test/ui/issues/issue-17718-const-bad-values.rs
src/test/ui/issues/issue-17718-const-bad-values.stderr
src/test/ui/issues/issue-22034.rs
src/test/ui/issues/issue-22034.stderr
src/test/ui/issues/issue-23024.rs
src/test/ui/issues/issue-23024.stderr
src/test/ui/issues/issue-23966.stderr
src/test/ui/issues/issue-31845.rs
src/test/ui/issues/issue-3214.stderr
src/test/ui/issues/issue-32655.stderr
src/test/ui/issues/issue-32829.rs
src/test/ui/issues/issue-32829.stderr
src/test/ui/issues/issue-38715.rs
src/test/ui/issues/issue-38715.stderr
src/test/ui/issues/issue-42755.rs
src/test/ui/issues/issue-42755.stderr
src/test/ui/issues/issue-43784-associated-type.rs
src/test/ui/issues/issue-43784-associated-type.stderr
src/test/ui/issues/issue-43784-supertrait.rs
src/test/ui/issues/issue-43784-supertrait.stderr
src/test/ui/issues/issue-43925.rs
src/test/ui/issues/issue-43925.stderr
src/test/ui/issues/issue-44415.rs
src/test/ui/issues/issue-45696-no-variant-box-recur.rs
src/test/ui/issues/issue-46471-1.stderr
src/test/ui/issues/issue-49074.stderr
src/test/ui/issues/issue-50761.rs
src/test/ui/issues/issue-52060.rs [new file with mode: 0644]
src/test/ui/issues/issue-52060.stderr [new file with mode: 0644]
src/test/ui/label/label_break_value_illegal_uses.rs
src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs
src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.rs
src/test/ui/lint/lint-anon-param-edition.fixed [deleted file]
src/test/ui/lint/lint-anon-param-edition.rs [deleted file]
src/test/ui/lint/lint-anon-param-edition.stderr [deleted file]
src/test/ui/lint/lint-group-style.rs
src/test/ui/lint/lint-group-style.stderr
src/test/ui/lint/lint-shorthand-field.rs
src/test/ui/lint/lint-unused-extern-crate.rs
src/test/ui/lint/lints-in-foreign-macros.rs
src/test/ui/lint/lints-in-foreign-macros.stderr
src/test/ui/lint/outer-forbid.rs
src/test/ui/lint/outer-forbid.stderr
src/test/ui/lint/unreachable_pub-pub_crate.rs
src/test/ui/lint/unreachable_pub.rs
src/test/ui/macros/macro-reexport-removed.stderr
src/test/ui/macros/macro-use-bad-args-1.rs
src/test/ui/macros/macro-use-bad-args-1.stderr
src/test/ui/macros/macro-use-bad-args-2.rs
src/test/ui/macros/macro-use-bad-args-2.stderr
src/test/ui/match/match-ref-mut-invariance.nll.stderr
src/test/ui/match/match-ref-mut-let-invariance.nll.stderr
src/test/ui/methods/method-call-lifetime-args-fail.stderr
src/test/ui/missing/missing-alloc_error_handler.rs
src/test/ui/missing/missing-allocator.rs
src/test/ui/nested-ty-params.rs
src/test/ui/nested-ty-params.stderr
src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs
src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr
src/test/ui/nll/mir_check_cast_unsize.rs
src/test/ui/nll/mir_check_cast_unsize.stderr
src/test/ui/nll/user-annotations/adt-brace-enums.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/adt-brace-enums.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/adt-brace-structs.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/adt-brace-structs.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/adt-nullary-enums.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/adt-nullary-enums.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/adt-tuple-enums.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/adt-tuple-enums.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/adt-tuple-struct.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/adt-tuple-struct.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/dump-fn-method.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/dump-fn-method.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/fns.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/fns.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/method-call.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/method-call.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/method-ufcs-1.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/method-ufcs-1.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/method-ufcs-2.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/method-ufcs-2.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/method-ufcs-3.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/method-ufcs-3.stderr [new file with mode: 0644]
src/test/ui/object-lifetime/object-lifetime-default-elision.nll.stderr
src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr
src/test/ui/panic-handler/auxiliary/some-panic-impl.rs [new file with mode: 0644]
src/test/ui/panic-handler/panic-handler-bad-signature-1.rs [new file with mode: 0644]
src/test/ui/panic-handler/panic-handler-bad-signature-1.stderr [new file with mode: 0644]
src/test/ui/panic-handler/panic-handler-bad-signature-2.rs [new file with mode: 0644]
src/test/ui/panic-handler/panic-handler-bad-signature-2.stderr [new file with mode: 0644]
src/test/ui/panic-handler/panic-handler-bad-signature-3.rs [new file with mode: 0644]
src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr [new file with mode: 0644]
src/test/ui/panic-handler/panic-handler-bad-signature-4.rs [new file with mode: 0644]
src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr [new file with mode: 0644]
src/test/ui/panic-handler/panic-handler-duplicate.rs [new file with mode: 0644]
src/test/ui/panic-handler/panic-handler-duplicate.stderr [new file with mode: 0644]
src/test/ui/panic-handler/panic-handler-requires-panic-info.rs [new file with mode: 0644]
src/test/ui/panic-handler/panic-handler-requires-panic-info.stderr [new file with mode: 0644]
src/test/ui/panic-handler/panic-handler-std.rs [new file with mode: 0644]
src/test/ui/panic-handler/panic-handler-std.stderr [new file with mode: 0644]
src/test/ui/panic-implementation/auxiliary/some-panic-impl.rs [deleted file]
src/test/ui/panic-implementation/panic-implementation-bad-signature-1.rs [deleted file]
src/test/ui/panic-implementation/panic-implementation-bad-signature-1.stderr [deleted file]
src/test/ui/panic-implementation/panic-implementation-bad-signature-2.rs [deleted file]
src/test/ui/panic-implementation/panic-implementation-bad-signature-2.stderr [deleted file]
src/test/ui/panic-implementation/panic-implementation-bad-signature-3.rs [deleted file]
src/test/ui/panic-implementation/panic-implementation-bad-signature-3.stderr [deleted file]
src/test/ui/panic-implementation/panic-implementation-bad-signature-4.rs [deleted file]
src/test/ui/panic-implementation/panic-implementation-bad-signature-4.stderr [deleted file]
src/test/ui/panic-implementation/panic-implementation-deprecated.rs [new file with mode: 0644]
src/test/ui/panic-implementation/panic-implementation-deprecated.stderr [new file with mode: 0644]
src/test/ui/panic-implementation/panic-implementation-duplicate.rs [deleted file]
src/test/ui/panic-implementation/panic-implementation-duplicate.stderr [deleted file]
src/test/ui/panic-implementation/panic-implementation-requires-panic-info.rs [deleted file]
src/test/ui/panic-implementation/panic-implementation-requires-panic-info.stderr [deleted file]
src/test/ui/panic-implementation/panic-implementation-std.rs [deleted file]
src/test/ui/panic-implementation/panic-implementation-std.stderr [deleted file]
src/test/ui/panic_implementation-closures.rs
src/test/ui/parser/expected-comma-found-token.rs
src/test/ui/raw/raw-literal-keywords.rs
src/test/ui/raw/raw-literal-keywords.stderr
src/test/ui/raw/raw-literal-self.rs
src/test/ui/raw/raw-literal-self.stderr
src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
src/test/ui/regions/regions-close-object-into-object-2.nll.stderr
src/test/ui/regions/regions-close-object-into-object-4.nll.stderr
src/test/ui/regions/regions-proc-bound-capture.nll.stderr
src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.nll.stderr
src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.nll.stderr
src/test/ui/regions/regions-trait-object-subtyping.nll.stderr
src/test/ui/repr/repr-transparent-other-items.rs
src/test/ui/repr/repr-transparent-other-items.stderr
src/test/ui/repr/repr-transparent-other-reprs.rs
src/test/ui/repr/repr-transparent-other-reprs.stderr
src/test/ui/repr/repr-transparent.rs
src/test/ui/repr/repr-transparent.stderr
src/test/ui/reserved/reserved-attr-on-macro.stderr
src/test/ui/resolve/resolve-unknown-trait.rs
src/test/ui/resolve/resolve-unknown-trait.stderr
src/test/ui/resolve_self_super_hint.rs
src/test/ui/resolve_self_super_hint.stderr
src/test/ui/rfc-2166-underscore-imports/basic.rs
src/test/ui/rfc-2166-underscore-imports/basic.stderr
src/test/ui/rfc1598-generic-associated-types/shadowing.rs
src/test/ui/rust-2018/async-ident-allowed.rs
src/test/ui/rust-2018/async-ident-allowed.stderr
src/test/ui/rust-2018/async-ident.fixed
src/test/ui/rust-2018/async-ident.rs
src/test/ui/rust-2018/async-ident.stderr
src/test/ui/rust-2018/auxiliary/remove-extern-crate.rs [new file with mode: 0644]
src/test/ui/rust-2018/remove-extern-crate.fixed [new file with mode: 0644]
src/test/ui/rust-2018/remove-extern-crate.rs [new file with mode: 0644]
src/test/ui/rust-2018/remove-extern-crate.stderr [new file with mode: 0644]
src/test/ui/rust-2018/try-ident.fixed [new file with mode: 0644]
src/test/ui/rust-2018/try-ident.rs [new file with mode: 0644]
src/test/ui/rust-2018/try-ident.stderr [new file with mode: 0644]
src/test/ui/rustc-args-required-const.rs
src/test/ui/rustc-args-required-const2.rs
src/test/ui/seq-args.stderr
src/test/ui/single-use-lifetime/two-uses-in-fn-arguments.rs
src/test/ui/span/issue-36530.stderr
src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr
src/test/ui/specialization/defaultimpl/validation.rs
src/test/ui/specialization/defaultimpl/validation.stderr
src/test/ui/structs/structure-constructor-type-mismatch.stderr
src/test/ui/suffixed-literal-meta.rs
src/test/ui/suffixed-literal-meta.stderr
src/test/ui/tag-type-args.stderr
src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
src/test/ui/tool-attributes/tool-attributes-misplaced-2.rs
src/test/ui/tool-attributes/tool-attributes-misplaced-2.stderr
src/test/ui/tool-attributes/tool-attributes-shadowing.rs
src/test/ui/tool-attributes/tool-attributes-shadowing.stderr
src/test/ui/traits/trait-object-vs-lifetime.stderr
src/test/ui/traits/trait-test-2.stderr
src/test/ui/try-block/try-block-bad-lifetime.rs [new file with mode: 0644]
src/test/ui/try-block/try-block-bad-lifetime.stderr [new file with mode: 0644]
src/test/ui/try-block/try-block-bad-type.rs [new file with mode: 0644]
src/test/ui/try-block/try-block-bad-type.stderr [new file with mode: 0644]
src/test/ui/try-block/try-block-in-edition2015.rs [new file with mode: 0644]
src/test/ui/try-block/try-block-in-edition2015.stderr [new file with mode: 0644]
src/test/ui/try-block/try-block-in-match.rs [new file with mode: 0644]
src/test/ui/try-block/try-block-in-match.stderr [new file with mode: 0644]
src/test/ui/try-block/try-block-in-while.rs [new file with mode: 0644]
src/test/ui/try-block/try-block-in-while.stderr [new file with mode: 0644]
src/test/ui/try-block/try-block-maybe-bad-lifetime.rs [new file with mode: 0644]
src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr [new file with mode: 0644]
src/test/ui/try-block/try-block-opt-init.rs [new file with mode: 0644]
src/test/ui/try-block/try-block-opt-init.stderr [new file with mode: 0644]
src/test/ui/try-block/try-block-type-error.rs [new file with mode: 0644]
src/test/ui/try-block/try-block-type-error.stderr [new file with mode: 0644]
src/test/ui/tuple/tuple-struct-fields/test.rs
src/test/ui/tuple/tuple-struct-fields/test.stderr
src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs
src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr
src/test/ui/typeck/typeck_type_placeholder_lifetime_1.rs
src/test/ui/typeck/typeck_type_placeholder_lifetime_1.stderr
src/test/ui/typeck/typeck_type_placeholder_lifetime_2.rs
src/test/ui/typeck/typeck_type_placeholder_lifetime_2.stderr
src/test/ui/ufcs/ufcs-qpath-missing-params.stderr
src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr
src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs
src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr
src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr
src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr
src/test/ui/union-ub-fat-ptr.rs
src/test/ui/union-ub-fat-ptr.stderr
src/test/ui/unknown-tool-name.rs
src/test/ui/unknown-tool-name.stderr
src/test/ui/unresolved/unresolved-import.rs
src/test/ui/unresolved/unresolved-import.stderr
src/test/ui/unsafe/unsafe-const-fn.rs
src/test/ui/user-defined-macro-rules.rs
src/test/ui/user-defined-macro-rules.stderr
src/test/ui/variadic/variadic-ffi-2.rs
src/test/ui/variadic/variadic-ffi.rs
src/test/ui/wasm-custom-section-relocations.rs
src/test/ui/wasm-custom-section-relocations.stderr
src/test/ui/where-clauses/where-for-self-2.rs
src/tools/build-manifest/README.md [new file with mode: 0644]
src/tools/build-manifest/src/main.rs
src/tools/cargo
src/tools/clippy
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/runtest.rs
src/tools/lld
src/tools/rls
src/tools/rustc-workspace-hack/Cargo.toml
src/tools/tidy/src/deps.rs
src/tools/tidy/src/features.rs
src/tools/tidy/src/lib.rs
src/tools/tidy/src/style.rs

index 9ffaa82e1c8b5dace88ca77f19aa55047dc4f7cc..e18acfd98e241b14cf69e554406705d83f7e569d 100644 (file)
@@ -1,49 +1,3 @@
-*.a
-*.aux
-*.bc
-*.boot
-*.bz2
-*.cmi
-*.cmo
-*.cmx
-*.cp
-*.cps
-*.d
-*.dSYM
-*.def
-*.diff
-*.dll
-*.dylib
-*.elc
-*.epub
-*.exe
-*.fn
-*.html
-*.kdev4
-*.ky
-*.ll
-*.llvm
-*.log
-*.o
-*.orig
-*.out
-*.patch
-*.pdb
-*.pdf
-*.pg
-*.pot
-*.pyc
-*.rej
-*.rlib
-*.rustc
-*.so
-*.swo
-*.swp
-*.tmp
-*.toc
-*.tp
-*.vr
-*.x86
 *~
 .#*
 .DS_Store
index b1701e4a65451aa82205f0c1af1211ef3e007ae2..4a7c8f4b7cf41ff835111109689578aaedb56e21 100644 (file)
@@ -30,7 +30,7 @@ matrix:
 
     - env: >
         RUST_CHECK_TARGET=dist
-        RUST_CONFIGURE_ARGS="--enable-extended --enable-profiler --enable-lldb"
+        RUST_CONFIGURE_ARGS="--enable-extended --enable-profiler"
         SRC=.
         DEPLOY_ALT=1
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
@@ -87,7 +87,7 @@ matrix:
     # OSX 10.7 and `xcode7` is the latest Xcode able to compile LLVM for 10.7.
     - env: >
         RUST_CHECK_TARGET=dist
-        RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb"
+        RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-full-tools --enable-profiler"
         SRC=.
         DEPLOY=1
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
@@ -101,7 +101,7 @@ matrix:
 
     - env: >
         RUST_CHECK_TARGET=dist
-        RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --enable-lldb"
+        RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler"
         SRC=.
         DEPLOY=1
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
index ea9f2c194300507798ef377ea2f821035d82a5d1..21b14d011f91182d815acb4f610dff1a5f0b5a1c 100644 (file)
@@ -405,7 +405,8 @@ before the PR is merged.
 [breaking-tools-built-with-the-compiler]: #breaking-tools-built-with-the-compiler
 
 Rust's build system builds a number of tools that make use of the
-internals of the compiler. This includes clippy,
+internals of the compiler. This includes 
+[Clippy](https://github.com/rust-lang-nursery/rust-clippy),
 [RLS](https://github.com/rust-lang-nursery/rls) and
 [rustfmt](https://github.com/rust-lang-nursery/rustfmt). If these tools
 break because of your changes, you may run into a sort of "chicken and egg"
index 1f7ffb53d3cadcfcb6811da4cafcc7583b5c276a..7e727e0d41bb3546a6aad39c6052a4c92003627e 100644 (file)
@@ -1,3 +1,81 @@
+Version 1.29.0 (2018-09-13)
+==========================
+
+Compiler
+--------
+- [Bumped minimum LLVM version to 5.0.][51899]
+- [Added `powerpc64le-unknown-linux-musl` target.][51619]
+- [Added `aarch64-unknown-hermit` and `x86_64-unknown-hermit` targets.][52861]
+
+Libraries
+---------
+- [`Once::call_once` now no longer requires `Once` to be `'static`.][52239]
+- [`BuildHasherDefault` now implements `PartialEq` and `Eq`.][52402]
+- [`Box<CStr>`, `Box<OsStr>`, and `Box<Path>` now implement `Clone`.][51912]
+- [Implemented `PartialEq<&str>` for `OsString` and `PartialEq<OsString>`
+  for `&str`.][51178]
+- [`Cell<T>` now allows `T` to be unsized.][50494]
+- [`SocketAddr` is now stable on Redox.][52656]
+
+Stabilized APIs
+---------------
+- [`Arc::downcast`]
+- [`Iterator::flatten`]
+- [`Rc::downcast`]
+
+Cargo
+-----
+- [Cargo can silently fix some bad lockfiles ][cargo/5831] You can use
+  `--locked` to disable this behaviour.
+- [`cargo-install` will now allow you to cross compile an install
+  using `--target`][cargo/5614]
+- [Added the `cargo-fix` subcommand to automatically move project code from
+  2015 edition to 2018.][cargo/5723]
+
+Misc
+----
+- [`rustdoc` now has the `--cap-lints` option which demotes all lints above
+  the specified level to that level.][52354] For example `--cap-lints warn`
+  will demote `deny` and `forbid` lints to `warn`.
+- [`rustc` and `rustdoc` will now have the exit code of `1` if compilation
+  fails, and `101` if there is a panic.][52197]
+- [A preview of clippy has been made available through rustup.][51122]
+  You can install the preview with `rustup component add clippy-preview`
+
+Compatibility Notes
+-------------------
+- [`str::{slice_unchecked, slice_unchecked_mut}` are now deprecated.][51807]
+  Use `str::get_unchecked(begin..end)` instead.
+- [`std::env::home_dir` is now deprecated for its unintuitive behaviour.][51656]
+  Consider using the `home_dir` function from
+  https://crates.io/crates/dirs instead.
+- [`rustc` will no longer silently ignore invalid data in target spec.][52330]
+
+[52861]: https://github.com/rust-lang/rust/pull/52861/
+[52656]: https://github.com/rust-lang/rust/pull/52656/
+[52239]: https://github.com/rust-lang/rust/pull/52239/
+[52330]: https://github.com/rust-lang/rust/pull/52330/
+[52354]: https://github.com/rust-lang/rust/pull/52354/
+[52402]: https://github.com/rust-lang/rust/pull/52402/
+[52103]: https://github.com/rust-lang/rust/pull/52103/
+[52197]: https://github.com/rust-lang/rust/pull/52197/
+[51807]: https://github.com/rust-lang/rust/pull/51807/
+[51899]: https://github.com/rust-lang/rust/pull/51899/
+[51912]: https://github.com/rust-lang/rust/pull/51912/
+[51511]: https://github.com/rust-lang/rust/pull/51511/
+[51619]: https://github.com/rust-lang/rust/pull/51619/
+[51656]: https://github.com/rust-lang/rust/pull/51656/
+[51178]: https://github.com/rust-lang/rust/pull/51178/
+[51122]: https://github.com/rust-lang/rust/pull/51122
+[50494]: https://github.com/rust-lang/rust/pull/50494/
+[cargo/5614]: https://github.com/rust-lang/cargo/pull/5614/
+[cargo/5723]: https://github.com/rust-lang/cargo/pull/5723/
+[cargo/5831]: https://github.com/rust-lang/cargo/pull/5831/
+[`Arc::downcast`]: https://doc.rust-lang.org/std/sync/struct.Arc.html#method.downcast
+[`Iterator::flatten`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.flatten
+[`Rc::downcast`]: https://doc.rust-lang.org/std/rc/struct.Rc.html#method.downcast
+
+
 Version 1.28.0 (2018-08-02)
 ===========================
 
index 107375ac5cc3a3fa0ce254f11adde571d29d6e60..35f69cd05b607098028140e8edcb79000ae0c003 100644 (file)
 # Indicates whether the LLVM build is a Release or Debug build
 #optimize = true
 
+# Indicates whether LLVM should be built with ThinLTO. Note that this will
+# only succeed if you use clang, lld, llvm-ar, and llvm-ranlib in your C/C++
+# toolchain (see the `cc`, `cxx`, `linker`, `ar`, and `ranlib` options below).
+# More info at: https://clang.llvm.org/docs/ThinLTO.html#clang-bootstrap
+#thin-lto = false
+
 # Indicates whether an LLVM Release build should include debug info
 #release-debuginfo = false
 
 # Note: an absolute path should be used, otherwise LLVM build will break.
 #ar = "ar"
 
+# Ranlib to be used to assemble static libraries compiled from C/C++ code.
+# Note: an absolute path should be used, otherwise LLVM build will break.
+#ranlib = "ranlib"
+
 # Linker to be used to link Rust code. Note that the
 # default value is platform specific, and if not specified it may also depend on
 # what platform is crossing to what platform.
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644 (file)
index 0000000..f1b36f5
--- /dev/null
@@ -0,0 +1,46 @@
+*.a
+*.aux
+*.bc
+*.boot
+*.bz2
+*.cmi
+*.cmo
+*.cmx
+*.cp
+*.cps
+*.d
+*.dSYM
+*.def
+*.diff
+*.dll
+*.dylib
+*.elc
+*.epub
+*.exe
+*.fn
+*.html
+*.kdev4
+*.ky
+*.ll
+*.llvm
+*.log
+*.o
+*.orig
+*.out
+*.patch
+*.pdb
+*.pdf
+*.pg
+*.pot
+*.pyc
+*.rej
+*.rlib
+*.rustc
+*.so
+*.swo
+*.swp
+*.tmp
+*.toc
+*.tp
+*.vr
+*.x86
index 4e16e61aa0d398cb0f21cfd60a67a64af037403c..e4d9f6e23945e535d4df79dbb8461417c0ae9a49 100644 (file)
@@ -1,9 +1,9 @@
 [[package]]
 name = "aho-corasick"
-version = "0.6.6"
+version = "0.6.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -12,7 +12,7 @@ version = "0.0.0"
 dependencies = [
  "compiler_builtins 0.0.0",
  "core 0.0.0",
- "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -20,7 +20,7 @@ name = "alloc_jemalloc"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
  "libc 0.0.0",
@@ -42,9 +42,9 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -82,7 +82,7 @@ dependencies = [
  "environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -101,9 +101,9 @@ version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -112,7 +112,7 @@ name = "backtrace-sys"
 version = "0.1.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -123,7 +123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "bitflags"
-version = "1.0.3"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -131,8 +131,8 @@ name = "bootstrap"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -140,9 +140,9 @@ dependencies = [
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -156,8 +156,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "build-manifest"
 version = "0.1.0"
 dependencies = [
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -170,53 +170,6 @@ name = "byteorder"
 version = "1.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "cargo"
-version = "0.28.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "crates-io 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "git2-curl 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "home 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "ignore 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libgit2-sys 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "cargo"
 version = "0.30.0"
@@ -228,58 +181,47 @@ dependencies = [
  "crates-io 0.18.0",
  "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2-curl 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "home 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "ignore 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ignore 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "libgit2-sys 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "opener 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-workspace-hack 1.0.0",
  "rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "cargo_metadata"
-version = "0.5.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "cargo_metadata"
 version = "0.6.0"
@@ -287,9 +229,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -298,12 +240,12 @@ version = "0.1.0"
 
 [[package]]
 name = "cc"
-version = "1.0.18"
+version = "1.0.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cfg-if"
-version = "0.1.4"
+version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -340,7 +282,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -352,19 +294,17 @@ dependencies = [
 name = "clippy"
 version = "0.0.212"
 dependencies = [
- "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "clippy-mini-macro-test 0.2.0",
  "clippy_lints 0.0.212",
  "compiletest_rs 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-workspace-hack 1.0.0",
- "rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -375,17 +315,17 @@ version = "0.2.0"
 name = "clippy_lints"
 version = "0.0.212"
 dependencies = [
- "cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -396,15 +336,15 @@ name = "cloudabi"
 version = "0.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cmake"
-version = "0.1.31"
+version = "0.1.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -435,7 +375,7 @@ dependencies = [
 name = "compiler_builtins"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -444,18 +384,18 @@ name = "compiletest"
 version = "0.0.0"
 dependencies = [
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -468,12 +408,12 @@ dependencies = [
  "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -481,16 +421,7 @@ dependencies = [
 name = "core"
 version = "0.0.0"
 dependencies = [
- "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "core-foundation"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -502,41 +433,20 @@ dependencies = [
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "core-foundation-sys"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "core-foundation-sys"
 version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "crates-io"
-version = "0.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "crates-io"
 version = "0.18.0"
 dependencies = [
- "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -554,7 +464,7 @@ dependencies = [
  "crossbeam-utils 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -572,9 +482,9 @@ version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -586,9 +496,9 @@ version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "crossbeam-utils 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -598,7 +508,7 @@ name = "crossbeam-utils"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -624,10 +534,10 @@ dependencies = [
 
 [[package]]
 name = "curl"
-version = "0.4.13"
+version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "curl-sys 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -639,15 +549,15 @@ dependencies = [
 
 [[package]]
 name = "curl-sys"
-version = "0.4.7"
+version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -694,11 +604,6 @@ dependencies = [
  "core 0.0.0",
 ]
 
-[[package]]
-name = "dtoa"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "either"
 version = "1.5.0"
@@ -709,11 +614,11 @@ name = "elasticlunr-rs"
 version = "2.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "strum 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "strum_macros 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -723,19 +628,19 @@ name = "ena"
 version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "env_logger"
-version = "0.5.10"
+version = "0.5.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -780,9 +685,9 @@ name = "failure_derive"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -791,7 +696,7 @@ name = "filetime"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -803,7 +708,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "flate2"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -847,7 +752,6 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -855,7 +759,7 @@ name = "fuchsia-zircon"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -883,8 +787,8 @@ name = "fwdansi"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -897,10 +801,10 @@ name = "git2"
 version = "0.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "libgit2-sys 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -911,9 +815,9 @@ name = "git2-curl"
 version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -924,14 +828,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "globset"
-version = "0.4.0"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -943,14 +847,14 @@ name = "handlebars"
 version = "0.32.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -960,11 +864,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "home"
-version = "0.3.2"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "userenv-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -973,7 +876,7 @@ name = "html5ever"
 version = "0.22.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -994,7 +897,7 @@ name = "idna"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1006,18 +909,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "ignore"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "globset 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "globset 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1027,11 +930,11 @@ version = "0.0.0"
 dependencies = [
  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "xz2 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1070,10 +973,15 @@ version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "json"
+version = "0.11.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "jsonrpc-core"
 version = "8.0.1"
@@ -1081,9 +989,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1100,12 +1008,12 @@ name = "languageserver-types"
 version = "0.45.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1117,13 +1025,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "lazy_static"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "lazycell"
-version = "0.6.0"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "lazycell"
@@ -1148,38 +1054,38 @@ name = "libgit2-sys"
 version = "0.7.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl-sys 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libssh2-sys 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libssh2-sys 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "libssh2-sys"
-version = "0.2.8"
+version = "0.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "libz-sys"
-version = "1.0.18"
+version = "1.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1191,15 +1097,15 @@ name = "log"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "log"
-version = "0.4.3"
+version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1207,7 +1113,7 @@ name = "log_settings"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1215,10 +1121,10 @@ name = "lzma-sys"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1243,9 +1149,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1253,7 +1159,7 @@ dependencies = [
 
 [[package]]
 name = "matches"
-version = "0.1.7"
+version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1265,40 +1171,31 @@ dependencies = [
  "chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "elasticlunr-rs 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "handlebars 0.32.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "memchr"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "memmap"
-version = "0.6.2"
+version = "2.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1319,13 +1216,13 @@ name = "miniz-sys"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "miow"
-version = "0.3.1"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "socket2 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1340,10 +1237,10 @@ dependencies = [
  "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiletest_rs 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1365,9 +1262,9 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1396,15 +1293,25 @@ name = "open"
 version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "opener"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "openssl"
 version = "0.10.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1416,10 +1323,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "openssl-src"
-version = "110.0.6+1.1.0h"
+version = "110.0.7+1.1.0i"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1427,11 +1334,11 @@ name = "openssl-sys"
 version = "0.9.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-src 110.0.6+1.1.0h (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-src 110.0.7+1.1.0i (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1487,8 +1394,8 @@ version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1544,7 +1451,7 @@ version = "0.7.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1557,7 +1464,7 @@ dependencies = [
 
 [[package]]
 name = "pkg-config"
-version = "0.3.11"
+version = "0.3.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1566,7 +1473,7 @@ version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1594,7 +1501,7 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "0.4.8"
+version = "0.4.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1614,7 +1521,7 @@ dependencies = [
 name = "profiler_builtins"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
@@ -1653,10 +1560,10 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "0.6.3"
+version = "0.6.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1664,21 +1571,20 @@ name = "racer"
 version = "2.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "cargo 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive_more 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-ap-syntax 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rand"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1718,10 +1624,10 @@ version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1742,23 +1648,23 @@ name = "regex"
 version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "regex"
-version = "1.0.1"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1771,7 +1677,7 @@ dependencies = [
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.1"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1798,46 +1704,47 @@ name = "rls"
 version = "0.130.5"
 dependencies = [
  "cargo 0.30.0",
- "cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "clippy_lints 0.0.212",
  "crossbeam-channel 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "languageserver-types 0.45.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "racer 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-analysis 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-analysis 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-data 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-rustc 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-vfs 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-workspace-hack 1.0.0",
  "rustfmt-nightly 0.99.2",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rls-analysis"
-version = "0.14.0"
+version = "0.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "fst 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-data 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1849,13 +1756,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rls-data"
-version = "0.16.0"
+version = "0.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1869,8 +1776,8 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1895,15 +1802,15 @@ version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
  "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "fmt_macros 0.0.0",
  "graphviz 0.0.0",
  "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
@@ -1916,9 +1823,10 @@ dependencies = [
  "rustc_target 0.0.0",
  "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
- "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1934,8 +1842,8 @@ name = "rustc-ap-rustc_cratesio_shim"
 version = "218.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1943,9 +1851,9 @@ name = "rustc-ap-rustc_data_structures"
 version = "218.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-ap-rustc_cratesio_shim 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1974,8 +1882,8 @@ name = "rustc-ap-rustc_target"
 version = "218.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-ap-rustc_cratesio_shim 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-ap-serialize 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1990,8 +1898,8 @@ name = "rustc-ap-syntax"
 version = "218.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-ap-rustc_data_structures 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-ap-rustc_errors 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-ap-rustc_target 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2005,7 +1913,7 @@ name = "rustc-ap-syntax_pos"
 version = "218.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-ap-arena 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-ap-rustc_data_structures 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-ap-serialize 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2015,7 +1923,7 @@ dependencies = [
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.8"
+version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -2049,10 +1957,10 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2064,7 +1972,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "rustc-workspace-hack"
 version = "1.0.0"
 dependencies = [
- "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2072,11 +1980,12 @@ dependencies = [
 name = "rustc_allocator"
 version = "0.0.0"
 dependencies = [
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_target 0.0.0",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -2085,7 +1994,7 @@ dependencies = [
 name = "rustc_apfloat"
 version = "0.0.0"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
 ]
 
@@ -2096,7 +2005,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
@@ -2106,7 +2015,7 @@ name = "rustc_borrowck"
 version = "0.0.0"
 dependencies = [
  "graphviz 0.0.0",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
@@ -2119,9 +2028,9 @@ dependencies = [
 name = "rustc_codegen_llvm"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_llvm 0.0.0",
 ]
 
@@ -2129,8 +2038,8 @@ dependencies = [
 name = "rustc_codegen_utils"
 version = "0.0.0"
 dependencies = [
- "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_incremental 0.0.0",
@@ -2145,17 +2054,17 @@ dependencies = [
 name = "rustc_cratesio_shim"
 version = "0.0.0"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc_data_structures"
 version = "0.0.0"
 dependencies = [
- "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2163,6 +2072,7 @@ dependencies = [
  "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
  "serialize 0.0.0",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2171,9 +2081,9 @@ name = "rustc_driver"
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
- "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
@@ -2221,8 +2131,8 @@ name = "rustc_incremental"
 version = "0.0.0"
 dependencies = [
  "graphviz 0.0.0",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_fs_util 0.0.0",
@@ -2235,7 +2145,7 @@ dependencies = [
 name = "rustc_lint"
 version = "0.0.0"
 dependencies = [
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_mir 0.0.0",
  "rustc_target 0.0.0",
@@ -2248,7 +2158,7 @@ name = "rustc_llvm"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2258,7 +2168,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
@@ -2267,8 +2177,8 @@ dependencies = [
 name = "rustc_metadata"
 version = "0.0.0"
 dependencies = [
- "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
@@ -2295,11 +2205,11 @@ name = "rustc_mir"
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
@@ -2308,6 +2218,7 @@ dependencies = [
  "rustc_errors 0.0.0",
  "rustc_target 0.0.0",
  "serialize 0.0.0",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -2319,7 +2230,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
@@ -2328,7 +2239,7 @@ dependencies = [
 name = "rustc_passes"
 version = "0.0.0"
 dependencies = [
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
@@ -2368,7 +2279,7 @@ name = "rustc_resolve"
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
@@ -2381,8 +2292,8 @@ dependencies = [
 name = "rustc_save_analysis"
 version = "0.0.0"
 dependencies = [
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-data 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2397,8 +2308,8 @@ dependencies = [
 name = "rustc_target"
 version = "0.0.0"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
  "serialize 0.0.0",
 ]
@@ -2407,12 +2318,13 @@ dependencies = [
 name = "rustc_traits"
 version = "0.0.0"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -2424,7 +2336,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
@@ -2434,12 +2346,13 @@ name = "rustc_typeck"
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_platform_intrinsics 0.0.0",
  "rustc_target 0.0.0",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -2458,7 +2371,7 @@ version = "0.0.0"
 dependencies = [
  "minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2478,10 +2391,10 @@ version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2492,31 +2405,36 @@ dependencies = [
  "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "isatty 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-ap-rustc_target 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-ap-syntax 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-ap-syntax_pos 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "ryu"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "same-file"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2524,7 +2442,7 @@ name = "schannel"
 version = "0.1.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2544,7 +2462,7 @@ version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2554,17 +2472,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde"
-version = "1.0.70"
+version = "1.0.75"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde_derive"
-version = "1.0.70"
+version = "1.0.75"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2572,22 +2490,25 @@ name = "serde_ignored"
 version = "0.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.24"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serialize"
 version = "0.0.0"
+dependencies = [
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "shell-escape"
@@ -2606,7 +2527,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "smallvec"
-version = "0.6.3"
+version = "0.6.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2617,7 +2538,7 @@ name = "socket2"
 version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2636,14 +2557,14 @@ dependencies = [
  "alloc_jemalloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
  "libc 0.0.0",
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
  "profiler_builtins 0.0.0",
- "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_asan 0.0.0",
  "rustc_lsan 0.0.0",
  "rustc_msan 0.0.0",
@@ -2656,11 +2577,11 @@ name = "string_cache"
 version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2697,9 +2618,9 @@ name = "strum_macros"
 version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2724,11 +2645,11 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "0.14.4"
+version = "0.14.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2745,9 +2666,9 @@ name = "synstructure"
 version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2755,13 +2676,14 @@ dependencies = [
 name = "syntax"
 version = "0.0.0"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_target 0.0.0",
  "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax_pos 0.0.0",
 ]
 
@@ -2774,6 +2696,7 @@ dependencies = [
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_target 0.0.0",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -2783,7 +2706,7 @@ name = "syntax_pos"
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
- "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_data_structures 0.0.0",
  "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
@@ -2803,11 +2726,11 @@ dependencies = [
 
 [[package]]
 name = "tempfile"
-version = "3.0.2"
+version = "3.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2846,10 +2769,10 @@ dependencies = [
 
 [[package]]
 name = "termcolor"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "wincolor 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2880,20 +2803,19 @@ dependencies = [
 
 [[package]]
 name = "thread_local"
-version = "0.3.5"
+version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "tidy"
 version = "0.1.0"
 dependencies = [
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2911,7 +2833,7 @@ name = "toml"
 version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2921,7 +2843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2936,7 +2858,7 @@ name = "unicode-bidi"
 version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2995,7 +2917,7 @@ version = "1.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -3004,19 +2926,10 @@ name = "url_serde"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "userenv-sys"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "utf-8"
 version = "0.7.2"
@@ -3024,12 +2937,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "utf8-ranges"
-version = "1.0.0"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "vcpkg"
-version = "0.2.4"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -3037,6 +2950,11 @@ name = "vec_map"
 version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "version_check"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "void"
 version = "1.0.2"
@@ -3044,11 +2962,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "walkdir"
-version = "2.1.4"
+version = "2.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -3075,6 +2994,14 @@ name = "winapi-i686-pc-windows-gnu"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "winapi-util"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "winapi-x86_64-pc-windows-gnu"
 version = "0.4.0"
@@ -3090,10 +3017,11 @@ dependencies = [
 
 [[package]]
 name = "wincolor"
-version = "1.0.0"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -3118,7 +3046,7 @@ version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [metadata]
-"checksum aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c6d463cbe7ed28720b5b489e7c083eeb8f90d08be2a0d6bb9e1ffea9ce1afa"
+"checksum aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee94e9463ccb9d681e7b708082687b2c56d2bd420ca8a3d3157d27d59508ec0"
 "checksum ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd4c682378117e4186a492b2252b9537990e1617f44aed9788b9a1149de45477"
 "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
@@ -3127,29 +3055,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
 "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
 "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
-"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
+"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
 "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
 "checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9"
-"checksum cargo 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21dd0ac7737313b8c5c6fbfaf351aa93d4e90f66d4a33a11d1f3fb29584ac631"
-"checksum cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1efca0b863ca03ed4c109fb1c55e0bc4bbeb221d3e103d86251046b06a526bd0"
 "checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1"
-"checksum cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275"
-"checksum cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efe5c877e17a9c717a0bf3613b2709f723202c4e4675cc8f12926ded29bcb17e"
+"checksum cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4a6007c146fdd28d4512a794b07ffe9d8e89e6bf86e2e0c4ddff2e1fb54a0007"
+"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3"
 "checksum chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25ce2f28f55ed544a2a3756b7acf41dd7d6f27acffb2086439950925506af7d0"
 "checksum chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e"
 "checksum chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6962c635d530328acc53ac6a955e83093fedc91c5809dfac1fa60fa470830a37"
 "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
-"checksum cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "95470235c31c726d72bf2e1f421adc1e65b9d561bf5529612cbe1a72da1467b3"
+"checksum cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "704fbf3bb5149daab0afb255dbea24a1f08d2f4099cedb9baab6d470d4c5eefb"
 "checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc"
 "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007"
 "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2"
 "checksum compiletest_rs 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "d3064bc712922596dd5ab449fca9261d411893356581fe5297b96aa8f53bb1b8"
-"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980"
 "checksum core-foundation 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cc3532ec724375c7cb7ff0a097b714fde180bb1f6ed2ab27cfcd99ffca873cd2"
-"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa"
 "checksum core-foundation-sys 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a3fb15cdbdd9cf8b82d97d0296bb5cd3631bba58d6e31650a002a8e7fb5721f9"
-"checksum crates-io 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f78703ef5348db1e3244fb6b496e840965fb4754a5319270f2bd77ddb856e1c"
 "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19"
 "checksum crossbeam-channel 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "efff2d411e0ac3731b9f6de882b2790fdd2de651577500a806ce78b95b2b9f31"
 "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
@@ -3159,18 +3082,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum crossbeam-utils 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ea52fab26a99d96cdff39d0ca75c9716125937f5dba2ab83923aaaf5928f684a"
 "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
 "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4"
-"checksum curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "893713db705eab9847e050268507b0e2a2aad64e90a831874bd4e8e0d67f9523"
-"checksum curl-sys 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "de9cf174efdf90b5887c4e2e900769373c89c5e18152e8f3ed75b501a6f1c0fb"
+"checksum curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "444c2f9e71458b34e75471ed8d756947a0bb920b8b8b9bfc56dfcc4fc6819a13"
+"checksum curl-sys 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "981bd902fcd8b8b999cf71b81447e27d66c3493a7f62f1372866fd32986c0c82"
 "checksum datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16d724bf4ffe77cdceeecd461009b5f8d9e23c5d645d68bedb4586bf43e7e142"
 "checksum derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ceed73957c449214f8440eec8ad7fa282b67dc9eacbb24a3085b15d60397a17a"
 "checksum derive_more 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46c7f14685a20f5dd08e7f754f2ea8cc064d8f4214ae21116c106a2768ba7b9b"
 "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
 "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
-"checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd"
 "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
 "checksum elasticlunr-rs 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4837d77a1e157489a3933b743fd774ae75074e0e390b2b7f071530048a0d87ee"
 "checksum ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dc8393b3c7352f94092497f6b52019643e493b6b890eb417cdb7c46117e621"
-"checksum env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0e6e40ebb0e66918a37b38c7acab4e10d299e0463fe2af5d29b9cc86710cfd2a"
+"checksum env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f4d7e69c283751083d53d01eac767407343b8b69c4bd70058e08adc2637cb257"
 "checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
 "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
@@ -3178,7 +3100,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426"
 "checksum filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da4b9849e77b13195302c174324b5ba73eec9b236b24c221a61000daefb95c5f"
 "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
-"checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
+"checksum flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "37847f133aae7acf82bb9577ccd8bda241df836787642654286e79679826a54b"
 "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
 "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
 "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
@@ -3193,47 +3115,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "591f8be1674b421644b6c030969520bc3fa12114d2eb467471982ed3e9584e71"
 "checksum git2-curl 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b502f6b1b467957403d168f0039e0c46fa6a1220efa2adaef25d5b267b5fe024"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
-"checksum globset 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "142754da2c9b3722affd909f9e27f2a6700a7a303f362971e0a74c652005a43d"
+"checksum globset 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8e49edbcc9c7fc5beb8c0a54e7319ff8bed353a2b55e85811c6281188c2a6c84"
 "checksum handlebars 0.32.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d89ec99d1594f285d4590fc32bac5f75cdab383f1123d504d27862c644a807dd"
 "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
-"checksum home 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f94f6fbdc000a6eba0c8cf08632b2091bb59141d36ac321a2a96d6365e5e4dc"
+"checksum home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "80dff82fb58cfbbc617fb9a9184b010be0529201553cda50ad04372bc2333aff"
 "checksum html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b04478cf718862650a0bf66acaf8f2f8c906fbc703f35c916c1f4211b069a364"
 "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
 "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
 "checksum if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4bac95d9aa0624e7b78187d6fb8ab012b41d9f6f54b1bcb61e61c4845f8357ec"
-"checksum ignore 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "787a5940ab88e0f2f3b2cad3687060bddcf67520f3b761abc31065c9c495d088"
+"checksum ignore 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9faa7c84064f07b40da27044af629f578bc7994b650d3e458d0c29183c1d91"
 "checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053"
 "checksum isatty 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6c324313540cd4d7ba008d43dc6606a32a5579f13cc17b2804c13096f0a5c522"
 "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450"
 "checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606"
 "checksum jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "60af5f849e1981434e4a31d3d782c4774ae9b434ce55b101a96ecfd09147e8be"
+"checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be"
 "checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum languageserver-types 0.45.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d91d91d1c23db74187096d191967cb49f49bb175ad6d855fa9229d16ef2c982"
 "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
-"checksum lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fb497c35d362b6a331cfd94956a07fc2c78a4604cdbee844a81170386b996dd3"
-"checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef"
+"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7"
 "checksum lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d33a48d0365c96081958cc663eef834975cb1e8d8bea3378513fc72bdbf11e50"
 "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
 "checksum libgit2-sys 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6ab62b46003ba97701554631fa570d9f7e7947e2480ae3d941e555a54a2c0f05"
-"checksum libssh2-sys 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c628b499e8d1a4f4bd09a95d6cb1f8aeb231b46a9d40959bbd0408f14dd63adf"
-"checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16"
+"checksum libssh2-sys 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "10dbc0957a27626444f5a3f523e6b97a70c3d702999bf1c7161cfbe7a25a9368"
+"checksum libz-sys 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "f5f9aba969b3c45fe9c94bec65895868a9ceca9a600699f4054b75747a19c7c6"
 "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
-"checksum log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "61bd98ae7f7b754bc53dca7d44b604f733c6bba044ea6f41bc8d89272d8161d2"
+"checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2"
 "checksum log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19af41f0565d7c19b2058153ad0b42d4d5ce89ec4dbf06ed6741114a8b63e7cd"
 "checksum lzma-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d1eaa027402541975218bb0eec67d6b0412f6233af96e0d096d31dbdfd22e614"
 "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 "checksum macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2c4deaccc2ead6a28c16c0ba82f07d52b6475397415ce40876e559b0b0ea510"
 "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
 "checksum markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfedc97d5a503e96816d10fedcd5b42f760b2e525ce2f7ec71f6a41780548475"
-"checksum matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "835511bab37c34c47da5cb44844bea2cfde0236db0b506f90ea4224482c9774a"
+"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
 "checksum mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "90b5a8d7e341ceee5db3882a06078d42661ddcfa2b3687319cc5da76ec4e782f"
-"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
-"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
+"checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d"
 "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
 "checksum minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "9908ed7c62f990c21ab41fdca53a864a3ada0da69d8729c4de727b397e27bc11"
 "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
-"checksum miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9224c91f82b3c47cf53dcf78dfaa20d6888fbcc5d272d5f2fcdf8a697f3c987d"
+"checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226"
 "checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
 "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
 "checksum num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2c31b75c36a993d30c7a13d70513cb93f02acafdd5b7ba250f9b0e18615de7"
@@ -3241,9 +3162,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe"
 "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
 "checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113"
+"checksum opener 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "176cd8eadff5ef9fa5c6d19452535662c02c6bf29b3d594a3fc01f749bb24c94"
 "checksum openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)" = "6c24d3508b4fb6da175c10baac54c578b33f09c89ae90c6fe9788b3b4768efdc"
 "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
-"checksum openssl-src 110.0.6+1.1.0h (registry+https://github.com/rust-lang/crates.io-index)" = "2011250f011d9c0f2e982f36721c9cbf451a9b04f425ea43a6a3f1bfa889a3b4"
+"checksum openssl-src 110.0.7+1.1.0i (registry+https://github.com/rust-lang/crates.io-index)" = "c02d15268b7d1b3f0c83a2358f3d981139b54079440f1e2a29c60c1818ad5516"
 "checksum openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)" = "912f301a749394e1025d9dcddef6106ddee9252620e6d0a0e5f8d0681de9b129"
 "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
 "checksum ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024"
@@ -3258,20 +3180,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4048fe7dd7a06b8127ecd6d3803149126e9b33c7558879846da3a63f734f2b"
 "checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998"
 "checksum phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2261d544c2bb6aa3b10022b0be371b9c7c64f762ef28c6f5d4f1ef6d97b5930"
-"checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f"
+"checksum pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "104630aa1c83213cbc76db0703630fcb0421dac3585063be4ce9a8a2feeaa745"
 "checksum polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b6b0a7f5f4278b991ffd14abce1d01b013121ad297460237ef0a2f08d43201"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
 "checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7"
-"checksum proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c65b1ea15bb859d922cade2d1765b4b88beac339cbfad545ef2d2ef8c8215ee6"
+"checksum proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5697238f0d893c7f0ecc59c0999f18d2af85e424de441178bcacc9f9e6cf67"
 "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32"
 "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
 "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
 "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"
-"checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035"
+"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5"
 "checksum racer 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "dcbc5ababaffee8d8f34910f925287c8f716b1ead48561c4278a152d08264f7c"
-"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
+"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
 "checksum rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "12397506224b2f93e6664ffc4f664b29be8208e5157d3d90b44f09b5fae470ea"
 "checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2"
 "checksum rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80e811e76f1dbf68abf87a759083d34600017fc4e10b6bd5ad84a700f9dba4b1"
@@ -3279,13 +3201,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
 "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
 "checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384"
-"checksum regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13c93d55961981ba9226a213b385216f83ab43bd6ac53ab16b2eeb47e337cf4e"
+"checksum regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "67d0301b0c6804eca7e3c275119d0b01ff3b7ab9258a65709e608a66312a1025"
 "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
-"checksum regex-syntax 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05b06a75f5217880fc5e905952a42750bf44787e56a6c6d6852ed0992f5e1d54"
+"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d"
 "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
-"checksum rls-analysis 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96f84d303dcbe1c1bdd41b10867d3399c38fbdac32c4e3645cdb6dbd7f82db1d"
+"checksum rls-analysis 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c18011f4654e9f1c41717c5ac1323768af34de0f41e421bbe913d7e9b93581fd"
 "checksum rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e4a9cc2545ccb7e05b355bfe047b8039a6ec12270d5f3c996b766b340a50f7d2"
-"checksum rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd20763e1c60ae8945384c8a8fa4ac44f8afa7b0a817511f5e8927e5d24f988"
+"checksum rls-data 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f81e838ecff6830ed33c2907fd236f38d441c206e983a2aa29fbce99295fab9"
 "checksum rls-rustc 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9dba7390427aefa953608429701e3665192ca810ba8ae09301e001b7c7bed0"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ecbc8541b4c341d6271eae10f869dd9d36db871afe184f5b6f9bffbd6ed0373f"
@@ -3297,27 +3219,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rustc-ap-serialize 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffcfb1102cd7cbf5f25c008a00f7253427af9dfac8989ede48c19bd47f556893"
 "checksum rustc-ap-syntax 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a2ca0ef078a735c81a0d33589e04148dcf41f80ee7ebe30e72904a631b7c669"
 "checksum rustc-ap-syntax_pos 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1bbd31d1bbc7210983c3bbbcb9ee35bac443c6c899f979b8114e58bb7101c28"
-"checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649"
+"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
 "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306"
 "checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a"
 "checksum rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "756567f00f7d89c9f89a5c401b8b1caaa122e27240b9eaadd0bb52ee0b680b1b"
-"checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
+"checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7"
+"checksum same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10f7794e2fda7f594866840e95f5c5962e886e228e68b6505885811a94dd728c"
 "checksum schannel 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "dc1fabf2a7b6483a141426e1afd09ad543520a77ac49bd03c286e7696ccfd77f"
 "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28"
 "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-"checksum serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "0c3adf19c07af6d186d91dae8927b83b0553d07ca56cbf7f2f32560455c91920"
-"checksum serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "3525a779832b08693031b8ecfb0de81cd71cfd3812088fafe9a7496789572124"
+"checksum serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)" = "22d340507cea0b7e6632900a176101fea959c7065d93ba555072da90aaaafc87"
+"checksum serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)" = "234fc8b737737b148ccd625175fc6390f5e4dacfdaa543cb93a3430d984a9119"
 "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142"
-"checksum serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c6908c7b925cd6c590358a4034de93dbddb20c45e1d021931459fd419bf0e2"
+"checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae"
 "checksum shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "170a13e64f2a51b77a45702ba77287f5c6829375b04a69cf2222acd17d0cfab9"
 "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
 "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
-"checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8"
+"checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d"
 "checksum socket2 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "962a516af4d3a7c272cb3a1d50a8cc4e5b41802e4ad54cfb7bee8ba61d37d703"
 "checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa"
 "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"
@@ -3328,18 +3251,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum strum_macros 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1292d85e688e4696ecb69b2db2648994fb8af266974e89be53cefdf003861a5d"
 "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
 "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b"
-"checksum syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2beff8ebc3658f07512a413866875adddd20f4fd47b2a4e6c9da65cd281baaea"
+"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
 "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
 "checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7"
 "checksum tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)" = "e8f41ca4a5689f06998f0247fcb60da6c760f1950cc9df2a10d71575ad0b062a"
-"checksum tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "47776f63b85777d984a50ce49d6b9e58826b6a3766a449fc95bc66cd5663c15b"
+"checksum tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c4b103c6d08d323b92ff42c8ce62abcd83ca8efa7fd5bf7927efefec75f58c76"
 "checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508"
 "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
 "checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83"
-"checksum termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "722426c4a0539da2c4ffd9b419d90ad540b4cff4a053be9069c908d4d07e2836"
+"checksum termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3390f44f1f706d8870297b6a2c4f92d9ab65a37c265fbbc6ac4ee72bcc2f3698"
 "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
 "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
-"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
+"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
 "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
 "checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9"
 "checksum toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6854664bfc6df0360c695480836ee90e2d0c965f06db291d10be9344792d43e8"
@@ -3353,20 +3276,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
 "checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6"
 "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea"
-"checksum userenv-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d28ea36bbd9192d75bd9fa9b39f96ddb986eaee824adae5d53b6e51919b2f3"
 "checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c"
-"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
-"checksum vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cbe533e138811704c0e3cbde65a818b35d3240409b4346256c5ede403e082474"
+"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4"
+"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d"
 "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
+"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
-"checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369"
+"checksum walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "af464bc7be7b785c7ac72e266a6b67c4c9070155606f51655a650a6686204e35"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab"
 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 "checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767"
-"checksum wincolor 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9dc3aa9dcda98b5a16150c54619c1ead22e3d3a5d458778ae914be760aa981a"
+"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba"
 "checksum xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
 "checksum xz2 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "df8bf41d3030c3577c9458fd6640a05afbf43b150d0b531b16bd77d3f794f27a"
 "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992"
index a54e58665cceb8177b936b6744c0bfe50537e683..bb5a21e3e405fd034f35d33373006369333bfc21 100644 (file)
@@ -37,6 +37,8 @@ fn main() {
     let mut dylib_path = bootstrap::util::dylib_path();
     dylib_path.insert(0, PathBuf::from(libdir.clone()));
 
+    //FIXME(misdreavus): once stdsimd uses cfg(rustdoc) instead of cfg(dox), remove the `--cfg dox`
+    //arguments here
     let mut cmd = Command::new(rustdoc);
     cmd.args(&args)
         .arg("--cfg")
index 12c1972c22039aa4b4b8a498b326bfc70823269a..5c287f25e26bc6321a7411772c8905fc9436df6f 100644 (file)
@@ -827,7 +827,7 @@ pub fn cargo(
         if let Some(ref error_format) = self.config.rustc_error_format {
             cargo.env("RUSTC_ERROR_FORMAT", error_format);
         }
-        if cmd != "build" && cmd != "check" && want_rustdoc {
+        if cmd != "build" && cmd != "check" && cmd != "rustc" && want_rustdoc {
             cargo.env("RUSTDOC_LIBDIR", self.sysroot_libdir(compiler, self.config.build));
         }
 
@@ -988,7 +988,7 @@ pub fn cargo(
             }
         }
 
-        if cmd == "build"
+        if (cmd == "build" || cmd == "rustc")
             && mode == Mode::Std
             && self.config.extended
             && compiler.is_final_stage(self)
index 133e5aa37a7db9715e55b83867e8a9ab0ad3fff2..20cdfcb3d298134ebbab2d4900c741e70c7b8080 100644 (file)
@@ -50,6 +50,7 @@ fn run(self, builder: &Builder) {
         println!("Checking std artifacts ({} -> {})", &compiler.host, target);
         run_cargo(builder,
                   &mut cargo,
+                  vec![],
                   &libstd_stamp(builder, compiler, target),
                   true);
 
@@ -98,6 +99,7 @@ fn run(self, builder: &Builder) {
         println!("Checking compiler artifacts ({} -> {})", &compiler.host, target);
         run_cargo(builder,
                   &mut cargo,
+                  vec![],
                   &librustc_stamp(builder, compiler, target),
                   true);
 
@@ -149,6 +151,7 @@ fn run(self, builder: &Builder) {
         let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage));
         run_cargo(builder,
                   &mut cargo,
+                  vec![],
                   &codegen_backend_stamp(builder, compiler, target, backend),
                   true);
     }
@@ -187,6 +190,7 @@ fn run(self, builder: &Builder) {
         println!("Checking test artifacts ({} -> {})", &compiler.host, target);
         run_cargo(builder,
                   &mut cargo,
+                  vec![],
                   &libtest_stamp(builder, compiler, target),
                   true);
 
@@ -236,6 +240,7 @@ fn run(self, builder: &Builder) {
         println!("Checking rustdoc artifacts ({} -> {})", &compiler.host, target);
         run_cargo(builder,
                   &mut cargo,
+                  vec![],
                   &rustdoc_stamp(builder, compiler, target),
                   true);
 
index 2f8816d111a9d2b4d6f89171d897d8fcca36088b..da0ccf5e1773d164cbffbe015433bd127e007448 100644 (file)
@@ -117,6 +117,7 @@ fn run(self, builder: &Builder) {
                 &compiler.host, target));
         run_cargo(builder,
                   &mut cargo,
+                  vec![],
                   &libstd_stamp(builder, compiler, target),
                   false);
 
@@ -396,6 +397,7 @@ fn run(self, builder: &Builder) {
                 &compiler.host, target));
         run_cargo(builder,
                   &mut cargo,
+                  vec![],
                   &libtest_stamp(builder, compiler, target),
                   false);
 
@@ -529,6 +531,7 @@ fn run(self, builder: &Builder) {
                  compiler.stage, &compiler.host, target));
         run_cargo(builder,
                   &mut cargo,
+                  vec![],
                   &librustc_stamp(builder, compiler, target),
                   false);
 
@@ -673,18 +676,47 @@ fn run(self, builder: &Builder) {
         let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
         builder.clear_if_dirty(&out_dir, &librustc_stamp(builder, compiler, target));
 
-        let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "build");
+        let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "rustc");
         cargo.arg("--manifest-path")
             .arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
         rustc_cargo_env(builder, &mut cargo);
 
         let features = build_codegen_backend(&builder, &mut cargo, &compiler, target, backend);
 
+        let mut cargo_tails_args = vec![];
+
+        if builder.config.llvm_thin_lto {
+            cargo_tails_args.push("--".to_string());
+
+            let num_jobs = builder.jobs();
+
+            if !target.contains("msvc") {
+                // Here we assume that the linker is clang. If it's not, there'll
+                // be linker errors.
+                cargo_tails_args.push("-Clink-arg=-fuse-ld=lld".to_string());
+                cargo_tails_args.push("-Clink-arg=-flto=thin".to_string());
+
+                if builder.config.llvm_optimize {
+                    cargo_tails_args.push("-Clink-arg=-O2".to_string());
+                }
+
+                // Let's make LLD respect the `-j` option.
+                let num_jobs_arg = format!("-Clink-arg=-Wl,--thinlto-jobs={}", num_jobs);
+                cargo_tails_args.push(num_jobs_arg);
+            } else {
+                // Here we assume that the linker is lld-link.exe. lld-link.exe
+                // does not need the extra arguments except for num_jobs
+                let num_jobs_arg = format!("-Clink-arg=/opt:lldltojobs={}", num_jobs);
+                cargo_tails_args.push(num_jobs_arg);
+            }
+        }
+
         let tmp_stamp = out_dir.join(".tmp.stamp");
 
         let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage));
         let files = run_cargo(builder,
                               cargo.arg("--features").arg(features),
+                              cargo_tails_args,
                               &tmp_stamp,
                               false);
         if builder.config.dry_run {
@@ -1045,7 +1077,11 @@ fn stderr_isatty() -> bool {
     }
 }
 
-pub fn run_cargo(builder: &Builder, cargo: &mut Command, stamp: &Path, is_check: bool)
+pub fn run_cargo(builder: &Builder,
+                 cargo: &mut Command,
+                 tail_args: Vec<String>,
+                 stamp: &Path,
+                 is_check: bool)
     -> Vec<PathBuf>
 {
     if builder.config.dry_run {
@@ -1066,7 +1102,7 @@ pub fn run_cargo(builder: &Builder, cargo: &mut Command, stamp: &Path, is_check:
     // files we need to probe for later.
     let mut deps = Vec::new();
     let mut toplevel = Vec::new();
-    let ok = stream_cargo(builder, cargo, &mut |msg| {
+    let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
         let filenames = match msg {
             CargoMessage::CompilerArtifact { filenames, .. } => filenames,
             _ => return,
@@ -1191,6 +1227,7 @@ pub fn run_cargo(builder: &Builder, cargo: &mut Command, stamp: &Path, is_check:
 pub fn stream_cargo(
     builder: &Builder,
     cargo: &mut Command,
+    tail_args: Vec<String>,
     cb: &mut dyn FnMut(CargoMessage),
 ) -> bool {
     if builder.config.dry_run {
@@ -1210,6 +1247,10 @@ pub fn stream_cargo(
         cargo.env("RUSTC_COLOR", "1");
     }
 
+    for arg in tail_args {
+        cargo.arg(arg);
+    }
+
     builder.verbose(&format!("running: {:?}", cargo));
     let mut child = match cargo.spawn() {
         Ok(child) => child,
index 43650332d3b67c901df7c8783b09953cd175401d..bf4d39c4947e51202945a14076f32dc89aefc998 100644 (file)
@@ -77,6 +77,7 @@ pub struct Config {
     pub llvm_enabled: bool,
     pub llvm_assertions: bool,
     pub llvm_optimize: bool,
+    pub llvm_thin_lto: bool,
     pub llvm_release_debuginfo: bool,
     pub llvm_version_check: bool,
     pub llvm_static_stdcpp: bool,
@@ -163,6 +164,7 @@ pub struct Target {
     pub cc: Option<PathBuf>,
     pub cxx: Option<PathBuf>,
     pub ar: Option<PathBuf>,
+    pub ranlib: Option<PathBuf>,
     pub linker: Option<PathBuf>,
     pub ndk: Option<PathBuf>,
     pub crt_static: Option<bool>,
@@ -246,6 +248,7 @@ struct Llvm {
     ninja: Option<bool>,
     assertions: Option<bool>,
     optimize: Option<bool>,
+    thin_lto: Option<bool>,
     release_debuginfo: Option<bool>,
     version_check: Option<bool>,
     static_libstdcpp: Option<bool>,
@@ -327,6 +330,7 @@ struct TomlTarget {
     cc: Option<String>,
     cxx: Option<String>,
     ar: Option<String>,
+    ranlib: Option<String>,
     linker: Option<String>,
     android_ndk: Option<String>,
     crt_static: Option<bool>,
@@ -503,6 +507,7 @@ pub fn parse(args: &[String]) -> Config {
             set(&mut config.llvm_enabled, llvm.enabled);
             llvm_assertions = llvm.assertions;
             set(&mut config.llvm_optimize, llvm.optimize);
+            set(&mut config.llvm_thin_lto, llvm.thin_lto);
             set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo);
             set(&mut config.llvm_version_check, llvm.version_check);
             set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp);
@@ -581,6 +586,7 @@ pub fn parse(args: &[String]) -> Config {
                 target.cc = cfg.cc.clone().map(PathBuf::from);
                 target.cxx = cfg.cxx.clone().map(PathBuf::from);
                 target.ar = cfg.ar.clone().map(PathBuf::from);
+                target.ranlib = cfg.ranlib.clone().map(PathBuf::from);
                 target.linker = cfg.linker.clone().map(PathBuf::from);
                 target.crt_static = cfg.crt_static.clone();
                 target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
index 6e473fae3be5c0208279c662f12e0ead34e9bca1..92c0a088b5eefbdb3ca0213f29da034e35d7529c 100644 (file)
@@ -501,6 +501,13 @@ fn prepare_image(builder: &Builder, compiler: Compiler, image: &Path) {
             t!(fs::create_dir_all(&backends_dst));
             builder.cp_r(&backends_src, &backends_dst);
 
+            // Copy libLLVM.so to the lib dir as well, if needed. While not
+            // technically needed by rustc itself it's needed by lots of other
+            // components like the llvm tools and LLD. LLD is included below and
+            // tools/LLDB come later, so let's just throw it in the rustc
+            // component for now.
+            maybe_install_llvm_dylib(builder, host, image);
+
             // Copy over lld if it's there
             if builder.config.lld_enabled {
                 let exe = exe("rust-lld", &compiler.host);
@@ -1885,6 +1892,34 @@ fn run(self, builder: &Builder) {
     }
 }
 
+// Maybe add libLLVM.so to the lib-dir. It will only have been built if
+// LLVM tools are linked dynamically.
+// Note: This function does no yet support Windows but we also don't support
+//       linking LLVM tools dynamically on Windows yet.
+fn maybe_install_llvm_dylib(builder: &Builder,
+                            target: Interned<String>,
+                            image: &Path) {
+    let src_libdir = builder
+        .llvm_out(target)
+        .join("lib");
+
+    // Usually libLLVM.so is a symlink to something like libLLVM-6.0.so.
+    // Since tools link to the latter rather than the former, we have to
+    // follow the symlink to find out what to distribute.
+    let llvm_dylib_path = src_libdir.join("libLLVM.so");
+    if llvm_dylib_path.exists() {
+        let llvm_dylib_path = llvm_dylib_path.canonicalize().unwrap_or_else(|e| {
+            panic!("dist: Error calling canonicalize path `{}`: {}",
+                   llvm_dylib_path.display(), e);
+        });
+
+        let dst_libdir = image.join("lib");
+        t!(fs::create_dir_all(&dst_libdir));
+
+        builder.install(&llvm_dylib_path, &dst_libdir, 0o644);
+    }
+}
+
 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
 pub struct LlvmTools {
     pub stage: u32,
@@ -1929,16 +1964,14 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
         drop(fs::remove_dir_all(&image));
 
         // Prepare the image directory
-        let bindir = builder
+        let src_bindir = builder
             .llvm_out(target)
             .join("bin");
-        let dst = image.join("lib/rustlib")
-            .join(target)
-            .join("bin");
-        t!(fs::create_dir_all(&dst));
+        let dst_bindir = image.join("bin");
+        t!(fs::create_dir_all(&dst_bindir));
         for tool in LLVM_TOOLS {
-            let exe = bindir.join(exe(tool, &target));
-            builder.install(&exe, &dst, 0o755);
+            let exe = src_bindir.join(exe(tool, &target));
+            builder.install(&exe, &dst_bindir, 0o755);
         }
 
         // Prepare the overlay
@@ -2025,7 +2058,6 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
         let dst = image.join("lib");
         t!(fs::create_dir_all(&dst));
         for entry in t!(fs::read_dir(&libdir)) {
-            // let entry = t!(entry);
             let entry = entry.unwrap();
             if let Ok(name) = entry.file_name().into_string() {
                 if name.starts_with("liblldb.") && !name.ends_with(".a") {
index ed9b5b1773fae0de01342200b363505902394a12..9a5d78e58ea3fcfa7e529b87e56868dcb7de6aaa 100644 (file)
@@ -712,7 +712,7 @@ fn run(self, builder: &Builder) {
 
         // Find dependencies for top level crates.
         let mut compiler_crates = HashSet::new();
-        for root_crate in &["rustc", "rustc_driver"] {
+        for root_crate in &["rustc", "rustc_driver", "rustc_codegen_llvm"] {
             let interned_root_crate = INTERNER.intern_str(root_crate);
             find_compiler_crates(builder, &interned_root_crate, &mut compiler_crates);
         }
index 60b4d65f444014133bd81262a7cbdcabea84bdfe..2084b8bdb65ffb859bb74195c6ec764ad4069afc 100644 (file)
@@ -125,7 +125,8 @@ pub fn parse(args: &[String]) -> Flags {
             "stage to build (indicates compiler to use/test, e.g. stage 0 uses the \
              bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)",
             "N");
-        opts.optmulti("", "keep-stage", "stage(s) to keep without recompiling", "N");
+        opts.optmulti("", "keep-stage", "stage(s) to keep without recompiling \
+            (pass multiple times to keep e.g. both stages 0 and 1)", "N");
         opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
         opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS");
         opts.optflag("h", "help", "print this help message");
index 6445ce8da332ea95904fb6b8a7ebbfd16f09d029..e6ee525ca2e0304bf4a8f615b3a6288361f2bc17 100644 (file)
@@ -37,7 +37,7 @@
 //! Note that this module has a #[cfg(windows)] above it as none of this logic
 //! is required on Unix.
 
-#![allow(bad_style, dead_code)]
+#![allow(nonstandard_style, dead_code)]
 
 use std::env;
 use std::io;
index 5bb475e07ba8db1fb4ae46b6180b96f1a267b12d..2725abdc3d95f4774ee4cfe31040aa68634a9155 100644 (file)
@@ -211,6 +211,7 @@ pub unsafe fn setup(_build: &mut ::Build) {
     "llvm-objcopy", // used to transform ELFs into binary format which flashing tools consume
     "llvm-objdump", // used to disassemble programs
     "llvm-profdata", // used to inspect and merge files generated by profiles
+    "llvm-readobj", // used to get information from ELFs/objects that the other tools don't provide
     "llvm-size", // used to prints the size of the linker sections of a program
     "llvm-strip", // used to discard symbols from binary files to reduce their size
 ];
@@ -281,6 +282,7 @@ pub struct Build {
     cc: HashMap<Interned<String>, cc::Tool>,
     cxx: HashMap<Interned<String>, cc::Tool>,
     ar: HashMap<Interned<String>, PathBuf>,
+    ranlib: HashMap<Interned<String>, PathBuf>,
     // Misc
     crates: HashMap<Interned<String>, Crate>,
     is_sudo: bool,
@@ -406,6 +408,7 @@ pub fn new(config: Config) -> Build {
             cc: HashMap::new(),
             cxx: HashMap::new(),
             ar: HashMap::new(),
+            ranlib: HashMap::new(),
             crates: HashMap::new(),
             lldb_version: None,
             lldb_python_dir: None,
@@ -772,6 +775,11 @@ fn ar(&self, target: Interned<String>) -> Option<&Path> {
         self.ar.get(&target).map(|p| &**p)
     }
 
+    /// Returns the path to the `ranlib` utility for the target specified.
+    fn ranlib(&self, target: Interned<String>) -> Option<&Path> {
+        self.ranlib.get(&target).map(|p| &**p)
+    }
+
     /// Returns the path to the C++ compiler for the target specified.
     fn cxx(&self, target: Interned<String>) -> Result<&Path, String> {
         match self.cxx.get(&target) {
@@ -1018,6 +1026,10 @@ fn lldb_vers(&self) -> String {
         self.rust_version()
     }
 
+    fn llvm_link_tools_dynamically(&self, target: Interned<String>) -> bool {
+        (target.contains("linux-gnu") || target.contains("apple-darwin"))
+    }
+
     /// Returns the `version` string associated with this compiler for Rust
     /// itself.
     ///
index c99347aa94e6637548a86f2e49cf15262ad33775..347c2472c6b9b6d75197795090bf4ed85fda3771 100644 (file)
@@ -145,6 +145,7 @@ fn run(self, builder: &Builder) -> PathBuf {
            .define("LLVM_INCLUDE_EXAMPLES", "OFF")
            .define("LLVM_INCLUDE_TESTS", "OFF")
            .define("LLVM_INCLUDE_DOCS", "OFF")
+           .define("LLVM_INCLUDE_BENCHMARKS", "OFF")
            .define("LLVM_ENABLE_ZLIB", "OFF")
            .define("WITH_POLLY", "OFF")
            .define("LLVM_ENABLE_TERMINFO", "OFF")
@@ -153,6 +154,11 @@ fn run(self, builder: &Builder) -> PathBuf {
            .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
            .define("LLVM_DEFAULT_TARGET_TRIPLE", target);
 
+        if builder.config.llvm_thin_lto && !emscripten {
+            cfg.define("LLVM_ENABLE_LTO", "Thin")
+               .define("LLVM_ENABLE_LLD", "ON");
+        }
+
         // By default, LLVM will automatically find OCaml and, if it finds it,
         // install the LLVM bindings in LLVM_OCAML_INSTALL_PATH, which defaults
         // to /usr/bin/ocaml.
@@ -166,14 +172,10 @@ fn run(self, builder: &Builder) -> PathBuf {
 
         // This setting makes the LLVM tools link to the dynamic LLVM library,
         // which saves both memory during parallel links and overall disk space
-        // for the tools.  We don't distribute any of those tools, so this is
-        // just a local concern.  However, it doesn't work well everywhere.
-        //
-        // If we are shipping llvm tools then we statically link them LLVM
-        if (target.contains("linux-gnu") || target.contains("apple-darwin")) &&
-            !builder.config.llvm_tools_enabled &&
-            !want_lldb {
-                cfg.define("LLVM_LINK_LLVM_DYLIB", "ON");
+        // for the tools. We don't do this on every platform as it doesn't work
+        // equally well everywhere.
+        if builder.llvm_link_tools_dynamically(target) && !emscripten {
+            cfg.define("LLVM_LINK_LLVM_DYLIB", "ON");
         }
 
         // For distribution we want the LLVM tools to be *statically* linked to libstdc++
@@ -379,6 +381,14 @@ fn configure_cmake(builder: &Builder,
         }
     }
 
+    if let Some(ranlib) = builder.ranlib(target) {
+        if ranlib.is_absolute() {
+            // LLVM build breaks if `CMAKE_RANLIB` is a relative path, for some reason it
+            // tries to resolve this path in the LLVM build directory.
+            cfg.define("CMAKE_RANLIB", sanitize_cc(ranlib));
+        }
+    }
+
     if env::var_os("SCCACHE_ERROR_LOG").is_some() {
         cfg.env("RUST_LOG", "sccache=warn");
     }
index 23ef031dcb703b094e09bceb0d9678283df5d51b..04aaa970654730dd3c63a6aedbabddbb37b3d6d0 100644 (file)
@@ -136,7 +136,7 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
         let _folder = builder.fold_output(|| format!("stage{}-{}", compiler.stage, tool));
         builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target));
         let mut duplicates = Vec::new();
-        let is_expected = compile::stream_cargo(builder, &mut cargo, &mut |msg| {
+        let is_expected = compile::stream_cargo(builder, &mut cargo, vec![], &mut |msg| {
             // Only care about big things like the RLS/Cargo for now
             match tool {
                 | "rls"
index be03796921af865b7c2c3d0a16b75d6d6272c888..8ce8f20add3ad20fa2d5e61ae629cf7364cd0888 100644 (file)
@@ -137,7 +137,7 @@ fn symlink_dir_inner(src: &Path, dest: &Path) -> io::Result<()> {
     //
     // Copied from std
     #[cfg(windows)]
-    #[allow(bad_style)]
+    #[allow(nonstandard_style)]
     fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> {
         use std::ptr;
         use std::ffi::OsStr;
diff --git a/src/ci/docker/disabled/dist-armebv7r-none-eabihf/Dockerfile b/src/ci/docker/disabled/dist-armebv7r-none-eabihf/Dockerfile
deleted file mode 100644 (file)
index 34c6e64..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++ \
-  make \
-  file \
-  curl \
-  ca-certificates \
-  python2.7 \
-  git \
-  cmake \
-  sudo \
-  xz-utils \
-  bzip2 \
-  libssl-dev \
-  pkg-config
-
-
-COPY scripts/sccache.sh /scripts/
-RUN sh /scripts/sccache.sh
-
-ENV BASE_URL=https://releases.linaro.org/components/toolchain/binaries/latest/armeb-eabi/
-ENV GCC_LINARO=gcc-linaro-7.2.1-2017.11-x86_64_armeb-eabi
-
-RUN curl -sL $BASE_URL/$GCC_LINARO.tar.xz | tar -xJ
-
-ENV PATH=$PATH:/$GCC_LINARO/bin
-
-ENV TARGET=armebv7r-none-eabihf
-
-ENV CC_armebv7r_none_eabihf=armeb-eabi-gcc \
-    CFLAGS_armebv7r_none_eabihf="-march=armv7-r"
-
-ENV RUST_CONFIGURE_ARGS --disable-docs
-
-ENV SCRIPT python2.7 ../x.py dist --target $TARGET
index bfc5e712f76c3aa1802e5a66fe45472454728b9b..e2484b7224b26fb96decc794a86464ee6fb3a495 100644 (file)
@@ -102,12 +102,18 @@ ENV TARGETS=$TARGETS,thumbv6m-none-eabi
 ENV TARGETS=$TARGETS,thumbv7m-none-eabi
 ENV TARGETS=$TARGETS,thumbv7em-none-eabi
 ENV TARGETS=$TARGETS,thumbv7em-none-eabihf
+ENV TARGETS=$TARGETS,riscv32imc-unknown-none-elf
 ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf
+ENV TARGETS=$TARGETS,armebv7r-none-eabi
+ENV TARGETS=$TARGETS,armebv7r-none-eabihf
+ENV TARGETS=$TARGETS,armv7r-none-eabi
+ENV TARGETS=$TARGETS,armv7r-none-eabihf
 
 ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
     CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \
     CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \
-    CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc
+    CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \
+    CC_armebv7r_none_eabi=arm-none-eabi-gcc
 
 ENV RUST_CONFIGURE_ARGS \
       --musl-root-armv5te=/musl-armv5te \
@@ -120,7 +126,7 @@ ENV RUST_CONFIGURE_ARGS \
       --enable-emscripten \
       --disable-docs
 
-ENV SCRIPT \ 
+ENV SCRIPT \
       python2.7 ../x.py test --target $RUN_MAKE_TARGETS src/test/run-make && \
       python2.7 ../x.py dist --target $TARGETS
 
index 5726fab7524ae88a55e35d27d8b1291f18fa8816..01f6db03e8ee0dd2560e0568e9e326937f7c953c 100644 (file)
@@ -93,7 +93,10 @@ ENV RUST_CONFIGURE_ARGS \
       --enable-sanitizers \
       --enable-profiler \
       --enable-compiler-docs \
-      --set target.x86_64-unknown-linux-gnu.linker=clang
+      --set target.x86_64-unknown-linux-gnu.linker=clang \
+      --set target.x86_64-unknown-linux-gnu.ar=/rustroot/bin/llvm-ar \
+      --set target.x86_64-unknown-linux-gnu.ranlib=/rustroot/bin/llvm-ranlib \
+      --set llvm.thin-lto=true
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
 ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang
 
index b0c27aa45bf9319d50c1574319c9d16ba0852be0..4595eacb31061e8223243affe4c7bf00f8283729 100755 (executable)
@@ -30,6 +30,12 @@ curl https://releases.llvm.org/$LLVM/cfe-$LLVM.src.tar.xz | \
   xz -d | \
   tar xf - -C tools/clang --strip-components=1
 
+mkdir -p tools/lld
+
+curl https://releases.llvm.org/$LLVM/lld-$LLVM.src.tar.xz | \
+  xz -d | \
+  tar xf - -C tools/lld --strip-components=1
+
 mkdir ../clang-build
 cd ../clang-build
 
index 4ca7389d6d1a53102eca067a43697f88250dbcd9..e6a48a96da464ab1a034d926833492a768057e29 100644 (file)
@@ -32,7 +32,7 @@ shift
 
 export CFLAGS="-fPIC $CFLAGS"
 
-# FIXME: remove the patch when upate to 1.1.20
+# FIXME: remove the patch when updating to 1.1.20
 MUSL=musl-1.1.19
 
 # may have been downloaded in a previous run
index 88cdde350fd3a90c93f3bac8b4f168f105d28060..16c9dee7666c2b2766fd98d89003e028679d1207 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 88cdde350fd3a90c93f3bac8b4f168f105d28060
+Subproject commit 16c9dee7666c2b2766fd98d89003e028679d1207
index 3a4f51069fc3b7f1534b7a5505633f5cfc04f90f..11313ba99e1a6ea8398908ba514b96db585f8897 100644 (file)
@@ -34,7 +34,7 @@ minimum. It also includes exercises!
 
 # Use Rust
 
-Once you've gotten familliar with the language, these resources can help you
+Once you've gotten familiar with the language, these resources can help you
 when you're actually using it day-to-day.
 
 ## The Standard Library
index 790e96b87f4b5817cac310e73a524d25c3d076d8..ae42ad7aa4d7907cca941371c9eee8de8c2ee40d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 790e96b87f4b5817cac310e73a524d25c3d076d8
+Subproject commit ae42ad7aa4d7907cca941371c9eee8de8c2ee40d
index eff09428902e8012669b88ddc87266e06894f238..4fc5f42dd552708867aa37c09dbc32ad2fa33c8d 100644 (file)
@@ -153,7 +153,7 @@ This option allows you to put extra data in each output filename.
 This flag lets you control how many threads are used when doing
 code generation.
 
-Increasing paralellism may speed up compile times, but may also
+Increasing parallelism may speed up compile times, but may also
 produce slower code.
 
 ## remark
index 3a85a40fd1fdb9af606df8414f8289b4330949ee..ff9e0235a0435e8a95e0f160ad63c7ab2ba4711b 100644 (file)
@@ -56,7 +56,7 @@ mod m {
     pub struct S(u8);
     
     fn f() {
-        // this is trying to use S from the 'use' line, but becuase the `u8` is
+        // this is trying to use S from the 'use' line, but because the `u8` is
         // not pub, it is private
         ::S;
     }
@@ -103,7 +103,7 @@ This warning can always be fixed by removing the unused pattern in the
 
 ## mutable-transmutes
 
-This lint catches transmuting from `&T` to `&mut T` becuase it is undefined
+This lint catches transmuting from `&T` to `&mut T` because it is undefined
 behavior. Some example code that triggers this lint:
 
 ```rust,ignore
index 7f110d6a3d22c20e4550047121fad058f565312e..32fb8c2f7d58e4f9330946fef58512f133d37076 100644 (file)
@@ -1,6 +1,6 @@
 # Unstable features
 
-Rustdoc is under active developement, and like the Rust compiler, some features are only available
+Rustdoc is under active development, and like the Rust compiler, some features are only available
 on the nightly releases. Some of these are new and need some more testing before they're able to get
 released to the world at large, and some of them are tied to features in the Rust compiler that are
 themselves unstable. Several features here require a matching `#![feature(...)]` attribute to
@@ -106,27 +106,25 @@ The `#[doc(cfg(...))]` attribute has another effect: When Rustdoc renders docume
 item, it will be accompanied by a banner explaining that the item is only available on certain
 platforms.
 
-As mentioned earlier, getting the items to Rustdoc requires some extra preparation. The standard
-library adds a `--cfg dox` flag to every Rustdoc command, but the same thing can be accomplished by
-adding a feature to your Cargo.toml and adding `--feature dox` (or whatever you choose to name the
-feature) to your `cargo doc` calls.
+For Rustdoc to document an item, it needs to see it, regardless of what platform it's currently
+running on. To aid this, Rustdoc sets the flag `#[cfg(rustdoc)]` when running on your crate.
+Combining this with the target platform of a given item allows it to appear when building your crate
+normally on that platform, as well as when building documentation anywhere.
 
-Either way, once you create an environment for the documentation, you can start to augment your
-`#[cfg]` attributes to allow both the target platform *and* the documentation configuration to leave
-the item in. For example, `#[cfg(any(windows, feature = "dox"))]` will preserve the item either on
-Windows or during the documentation process. Then, adding a new attribute `#[doc(cfg(windows))]`
-will tell Rustdoc that the item is supposed to be used on Windows. For example:
+For example, `#[cfg(any(windows, rustdoc))]` will preserve the item either on Windows or during the
+documentation process. Then, adding a new attribute `#[doc(cfg(windows))]` will tell Rustdoc that
+the item is supposed to be used on Windows. For example:
 
 ```rust
 #![feature(doc_cfg)]
 
 /// Token struct that can only be used on Windows.
-#[cfg(any(windows, feature = "dox"))]
+#[cfg(any(windows, rustdoc))]
 #[doc(cfg(windows))]
 pub struct WindowsToken;
 
 /// Token struct that can only be used on Unix.
-#[cfg(any(unix, feature = "dox"))]
+#[cfg(any(unix, rustdoc))]
 #[doc(cfg(unix))]
 pub struct UnixToken;
 ```
@@ -361,6 +359,21 @@ This flag allows rustdoc to treat your rust code as the given edition. It will c
 the given edition as well. As with `rustc`, the default edition that `rustdoc` will use is `2015`
 (the first edition).
 
+### `--extern-html-root-url`: control how rustdoc links to non-local crates
+
+Using this flag looks like this:
+
+```bash
+$ rustdoc src/lib.rs -Z unstable-options --extern-html-root-url some-crate=https://example.com/some-crate/1.0.1
+```
+
+Ordinarily, when rustdoc wants to link to a type from a different crate, it looks in two places:
+docs that already exist in the output directory, or the `#![doc(doc_html_root)]` set in the other
+crate. However, if you want to link to docs that exist in neither of those places, you can use these
+flags to control that behavior. When the `--extern-html-root-url` flag is given with a name matching
+one of your dependencies, rustdoc use that URL for those docs. Keep in mind that if those docs exist
+in the output directory, those local docs will still override this flag.
+
 ### `-Z force-unstable-if-unmarked`
 
 Using this flag looks like this:
diff --git a/src/doc/unstable-book/src/language-features/attr-literals.md b/src/doc/unstable-book/src/language-features/attr-literals.md
deleted file mode 100644 (file)
index 6606f3c..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# `attr_literals`
-
-The tracking issue for this feature is: [#34981]
-
-[#34981]: https://github.com/rust-lang/rust/issues/34981
-
-------------------------
-
-At present, literals are only accepted as the value of a key-value pair in
-attributes. What's more, only _string_ literals are accepted. This means that
-literals can only appear in forms of `#[attr(name = "value")]` or
-`#[attr = "value"]`.
-
-The `attr_literals` unstable feature allows other types of literals to be used
-in attributes. Here are some examples of attributes that can now be used with
-this feature enabled:
-
-```rust,ignore
-#[attr]
-#[attr(true)]
-#[attr(ident)]
-#[attr(ident, 100, true, "true", ident = 100, ident = "hello", ident(100))]
-#[attr(100)]
-#[attr(enabled = true)]
-#[enabled(true)]
-#[attr("hello")]
-#[repr(C, align = 4)]
-#[repr(C, align(4))]
-```
-
diff --git a/src/doc/unstable-book/src/language-features/catch-expr.md b/src/doc/unstable-book/src/language-features/catch-expr.md
deleted file mode 100644 (file)
index 247333d..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# `catch_expr`
-
-The tracking issue for this feature is: [#31436]
-
-[#31436]: https://github.com/rust-lang/rust/issues/31436
-
-------------------------
-
-The `catch_expr` feature adds support for a `catch` expression. The `catch`
-expression creates a new scope one can use the `?` operator in.
-
-```rust
-#![feature(catch_expr)]
-
-use std::num::ParseIntError;
-
-let result: Result<i32, ParseIntError> = do catch {
-    "1".parse::<i32>()?
-        + "2".parse::<i32>()?
-        + "3".parse::<i32>()?
-};
-assert_eq!(result, Ok(6));
-
-let result: Result<i32, ParseIntError> = do catch {
-    "1".parse::<i32>()?
-        + "foo".parse::<i32>()?
-        + "3".parse::<i32>()?
-};
-assert!(result.is_err());
-```
index ddc538e12144ac5ff5a2d692d5aba400c4ca3843..96c66a1515ed5495b2da721e641ce191fe5167f7 100644 (file)
@@ -12,13 +12,17 @@ This attribute has two effects:
 
 2. The item's doc-tests will only run on the specific platform.
 
+In addition to allowing the use of the `#[doc(cfg)]` attribute, this feature enables the use of a
+special conditional compilation flag, `#[cfg(rustdoc)]`, set whenever building documentation on your
+crate.
+
 This feature was introduced as part of PR [#43348] to allow the platform-specific parts of the
 standard library be documented.
 
 ```rust
 #![feature(doc_cfg)]
 
-#[cfg(any(windows, feature = "documentation"))]
+#[cfg(any(windows, rustdoc))]
 #[doc(cfg(windows))]
 /// The application's icon in the notification area (a.k.a. system tray).
 ///
@@ -39,4 +43,4 @@ pub struct Icon {
 ```
 
 [#43781]: https://github.com/rust-lang/rust/issues/43781
-[#43348]: https://github.com/rust-lang/rust/issues/43348
\ No newline at end of file
+[#43348]: https://github.com/rust-lang/rust/issues/43348
index 73c7eafdb98d583b24f65201714e3ba07d5babb0..fe82f8555da329e3ba96fbb10bb8b440891121e0 100644 (file)
@@ -6,12 +6,12 @@ The tracking issue for this feature is: [#44493]
 
 ------------------------
 The `infer_outlives_requirements` feature indicates that certain
-outlives requirements can be infered by the compiler rather than
+outlives requirements can be inferred by the compiler rather than
 stating them explicitly.
 
 For example, currently generic struct definitions that contain
 references, require where-clauses of the form T: 'a. By using
-this feature the outlives predicates will be infered, although
+this feature the outlives predicates will be inferred, although
 they may still be written explicitly.
 
 ```rust,ignore (pseudo-Rust)
index f50472fb41e31128d1dcb1da186dc66516ecd35f..6187f395b0498ebf70c856d2b5d9d26292e25a5e 100644 (file)
@@ -6,7 +6,7 @@ The tracking issue for this feature is: [#44493]
 
 ------------------------
 The `infer_static_outlives_requirements` feature indicates that certain
-`'static` outlives requirements can be infered by the compiler rather than
+`'static` outlives requirements can be inferred by the compiler rather than
 stating them explicitly.
 
 Note: It is an accompanying feature to `infer_outlives_requirements`,
@@ -14,7 +14,7 @@ which must be enabled to infer outlives requirements.
 
 For example, currently generic struct definitions that contain
 references, require where-clauses of the form T: 'static. By using
-this feature the outlives predicates will be infered, although
+this feature the outlives predicates will be inferred, although
 they may still be written explicitly.
 
 ```rust,ignore (pseudo-Rust)
diff --git a/src/doc/unstable-book/src/language-features/macro-vis-matcher.md b/src/doc/unstable-book/src/language-features/macro-vis-matcher.md
deleted file mode 100644 (file)
index 7918a35..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-# `macro_vis_matcher`
-
-The tracking issue for this feature is: [#41022]
-
-With this feature gate enabled, the [list of fragment specifiers][frags] gains one more entry:
-
-* `vis`: a visibility qualifier. Examples: nothing (default visibility); `pub`; `pub(crate)`.
-
-A `vis` variable may be followed by a comma, ident, type, or path.
-
-[#41022]: https://github.com/rust-lang/rust/issues/41022
-[frags]: ../book/first-edition/macros.html#syntactic-requirements
-
-------------------------
index 19ece09509078d450c11f6a1efe0f09d12900139..b408d5d0805152008ed803dbd6c5fa8ef0fd5128 100644 (file)
@@ -183,7 +183,6 @@ that warns about any item named `lintme`.
 ```rust,ignore
 #![feature(plugin_registrar)]
 #![feature(box_syntax, rustc_private)]
-#![feature(macro_vis_matcher)]
 #![feature(macro_at_most_once_rep)]
 
 extern crate syntax;
diff --git a/src/doc/unstable-book/src/language-features/tool-attributes.md b/src/doc/unstable-book/src/language-features/tool-attributes.md
deleted file mode 100644 (file)
index 15fc84a..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-# `tool_attributes`
-
-The tracking issue for this feature is: [#44690]
-
-[#44690]: https://github.com/rust-lang/rust/issues/44690
-
-------------------------
-
-Tool attributes let you use scoped attributes to control the behavior
-of certain tools.
-
-Currently tool names which can be appear in scoped attributes are restricted to
-`clippy` and `rustfmt`.
-
-## An example
-
-```rust
-#![feature(tool_attributes)]
-
-#[rustfmt::skip]
-fn foo() { println!("hello, world"); }
-
-fn main() {
-    foo();
-}
-```
diff --git a/src/doc/unstable-book/src/language-features/try-blocks.md b/src/doc/unstable-book/src/language-features/try-blocks.md
new file mode 100644 (file)
index 0000000..866b37a
--- /dev/null
@@ -0,0 +1,32 @@
+# `try_blocks`
+
+The tracking issue for this feature is: [#31436]
+
+[#31436]: https://github.com/rust-lang/rust/issues/31436
+
+------------------------
+
+The `try_blocks` feature adds support for `try` blocks. A `try`
+block creates a new scope one can use the `?` operator in.
+
+```rust,ignore
+// This code needs the 2018 edition
+
+#![feature(try_blocks)]
+
+use std::num::ParseIntError;
+
+let result: Result<i32, ParseIntError> = try {
+    "1".parse::<i32>()?
+        + "2".parse::<i32>()?
+        + "3".parse::<i32>()?
+};
+assert_eq!(result, Ok(6));
+
+let result: Result<i32, ParseIntError> = try {
+    "1".parse::<i32>()?
+        + "foo".parse::<i32>()?
+        + "3".parse::<i32>()?
+};
+assert!(result.is_err());
+```
index c3b7f2e41e15b27b265f37fcc75e53801538ef8c..d49271382b60496d7e1b69d065f5408119e4f4d8 100644 (file)
@@ -87,7 +87,7 @@ This condition can be met using `#[used]` and `#[link_section]` plus a linker
 script.
 
 ``` rust,ignore
-#![feature(panic_implementation)]
+#![feature(panic_handler)]
 #![feature(used)]
 #![no_main]
 #![no_std]
@@ -102,8 +102,8 @@ extern "C" fn reset_handler() -> ! {
 #[used]
 static RESET_HANDLER: extern "C" fn() -> ! = reset_handler;
 
-#[panic_implementation]
-fn panic_impl(info: &PanicInfo) -> ! {
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
     loop {}
 }
 ```
index 6835d6aa90874b7b7372dc8d68e557246a644696..743952a5bef89894134c7c785e11097dd2efe95d 100755 (executable)
@@ -20,7 +20,7 @@ GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc"
 # Set the environment variable `RUST_GDB` to overwrite the call to a
 # different/specific command (defaults to `gdb`).
 RUST_GDB="${RUST_GDB:-gdb}"
-PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" ${RUST_GDB} \
+PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" exec ${RUST_GDB} \
   --directory="$GDB_PYTHON_MODULE_DIRECTORY" \
   -iex "add-auto-load-safe-path $GDB_PYTHON_MODULE_DIRECTORY" \
   "$@"
diff --git a/src/etc/rust-gdbgui b/src/etc/rust-gdbgui
new file mode 100755 (executable)
index 0000000..7e179ba
--- /dev/null
@@ -0,0 +1,65 @@
+#!/bin/sh
+# 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.
+
+# Exit if anything fails
+set -e
+
+if [ $# -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "-help" ] || [ "$1" = "--help" ]; then
+    echo "
+rust-gdbgui
+===========
+gdbgui - https://gdbgui.com - is a graphical front-end to GDB
+that runs in a browser. This script invokes gdbgui with the Rust
+pretty printers loaded.
+
+Simple usage  : rust-gdbgui target/debug/myprog
+With arguments: rust-gdbgui 'target/debug/myprog arg1 arg2...'
+  (note the quotes)
+
+
+Hints
+=====
+gdbgui won't be able to find the rust 'main' method automatically, so
+in its options make sure to disable the 'Add breakpoint to main after
+loading executable' setting to avoid a 'File not found: main' warning
+on startup.
+
+Instead, type 'main' into gdbgui's file browser and you should get
+auto-completion on the filename. Just pick 'main.rs', add a breakpoint
+by clicking in the line number gutter, and type 'r' or hit the Restart
+icon to start your program running.
+"
+    exit 0
+fi
+
+# Find out where the pretty printer Python module is
+RUSTC_SYSROOT=`rustc --print=sysroot`
+GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc"
+
+# Set the environment variable `RUST_GDB` to overwrite the call to a
+# different/specific command (defaults to `gdb`).
+RUST_GDB="${RUST_GDB:-gdb}"
+
+# Set the environment variable `RUST_GDBGUI` to overwrite the call to a
+# different/specific command (defaults to `gdbgui`).
+RUST_GDBGUI="${RUST_GDBGUI:-gdbgui}"
+
+# These arguments get passed through to GDB and make it load the
+# Rust pretty printers.
+GDB_ARGS="--directory=\"$GDB_PYTHON_MODULE_DIRECTORY\" -iex \"add-auto-load-safe-path $GDB_PYTHON_MODULE_DIRECTORY\""
+
+# Finally we execute gdbgui.
+PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" \
+  exec ${RUST_GDBGUI} \
+  --gdb ${RUST_GDB} \
+  --gdb-args "${GDB_ARGS}" \
+  "${@}"
+
index f70ab65bce717044d448d893c445339268293795..6a2849b55485e0ae05454ce93c96d6c518ab5bb5 100755 (executable)
@@ -23,19 +23,16 @@ display the contents of local variables!"
     echo "***"
 fi
 
-# Create a tempfile containing the LLDB script we want to execute on startup
-TMPFILE=`mktemp /tmp/rust-lldb-commands.XXXXXX`
-
-# Make sure to delete the tempfile no matter what
-trap "rm -f $TMPFILE; exit" INT TERM EXIT
-
 # Find out where to look for the pretty printer Python module
 RUSTC_SYSROOT=`rustc --print sysroot`
 
-# Write the LLDB script to the tempfile
-echo "command script import \"$RUSTC_SYSROOT/lib/rustlib/etc/lldb_rust_formatters.py\"" >> $TMPFILE
-echo "type summary add --no-value --python-function lldb_rust_formatters.print_val -x \".*\" --category Rust" >> $TMPFILE
-echo "type category enable Rust" >> $TMPFILE
+# Prepare commands that will be loaded before any file on the command line has been loaded
+script_import="command script import \"$RUSTC_SYSROOT/lib/rustlib/etc/lldb_rust_formatters.py\""
+category_definition="type summary add --no-value --python-function lldb_rust_formatters.print_val -x \".*\" --category Rust"
+category_enable="type category enable Rust"
 
-# Call LLDB with the script added to the argument list
-lldb --source-before-file="$TMPFILE" "$@"
+# Call LLDB with the commands added to the argument list
+exec lldb --one-line-before-file="$script_import" \
+    --one-line-before-file="$category_definition" \
+    --one-line-before-file="$category_enable" \
+    "$@"
index c69b2fb5e1c2a3e27619f5994f767d8f49d036db..3bd0c243b39acfd3e6eca39abf5b51c08f52b0ff 100644 (file)
@@ -245,7 +245,7 @@ fn allocate_zeroed() {
                 .unwrap_or_else(|_| handle_alloc_error(layout));
 
             let mut i = ptr.cast::<u8>().as_ptr();
-            let end = i.offset(layout.size() as isize);
+            let end = i.add(layout.size());
             while i < end {
                 assert_eq!(*i, 0);
                 i = i.offset(1);
index c6741ddb822d5bb9114889bc71fdd2203f72e559..5ae5339138fbed3ef3bbc1049ca1d686f094f924 100644 (file)
@@ -141,6 +141,41 @@ fn clone_into(&self, target: &mut T) {
 /// let mut input = Cow::from(vec![-1, 0, 1]);
 /// abs_all(&mut input);
 /// ```
+///
+/// Another example showing how to keep `Cow` in a struct:
+///
+/// ```
+/// use std::borrow::{Cow, ToOwned};
+///
+/// struct Items<'a, X: 'a> where [X]: ToOwned<Owned=Vec<X>> {
+///     values: Cow<'a, [X]>,
+/// }
+///
+/// impl<'a, X: Clone + 'a> Items<'a, X> where [X]: ToOwned<Owned=Vec<X>> {
+///     fn new(v: Cow<'a, [X]>) -> Self {
+///         Items { values: v }
+///     }
+/// }
+///
+/// // Creates a container from borrowed values of a slice
+/// let readonly = [1, 2];
+/// let borrowed = Items::new((&readonly[..]).into());
+/// match borrowed {
+///     Items { values: Cow::Borrowed(b) } => println!("borrowed {:?}", b),
+///     _ => panic!("expect borrowed value"),
+/// }
+///
+/// let mut clone_on_write = borrowed;
+/// // Mutates the data from slice into owned vec and pushes a new value on top
+/// clone_on_write.values.to_mut().push(3);
+/// println!("clone_on_write = {:?}", clone_on_write.values);
+///
+/// // The data was mutated. Let check it out.
+/// match clone_on_write {
+///     Items { values: Cow::Owned(_) } => println!("clone_on_write contains owned data"),
+///     _ => panic!("expect owned data"),
+/// }
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Cow<'a, B: ?Sized + 'a>
     where B: ToOwned
index 08db5136d040450c0164841ed8fed83d0be2ad1f..c25f3eb8f17504776b8da2abb6f448e53309661d 100644 (file)
 use core::hash::{Hash, Hasher};
 use core::iter::FusedIterator;
 use core::marker::{Unpin, Unsize};
-use core::mem::{self, PinMut};
+use core::mem;
+use core::pin::PinMut;
 use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
 use core::ptr::{self, NonNull, Unique};
 use core::task::{Context, Poll, Spawn, SpawnErrorKind, SpawnObjError};
 
 use raw_vec::RawVec;
+use pin::PinBox;
 use str::from_boxed_utf8_unchecked;
 
 /// A pointer type for heap allocation.
@@ -126,7 +128,9 @@ pub unsafe fn from_raw(raw: *mut T) -> Self {
         Box(Unique::new_unchecked(raw))
     }
 
-    /// Consumes the `Box`, returning the wrapped raw pointer.
+    /// Consumes the `Box`, returning a wrapped raw pointer.
+    ///
+    /// The pointer will be properly aligned and non-null.
     ///
     /// After calling this function, the caller is responsible for the
     /// memory previously managed by the `Box`. In particular, the
@@ -704,7 +708,7 @@ unsafe fn into_box(self) -> Box<[T]> {
         impl<T> Drop for BoxBuilder<T> {
             fn drop(&mut self) {
                 let mut data = self.data.ptr();
-                let max = unsafe { data.offset(self.len as isize) };
+                let max = unsafe { data.add(self.len) };
 
                 while data != max {
                     unsafe {
@@ -756,166 +760,6 @@ unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
     }
 }
 
-/// A pinned, heap allocated reference.
-#[unstable(feature = "pin", issue = "49150")]
-#[fundamental]
-#[repr(transparent)]
-pub struct PinBox<T: ?Sized> {
-    inner: Box<T>,
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<T> PinBox<T> {
-    /// Allocate memory on the heap, move the data into it and pin it.
-    #[unstable(feature = "pin", issue = "49150")]
-    pub fn new(data: T) -> PinBox<T> {
-        PinBox { inner: Box::new(data) }
-    }
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<T: ?Sized> PinBox<T> {
-    /// Get a pinned reference to the data in this PinBox.
-    #[inline]
-    pub fn as_pin_mut<'a>(&'a mut self) -> PinMut<'a, T> {
-        unsafe { PinMut::new_unchecked(&mut *self.inner) }
-    }
-
-    /// Constructs a `PinBox` from a raw pointer.
-    ///
-    /// After calling this function, the raw pointer is owned by the
-    /// resulting `PinBox`. Specifically, the `PinBox` destructor will call
-    /// the destructor of `T` and free the allocated memory. Since the
-    /// way `PinBox` allocates and releases memory is unspecified, the
-    /// only valid pointer to pass to this function is the one taken
-    /// from another `PinBox` via the [`PinBox::into_raw`] function.
-    ///
-    /// This function is unsafe because improper use may lead to
-    /// memory problems. For example, a double-free may occur if the
-    /// function is called twice on the same raw pointer.
-    ///
-    /// [`PinBox::into_raw`]: struct.PinBox.html#method.into_raw
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(pin)]
-    /// use std::boxed::PinBox;
-    /// let x = PinBox::new(5);
-    /// let ptr = PinBox::into_raw(x);
-    /// let x = unsafe { PinBox::from_raw(ptr) };
-    /// ```
-    #[inline]
-    pub unsafe fn from_raw(raw: *mut T) -> Self {
-        PinBox { inner: Box::from_raw(raw) }
-    }
-
-    /// Consumes the `PinBox`, returning the wrapped raw pointer.
-    ///
-    /// After calling this function, the caller is responsible for the
-    /// memory previously managed by the `PinBox`. In particular, the
-    /// caller should properly destroy `T` and release the memory. The
-    /// proper way to do so is to convert the raw pointer back into a
-    /// `PinBox` with the [`PinBox::from_raw`] function.
-    ///
-    /// Note: this is an associated function, which means that you have
-    /// to call it as `PinBox::into_raw(b)` instead of `b.into_raw()`. This
-    /// is so that there is no conflict with a method on the inner type.
-    ///
-    /// [`PinBox::from_raw`]: struct.PinBox.html#method.from_raw
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(pin)]
-    /// use std::boxed::PinBox;
-    /// let x = PinBox::new(5);
-    /// let ptr = PinBox::into_raw(x);
-    /// ```
-    #[inline]
-    pub fn into_raw(b: PinBox<T>) -> *mut T {
-        Box::into_raw(b.inner)
-    }
-
-    /// Get a mutable reference to the data inside this PinBox.
-    ///
-    /// This function is unsafe. Users must guarantee that the data is never
-    /// moved out of this reference.
-    #[inline]
-    pub unsafe fn get_mut<'a>(this: &'a mut PinBox<T>) -> &'a mut T {
-        &mut *this.inner
-    }
-
-    /// Convert this PinBox into an unpinned Box.
-    ///
-    /// This function is unsafe. Users must guarantee that the data is never
-    /// moved out of the box.
-    #[inline]
-    pub unsafe fn unpin(this: PinBox<T>) -> Box<T> {
-        this.inner
-    }
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<T: ?Sized> From<Box<T>> for PinBox<T> {
-    fn from(boxed: Box<T>) -> PinBox<T> {
-        PinBox { inner: boxed }
-    }
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<T: Unpin + ?Sized> From<PinBox<T>> for Box<T> {
-    fn from(pinned: PinBox<T>) -> Box<T> {
-        pinned.inner
-    }
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<T: ?Sized> Deref for PinBox<T> {
-    type Target = T;
-
-    fn deref(&self) -> &T {
-        &*self.inner
-    }
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<T: Unpin + ?Sized> DerefMut for PinBox<T> {
-    fn deref_mut(&mut self) -> &mut T {
-        &mut *self.inner
-    }
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<T: fmt::Display + ?Sized> fmt::Display for PinBox<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&*self.inner, f)
-    }
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<T: fmt::Debug + ?Sized> fmt::Debug for PinBox<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(&*self.inner, f)
-    }
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<T: ?Sized> fmt::Pointer for PinBox<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        // It's not possible to extract the inner Uniq directly from the Box,
-        // instead we cast it to a *const which aliases the Unique
-        let ptr: *const T = &*self.inner;
-        fmt::Pointer::fmt(&ptr, f)
-    }
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinBox<U>> for PinBox<T> {}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<T: ?Sized> Unpin for PinBox<T> {}
-
 #[unstable(feature = "futures_api", issue = "50547")]
 impl<F: ?Sized + Future + Unpin> Future for Box<F> {
     type Output = F::Output;
@@ -925,15 +769,6 @@ fn poll(mut self: PinMut<Self>, cx: &mut Context) -> Poll<Self::Output> {
     }
 }
 
-#[unstable(feature = "futures_api", issue = "50547")]
-impl<F: ?Sized + Future> Future for PinBox<F> {
-    type Output = F::Output;
-
-    fn poll(mut self: PinMut<Self>, cx: &mut Context) -> Poll<Self::Output> {
-        self.as_pin_mut().poll(cx)
-    }
-}
-
 #[unstable(feature = "futures_api", issue = "50547")]
 unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box<F>
     where F: Future<Output = T> + 'a
@@ -953,25 +788,6 @@ unsafe fn drop(ptr: *mut ()) {
     }
 }
 
-#[unstable(feature = "futures_api", issue = "50547")]
-unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinBox<F>
-    where F: Future<Output = T> + 'a
-{
-    fn into_raw(self) -> *mut () {
-        PinBox::into_raw(self) as *mut ()
-    }
-
-    unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> {
-        let ptr = ptr as *mut F;
-        let pin: PinMut<F> = PinMut::new_unchecked(&mut *ptr);
-        pin.poll(cx)
-    }
-
-    unsafe fn drop(ptr: *mut ()) {
-        drop(PinBox::from_raw(ptr as *mut F))
-    }
-}
-
 #[unstable(feature = "futures_api", issue = "50547")]
 impl<Sp> Spawn for Box<Sp>
     where Sp: Spawn + ?Sized
@@ -988,13 +804,6 @@ fn status(&self) -> Result<(), SpawnErrorKind> {
     }
 }
 
-#[unstable(feature = "futures_api", issue = "50547")]
-impl<'a, F: Future<Output = ()> + Send + 'a> From<PinBox<F>> for FutureObj<'a, ()> {
-    fn from(boxed: PinBox<F>) -> Self {
-        FutureObj::new(boxed)
-    }
-}
-
 #[unstable(feature = "futures_api", issue = "50547")]
 impl<'a, F: Future<Output = ()> + Send + 'a> From<Box<F>> for FutureObj<'a, ()> {
     fn from(boxed: Box<F>) -> Self {
@@ -1003,15 +812,15 @@ fn from(boxed: Box<F>) -> Self {
 }
 
 #[unstable(feature = "futures_api", issue = "50547")]
-impl<'a, F: Future<Output = ()> + 'a> From<PinBox<F>> for LocalFutureObj<'a, ()> {
-    fn from(boxed: PinBox<F>) -> Self {
+impl<'a, F: Future<Output = ()> + 'a> From<Box<F>> for LocalFutureObj<'a, ()> {
+    fn from(boxed: Box<F>) -> Self {
         LocalFutureObj::new(boxed)
     }
 }
 
-#[unstable(feature = "futures_api", issue = "50547")]
-impl<'a, F: Future<Output = ()> + 'a> From<Box<F>> for LocalFutureObj<'a, ()> {
-    fn from(boxed: Box<F>) -> Self {
-        LocalFutureObj::new(boxed)
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: Unpin + ?Sized> From<PinBox<T>> for Box<T> {
+    fn from(pinned: PinBox<T>) -> Box<T> {
+        unsafe { PinBox::unpin(pinned) }
     }
 }
index 0ae45b3123259a2b7dbb4c7286d3207757f3f3b4..0315545262b6bc0a295953f22b4328070223356b 100644 (file)
@@ -1151,12 +1151,12 @@ pub fn split(mut self)
             let new_len = self.node.len() - self.idx - 1;
 
             ptr::copy_nonoverlapping(
-                self.node.keys().as_ptr().offset(self.idx as isize + 1),
+                self.node.keys().as_ptr().add(self.idx + 1),
                 new_node.keys.as_mut_ptr(),
                 new_len
             );
             ptr::copy_nonoverlapping(
-                self.node.vals().as_ptr().offset(self.idx as isize + 1),
+                self.node.vals().as_ptr().add(self.idx + 1),
                 new_node.vals.as_mut_ptr(),
                 new_len
             );
@@ -1209,17 +1209,17 @@ pub fn split(mut self)
             let new_len = self.node.len() - self.idx - 1;
 
             ptr::copy_nonoverlapping(
-                self.node.keys().as_ptr().offset(self.idx as isize + 1),
+                self.node.keys().as_ptr().add(self.idx + 1),
                 new_node.data.keys.as_mut_ptr(),
                 new_len
             );
             ptr::copy_nonoverlapping(
-                self.node.vals().as_ptr().offset(self.idx as isize + 1),
+                self.node.vals().as_ptr().add(self.idx + 1),
                 new_node.data.vals.as_mut_ptr(),
                 new_len
             );
             ptr::copy_nonoverlapping(
-                self.node.as_internal().edges.as_ptr().offset(self.idx as isize + 1),
+                self.node.as_internal().edges.as_ptr().add(self.idx + 1),
                 new_node.edges.as_mut_ptr(),
                 new_len + 1
             );
@@ -1283,14 +1283,14 @@ pub fn merge(mut self)
                        slice_remove(self.node.keys_mut(), self.idx));
             ptr::copy_nonoverlapping(
                 right_node.keys().as_ptr(),
-                left_node.keys_mut().as_mut_ptr().offset(left_len as isize + 1),
+                left_node.keys_mut().as_mut_ptr().add(left_len + 1),
                 right_len
             );
             ptr::write(left_node.vals_mut().get_unchecked_mut(left_len),
                        slice_remove(self.node.vals_mut(), self.idx));
             ptr::copy_nonoverlapping(
                 right_node.vals().as_ptr(),
-                left_node.vals_mut().as_mut_ptr().offset(left_len as isize + 1),
+                left_node.vals_mut().as_mut_ptr().add(left_len + 1),
                 right_len
             );
 
@@ -1309,7 +1309,7 @@ pub fn merge(mut self)
                              .as_internal_mut()
                              .edges
                              .as_mut_ptr()
-                             .offset(left_len as isize + 1),
+                             .add(left_len + 1),
                     right_len + 1
                 );
 
@@ -1394,10 +1394,10 @@ pub fn bulk_steal_left(&mut self, count: usize) {
 
                 // Make room for stolen elements in the right child.
                 ptr::copy(right_kv.0,
-                          right_kv.0.offset(count as isize),
+                          right_kv.0.add(count),
                           right_len);
                 ptr::copy(right_kv.1,
-                          right_kv.1.offset(count as isize),
+                          right_kv.1.add(count),
                           right_len);
 
                 // Move elements from the left child to the right one.
@@ -1418,7 +1418,7 @@ pub fn bulk_steal_left(&mut self, count: usize) {
                     // Make room for stolen edges.
                     let right_edges = right.reborrow_mut().as_internal_mut().edges.as_mut_ptr();
                     ptr::copy(right_edges,
-                              right_edges.offset(count as isize),
+                              right_edges.add(count),
                               right_len + 1);
                     right.correct_childrens_parent_links(count, count + right_len + 1);
 
@@ -1463,10 +1463,10 @@ pub fn bulk_steal_right(&mut self, count: usize) {
                 move_kv(right_kv, count - 1, parent_kv, 0, 1);
 
                 // Fix right indexing
-                ptr::copy(right_kv.0.offset(count as isize),
+                ptr::copy(right_kv.0.add(count),
                           right_kv.0,
                           new_right_len);
-                ptr::copy(right_kv.1.offset(count as isize),
+                ptr::copy(right_kv.1.add(count),
                           right_kv.1,
                           new_right_len);
             }
@@ -1480,7 +1480,7 @@ pub fn bulk_steal_right(&mut self, count: usize) {
 
                     // Fix right indexing.
                     let right_edges = right.reborrow_mut().as_internal_mut().edges.as_mut_ptr();
-                    ptr::copy(right_edges.offset(count as isize),
+                    ptr::copy(right_edges.add(count),
                               right_edges,
                               new_right_len + 1);
                     right.correct_childrens_parent_links(0, new_right_len + 1);
@@ -1497,11 +1497,11 @@ unsafe fn move_kv<K, V>(
     dest: (*mut K, *mut V), dest_offset: usize,
     count: usize)
 {
-    ptr::copy_nonoverlapping(source.0.offset(source_offset as isize),
-                             dest.0.offset(dest_offset as isize),
+    ptr::copy_nonoverlapping(source.0.add(source_offset),
+                             dest.0.add(dest_offset),
                              count);
-    ptr::copy_nonoverlapping(source.1.offset(source_offset as isize),
-                             dest.1.offset(dest_offset as isize),
+    ptr::copy_nonoverlapping(source.1.add(source_offset),
+                             dest.1.add(dest_offset),
                              count);
 }
 
@@ -1513,8 +1513,8 @@ unsafe fn move_edges<K, V>(
 {
     let source_ptr = source.as_internal_mut().edges.as_mut_ptr();
     let dest_ptr = dest.as_internal_mut().edges.as_mut_ptr();
-    ptr::copy_nonoverlapping(source_ptr.offset(source_offset as isize),
-                             dest_ptr.offset(dest_offset as isize),
+    ptr::copy_nonoverlapping(source_ptr.add(source_offset),
+                             dest_ptr.add(dest_offset),
                              count);
     dest.correct_childrens_parent_links(dest_offset, dest_offset + count);
 }
@@ -1604,8 +1604,8 @@ pub enum Edge { }
 
 unsafe fn slice_insert<T>(slice: &mut [T], idx: usize, val: T) {
     ptr::copy(
-        slice.as_ptr().offset(idx as isize),
-        slice.as_mut_ptr().offset(idx as isize + 1),
+        slice.as_ptr().add(idx),
+        slice.as_mut_ptr().add(idx + 1),
         slice.len() - idx
     );
     ptr::write(slice.get_unchecked_mut(idx), val);
@@ -1614,8 +1614,8 @@ unsafe fn slice_insert<T>(slice: &mut [T], idx: usize, val: T) {
 unsafe fn slice_remove<T>(slice: &mut [T], idx: usize) -> T {
     let ret = ptr::read(slice.get_unchecked(idx));
     ptr::copy(
-        slice.as_ptr().offset(idx as isize + 1),
-        slice.as_mut_ptr().offset(idx as isize),
+        slice.as_ptr().add(idx + 1),
+        slice.as_mut_ptr().add(idx),
         slice.len() - idx - 1
     );
     ret
index 0f759bb8f0b4f9e2f97daf96ca4c6919e75d82cc..c53549ab85d6d5aa075e9f0e168f0d4e512ae206 100644 (file)
@@ -19,6 +19,7 @@
 
 use core::cmp::Ordering;
 use core::fmt;
+use core::isize;
 use core::iter::{repeat, FromIterator, FusedIterator};
 use core::mem;
 use core::ops::Bound::{Excluded, Included, Unbounded};
@@ -126,13 +127,13 @@ unsafe fn buffer_as_mut_slice(&mut self) -> &mut [T] {
     /// Moves an element out of the buffer
     #[inline]
     unsafe fn buffer_read(&mut self, off: usize) -> T {
-        ptr::read(self.ptr().offset(off as isize))
+        ptr::read(self.ptr().add(off))
     }
 
     /// Writes an element into the buffer, moving it.
     #[inline]
     unsafe fn buffer_write(&mut self, off: usize, value: T) {
-        ptr::write(self.ptr().offset(off as isize), value);
+        ptr::write(self.ptr().add(off), value);
     }
 
     /// Returns `true` if and only if the buffer is at full capacity.
@@ -177,8 +178,8 @@ unsafe fn copy(&self, dst: usize, src: usize, len: usize) {
                       src,
                       len,
                       self.cap());
-        ptr::copy(self.ptr().offset(src as isize),
-                  self.ptr().offset(dst as isize),
+        ptr::copy(self.ptr().add(src),
+                  self.ptr().add(dst),
                   len);
     }
 
@@ -197,26 +198,36 @@ unsafe fn copy_nonoverlapping(&self, dst: usize, src: usize, len: usize) {
                       src,
                       len,
                       self.cap());
-        ptr::copy_nonoverlapping(self.ptr().offset(src as isize),
-                                 self.ptr().offset(dst as isize),
+        ptr::copy_nonoverlapping(self.ptr().add(src),
+                                 self.ptr().add(dst),
                                  len);
     }
 
-    /// Returns a pair of slices which contain the contents of the buffer not used by the VecDeque.
+    /// Copies all values from `src` to the back of `self`, wrapping around if needed.
+    ///
+    /// # Safety
+    ///
+    /// The capacity must be sufficient to hold self.len() + src.len() elements.
+    /// If so, this function never panics.
     #[inline]
-    unsafe fn unused_as_mut_slices<'a>(&'a mut self) -> (&'a mut [T], &'a mut [T]) {
-        let head = self.head;
-        let tail = self.tail;
-        let buf = self.buffer_as_mut_slice();
-        if head != tail {
-            // In buf, head..tail contains the VecDeque and tail..head is unused.
-            // So calling `ring_slices` with tail and head swapped returns unused slices.
-            RingSlices::ring_slices(buf, tail, head)
-        } else {
-            // Swapping doesn't help when head == tail.
-            let (before, after) = buf.split_at_mut(head);
-            (after, before)
-        }
+    unsafe fn copy_slice(&mut self, src: &[T]) {
+        /// This is guaranteed by `RawVec`.
+        debug_assert!(self.capacity() <= isize::MAX as usize);
+
+        let expected_new_len = self.len() + src.len();
+        debug_assert!(self.capacity() >= expected_new_len);
+
+        let dst_high_ptr = self.ptr().add(self.head);
+        let dst_high_len = self.cap() - self.head;
+
+        let split = cmp::min(src.len(), dst_high_len);
+        let (src_high, src_low) = src.split_at(split);
+
+        ptr::copy_nonoverlapping(src_high.as_ptr(), dst_high_ptr, src_high.len());
+        ptr::copy_nonoverlapping(src_low.as_ptr(), self.ptr(), src_low.len());
+
+        self.head = self.wrap_add(self.head, src.len());
+        debug_assert!(self.len() == expected_new_len);
     }
 
     /// Copies a potentially wrapping block of memory len long from src to dest.
@@ -436,7 +447,7 @@ pub fn with_capacity(n: usize) -> VecDeque<T> {
     pub fn get(&self, index: usize) -> Option<&T> {
         if index < self.len() {
             let idx = self.wrap_add(self.tail, index);
-            unsafe { Some(&*self.ptr().offset(idx as isize)) }
+            unsafe { Some(&*self.ptr().add(idx)) }
         } else {
             None
         }
@@ -465,7 +476,7 @@ pub fn get(&self, index: usize) -> Option<&T> {
     pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
         if index < self.len() {
             let idx = self.wrap_add(self.tail, index);
-            unsafe { Some(&mut *self.ptr().offset(idx as isize)) }
+            unsafe { Some(&mut *self.ptr().add(idx)) }
         } else {
             None
         }
@@ -501,8 +512,8 @@ pub fn swap(&mut self, i: usize, j: usize) {
         let ri = self.wrap_add(self.tail, i);
         let rj = self.wrap_add(self.tail, j);
         unsafe {
-            ptr::swap(self.ptr().offset(ri as isize),
-                      self.ptr().offset(rj as isize))
+            ptr::swap(self.ptr().add(ri),
+                      self.ptr().add(rj))
         }
     }
 
@@ -1041,7 +1052,7 @@ pub fn drain<R>(&mut self, range: R) -> Drain<T>
             iter: Iter {
                 tail: drain_tail,
                 head: drain_head,
-                ring: unsafe { self.buffer_as_mut_slice() },
+                ring: unsafe { self.buffer_as_slice() },
             },
         }
     }
@@ -1805,20 +1816,20 @@ pub fn split_off(&mut self, at: usize) -> Self {
                 // `at` lies in the first half.
                 let amount_in_first = first_len - at;
 
-                ptr::copy_nonoverlapping(first_half.as_ptr().offset(at as isize),
+                ptr::copy_nonoverlapping(first_half.as_ptr().add(at),
                                          other.ptr(),
                                          amount_in_first);
 
                 // just take all of the second half.
                 ptr::copy_nonoverlapping(second_half.as_ptr(),
-                                         other.ptr().offset(amount_in_first as isize),
+                                         other.ptr().add(amount_in_first),
                                          second_len);
             } else {
                 // `at` lies in the second half, need to factor in the elements we skipped
                 // in the first half.
                 let offset = at - first_len;
                 let amount_in_second = second_len - offset;
-                ptr::copy_nonoverlapping(second_half.as_ptr().offset(offset as isize),
+                ptr::copy_nonoverlapping(second_half.as_ptr().add(offset),
                                          other.ptr(),
                                          amount_in_second);
             }
@@ -1851,148 +1862,22 @@ pub fn split_off(&mut self, at: usize) -> Self {
     #[inline]
     #[stable(feature = "append", since = "1.4.0")]
     pub fn append(&mut self, other: &mut Self) {
-        // Copies all values from `src_slice` to the start of `dst_slice`.
-        unsafe fn copy_whole_slice<T>(src_slice: &[T], dst_slice: &mut [T]) {
-            let len = src_slice.len();
-            ptr::copy_nonoverlapping(src_slice.as_ptr(), dst_slice[..len].as_mut_ptr(), len);
-        }
-
-        let src_total = other.len();
-
-        // Guarantees there is space in `self` for `other`.
-        self.reserve(src_total);
-
-        self.head = {
-            let original_head = self.head;
-
-            // The goal is to copy all values from `other` into `self`. To avoid any
-            // mismatch, all valid values in `other` are retrieved...
-            let (src_high, src_low) = other.as_slices();
-            // and unoccupied parts of self are retrieved.
-            let (dst_high, dst_low) = unsafe { self.unused_as_mut_slices() };
-
-            // Then all that is needed is to copy all values from
-            // src (src_high and src_low) to dst (dst_high and dst_low).
-            //
-            // other [o o o . . . . . o o o o]
-            //       [5 6 7]         [1 2 3 4]
-            //       src_low         src_high
-            //
-            // self  [. . . . . . o o o o . .]
-            //       [3 4 5 6 7 .]       [1 2]
-            //       dst_low             dst_high
-            //
-            // Values are not copied one by one but as slices in `copy_whole_slice`.
-            // What slices are used depends on various properties of src and dst.
-            // There are 6 cases in total:
-            //     1. `src` is contiguous and fits in dst_high
-            //     2. `src` is contiguous and does not fit in dst_high
-            //     3. `src` is discontiguous and fits in dst_high
-            //     4. `src` is discontiguous and does not fit in dst_high
-            //        + src_high is smaller than dst_high
-            //     5. `src` is discontiguous and does not fit in dst_high
-            //        + dst_high is smaller than src_high
-            //     6. `src` is discontiguous and does not fit in dst_high
-            //        + dst_high is the same size as src_high
-            let src_contiguous = src_low.is_empty();
-            let dst_high_fits_src = dst_high.len() >= src_total;
-            match (src_contiguous, dst_high_fits_src) {
-                (true, true) => {
-                    // 1.
-                    // other [. . . o o o . . . . . .]
-                    //       []    [1 1 1]
-                    //
-                    // self  [. o o o o o . . . . . .]
-                    //       [.]         [1 1 1 . . .]
-
-                    unsafe {
-                        copy_whole_slice(src_high, dst_high);
-                    }
-                    original_head + src_total
-                }
-                (true, false) => {
-                    // 2.
-                    // other [. . . o o o o o . . . .]
-                    //       []    [1 1 2 2 2]
-                    //
-                    // self  [. . . . . . . o o o . .]
-                    //       [2 2 2 . . . .]     [1 1]
+        unsafe {
+            // Guarantees there is space in `self` for `other`.
+            self.reserve(other.len());
 
-                    let (src_1, src_2) = src_high.split_at(dst_high.len());
-                    unsafe {
-                        copy_whole_slice(src_1, dst_high);
-                        copy_whole_slice(src_2, dst_low);
-                    }
-                    src_total - dst_high.len()
-                }
-                (false, true) => {
-                    // 3.
-                    // other [o o . . . . . . . o o o]
-                    //       [2 2]             [1 1 1]
-                    //
-                    // self  [. o o . . . . . . . . .]
-                    //       [.]   [1 1 1 2 2 . . . .]
+            {
+                let (src_high, src_low) = other.as_slices();
 
-                    let (dst_1, dst_2) = dst_high.split_at_mut(src_high.len());
-                    unsafe {
-                        copy_whole_slice(src_high, dst_1);
-                        copy_whole_slice(src_low, dst_2);
-                    }
-                    original_head + src_total
-                }
-                (false, false) => {
-                    if src_high.len() < dst_high.len() {
-                        // 4.
-                        // other [o o o . . . . . . o o o]
-                        //       [2 3 3]           [1 1 1]
-                        //
-                        // self  [. . . . . . o o . . . .]
-                        //       [3 3 . . . .]   [1 1 1 2]
-
-                        let (dst_1, dst_2) = dst_high.split_at_mut(src_high.len());
-                        let (src_2, src_3) = src_low.split_at(dst_2.len());
-                        unsafe {
-                            copy_whole_slice(src_high, dst_1);
-                            copy_whole_slice(src_2, dst_2);
-                            copy_whole_slice(src_3, dst_low);
-                        }
-                        src_3.len()
-                    } else if src_high.len() > dst_high.len() {
-                        // 5.
-                        // other [o o o . . . . . o o o o]
-                        //       [3 3 3]         [1 1 2 2]
-                        //
-                        // self  [. . . . . . o o o o . .]
-                        //       [2 2 3 3 3 .]       [1 1]
-
-                        let (src_1, src_2) = src_high.split_at(dst_high.len());
-                        let (dst_2, dst_3) = dst_low.split_at_mut(src_2.len());
-                        unsafe {
-                            copy_whole_slice(src_1, dst_high);
-                            copy_whole_slice(src_2, dst_2);
-                            copy_whole_slice(src_low, dst_3);
-                        }
-                        dst_2.len() + src_low.len()
-                    } else {
-                        // 6.
-                        // other [o o . . . . . . . o o o]
-                        //       [2 2]             [1 1 1]
-                        //
-                        // self  [. . . . . . . o o . . .]
-                        //       [2 2 . . . . .]   [1 1 1]
-
-                        unsafe {
-                            copy_whole_slice(src_high, dst_high);
-                            copy_whole_slice(src_low, dst_low);
-                        }
-                        src_low.len()
-                    }
-                }
+                // This is only safe because copy_slice never panics when capacity is sufficient.
+                self.copy_slice(src_low);
+                self.copy_slice(src_high);
             }
-        };
 
-        // Some values now exist in both `other` and `self` but are made inaccessible in `other`.
-        other.tail = other.head;
+            // Some values now exist in both `other` and `self` but are made inaccessible
+            // in`other`.
+            other.tail = other.head;
+        }
     }
 
     /// Retains only the elements specified by the predicate.
@@ -2145,11 +2030,11 @@ pub struct Iter<'a, T: 'a> {
 #[stable(feature = "collection_debug", since = "1.17.0")]
 impl<'a, T: 'a + fmt::Debug> fmt::Debug for Iter<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
         f.debug_tuple("Iter")
-         .field(&self.ring)
-         .field(&self.tail)
-         .field(&self.head)
-         .finish()
+            .field(&front)
+            .field(&back)
+            .finish()
     }
 }
 
@@ -2242,11 +2127,11 @@ pub struct IterMut<'a, T: 'a> {
 #[stable(feature = "collection_debug", since = "1.17.0")]
 impl<'a, T: 'a + fmt::Debug> fmt::Debug for IterMut<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let (front, back) = RingSlices::ring_slices(&*self.ring, self.head, self.tail);
         f.debug_tuple("IterMut")
-         .field(&self.ring)
-         .field(&self.tail)
-         .field(&self.head)
-         .finish()
+            .field(&front)
+            .field(&back)
+            .finish()
     }
 }
 
@@ -2709,24 +2594,24 @@ fn from(other: VecDeque<T>) -> Self {
 
             // Need to move the ring to the front of the buffer, as vec will expect this.
             if other.is_contiguous() {
-                ptr::copy(buf.offset(tail as isize), buf, len);
+                ptr::copy(buf.add(tail), buf, len);
             } else {
                 if (tail - head) >= cmp::min(cap - tail, head) {
                     // There is enough free space in the centre for the shortest block so we can
                     // 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),
+                        ptr::copy(buf.add(tail),
+                                  buf.add(tail - head),
                                   cap - tail);
                         // copy left in the end
-                        ptr::copy(buf, buf.offset((cap - head) as isize), head);
+                        ptr::copy(buf, buf.add(cap - head), head);
                         // shift the new thing to the start
-                        ptr::copy(buf.offset((tail - head) as isize), buf, len);
+                        ptr::copy(buf.add(tail - head), 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.add(cap - tail), head);
+                        ptr::copy(buf.add(tail), buf, cap - tail);
                     }
                 } else {
                     // Need to use N swaps to move the ring
@@ -2750,8 +2635,8 @@ fn from(other: VecDeque<T>) -> Self {
                         let mut right_offset = 0;
                         for i in left_edge..right_edge {
                             right_offset = (i - left_edge) % (cap - right_edge);
-                            let src: isize = (right_edge + right_offset) as isize;
-                            ptr::swap(buf.offset(i as isize), buf.offset(src));
+                            let src = right_edge + right_offset;
+                            ptr::swap(buf.add(i), buf.add(src));
                         }
                         let n_ops = right_edge - left_edge;
                         left_edge += n_ops;
@@ -3124,4 +3009,21 @@ fn create_vec_and_test_convert(cap: usize, offset: usize, len: usize) {
         }
     }
 
+    #[test]
+    fn issue_53529() {
+        use boxed::Box;
+
+        let mut dst = VecDeque::new();
+        dst.push_front(Box::new(1));
+        dst.push_front(Box::new(2));
+        assert_eq!(*dst.pop_back().unwrap(), 1);
+
+        let mut src = VecDeque::new();
+        src.push_front(Box::new(2));
+        dst.append(&mut src);
+        for a in dst {
+            assert_eq!(*a, 2);
+        }
+    }
+
 }
index bcdfd8c9aa5d54b00eba93d67eb8a7d027d174e7..452d2b1472ff4a2fb8d9b29e7097ae6da75700fb 100644 (file)
@@ -77,6 +77,7 @@
 #![cfg_attr(not(test), feature(fn_traits))]
 #![cfg_attr(not(test), feature(generator_trait))]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![cfg_attr(test, feature(test))]
 
 #![feature(allocator_api)]
@@ -87,7 +88,8 @@
 #![feature(box_syntax)]
 #![feature(cfg_target_has_atomic)]
 #![feature(coerce_unsized)]
-#![feature(const_fn)]
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(min_const_fn))]
 #![feature(core_intrinsics)]
 #![feature(custom_attribute)]
 #![feature(dropck_eyepatch)]
@@ -159,6 +161,7 @@ mod boxed {
 pub mod sync;
 pub mod rc;
 pub mod raw_vec;
+pub mod pin;
 pub mod prelude;
 pub mod borrow;
 pub mod fmt;
diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs
new file mode 100644 (file)
index 0000000..17bbc98
--- /dev/null
@@ -0,0 +1,302 @@
+//! Types which pin data to its location in memory
+//!
+//! It is sometimes useful to have objects that are guaranteed to not move,
+//! in the sense that their placement in memory does not change, and can thus be relied upon.
+//!
+//! A prime example of such a scenario would be building self-referencial structs,
+//! since moving an object with pointers to itself will invalidate them,
+//! which could cause undefined behavior.
+//!
+//! In order to prevent objects from moving, they must be *pinned*,
+//! by wrapping the data in pinning pointer types, such as [`PinMut`] and [`PinBox`],
+//! which are otherwise equivalent to `& mut` and [`Box`], respectively.
+//!
+//! First of all, these are pointer types because pinned data mustn't be passed around by value
+//! (that would change its location in memory).
+//! Secondly, since data can be moved out of `&mut` and [`Box`] with functions such as [`swap`],
+//! which causes their contents to swap places in memory,
+//! we need dedicated types that prohibit such operations.
+//!
+//! However, these restrictions are usually not necessary,
+//! so most types implement the [`Unpin`] auto-trait,
+//! which indicates that the type can be moved out safely.
+//! Doing so removes the limitations of pinning types,
+//! making them the same as their non-pinning counterparts.
+//!
+//! [`PinMut`]: struct.PinMut.html
+//! [`PinBox`]: struct.PinBox.html
+//! [`Unpin`]: trait.Unpin.html
+//! [`swap`]: ../../std/mem/fn.swap.html
+//! [`Box`]: ../boxed/struct.Box.html
+//!
+//! # Examples
+//!
+//! ```rust
+//! #![feature(pin)]
+//!
+//! use std::pin::PinBox;
+//! use std::marker::Pinned;
+//! use std::ptr::NonNull;
+//!
+//! // This is a self referencial struct since the slice field points to the data field.
+//! // We cannot inform the compiler about that with a normal reference,
+//! // since this pattern cannot be described with the usual borrowing rules.
+//! // Instead we use a raw pointer, though one which is known to not be null,
+//! // since we know it's pointing at the string.
+//! struct Unmovable {
+//!     data: String,
+//!     slice: NonNull<String>,
+//!     _pin: Pinned,
+//! }
+//!
+//! impl Unmovable {
+//!     // To ensure the data doesn't move when the function returns,
+//!     // we place it in the heap where it will stay for the lifetime of the object,
+//!     // and the only way to access it would be through a pointer to it.
+//!     fn new(data: String) -> PinBox<Self> {
+//!         let res = Unmovable {
+//!             data,
+//!             // we only create the pointer once the data is in place
+//!             // otherwise it will have already moved before we even started
+//!             slice: NonNull::dangling(),
+//!             _pin: Pinned,
+//!         };
+//!         let mut boxed = PinBox::new(res);
+//!
+//!         let slice = NonNull::from(&boxed.data);
+//!         // we know this is safe because modifying a field doesn't move the whole struct
+//!         unsafe { PinBox::get_mut(&mut boxed).slice = slice };
+//!         boxed
+//!     }
+//! }
+//!
+//! let unmoved = Unmovable::new("hello".to_string());
+//! // The pointer should point to the correct location,
+//! // so long as the struct hasn't moved.
+//! // Meanwhile, we are free to move the pointer around.
+//! # #[allow(unused_mut)]
+//! let mut still_unmoved = unmoved;
+//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data));
+//!
+//! // Since our type doesn't implement Unpin, this will fail to compile:
+//! // let new_unmoved = Unmovable::new("world".to_string());
+//! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved);
+//! ```
+
+#![unstable(feature = "pin", issue = "49150")]
+
+pub use core::pin::*;
+pub use core::marker::Unpin;
+
+use core::convert::From;
+use core::fmt;
+use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj};
+use core::marker::Unsize;
+use core::ops::{CoerceUnsized, Deref, DerefMut};
+use core::task::{Context, Poll};
+
+use boxed::Box;
+
+/// A pinned, heap allocated reference.
+///
+/// This type is similar to [`Box`], except that it pins its value,
+/// which prevents it from moving out of the reference, unless it implements [`Unpin`].
+///
+/// See the [module documentation] for furthur explaination on pinning.
+///
+/// [`Box`]: ../boxed/struct.Box.html
+/// [`Unpin`]: ../../std/marker/trait.Unpin.html
+/// [module documentation]: index.html
+#[unstable(feature = "pin", issue = "49150")]
+#[fundamental]
+#[repr(transparent)]
+pub struct PinBox<T: ?Sized> {
+    inner: Box<T>,
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T> PinBox<T> {
+    /// Allocate memory on the heap, move the data into it and pin it.
+    #[unstable(feature = "pin", issue = "49150")]
+    pub fn new(data: T) -> PinBox<T> {
+        PinBox { inner: Box::new(data) }
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized> PinBox<T> {
+    /// Get a pinned reference to the data in this PinBox.
+    #[inline]
+    pub fn as_pin_mut<'a>(&'a mut self) -> PinMut<'a, T> {
+        unsafe { PinMut::new_unchecked(&mut *self.inner) }
+    }
+
+    /// Constructs a `PinBox` from a raw pointer.
+    ///
+    /// After calling this function, the raw pointer is owned by the
+    /// resulting `PinBox`. Specifically, the `PinBox` destructor will call
+    /// the destructor of `T` and free the allocated memory. Since the
+    /// way `PinBox` allocates and releases memory is unspecified, the
+    /// only valid pointer to pass to this function is the one taken
+    /// from another `PinBox` via the [`PinBox::into_raw`] function.
+    ///
+    /// This function is unsafe because improper use may lead to
+    /// memory problems. For example, a double-free may occur if the
+    /// function is called twice on the same raw pointer.
+    ///
+    /// [`PinBox::into_raw`]: struct.PinBox.html#method.into_raw
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(pin)]
+    /// use std::pin::PinBox;
+    /// let x = PinBox::new(5);
+    /// let ptr = PinBox::into_raw(x);
+    /// let x = unsafe { PinBox::from_raw(ptr) };
+    /// ```
+    #[inline]
+    pub unsafe fn from_raw(raw: *mut T) -> Self {
+        PinBox { inner: Box::from_raw(raw) }
+    }
+
+    /// Consumes the `PinBox`, returning the wrapped raw pointer.
+    ///
+    /// After calling this function, the caller is responsible for the
+    /// memory previously managed by the `PinBox`. In particular, the
+    /// caller should properly destroy `T` and release the memory. The
+    /// proper way to do so is to convert the raw pointer back into a
+    /// `PinBox` with the [`PinBox::from_raw`] function.
+    ///
+    /// Note: this is an associated function, which means that you have
+    /// to call it as `PinBox::into_raw(b)` instead of `b.into_raw()`. This
+    /// is so that there is no conflict with a method on the inner type.
+    ///
+    /// [`PinBox::from_raw`]: struct.PinBox.html#method.from_raw
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(pin)]
+    /// use std::pin::PinBox;
+    /// let x = PinBox::new(5);
+    /// let ptr = PinBox::into_raw(x);
+    /// ```
+    #[inline]
+    pub fn into_raw(b: PinBox<T>) -> *mut T {
+        Box::into_raw(b.inner)
+    }
+
+    /// Get a mutable reference to the data inside this PinBox.
+    ///
+    /// This function is unsafe. Users must guarantee that the data is never
+    /// moved out of this reference.
+    #[inline]
+    pub unsafe fn get_mut<'a>(this: &'a mut PinBox<T>) -> &'a mut T {
+        &mut *this.inner
+    }
+
+    /// Convert this PinBox into an unpinned Box.
+    ///
+    /// This function is unsafe. Users must guarantee that the data is never
+    /// moved out of the box.
+    #[inline]
+    pub unsafe fn unpin(this: PinBox<T>) -> Box<T> {
+        this.inner
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized> From<Box<T>> for PinBox<T> {
+    fn from(boxed: Box<T>) -> PinBox<T> {
+        PinBox { inner: boxed }
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized> Deref for PinBox<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &*self.inner
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: Unpin + ?Sized> DerefMut for PinBox<T> {
+    fn deref_mut(&mut self) -> &mut T {
+        &mut *self.inner
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: fmt::Display + ?Sized> fmt::Display for PinBox<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&*self.inner, f)
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: fmt::Debug + ?Sized> fmt::Debug for PinBox<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&*self.inner, f)
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized> fmt::Pointer for PinBox<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // It's not possible to extract the inner Uniq directly from the Box,
+        // instead we cast it to a *const which aliases the Unique
+        let ptr: *const T = &*self.inner;
+        fmt::Pointer::fmt(&ptr, f)
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinBox<U>> for PinBox<T> {}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized> Unpin for PinBox<T> {}
+
+#[unstable(feature = "futures_api", issue = "50547")]
+impl<F: ?Sized + Future> Future for PinBox<F> {
+    type Output = F::Output;
+
+    fn poll(mut self: PinMut<Self>, cx: &mut Context) -> Poll<Self::Output> {
+        self.as_pin_mut().poll(cx)
+    }
+}
+
+#[unstable(feature = "futures_api", issue = "50547")]
+unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinBox<F>
+    where F: Future<Output = T> + 'a
+{
+    fn into_raw(self) -> *mut () {
+        PinBox::into_raw(self) as *mut ()
+    }
+
+    unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> {
+        let ptr = ptr as *mut F;
+        let pin: PinMut<F> = PinMut::new_unchecked(&mut *ptr);
+        pin.poll(cx)
+    }
+
+    unsafe fn drop(ptr: *mut ()) {
+        drop(PinBox::from_raw(ptr as *mut F))
+    }
+}
+
+#[unstable(feature = "futures_api", issue = "50547")]
+impl<'a, F: Future<Output = ()> + Send + 'a> From<PinBox<F>> for FutureObj<'a, ()> {
+    fn from(boxed: PinBox<F>) -> Self {
+        FutureObj::new(boxed)
+    }
+}
+
+#[unstable(feature = "futures_api", issue = "50547")]
+impl<'a, F: Future<Output = ()> + 'a> From<PinBox<F>> for LocalFutureObj<'a, ()> {
+    fn from(boxed: PinBox<F>) -> Self {
+        LocalFutureObj::new(boxed)
+    }
+}
index 4f2686abf4515fbb11554df4b81dd83114b51976..837770feecef596d7380dd009f6802a904877f32 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![unstable(feature = "raw_vec_internals", reason = "implemention detail", issue = "0")]
+#![unstable(feature = "raw_vec_internals", reason = "implementation detail", issue = "0")]
 #![doc(hidden)]
 
 use core::cmp;
@@ -282,7 +282,7 @@ fn current_layout(&self) -> Option<Layout> {
     ///         // double would have aborted or panicked if the len exceeded
     ///         // `isize::MAX` so this is safe to do unchecked now.
     ///         unsafe {
-    ///             ptr::write(self.buf.ptr().offset(self.len as isize), elem);
+    ///             ptr::write(self.buf.ptr().add(self.len), elem);
     ///         }
     ///         self.len += 1;
     ///     }
@@ -487,7 +487,7 @@ pub fn try_reserve(&mut self, used_cap: usize, needed_extra_cap: usize)
     ///         // `isize::MAX` so this is safe to do unchecked now.
     ///         for x in elems {
     ///             unsafe {
-    ///                 ptr::write(self.buf.ptr().offset(self.len as isize), x.clone());
+    ///                 ptr::write(self.buf.ptr().add(self.len), x.clone());
     ///             }
     ///             self.len += 1;
     ///         }
index 82e1c92359ccb5cdf3de1ad55310362e9a2db867..4860daa11e20c2f96a57ebc6a6e4a4ea8b16fc87 100644 (file)
@@ -771,7 +771,7 @@ fn drop(&mut self) {
             };
 
             for (i, item) in v.iter().enumerate() {
-                ptr::write(elems.offset(i as isize), item.clone());
+                ptr::write(elems.add(i), item.clone());
                 guard.n_elems += 1;
             }
 
index c27c596e7975a33463042261b9ec17d33aa7990c..9d442b3e00ca074ea7b6d1584272923bc8b922ef 100644 (file)
@@ -715,8 +715,8 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F)
 {
     let len = v.len();
     let v = v.as_mut_ptr();
-    let v_mid = v.offset(mid as isize);
-    let v_end = v.offset(len as isize);
+    let v_mid = v.add(mid);
+    let v_end = v.add(len);
 
     // The merge process first copies the shorter run into `buf`. Then it traces the newly copied
     // run and the longer run forwards (or backwards), comparing their next unconsumed elements and
@@ -742,7 +742,7 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F)
         ptr::copy_nonoverlapping(v, buf, mid);
         hole = MergeHole {
             start: buf,
-            end: buf.offset(mid as isize),
+            end: buf.add(mid),
             dest: v,
         };
 
@@ -766,7 +766,7 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F)
         ptr::copy_nonoverlapping(v_mid, buf, len - mid);
         hole = MergeHole {
             start: buf,
-            end: buf.offset((len - mid) as isize),
+            end: buf.add(len - mid),
             dest: v_mid,
         };
 
index 870bf971cd3f626d82c086dfd5021a94378b2df8..c451a051c74dcbfc2a7c92b209d05238ef92d3b6 100644 (file)
@@ -513,7 +513,7 @@ pub fn into_string(self: Box<str>) -> String {
         unsafe { String::from_utf8_unchecked(slice.into_vec()) }
     }
 
-    /// Create a [`String`] by repeating a string `n` times.
+    /// Creates a new [`String`] by repeating a string `n` times.
     ///
     /// [`String`]: string/struct.String.html
     ///
index dd559df08cce6b356e77e8efa9e538018f0f3507..aa821abb34cdfe5f38e3880f28b71b522b2d972a 100644 (file)
@@ -752,7 +752,7 @@ pub fn into_bytes(self) -> Vec<u8> {
         self.vec
     }
 
-    /// Extracts a string slice containing the entire string.
+    /// Extracts a string slice containing the entire `String`.
     ///
     /// # Examples
     ///
@@ -1190,8 +1190,8 @@ pub fn remove(&mut self, idx: usize) -> char {
         let next = idx + ch.len_utf8();
         let len = self.len();
         unsafe {
-            ptr::copy(self.vec.as_ptr().offset(next as isize),
-                      self.vec.as_mut_ptr().offset(idx as isize),
+            ptr::copy(self.vec.as_ptr().add(next),
+                      self.vec.as_mut_ptr().add(idx),
                       len - next);
             self.vec.set_len(len - (next - idx));
         }
@@ -1232,8 +1232,8 @@ pub fn retain<F>(&mut self, mut f: F)
                 del_bytes += ch_len;
             } else if del_bytes > 0 {
                 unsafe {
-                    ptr::copy(self.vec.as_ptr().offset(idx as isize),
-                              self.vec.as_mut_ptr().offset((idx - del_bytes) as isize),
+                    ptr::copy(self.vec.as_ptr().add(idx),
+                              self.vec.as_mut_ptr().add(idx - del_bytes),
                               ch_len);
                 }
             }
@@ -1289,11 +1289,11 @@ unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
         let amt = bytes.len();
         self.vec.reserve(amt);
 
-        ptr::copy(self.vec.as_ptr().offset(idx as isize),
-                  self.vec.as_mut_ptr().offset((idx + amt) as isize),
+        ptr::copy(self.vec.as_ptr().add(idx),
+                  self.vec.as_mut_ptr().add(idx + amt),
                   len - idx);
         ptr::copy(bytes.as_ptr(),
-                  self.vec.as_mut_ptr().offset(idx as isize),
+                  self.vec.as_mut_ptr().add(idx),
                   amt);
         self.vec.set_len(len + amt);
     }
@@ -1454,8 +1454,8 @@ pub fn clear(&mut self) {
         self.vec.clear()
     }
 
-    /// Creates a draining iterator that removes the specified range in the string
-    /// and yields the removed chars.
+    /// Creates a draining iterator that removes the specified range in the `String`
+    /// and yields the removed `chars`.
     ///
     /// Note: The element range is removed even if the iterator is not
     /// consumed until the end.
index a00b6b4e435f06e504f6521d4c137e4a9cd38343..db7a4044b267f7eedc0cecf47473790d73e4adbf 100644 (file)
 ///
 /// The type `Arc<T>` provides shared ownership of a value of type `T`,
 /// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces
-/// a new pointer to the same value in the heap. When the last `Arc`
-/// pointer to a given value is destroyed, the pointed-to value is
-/// also destroyed.
+/// a new `Arc` instance, which points to the same value on the heap as the
+/// source `Arc`, while increasing a reference count. When the last `Arc`
+/// pointer to a given value is destroyed, the pointed-to value is also
+/// destroyed.
 ///
 /// Shared references in Rust disallow mutation by default, and `Arc` is no
 /// exception: you cannot generally obtain a mutable reference to something
 /// // The two syntaxes below are equivalent.
 /// let a = foo.clone();
 /// let b = Arc::clone(&foo);
-/// // a and b both point to the same memory location as foo.
+/// // a, b, and foo are all Arcs that point to the same memory location
 /// ```
 ///
 /// The [`Arc::clone(&from)`] syntax is the most idiomatic because it conveys more explicitly
@@ -672,7 +673,7 @@ fn drop(&mut self) {
             };
 
             for (i, item) in v.iter().enumerate() {
-                ptr::write(elems.offset(i as isize), item.clone());
+                ptr::write(elems.add(i), item.clone());
                 guard.n_elems += 1;
             }
 
index c12c7a81f79c8905a3ee3b77f7eb2662919ea488..710c659ac53962b18c1b6bb4bf75900171ac9fca 100644 (file)
@@ -10,9 +10,9 @@
 
 #![feature(allocator_api)]
 #![feature(alloc_system)]
-#![feature(attr_literals)]
 #![feature(box_syntax)]
-#![feature(const_fn)]
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(min_const_fn))]
 #![feature(drain_filter)]
 #![feature(exact_size_is_empty)]
 #![feature(pattern)]
index cc913dfbb4b01e140abb47403998f7a65c224f3a..e9c1a3df518913cb709004445ee46e740dda94ac 100644 (file)
@@ -692,7 +692,7 @@ pub fn into_boxed_slice(mut self) -> Box<[T]> {
     pub fn truncate(&mut self, len: usize) {
         let current_len = self.len;
         unsafe {
-            let mut ptr = self.as_mut_ptr().offset(self.len as isize);
+            let mut ptr = self.as_mut_ptr().add(self.len);
             // Set the final length at the end, keeping in mind that
             // dropping an element might panic. Works around a missed
             // optimization, as seen in the following issue:
@@ -856,7 +856,7 @@ pub fn insert(&mut self, index: usize, element: T) {
             // infallible
             // The spot to put the new value
             {
-                let p = self.as_mut_ptr().offset(index as isize);
+                let p = self.as_mut_ptr().add(index);
                 // Shift everything over to make space. (Duplicating the
                 // `index`th element into two consecutive places.)
                 ptr::copy(p, p.offset(1), len - index);
@@ -891,7 +891,7 @@ pub fn remove(&mut self, index: usize) -> T {
             let ret;
             {
                 // the place we are taking from.
-                let ptr = self.as_mut_ptr().offset(index as isize);
+                let ptr = self.as_mut_ptr().add(index);
                 // copy it out, unsafely having a copy of the value on
                 // the stack and in the vector at the same time.
                 ret = ptr::read(ptr);
@@ -1034,8 +1034,8 @@ pub fn dedup_by<F>(&mut self, mut same_bucket: F) where F: FnMut(&mut T, &mut T)
             let mut w: usize = 1;
 
             while r < ln {
-                let p_r = p.offset(r as isize);
-                let p_wm1 = p.offset((w - 1) as isize);
+                let p_r = p.add(r);
+                let p_wm1 = p.add(w - 1);
                 if !same_bucket(&mut *p_r, &mut *p_wm1) {
                     if r != w {
                         let p_w = p_wm1.offset(1);
@@ -1072,7 +1072,7 @@ pub fn push(&mut self, value: T) {
             self.reserve(1);
         }
         unsafe {
-            let end = self.as_mut_ptr().offset(self.len as isize);
+            let end = self.as_mut_ptr().add(self.len);
             ptr::write(end, value);
             self.len += 1;
         }
@@ -1196,7 +1196,7 @@ pub fn drain<R>(&mut self, range: R) -> Drain<T>
             self.set_len(start);
             // Use the borrow in the IterMut to indicate borrowing behavior of the
             // whole Drain iterator (like &mut T).
-            let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().offset(start as isize),
+            let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(start),
                                                         end - start);
             Drain {
                 tail_start: end,
@@ -1290,7 +1290,7 @@ pub fn split_off(&mut self, at: usize) -> Self {
             self.set_len(at);
             other.set_len(other_len);
 
-            ptr::copy_nonoverlapping(self.as_ptr().offset(at as isize),
+            ptr::copy_nonoverlapping(self.as_ptr().add(at),
                                      other.as_mut_ptr(),
                                      other.len());
         }
@@ -1473,7 +1473,7 @@ fn extend_with<E: ExtendWith<T>>(&mut self, n: usize, mut value: E) {
         self.reserve(n);
 
         unsafe {
-            let mut ptr = self.as_mut_ptr().offset(self.len() as isize);
+            let mut ptr = self.as_mut_ptr().add(self.len());
             // Use SetLenOnDrop to work around bug where compiler
             // may not realize the store through `ptr` through self.set_len()
             // don't alias.
@@ -1799,7 +1799,7 @@ fn into_iter(mut self) -> IntoIter<T> {
             let end = if mem::size_of::<T>() == 0 {
                 arith_offset(begin as *const i8, self.len() as isize) as *const T
             } else {
-                begin.offset(self.len() as isize) as *const T
+                begin.add(self.len()) as *const T
             };
             let cap = self.buf.cap();
             mem::forget(self);
@@ -1898,7 +1898,7 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
         if let Some(additional) = high {
             self.reserve(additional);
             unsafe {
-                let mut ptr = self.as_mut_ptr().offset(self.len() as isize);
+                let mut ptr = self.as_mut_ptr().add(self.len());
                 let mut local_len = SetLenOnDrop::new(&mut self.len);
                 for element in iterator {
                     ptr::write(ptr, element);
@@ -2561,8 +2561,8 @@ fn drop(&mut self) {
                 let start = source_vec.len();
                 let tail = self.tail_start;
                 if tail != start {
-                    let src = source_vec.as_ptr().offset(tail as isize);
-                    let dst = source_vec.as_mut_ptr().offset(start as isize);
+                    let src = source_vec.as_ptr().add(tail);
+                    let dst = source_vec.as_mut_ptr().add(start);
                     ptr::copy(src, dst, self.tail_len);
                 }
                 source_vec.set_len(start + self.tail_len);
@@ -2672,7 +2672,7 @@ unsafe fn fill<I: Iterator<Item=T>>(&mut self, replace_with: &mut I) -> bool {
         let range_start = vec.len;
         let range_end = self.tail_start;
         let range_slice = slice::from_raw_parts_mut(
-            vec.as_mut_ptr().offset(range_start as isize),
+            vec.as_mut_ptr().add(range_start),
             range_end - range_start);
 
         for place in range_slice {
@@ -2693,8 +2693,8 @@ unsafe fn move_tail(&mut self, extra_capacity: usize) {
         vec.buf.reserve(used_capacity, extra_capacity);
 
         let new_tail_start = self.tail_start + extra_capacity;
-        let src = vec.as_ptr().offset(self.tail_start as isize);
-        let dst = vec.as_mut_ptr().offset(new_tail_start as isize);
+        let src = vec.as_ptr().add(self.tail_start);
+        let dst = vec.as_mut_ptr().add(new_tail_start);
         ptr::copy(src, dst, self.tail_len);
         self.tail_start = new_tail_start;
     }
index 480a24b9bd1f258ef94e1f8e04393384f3192e3a..3d2348f3e4546dd0701e127919c1b1cf7d3345ea 100644 (file)
@@ -17,6 +17,7 @@
 #![feature(libc)]
 #![feature(linkage)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(staged_api)]
 #![feature(rustc_attrs)]
 #![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))]
@@ -89,16 +90,16 @@ fn align_to_flags(align: usize, size: usize) -> c_int {
     // linkage directives are provided as part of the current compiler allocator
     // ABI
 
-    #[no_mangle]
     #[rustc_std_internal_symbol]
+    #[cfg_attr(stage0, no_mangle)]
     pub unsafe extern fn __rde_alloc(size: usize, align: usize) -> *mut u8 {
         let flags = align_to_flags(align, size);
         let ptr = mallocx(size as size_t, flags) as *mut u8;
         ptr
     }
 
-    #[no_mangle]
     #[rustc_std_internal_symbol]
+    #[cfg_attr(stage0, no_mangle)]
     pub unsafe extern fn __rde_dealloc(ptr: *mut u8,
                                        size: usize,
                                        align: usize) {
@@ -106,8 +107,8 @@ fn align_to_flags(align: usize, size: usize) -> c_int {
         sdallocx(ptr as *mut c_void, size, flags);
     }
 
-    #[no_mangle]
     #[rustc_std_internal_symbol]
+    #[cfg_attr(stage0, no_mangle)]
     pub unsafe extern fn __rde_realloc(ptr: *mut u8,
                                        _old_size: usize,
                                        align: usize,
@@ -117,8 +118,8 @@ fn align_to_flags(align: usize, size: usize) -> c_int {
         ptr
     }
 
-    #[no_mangle]
     #[rustc_std_internal_symbol]
+    #[cfg_attr(stage0, no_mangle)]
     pub unsafe extern fn __rde_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
         let ptr = if align <= MIN_ALIGN && align <= size {
             calloc(size as size_t, 1) as *mut u8
index c5e056f6b12bec1533cb698d450c72114b041a7f..8848be5903810ef96bdbc44dda078a543e1c4fe0 100644 (file)
@@ -18,6 +18,7 @@
 #![feature(allocator_api)]
 #![feature(core_intrinsics)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(staged_api)]
 #![feature(rustc_attrs)]
 #![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))]
@@ -219,7 +220,7 @@ unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
 }
 
 #[cfg(windows)]
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 mod platform {
     use MIN_ALIGN;
     use System;
@@ -249,7 +250,7 @@ unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
     }
 
     unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
-        let aligned = ptr.offset((align - (ptr as usize & (align - 1))) as isize);
+        let aligned = ptr.add(align - (ptr as usize & (align - 1)));
         *get_header(aligned) = Header(ptr);
         aligned
     }
index 265721c749755628f4f1f0b262f6bbf7e3c7bea4..5cb8975e9ce973cdf233afc74c3e398848558966 100644 (file)
@@ -27,6 +27,7 @@
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(raw_vec_internals)]
 #![cfg_attr(test, feature(test))]
 
@@ -106,7 +107,7 @@ fn end(&self) -> *mut T {
                 // A pointer as large as possible for zero-sized elements.
                 !0 as *mut T
             } else {
-                self.start().offset(self.storage.cap() as isize)
+                self.start().add(self.storage.cap())
             }
         }
     }
@@ -179,7 +180,7 @@ pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
         unsafe {
             let start_ptr = self.ptr.get();
             let arena_slice = slice::from_raw_parts_mut(start_ptr, slice.len());
-            self.ptr.set(start_ptr.offset(arena_slice.len() as isize));
+            self.ptr.set(start_ptr.add(arena_slice.len()));
             arena_slice.copy_from_slice(slice);
             arena_slice
         }
index d549d85b1735dc5066b2973f8549557a813bb9c8..f3a13eb2384c7cbb91b6db5b008377e9710d434c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d549d85b1735dc5066b2973f8549557a813bb9c8
+Subproject commit f3a13eb2384c7cbb91b6db5b008377e9710d434c
index 67e02cf9509b6cd8ba71db2be4dd19cea9946ce0..f4f01eb1cf5d29d84d8c4466a209e103bc24d99f 100644 (file)
@@ -15,7 +15,7 @@
 fn bench_downcast_ref(b: &mut Bencher) {
     b.iter(|| {
         let mut x = 0;
-        let mut y = &mut x as &mut Any;
+        let mut y = &mut x as &mut dyn Any;
         black_box(&mut y);
         black_box(y.downcast_ref::<isize>() == Some(&0));
     });
index 58d6c4f5e09236640c8be496f352e6797c84c5ef..ef7d83a0993da134e3d670408c7b0008e59ee7b1 100644 (file)
 /// the same book if their ISBN matches, even if the formats differ:
 ///
 /// ```
-/// enum BookFormat { Paperback, Hardback, Ebook }
+/// enum BookFormat {
+///     Paperback,
+///     Hardback,
+///     Ebook,
+/// }
+///
 /// struct Book {
 ///     isbn: i32,
 ///     format: BookFormat,
 /// assert!(b1 != b3);
 /// ```
 ///
+/// ## How can I compare two different types?
+///
+/// The type you can compare with is controlled by `PartialEq`'s type parameter.
+/// For example, let's tweak our previous code a bit:
+///
+/// ```
+/// enum BookFormat {
+///     Paperback,
+///     Hardback,
+///     Ebook,
+/// }
+///
+/// struct Book {
+///     isbn: i32,
+///     format: BookFormat,
+/// }
+///
+/// impl PartialEq<BookFormat> for Book {
+///     fn eq(&self, other: &BookFormat) -> bool {
+///         match (&self.format, other) {
+///            (BookFormat::Paperback, BookFormat::Paperback) => true,
+///            (BookFormat::Hardback,  BookFormat::Hardback)  => true,
+///            (BookFormat::Ebook,     BookFormat::Ebook)     => true,
+///            (_, _) => false,
+///         }
+///     }
+/// }
+///
+/// let b1 = Book { isbn: 3, format: BookFormat::Paperback };
+///
+/// assert!(b1 == BookFormat::Paperback);
+/// assert!(b1 != BookFormat::Ebook);
+/// ```
+///
+/// By changing `impl PartialEq for Book` to `impl PartialEq<BookFormat> for Book`,
+/// we've changed what type we can use on the right side of the `==` operator.
+/// This lets us use it in the `assert!` statements at the bottom.
+///
+/// You can also combine these implementations to let the `==` operator work with
+/// two different types:
+///
+/// ```
+/// enum BookFormat {
+///     Paperback,
+///     Hardback,
+///     Ebook,
+/// }
+///
+/// struct Book {
+///     isbn: i32,
+///     format: BookFormat,
+/// }
+///
+/// impl PartialEq<BookFormat> for Book {
+///     fn eq(&self, other: &BookFormat) -> bool {
+///         match (&self.format, other) {
+///            (&BookFormat::Paperback, &BookFormat::Paperback) => true,
+///            (&BookFormat::Hardback,  &BookFormat::Hardback)  => true,
+///            (&BookFormat::Ebook,     &BookFormat::Ebook)     => true,
+///            (_, _) => false,
+///         }
+///     }
+/// }
+///
+/// impl PartialEq for Book {
+///     fn eq(&self, other: &Book) -> bool {
+///         self.isbn == other.isbn
+///     }
+/// }
+///
+/// let b1 = Book { isbn: 3, format: BookFormat::Paperback };
+/// let b2 = Book { isbn: 3, format: BookFormat::Ebook };
+///
+/// assert!(b1 == BookFormat::Paperback);
+/// assert!(b1 != BookFormat::Ebook);
+/// assert!(b1 == b2);
+/// ```
+///
 /// # Examples
 ///
 /// ```
index 928f95e3ba2ea2a65c7cc2fa1aab225d2588dbec..7d131b5c99dc09c66b9bf6af2c9adab0d6423f65 100644 (file)
@@ -1132,6 +1132,36 @@ fn getcount(&mut self, cnt: &rt::v1::Count) -> Option<usize> {
     ///
     /// This function will correctly account for the flags provided as well as
     /// the minimum width. It will not take precision into account.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fmt;
+    ///
+    /// struct Foo { nb: i32 };
+    ///
+    /// impl Foo {
+    ///     fn new(nb: i32) -> Foo {
+    ///         Foo {
+    ///             nb,
+    ///         }
+    ///     }
+    /// }
+    ///
+    /// impl fmt::Display for Foo {
+    ///     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    ///         // We need to remove "-" from the number output.
+    ///         let tmp = self.nb.abs().to_string();
+    ///
+    ///         formatter.pad_integral(self.nb > 0, "Foo ", &tmp)
+    ///     }
+    /// }
+    ///
+    /// assert_eq!(&format!("{}", Foo::new(2)), "2");
+    /// assert_eq!(&format!("{}", Foo::new(-1)), "-1");
+    /// assert_eq!(&format!("{:#}", Foo::new(-1)), "-Foo 1");
+    /// assert_eq!(&format!("{:0>#8}", Foo::new(-1)), "00-Foo 1");
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pad_integral(&mut self,
                         is_nonnegative: bool,
@@ -1232,7 +1262,7 @@ pub fn pad(&mut self, s: &str) -> Result {
             // If our string is longer that the precision, then we must have
             // truncation. However other flags like `fill`, `width` and `align`
             // must act as always.
-            if let Some((i, _)) = s.char_indices().skip(max).next() {
+            if let Some((i, _)) = s.char_indices().nth(max) {
                 // LLVM here can't prove that `..i` won't panic `&s[..i]`, but
                 // we know that it can't panic. Use `get` + `unwrap_or` to avoid
                 // `unsafe` and otherwise don't emit any panic-related code
@@ -1381,12 +1411,48 @@ fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result {
 
     /// Writes some data to the underlying buffer contained within this
     /// formatter.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fmt;
+    ///
+    /// struct Foo;
+    ///
+    /// impl fmt::Display for Foo {
+    ///     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    ///         formatter.write_str("Foo")
+    ///         // This is equivalent to:
+    ///         // write!(formatter, "Foo")
+    ///     }
+    /// }
+    ///
+    /// assert_eq!(&format!("{}", Foo), "Foo");
+    /// assert_eq!(&format!("{:0>8}", Foo), "Foo");
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn write_str(&mut self, data: &str) -> Result {
         self.buf.write_str(data)
     }
 
     /// Writes some formatted information into this instance.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fmt;
+    ///
+    /// struct Foo(i32);
+    ///
+    /// impl fmt::Display for Foo {
+    ///     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    ///         formatter.write_fmt(format_args!("Foo {}", self.0))
+    ///     }
+    /// }
+    ///
+    /// assert_eq!(&format!("{}", Foo(-1)), "Foo -1");
+    /// assert_eq!(&format!("{:0>8}", Foo(2)), "Foo 2");
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn write_fmt(&mut self, fmt: Arguments) -> Result {
         write(self.buf, fmt)
index 10b4ca9b0b27a5e55f089501c1bf45f8ebaf633e..520b6ebbbaaa59a072eda6529d6f22acd1e4249e 100644 (file)
@@ -12,7 +12,7 @@
             reason = "futures in libcore are unstable",
             issue = "50547")]
 
-use mem::PinMut;
+use pin::PinMut;
 use marker::Unpin;
 use task::{self, Poll};
 
index 6045fac2b4b3d7fe096152772e6d6993d1383083..68fe461aeae86ebcb1e570a9796737fd5b034e6a 100644 (file)
@@ -15,7 +15,7 @@
 use fmt;
 use future::Future;
 use marker::{PhantomData, Unpin};
-use mem::PinMut;
+use pin::PinMut;
 use task::{Context, Poll};
 
 /// A custom trait object for polling futures, roughly akin to
@@ -27,7 +27,7 @@
 /// - The `Future` trait is currently not object safe: The `Future::poll`
 ///   method makes uses the arbitrary self types feature and traits in which
 ///   this feature is used are currently not object safe due to current compiler
-///   limitations. (See tracking issue for arbitray self types for more
+///   limitations. (See tracking issue for arbitrary self types for more
 ///   information #44874)
 pub struct LocalFutureObj<'a, T> {
     ptr: *mut (),
@@ -102,7 +102,7 @@ fn drop(&mut self) {
 /// - The `Future` trait is currently not object safe: The `Future::poll`
 ///   method makes uses the arbitrary self types feature and traits in which
 ///   this feature is used are currently not object safe due to current compiler
-///   limitations. (See tracking issue for arbitray self types for more
+///   limitations. (See tracking issue for arbitrary self types for more
 ///   information #44874)
 pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>);
 
index 9ddf902349dd2e633ae87aa2c03ebebb0e28e96f..7756a6f71dbd60a2cf68731a750b4d676646ae60 100644 (file)
     ///         // treat it as "dead", and therefore, you only have two real
     ///         // mutable slices.
     ///         (slice::from_raw_parts_mut(ptr, mid),
-    ///          slice::from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
+    ///          slice::from_raw_parts_mut(ptr.add(mid), len - mid))
     ///     }
     /// }
     /// ```
index 3918529105334b23ff2aa614beb704f37b2106df..d45c123d332eb0c9c768b71661cabf23562f4bf8 100644 (file)
@@ -1794,7 +1794,6 @@ fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
     /// # Examples
     ///
     /// ```
-    /// #![feature(iterator_find_map)]
     /// let a = ["lol", "NaN", "2", "5"];
     ///
     /// let mut first_number = a.iter().find_map(|s| s.parse().ok());
@@ -1802,9 +1801,7 @@ fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
     /// assert_eq!(first_number, Some(2));
     /// ```
     #[inline]
-    #[unstable(feature = "iterator_find_map",
-               reason = "unstable new API",
-               issue = "49602")]
+    #[stable(feature = "iterator_find_map", since = "1.30.0")]
     fn find_map<B, F>(&mut self, mut f: F) -> Option<B> where
         Self: Sized,
         F: FnMut(Self::Item) -> Option<B>,
index 651c7a35d413c6478b6e661b23dbd586208be6a6..55addd86bc1cef81810c8830952fc5a4e2a11c55 100644 (file)
@@ -165,8 +165,16 @@ fn add_usize(&self, n: usize) -> Option<Self> {
     )*)
 }
 
-step_impl_unsigned!(usize u8 u16 u32);
-step_impl_signed!([isize: usize] [i8: u8] [i16: u16] [i32: u32]);
+step_impl_unsigned!(usize u8 u16);
+#[cfg(not(target_pointer_witdth = "16"))]
+step_impl_unsigned!(u32);
+#[cfg(target_pointer_witdth = "16")]
+step_impl_no_between!(u32);
+step_impl_signed!([isize: usize] [i8: u8] [i16: u16]);
+#[cfg(not(target_pointer_witdth = "16"))]
+step_impl_signed!([i32: u32]);
+#[cfg(target_pointer_witdth = "16")]
+step_impl_no_between!(i32);
 #[cfg(target_pointer_width = "64")]
 step_impl_unsigned!(u64);
 #[cfg(target_pointer_width = "64")]
index e85bf1dfcad23c99116b2cd20497752a2f9991e2..2aa3226af8960b553dcd05ed3a7568021ce5af7d 100644 (file)
@@ -77,7 +77,6 @@
 #![feature(arbitrary_self_types)]
 #![feature(asm)]
 #![feature(associated_type_defaults)]
-#![feature(attr_literals)]
 #![feature(cfg_target_has_atomic)]
 #![feature(concat_idents)]
 #![feature(const_fn)]
@@ -93,6 +92,7 @@
 #![feature(link_llvm_intrinsics)]
 #![feature(never_type)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(exhaustive_patterns)]
 #![feature(macro_at_most_once_rep)]
 #![feature(no_core)]
 pub mod char;
 pub mod panic;
 pub mod panicking;
+pub mod pin;
 pub mod iter;
 pub mod option;
 pub mod raw;
index 5b3b2d1635688e8c04d5d9ee93e97321e2825a50..0032bedc7ed1de518390c363f30171a5900cc274 100644 (file)
@@ -541,7 +541,7 @@ macro_rules! unimplemented {
 /// into libsyntax itself.
 ///
 /// For more information, see documentation for `std`'s macros.
-#[cfg(dox)]
+#[cfg(rustdoc)]
 mod builtin {
 
     /// Unconditionally causes compilation to fail with the given error message when encountered.
index d18e167fc3fa4dcd02c1f6234b973ea9b8e793ed..dd57d2dd00910c4eee3062bc09ac6c20d626dc42 100644 (file)
@@ -511,7 +511,7 @@ fn default() -> $t<T> {
 ///     let ptr = vec.as_ptr();
 ///     Slice {
 ///         start: ptr,
-///         end: unsafe { ptr.offset(vec.len() as isize) },
+///         end: unsafe { ptr.add(vec.len()) },
 ///         phantom: PhantomData,
 ///     }
 /// }
@@ -603,15 +603,38 @@ unsafe impl<T: ?Sized> Freeze for *mut T {}
 unsafe impl<'a, T: ?Sized> Freeze for &'a T {}
 unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
 
-/// Types which can be moved out of a `PinMut`.
+/// Types which can be safely moved after being pinned.
 ///
-/// The `Unpin` trait is used to control the behavior of the [`PinMut`] type. If a
-/// type implements `Unpin`, it is safe to move a value of that type out of the
-/// `PinMut` pointer.
+/// Since Rust itself has no notion of immovable types, and will consider moves to always be safe,
+/// this trait cannot prevent types from moving by itself.
+///
+/// Instead it can be used to prevent moves through the type system,
+/// by controlling the behavior of special pointer types like [`PinMut`],
+/// which "pin" the type in place by not allowing it to be moved out of them.
+/// See the [`pin module`] documentation for more information on pinning.
+///
+/// Implementing this trait lifts the restrictions of pinning off a type,
+/// which then allows it to move out with functions such as [`replace`].
+///
+/// So this, for example, can only be done on types implementing `Unpin`:
+///
+/// ```rust
+/// #![feature(pin)]
+/// use std::mem::replace;
+/// use std::pin::PinMut;
+///
+/// let mut string = "this".to_string();
+/// let mut pinned_string = PinMut::new(&mut string);
+///
+/// // dereferencing the pointer mutably is only possible because String implements Unpin
+/// replace(&mut *pinned_string, "other".to_string());
+/// ```
 ///
 /// This trait is automatically implemented for almost every type.
 ///
-/// [`PinMut`]: ../mem/struct.PinMut.html
+/// [`replace`]: ../../std/mem/fn.replace.html
+/// [`PinMut`]: ../pin/struct.PinMut.html
+/// [`pin module`]: ../../std/pin/index.html
 #[unstable(feature = "pin", issue = "49150")]
 pub auto trait Unpin {}
 
index ea711c69393a4dbc34a6ae84af1124253eaaad04..e00a22bf8b6c360674bcd3ec5da5573e49cb0cf6 100644 (file)
 use clone;
 use cmp;
 use fmt;
-use future::{Future, UnsafeFutureObj};
 use hash;
 use intrinsics;
-use marker::{Copy, PhantomData, Sized, Unpin, Unsize};
+use marker::{Copy, PhantomData, Sized};
 use ptr;
-use task::{Context, Poll};
-use ops::{Deref, DerefMut, CoerceUnsized};
+use ops::{Deref, DerefMut};
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use intrinsics::transmute;
 
-/// Leaks a value: takes ownership and "forgets" about the value **without running
-/// its destructor**.
+/// Takes ownership and "forgets" about the value **without running its destructor**.
 ///
 /// Any resources the value manages, such as heap memory or a file handle, will linger
-/// forever in an unreachable state.
+/// forever in an unreachable state. However, it does not guarantee that pointers
+/// to this memory will remain valid.
 ///
-/// If you want to dispose of a value properly, running its destructor, see
+/// * If you want to leak memory, see [`Box::leak`][leak].
+/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`][into_raw].
+/// * If you want to dispose of a value properly, running its destructor, see
 /// [`mem::drop`][drop].
 ///
 /// # Safety
 ///
 /// # Examples
 ///
-/// Leak some heap memory by never deallocating it:
-///
-/// ```
-/// use std::mem;
-///
-/// let heap_memory = Box::new(3);
-/// mem::forget(heap_memory);
-/// ```
-///
 /// Leak an I/O object, never closing the file:
 ///
 /// ```no_run
 /// }
 /// ```
 ///
-/// ## Use case 3
-///
-/// You are transferring ownership across a [FFI] boundary to code written in
-/// another language. You need to `forget` the value on the Rust side because Rust
-/// code is no longer responsible for it.
-///
-/// ```no_run
-/// use std::mem;
-///
-/// extern "C" {
-///     fn my_c_function(x: *const u32);
-/// }
-///
-/// let x: Box<u32> = Box::new(3);
-///
-/// // Transfer ownership into C code.
-/// unsafe {
-///     my_c_function(&*x);
-/// }
-/// mem::forget(x);
-/// ```
-///
-/// In this case, C code must call back into Rust to free the object. Calling C's `free`
-/// function on a [`Box`][box] is *not* safe! Also, `Box` provides an [`into_raw`][into_raw]
-/// method which is the preferred way to do this in practice.
-///
 /// [drop]: fn.drop.html
 /// [uninit]: fn.uninitialized.html
 /// [clone]: ../clone/trait.Clone.html
 /// [swap]: fn.swap.html
 /// [FFI]: ../../book/first-edition/ffi.html
 /// [box]: ../../std/boxed/struct.Box.html
+/// [leak]: ../../std/boxed/struct.Box.html#method.leak
 /// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw
 /// [ub]: ../../reference/behavior-considered-undefined.html
 #[inline]
@@ -319,6 +285,15 @@ pub fn forget<T>(t: T) {
 /// [alignment]: ./fn.align_of.html
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(stage0))]
+pub const fn size_of<T>() -> usize {
+    intrinsics::size_of::<T>()
+}
+
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(stage0)]
+/// Ceci n'est pas la documentation
 pub const fn size_of<T>() -> usize {
     unsafe { intrinsics::size_of::<T>() }
 }
@@ -368,6 +343,16 @@ pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")]
+#[cfg(not(stage0))]
+pub fn min_align_of<T>() -> usize {
+    intrinsics::min_align_of::<T>()
+}
+
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")]
+#[cfg(stage0)]
+/// Ceci n'est pas la documentation
 pub fn min_align_of<T>() -> usize {
     unsafe { intrinsics::min_align_of::<T>() }
 }
@@ -410,6 +395,15 @@ pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(stage0))]
+pub const fn align_of<T>() -> usize {
+    intrinsics::min_align_of::<T>()
+}
+
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(stage0)]
+/// Ceci n'est pas la documentation
 pub const fn align_of<T>() -> usize {
     unsafe { intrinsics::min_align_of::<T>() }
 }
@@ -1024,146 +1018,3 @@ fn deref_mut(&mut self) -> &mut Self::Target {
         &mut self.value
     }
 }
-
-/// A pinned reference.
-///
-/// A pinned reference is a lot like a mutable reference, except that it is not
-/// safe to move a value out of a pinned reference unless the type of that
-/// value implements the `Unpin` trait.
-#[unstable(feature = "pin", issue = "49150")]
-#[fundamental]
-pub struct PinMut<'a, T: ?Sized + 'a> {
-    inner: &'a mut T,
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized + Unpin> PinMut<'a, T> {
-    /// Construct a new `PinMut` around a reference to some data of a type that
-    /// implements `Unpin`.
-    #[unstable(feature = "pin", issue = "49150")]
-    pub fn new(reference: &'a mut T) -> PinMut<'a, T> {
-        PinMut { inner: reference }
-    }
-
-    /// Get a mutable reference to the data inside of this `PinMut`.
-    #[unstable(feature = "pin", issue = "49150")]
-    pub fn get_mut(this: PinMut<'a, T>) -> &'a mut T {
-        this.inner
-    }
-}
-
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized> PinMut<'a, T> {
-    /// Construct a new `PinMut` around a reference to some data of a type that
-    /// may or may not implement `Unpin`.
-    ///
-    /// This constructor is unsafe because we do not know what will happen with
-    /// that data after the reference ends. If you cannot guarantee that the
-    /// data will never move again, calling this constructor is invalid.
-    #[unstable(feature = "pin", issue = "49150")]
-    pub unsafe fn new_unchecked(reference: &'a mut T) -> PinMut<'a, T> {
-        PinMut { inner: reference }
-    }
-
-    /// Reborrow a `PinMut` for a shorter lifetime.
-    ///
-    /// For example, `PinMut::get_mut(x.reborrow())` (unsafely) returns a
-    /// short-lived mutable reference reborrowing from `x`.
-    #[unstable(feature = "pin", issue = "49150")]
-    pub fn reborrow<'b>(&'b mut self) -> PinMut<'b, T> {
-        PinMut { inner: self.inner }
-    }
-
-    /// Get a mutable reference to the data inside of this `PinMut`.
-    ///
-    /// This function is unsafe. You must guarantee that you will never move
-    /// the data out of the mutable reference you receive when you call this
-    /// function.
-    #[unstable(feature = "pin", issue = "49150")]
-    pub unsafe fn get_mut_unchecked(this: PinMut<'a, T>) -> &'a mut T {
-        this.inner
-    }
-
-    /// Construct a new pin by mapping the interior value.
-    ///
-    /// For example, if you  wanted to get a `PinMut` of a field of something,
-    /// you could use this to get access to that field in one line of code.
-    ///
-    /// This function is unsafe. You must guarantee that the data you return
-    /// will not move so long as the argument value does not move (for example,
-    /// because it is one of the fields of that value), and also that you do
-    /// not move out of the argument you receive to the interior function.
-    #[unstable(feature = "pin", issue = "49150")]
-    pub unsafe fn map_unchecked<U, F>(this: PinMut<'a, T>, f: F) -> PinMut<'a, U> where
-        F: FnOnce(&mut T) -> &mut U
-    {
-        PinMut { inner: f(this.inner) }
-    }
-
-    /// Assign a new value to the memory behind the pinned reference.
-    #[unstable(feature = "pin", issue = "49150")]
-    pub fn set(this: PinMut<'a, T>, value: T)
-        where T: Sized,
-    {
-        *this.inner = value;
-    }
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized> Deref for PinMut<'a, T> {
-    type Target = T;
-
-    fn deref(&self) -> &T {
-        &*self.inner
-    }
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized + Unpin> DerefMut for PinMut<'a, T> {
-    fn deref_mut(&mut self) -> &mut T {
-        self.inner
-    }
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for PinMut<'a, T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(&**self, f)
-    }
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: fmt::Display + ?Sized> fmt::Display for PinMut<'a, T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&**self, f)
-    }
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized> fmt::Pointer for PinMut<'a, T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Pointer::fmt(&(&*self.inner as *const T), f)
-    }
-}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinMut<'a, U>> for PinMut<'a, T> {}
-
-#[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized> Unpin for PinMut<'a, T> {}
-
-#[unstable(feature = "futures_api", issue = "50547")]
-unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinMut<'a, F>
-    where F: Future<Output = T> + 'a
-{
-    fn into_raw(self) -> *mut () {
-        unsafe { PinMut::get_mut_unchecked(self) as *mut F as *mut () }
-    }
-
-    unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> {
-        PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx)
-    }
-
-    unsafe fn drop(_ptr: *mut ()) {}
-}
index 37856dc546935d3421153e26db476eba5437a166..fc405881b28da96fa2f43dfdbe0ada795a07c9fb 100644 (file)
@@ -34,22 +34,32 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+macro_rules! doc_comment {
+    ($x:expr, $($tt:tt)*) => {
+        #[doc = $x]
+        $($tt)*
+    };
+}
+
 macro_rules! nonzero_integers {
     ( $( $Ty: ident($Int: ty); )+ ) => {
         $(
-            /// An integer that is known not to equal zero.
-            ///
-            /// This enables some memory layout optimization.
-            /// For example, `Option<NonZeroU32>` is the same size as `u32`:
-            ///
-            /// ```rust
-            /// use std::mem::size_of;
-            /// assert_eq!(size_of::<Option<std::num::NonZeroU32>>(), size_of::<u32>());
-            /// ```
-            #[stable(feature = "nonzero", since = "1.28.0")]
-            #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
-            #[repr(transparent)]
-            pub struct $Ty(NonZero<$Int>);
+            doc_comment! {
+                concat!("An integer that is known not to equal zero.
+
+This enables some memory layout optimization.
+For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:
+
+```rust
+use std::mem::size_of;
+assert_eq!(size_of::<Option<std::num::", stringify!($Ty), ">>(), size_of::<", stringify!($Int),
+">());
+```"),
+                #[stable(feature = "nonzero", since = "1.28.0")]
+                #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+                #[repr(transparent)]
+                pub struct $Ty(NonZero<$Int>);
+            }
 
             impl $Ty {
                 /// Create a non-zero without checking the value.
@@ -176,13 +186,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 pub mod bignum;
 pub mod diy_float;
 
-macro_rules! doc_comment {
-    ($x:expr, $($tt:tt)*) => {
-        #[doc = $x]
-        $($tt)*
-    };
-}
-
 mod wrapping;
 
 // `Int` + `SignedInt` implemented for signed integers
@@ -4320,7 +4323,7 @@ fn from_str(src: &str) -> Result<Self, ParseIntError> {
 
 /// The error type returned when a checked integral type conversion fails.
 #[unstable(feature = "try_from", issue = "33417")]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
 pub struct TryFromIntError(());
 
 impl TryFromIntError {
index d10fcb86b2411723df17dd205a9375ea8c47b6b6..3ebd10a920919cde757e38cfa57e85a1dca2f0fd 100644 (file)
 #[lang = "fn"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_paren_sugar]
+#[rustc_on_unimplemented(
+    on(Args="()", note="wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"),
+    message="expected a `{Fn}<{Args}>` closure, found `{Self}`",
+    label="expected an `Fn<{Args}>` closure, found `{Self}`",
+)]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
 pub trait Fn<Args> : FnMut<Args> {
     /// Performs the call operation.
@@ -139,6 +144,11 @@ pub trait Fn<Args> : FnMut<Args> {
 #[lang = "fn_mut"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_paren_sugar]
+#[rustc_on_unimplemented(
+    on(Args="()", note="wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"),
+    message="expected a `{FnMut}<{Args}>` closure, found `{Self}`",
+    label="expected an `FnMut<{Args}>` closure, found `{Self}`",
+)]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
 pub trait FnMut<Args> : FnOnce<Args> {
     /// Performs the call operation.
@@ -212,6 +222,11 @@ pub trait FnMut<Args> : FnOnce<Args> {
 #[lang = "fn_once"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_paren_sugar]
+#[rustc_on_unimplemented(
+    on(Args="()", note="wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"),
+    message="expected a `{FnOnce}<{Args}>` closure, found `{Self}`",
+    label="expected an `FnOnce<{Args}>` closure, found `{Self}`",
+)]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
 pub trait FnOnce<Args> {
     /// The returned type after the call operator is used.
index f743fbfd0752b6931151abf9c54146d64141e2d1..3879abb0af973d7084c911f93c660cc686288d08 100644 (file)
 
 use iter::{FromIterator, FusedIterator, TrustedLen};
 use {hint, mem, ops::{self, Deref}};
-use mem::PinMut;
+use pin::PinMut;
 
 // Note that this is not a lang item per se, but it has a hidden dependency on
 // `Iterator`, which is one. The compiler assumes that the `next` method of
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
new file mode 100644 (file)
index 0000000..e9001f8
--- /dev/null
@@ -0,0 +1,160 @@
+//! Types which pin data to its location in memory
+//!
+//! See the [standard library module] for more information.
+//!
+//! [standard library module]: ../../std/pin/index.html
+
+#![unstable(feature = "pin", issue = "49150")]
+
+use fmt;
+use future::{Future, UnsafeFutureObj};
+use marker::{Sized, Unpin, Unsize};
+use task::{Context, Poll};
+use ops::{Deref, DerefMut, CoerceUnsized};
+
+/// A pinned reference.
+///
+/// This type is similar to a mutable reference, except that it pins its value,
+/// which prevents it from moving out of the reference, unless it implements [`Unpin`].
+///
+/// See the [`pin` module] documentation for furthur explanation on pinning.
+///
+/// [`Unpin`]: ../../std/marker/trait.Unpin.html
+/// [`pin` module]: ../../std/pin/index.html
+#[unstable(feature = "pin", issue = "49150")]
+#[fundamental]
+pub struct PinMut<'a, T: ?Sized + 'a> {
+    inner: &'a mut T,
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized + Unpin> PinMut<'a, T> {
+    /// Construct a new `PinMut` around a reference to some data of a type that
+    /// implements `Unpin`.
+    #[unstable(feature = "pin", issue = "49150")]
+    pub fn new(reference: &'a mut T) -> PinMut<'a, T> {
+        PinMut { inner: reference }
+    }
+
+    /// Get a mutable reference to the data inside of this `PinMut`.
+    #[unstable(feature = "pin", issue = "49150")]
+    pub fn get_mut(this: PinMut<'a, T>) -> &'a mut T {
+        this.inner
+    }
+}
+
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized> PinMut<'a, T> {
+    /// Construct a new `PinMut` around a reference to some data of a type that
+    /// may or may not implement `Unpin`.
+    ///
+    /// This constructor is unsafe because we do not know what will happen with
+    /// that data after the lifetime of the reference ends. If you cannot guarantee that the
+    /// data will never move again, calling this constructor is invalid.
+    #[unstable(feature = "pin", issue = "49150")]
+    pub unsafe fn new_unchecked(reference: &'a mut T) -> PinMut<'a, T> {
+        PinMut { inner: reference }
+    }
+
+    /// Reborrow a `PinMut` for a shorter lifetime.
+    ///
+    /// For example, `PinMut::get_mut(x.reborrow())` (unsafely) returns a
+    /// short-lived mutable reference reborrowing from `x`.
+    #[unstable(feature = "pin", issue = "49150")]
+    pub fn reborrow<'b>(&'b mut self) -> PinMut<'b, T> {
+        PinMut { inner: self.inner }
+    }
+
+    /// Get a mutable reference to the data inside of this `PinMut`.
+    ///
+    /// This function is unsafe. You must guarantee that you will never move
+    /// the data out of the mutable reference you receive when you call this
+    /// function.
+    #[unstable(feature = "pin", issue = "49150")]
+    pub unsafe fn get_mut_unchecked(this: PinMut<'a, T>) -> &'a mut T {
+        this.inner
+    }
+
+    /// Construct a new pin by mapping the interior value.
+    ///
+    /// For example, if you  wanted to get a `PinMut` of a field of something,
+    /// you could use this to get access to that field in one line of code.
+    ///
+    /// This function is unsafe. You must guarantee that the data you return
+    /// will not move so long as the argument value does not move (for example,
+    /// because it is one of the fields of that value), and also that you do
+    /// not move out of the argument you receive to the interior function.
+    #[unstable(feature = "pin", issue = "49150")]
+    pub unsafe fn map_unchecked<U, F>(this: PinMut<'a, T>, f: F) -> PinMut<'a, U> where
+        F: FnOnce(&mut T) -> &mut U
+    {
+        PinMut { inner: f(this.inner) }
+    }
+
+    /// Assign a new value to the memory behind the pinned reference.
+    #[unstable(feature = "pin", issue = "49150")]
+    pub fn set(this: PinMut<'a, T>, value: T)
+        where T: Sized,
+    {
+        *this.inner = value;
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized> Deref for PinMut<'a, T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &*self.inner
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized + Unpin> DerefMut for PinMut<'a, T> {
+    fn deref_mut(&mut self) -> &mut T {
+        self.inner
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for PinMut<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&**self, f)
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: fmt::Display + ?Sized> fmt::Display for PinMut<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&**self, f)
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized> fmt::Pointer for PinMut<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Pointer::fmt(&(&*self.inner as *const T), f)
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinMut<'a, U>> for PinMut<'a, T> {}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized> Unpin for PinMut<'a, T> {}
+
+#[unstable(feature = "futures_api", issue = "50547")]
+unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinMut<'a, F>
+    where F: Future<Output = T> + 'a
+{
+    fn into_raw(self) -> *mut () {
+        unsafe { PinMut::get_mut_unchecked(self) as *mut F as *mut () }
+    }
+
+    unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> {
+        PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx)
+    }
+
+    unsafe fn drop(_ptr: *mut ()) {}
+}
index 61033e7511253c858ee790bbbd2d0f292b48c121..57351822cc3cfe765ebd961dde0e12c61ff470e6 100644 (file)
@@ -226,8 +226,8 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
         // Declaring `t` here avoids aligning the stack when this loop is unused
         let mut t: Block = mem::uninitialized();
         let t = &mut t as *mut _ as *mut u8;
-        let x = x.offset(i as isize);
-        let y = y.offset(i as isize);
+        let x = x.add(i);
+        let y = y.add(i);
 
         // Swap a block of bytes of x & y, using t as a temporary buffer
         // This should be optimized into efficient SIMD operations where available
@@ -243,8 +243,8 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
         let rem = len - i;
 
         let t = &mut t as *mut _ as *mut u8;
-        let x = x.offset(i as isize);
-        let y = y.offset(i as isize);
+        let x = x.add(i);
+        let y = y.add(i);
 
         copy_nonoverlapping(x, t, rem);
         copy_nonoverlapping(y, x, rem);
@@ -582,6 +582,21 @@ pub fn is_null(self) -> bool {
     ///     }
     /// }
     /// ```
+    ///
+    /// # Null-unchecked version
+    ///
+    /// If you are sure the pointer can never be null and are looking for some kind of
+    /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>, know that you can
+    /// dereference the pointer directly.
+    ///
+    /// ```
+    /// let ptr: *const u8 = &10u8 as *const u8;
+    ///
+    /// unsafe {
+    ///     let val_back = &*ptr;
+    ///     println!("We got back the value: {}!", val_back);
+    /// }
+    /// ```
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
     pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
@@ -613,7 +628,7 @@ pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
     /// The compiler and standard library generally tries to ensure allocations
     /// never reach a size where an offset is a concern. For instance, `Vec`
     /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().offset(vec.len() as isize)` is always safe.
+    /// `vec.as_ptr().add(vec.len())` is always safe.
     ///
     /// Most platforms fundamentally can't even construct such an allocation.
     /// For instance, no known 64-bit platform can ever serve a request
@@ -1231,7 +1246,7 @@ pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
     /// let ptr = &x[n] as *const u8;
     /// let offset = ptr.align_offset(align_of::<u16>());
     /// if offset < x.len() - n - 1 {
-    ///     let u16_ptr = ptr.offset(offset as isize) as *const u16;
+    ///     let u16_ptr = ptr.add(offset) as *const u16;
     ///     assert_ne!(*u16_ptr, 500);
     /// } else {
     ///     // while the pointer can be aligned via `offset`, it would point
@@ -1303,6 +1318,21 @@ pub fn is_null(self) -> bool {
     ///     }
     /// }
     /// ```
+    ///
+    /// # Null-unchecked version
+    ///
+    /// If you are sure the pointer can never be null and are looking for some kind of
+    /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>, know that you can
+    /// dereference the pointer directly.
+    ///
+    /// ```
+    /// let ptr: *mut u8 = &mut 10u8 as *mut u8;
+    ///
+    /// unsafe {
+    ///     let val_back = &*ptr;
+    ///     println!("We got back the value: {}!", val_back);
+    /// }
+    /// ```
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
     pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
@@ -1334,7 +1364,7 @@ pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
     /// The compiler and standard library generally tries to ensure allocations
     /// never reach a size where an offset is a concern. For instance, `Vec`
     /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().offset(vec.len() as isize)` is always safe.
+    /// `vec.as_ptr().add(vec.len())` is always safe.
     ///
     /// Most platforms fundamentally can't even construct such an allocation.
     /// For instance, no known 64-bit platform can ever serve a request
@@ -2261,7 +2291,7 @@ pub unsafe fn swap(self, with: *mut T)
     /// let ptr = &x[n] as *const u8;
     /// let offset = ptr.align_offset(align_of::<u16>());
     /// if offset < x.len() - n - 1 {
-    ///     let u16_ptr = ptr.offset(offset as isize) as *const u16;
+    ///     let u16_ptr = ptr.add(offset) as *const u16;
     ///     assert_ne!(*u16_ptr, 500);
     /// } else {
     ///     // while the pointer can be aligned via `offset`, it would point
@@ -2291,7 +2321,7 @@ pub fn align_offset(self, align: usize) -> usize where T: Sized {
 ///
 /// If we ever decide to make it possible to call the intrinsic with `a` that is not a
 /// power-of-two, it will probably be more prudent to just change to a naive implementation rather
-/// than trying to adapt this to accomodate that change.
+/// than trying to adapt this to accommodate that change.
 ///
 /// Any questions go to @nagisa.
 #[lang="align_offset"]
index c9d3c7fea9839e1ed3da89ae8b61971ff69c493f..cf95333af9cbb1622a69244f25d4dba61b269b01 100644 (file)
@@ -72,8 +72,8 @@ pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
     if len >= 2 * usize_bytes {
         while offset <= len - 2 * usize_bytes {
             unsafe {
-                let u = *(ptr.offset(offset as isize) as *const usize);
-                let v = *(ptr.offset((offset + usize_bytes) as isize) as *const usize);
+                let u = *(ptr.add(offset) as *const usize);
+                let v = *(ptr.add(offset + usize_bytes) as *const usize);
 
                 // break if there is a matching byte
                 let zu = contains_zero_byte(u ^ repeated_x);
index a3960556d3412f404286d1440e64b1a0d37c294c..f8c3feba74ca616cc7e4c8687633163aad40cf39 100644 (file)
 // The library infrastructure for slices is fairly messy. There's
 // a lot of stuff defined here. Let's keep it clean.
 //
-// Since slices don't support inherent methods; all operations
-// on them are defined on traits, which are then re-exported from
-// the prelude for convenience. So there are a lot of traits here.
-//
 // The layout of this file is thus:
 //
-// * Slice-specific 'extension' traits and their implementations. This
-//   is where most of the slice API resides.
+// * Inherent methods. This is where most of the slice API resides.
 // * Implementations of a few common traits with important slice ops.
 // * Definitions of a bunch of iterators.
 // * Free functions.
@@ -383,7 +378,7 @@ pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
     ///
     /// unsafe {
     ///     for i in 0..x.len() {
-    ///         assert_eq!(x.get_unchecked(i), &*x_ptr.offset(i as isize));
+    ///         assert_eq!(x.get_unchecked(i), &*x_ptr.add(i));
     ///     }
     /// }
     /// ```
@@ -410,7 +405,7 @@ pub const fn as_ptr(&self) -> *const T {
     ///
     /// unsafe {
     ///     for i in 0..x.len() {
-    ///         *x_ptr.offset(i as isize) += 2;
+    ///         *x_ptr.add(i) += 2;
     ///     }
     /// }
     /// assert_eq!(x, &[3, 4, 6]);
@@ -546,9 +541,9 @@ pub fn iter(&self) -> Iter<T> {
             assume(!ptr.is_null());
 
             let end = if mem::size_of::<T>() == 0 {
-                (ptr as *const u8).wrapping_offset(self.len() as isize) as *const T
+                (ptr as *const u8).wrapping_add(self.len()) as *const T
             } else {
-                ptr.offset(self.len() as isize)
+                ptr.add(self.len())
             };
 
             Iter {
@@ -578,9 +573,9 @@ pub fn iter_mut(&mut self) -> IterMut<T> {
             assume(!ptr.is_null());
 
             let end = if mem::size_of::<T>() == 0 {
-                (ptr as *mut u8).wrapping_offset(self.len() as isize) as *mut T
+                (ptr as *mut u8).wrapping_add(self.len()) as *mut T
             } else {
-                ptr.offset(self.len() as isize)
+                ptr.add(self.len())
             };
 
             IterMut {
@@ -842,7 +837,7 @@ pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
             assert!(mid <= len);
 
             (from_raw_parts_mut(ptr, mid),
-             from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
+             from_raw_parts_mut(ptr.add(mid), len - mid))
         }
     }
 
@@ -1444,7 +1439,7 @@ pub fn rotate_left(&mut self, mid: usize) {
 
         unsafe {
             let p = self.as_mut_ptr();
-            rotate::ptr_rotate(mid, p.offset(mid as isize), k);
+            rotate::ptr_rotate(mid, p.add(mid), k);
         }
     }
 
@@ -1485,7 +1480,7 @@ pub fn rotate_right(&mut self, k: usize) {
 
         unsafe {
             let p = self.as_mut_ptr();
-            rotate::ptr_rotate(mid, p.offset(mid as isize), k);
+            rotate::ptr_rotate(mid, p.add(mid), k);
         }
     }
 
@@ -1680,7 +1675,7 @@ pub fn swap_with_slice(&mut self, other: &mut [T]) {
         }
     }
 
-    /// Function to calculate lenghts of the middle and trailing slice for `align_to{,_mut}`.
+    /// Function to calculate lengths of the middle and trailing slice for `align_to{,_mut}`.
     fn align_to_offsets<U>(&self) -> (usize, usize) {
         // What we gonna do about `rest` is figure out what multiple of `U`s we can put in a
         // lowest number of `T`s. And how many `T`s we need for each such "multiple".
@@ -1740,7 +1735,7 @@ fn gcd(a: usize, b: usize) -> usize {
         (us_len, ts_len)
     }
 
-    /// Transmute the slice to a slice of another type, ensuring aligment of the types is
+    /// Transmute the slice to a slice of another type, ensuring alignment of the types is
     /// maintained.
     ///
     /// This method splits the slice into three distinct slices: prefix, correctly aligned middle
@@ -1789,11 +1784,11 @@ pub unsafe fn align_to<U>(&self) -> (&[T], &[U], &[T]) {
             let (us_len, ts_len) = rest.align_to_offsets::<U>();
             (left,
              from_raw_parts(rest.as_ptr() as *const U, us_len),
-             from_raw_parts(rest.as_ptr().offset((rest.len() - ts_len) as isize), ts_len))
+             from_raw_parts(rest.as_ptr().add(rest.len() - ts_len), ts_len))
         }
     }
 
-    /// Transmute the slice to a slice of another type, ensuring aligment of the types is
+    /// Transmute the slice to a slice of another type, ensuring alignment of the types is
     /// maintained.
     ///
     /// This method splits the slice into three distinct slices: prefix, correctly aligned middle
@@ -1843,7 +1838,7 @@ pub unsafe fn align_to_mut<U>(&mut self) -> (&mut [T], &mut [U], &mut [T]) {
             let mut_ptr = rest.as_mut_ptr();
             (left,
              from_raw_parts_mut(mut_ptr as *mut U, us_len),
-             from_raw_parts_mut(mut_ptr.offset((rest.len() - ts_len) as isize), ts_len))
+             from_raw_parts_mut(mut_ptr.add(rest.len() - ts_len), ts_len))
         }
     }
 }
@@ -2037,12 +2032,12 @@ fn get_mut(self, slice: &mut [T]) -> Option<&mut T> {
 
     #[inline]
     unsafe fn get_unchecked(self, slice: &[T]) -> &T {
-        &*slice.as_ptr().offset(self as isize)
+        &*slice.as_ptr().add(self)
     }
 
     #[inline]
     unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut T {
-        &mut *slice.as_mut_ptr().offset(self as isize)
+        &mut *slice.as_mut_ptr().add(self)
     }
 
     #[inline]
@@ -2086,12 +2081,12 @@ fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
 
     #[inline]
     unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
-        from_raw_parts(slice.as_ptr().offset(self.start as isize), self.end - self.start)
+        from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start)
     }
 
     #[inline]
     unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
-        from_raw_parts_mut(slice.as_mut_ptr().offset(self.start as isize), self.end - self.start)
+        from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start)
     }
 
     #[inline]
@@ -2467,7 +2462,7 @@ fn nth(&mut self, n: usize) -> Option<$elem> {
                 }
                 // We are in bounds. `offset` does the right thing even for ZSTs.
                 unsafe {
-                    let elem = Some(& $( $mut_ )* *self.ptr.offset(n as isize));
+                    let elem = Some(& $( $mut_ )* *self.ptr.add(n));
                     self.post_inc_start((n as isize).wrapping_add(1));
                     elem
                 }
@@ -3347,7 +3342,7 @@ impl<'a, T> FusedIterator for Windows<'a, T> {}
 #[doc(hidden)]
 unsafe impl<'a, T> TrustedRandomAccess for Windows<'a, T> {
     unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
-        from_raw_parts(self.v.as_ptr().offset(i as isize), self.size)
+        from_raw_parts(self.v.as_ptr().add(i), self.size)
     }
     fn may_have_side_effect() -> bool { false }
 }
@@ -3474,7 +3469,7 @@ unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
             None => self.v.len(),
             Some(end) => cmp::min(end, self.v.len()),
         };
-        from_raw_parts(self.v.as_ptr().offset(start as isize), end - start)
+        from_raw_parts(self.v.as_ptr().add(start), end - start)
     }
     fn may_have_side_effect() -> bool { false }
 }
@@ -3593,7 +3588,7 @@ unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
             None => self.v.len(),
             Some(end) => cmp::min(end, self.v.len()),
         };
-        from_raw_parts_mut(self.v.as_mut_ptr().offset(start as isize), end - start)
+        from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start)
     }
     fn may_have_side_effect() -> bool { false }
 }
@@ -3716,7 +3711,7 @@ impl<'a, T> FusedIterator for ExactChunks<'a, T> {}
 unsafe impl<'a, T> TrustedRandomAccess for ExactChunks<'a, T> {
     unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
         let start = i * self.chunk_size;
-        from_raw_parts(self.v.as_ptr().offset(start as isize), self.chunk_size)
+        from_raw_parts(self.v.as_ptr().add(start), self.chunk_size)
     }
     fn may_have_side_effect() -> bool { false }
 }
@@ -3831,7 +3826,7 @@ impl<'a, T> FusedIterator for ExactChunksMut<'a, T> {}
 unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> {
     unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
         let start = i * self.chunk_size;
-        from_raw_parts_mut(self.v.as_mut_ptr().offset(start as isize), self.chunk_size)
+        from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size)
     }
     fn may_have_side_effect() -> bool { false }
 }
@@ -4116,7 +4111,7 @@ impl $traitname for $ty { }
 #[doc(hidden)]
 unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> {
     unsafe fn get_unchecked(&mut self, i: usize) -> &'a T {
-        &*self.ptr.offset(i as isize)
+        &*self.ptr.add(i)
     }
     fn may_have_side_effect() -> bool { false }
 }
@@ -4124,7 +4119,7 @@ fn may_have_side_effect() -> bool { false }
 #[doc(hidden)]
 unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> {
     unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T {
-        &mut *self.ptr.offset(i as isize)
+        &mut *self.ptr.add(i)
     }
     fn may_have_side_effect() -> bool { false }
 }
index 28ef53ccb5cb6b50547b5619bd7d5b7af86049c7..0d182b8497452e2bf7db6d6417b4b6e2092d3b34 100644 (file)
@@ -77,8 +77,8 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mid: *mut T, mut right: usize) {
         }
 
         ptr::swap_nonoverlapping(
-            mid.offset(-(left as isize)),
-            mid.offset((right-delta) as isize),
+            mid.sub(left),
+            mid.add(right - delta),
             delta);
 
         if left <= right {
@@ -91,15 +91,15 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mid: *mut T, mut right: usize) {
     let rawarray = RawArray::new();
     let buf = rawarray.ptr();
 
-    let dim = mid.offset(-(left as isize)).offset(right as isize);
+    let dim = mid.sub(left).add(right);
     if left <= right {
-        ptr::copy_nonoverlapping(mid.offset(-(left as isize)), buf, left);
-        ptr::copy(mid, mid.offset(-(left as isize)), right);
+        ptr::copy_nonoverlapping(mid.sub(left), buf, left);
+        ptr::copy(mid, mid.sub(left), right);
         ptr::copy_nonoverlapping(buf, dim, left);
     }
     else {
         ptr::copy_nonoverlapping(mid, buf, right);
-        ptr::copy(mid.offset(-(left as isize)), dim, left);
-        ptr::copy_nonoverlapping(buf, mid.offset(-(left as isize)), right);
+        ptr::copy(mid.sub(left), dim, left);
+        ptr::copy_nonoverlapping(buf, mid.sub(left), right);
     }
 }
index 518d56095d60105ecf05392ad73c45f2efa1769c..e4c1fd03f9eb384b1197e5a6d3b82ed14f85d349 100644 (file)
@@ -221,15 +221,15 @@ fn partition_in_blocks<T, F>(v: &mut [T], pivot: &T, is_less: &mut F) -> usize
     // 3. `end` - End pointer into the `offsets` array.
     // 4. `offsets - Indices of out-of-order elements within the block.
 
-    // The current block on the left side (from `l` to `l.offset(block_l)`).
+    // The current block on the left side (from `l` to `l.add(block_l)`).
     let mut l = v.as_mut_ptr();
     let mut block_l = BLOCK;
     let mut start_l = ptr::null_mut();
     let mut end_l = ptr::null_mut();
     let mut offsets_l: [u8; BLOCK] = unsafe { mem::uninitialized() };
 
-    // The current block on the right side (from `r.offset(-block_r)` to `r`).
-    let mut r = unsafe { l.offset(v.len() as isize) };
+    // The current block on the right side (from `r.sub(block_r)` to `r`).
+    let mut r = unsafe { l.add(v.len()) };
     let mut block_r = BLOCK;
     let mut start_r = ptr::null_mut();
     let mut end_r = ptr::null_mut();
index 810d19df0c5ba460a8dd707193c406c4af08a13f..64bdf4d9f486ad84d1d6d6dbdd72ad1ddaa3fe9f 100644 (file)
@@ -1518,12 +1518,12 @@ macro_rules! next { () => {{
             let ptr = v.as_ptr();
             let align = unsafe {
                 // the offset is safe, because `index` is guaranteed inbounds
-                ptr.offset(index as isize).align_offset(usize_bytes)
+                ptr.add(index).align_offset(usize_bytes)
             };
             if align == 0 {
                 while index < blocks_end {
                     unsafe {
-                        let block = ptr.offset(index as isize) as *const usize;
+                        let block = ptr.add(index) as *const usize;
                         // break if there is a nonascii byte
                         let zu = contains_nonascii(*block);
                         let zv = contains_nonascii(*block.offset(1));
@@ -1878,13 +1878,13 @@ fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
         }
         #[inline]
         unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
-            let ptr = slice.as_ptr().offset(self.start as isize);
+            let ptr = slice.as_ptr().add(self.start);
             let len = self.end - self.start;
             super::from_utf8_unchecked(slice::from_raw_parts(ptr, len))
         }
         #[inline]
         unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
-            let ptr = slice.as_ptr().offset(self.start as isize);
+            let ptr = slice.as_ptr().add(self.start);
             let len = self.end - self.start;
             super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, len))
         }
@@ -1973,13 +1973,13 @@ fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
         }
         #[inline]
         unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
-            let ptr = slice.as_ptr().offset(self.start as isize);
+            let ptr = slice.as_ptr().add(self.start);
             let len = slice.len() - self.start;
             super::from_utf8_unchecked(slice::from_raw_parts(ptr, len))
         }
         #[inline]
         unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
-            let ptr = slice.as_ptr().offset(self.start as isize);
+            let ptr = slice.as_ptr().add(self.start);
             let len = slice.len() - self.start;
             super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, len))
         }
@@ -2573,7 +2573,7 @@ pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
             unsafe {
                 (from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, mid)),
                  from_utf8_unchecked_mut(slice::from_raw_parts_mut(
-                    ptr.offset(mid as isize),
+                    ptr.add(mid),
                     len - mid
                  )))
             }
index fc92a5a222512a660da46ce339ae631b3220db37..e48f3b36c658675ddd8f48ff33c3842dcc9a482c 100644 (file)
@@ -37,7 +37,6 @@
 #![feature(slice_align_to)]
 #![feature(align_offset)]
 #![feature(reverse_bits)]
-#![feature(iterator_find_map)]
 #![feature(inner_deref)]
 #![feature(slice_internals)]
 #![feature(option_replace)]
index e2380f0fe2ff389464c4fb302de6bf7849e9d6b1..3720100700c9c2768249fae7fa488c62e39f78b0 100644 (file)
@@ -21,6 +21,7 @@
        test(attr(deny(warnings))))]
 
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 
 pub use self::Piece::*;
 pub use self::Position::*;
@@ -154,7 +155,7 @@ pub struct Parser<'a> {
     style: Option<usize>,
     /// How many newlines have been seen in the string so far, to adjust the error spans
     seen_newlines: usize,
-    /// Start and end byte offset of every successfuly parsed argument
+    /// Start and end byte offset of every successfully parsed argument
     pub arg_places: Vec<(usize, usize)>,
 }
 
index 9fa48adebdf07a523411152409a2e1465c07fc37..5a0c983b521a54c5afee7a4689ef59ca0478ea86 100644 (file)
        test(attr(allow(unused_variables), deny(warnings))))]
 
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(str_escape)]
 
 use self::LabelText::*;
index 6bdbf5dc937459bd10e6bc4dc52b0adbd8cf4358..1844a772b60771d0124a157019f627d60fea4e73 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 6bdbf5dc937459bd10e6bc4dc52b0adbd8cf4358
+Subproject commit 1844a772b60771d0124a157019f627d60fea4e73
index da568fae70e146e908326a17f13bbe0eaefb4ed2..4da88d8522196642536d29cc876dbeb355f4f84b 100644 (file)
 #![feature(core_intrinsics)]
 #![feature(libc)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(panic_runtime)]
 #![feature(staged_api)]
 #![feature(rustc_attrs)]
 
 // Rust's "try" function, but if we're aborting on panics we just call the
 // function as there's nothing else we need to do here.
-#[no_mangle]
+#[cfg_attr(stage0, no_mangle)]
 #[rustc_std_internal_symbol]
 pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8),
                                               data: *mut u8,
@@ -51,7 +52,7 @@
 // which would break compat with XP. For now just use `intrinsics::abort` which
 // will kill us with an illegal instruction, which will do a good enough job for
 // now hopefully.
-#[no_mangle]
+#[cfg_attr(stage0, no_mangle)]
 #[rustc_std_internal_symbol]
 pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 {
     abort();
index 5c05ac11d307d1c74884c4f18315a6caa0f48991..7e0c32fe03d8a57a43f5d7b17e8264e646fdbc88 100644 (file)
@@ -38,7 +38,7 @@ pub fn new(ptr: *const u8) -> DwarfReader {
     // telling the backend to generate "misalignment-safe" code.
     pub unsafe fn read<T: Copy>(&mut self) -> T {
         let Unaligned(result) = *(self.ptr as *const Unaligned<T>);
-        self.ptr = self.ptr.offset(mem::size_of::<T>() as isize);
+        self.ptr = self.ptr.add(mem::size_of::<T>());
         result
     }
 
index 9c3fc76c307a6f7696ba4ce2f163c1dea7812602..3368790b3f76fad2e61742431b09324a532ff8ee 100644 (file)
@@ -35,6 +35,7 @@
 #![feature(lang_items)]
 #![feature(libc)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(panic_unwind)]
 #![feature(raw)]
 #![feature(staged_api)]
index 8cbc4a623fa052ebf44664614dfeac7f1e036cfd..d6298a38a2601fbd3cee9699c40ec983e7f0af84 100644 (file)
@@ -54,7 +54,7 @@
 //! [win64]: http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx
 //! [llvm]: http://llvm.org/docs/ExceptionHandling.html#background-on-windows-exceptions
 
-#![allow(bad_style)]
+#![allow(nonstandard_style)]
 #![allow(private_no_mangle_fns)]
 
 use alloc::boxed::Box;
@@ -142,7 +142,7 @@ macro_rules! ptr {
 
 #[repr(C)]
 pub struct _ThrowInfo {
-    pub attribues: c_uint,
+    pub attributes: c_uint,
     pub pnfnUnwind: imp::ptr_t,
     pub pForwardCompat: imp::ptr_t,
     pub pCatchableTypeArray: imp::ptr_t,
@@ -178,7 +178,7 @@ pub struct _TypeDescriptor {
 }
 
 static mut THROW_INFO: _ThrowInfo = _ThrowInfo {
-    attribues: 0,
+    attributes: 0,
     pnfnUnwind: ptr!(0),
     pForwardCompat: ptr!(0),
     pCatchableTypeArray: ptr!(0),
index 0b08e54c6739a0684c41cf9478e87b35027f8e82..c2074db00385b8367c823eb44d3ba4365d65b1c0 100644 (file)
@@ -11,7 +11,7 @@
 //! Unwinding implementation of top of native Win64 SEH,
 //! however the unwind handler data (aka LSDA) uses GCC-compatible encoding.
 
-#![allow(bad_style)]
+#![allow(nonstandard_style)]
 #![allow(private_no_mangle_fns)]
 
 use alloc::boxed::Box;
index 5f1dda36a889ea0aff118b969d5da63d37f9d3ef..0a1c9b3adf183b67143f02a7f335dc16446d5591 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(bad_style)]
+#![allow(nonstandard_style)]
 #![allow(dead_code)]
 #![cfg(windows)]
 
index 0a32963a861de6c0764eb461a0f4d5cb5a12e5e8..8c667d2f8711180b421a816cf48921779e899cb4 100644 (file)
@@ -12,7 +12,7 @@
 //!
 //! This library, provided by the standard distribution, provides the types
 //! consumed in the interfaces of procedurally defined macro definitions such as
-//! function-like macros `#[proc_macro]`, macro attribures `#[proc_macro_attribute]` and
+//! function-like macros `#[proc_macro]`, macro attributes `#[proc_macro_attribute]` and
 //! custom derive attributes`#[proc_macro_derive]`.
 //!
 //! Note that this crate is intentionally bare-bones currently.
@@ -32,6 +32,7 @@
        test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
 
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(lang_items)]
index a85593253b100f8f184ab7a336335ef7961ea5e8..00dd87022c268533b20c55493f2359fa9dfdbc1e 100644 (file)
@@ -16,4 +16,5 @@
             issue = "0")]
 #![allow(unused_features)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(staged_api)]
index 59b5b58e61eac533f1c3245b28880c1028405c85..fc5d4a9c92331bb606e535b23a9f5b55eca2168c 100644 (file)
@@ -33,6 +33,7 @@ parking_lot = "0.5.5"
 byteorder = { version = "1.1", features = ["i128"]}
 chalk-engine = { version = "0.7.0", default-features=false }
 rustc_fs_util = { path = "../librustc_fs_util" }
+smallvec = { version = "0.6.5", features = ["union"] }
 
 # Note that these dependencies are a lie, they're just here to get linkage to
 # work.
index b7281cf0445cdf0a30c72cfc7f5c44030a215d4f..dfe0a395ca140678fac359aa24fc6236e0ca3d1e 100644 (file)
@@ -75,7 +75,7 @@
     CanonicalPredicateGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal,
 };
 use ty::{TyCtxt, FnSig, Instance, InstanceDef,
-         ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty, self};
+         ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty};
 use ty::subst::Substs;
 
 // erase!() just makes tokens go away. It's used to specify which macro argument
@@ -632,7 +632,6 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     // queries). Making them anonymous avoids hashing the result, which
     // may save a bit of time.
     [anon] EraseRegionsTy { ty: Ty<'tcx> },
-    [anon] ConstValueToAllocation { val: &'tcx ty::Const<'tcx> },
 
     [input] Freevars(DefId),
     [input] MaybeUnusedTraitImport(DefId),
index e308f2924a05c571c0efa4a4a24cdfc704c8789e..a285399657177a3ade729dc2421f45363c82b390 100644 (file)
@@ -12,7 +12,7 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
-use rustc_data_structures::small_vec::SmallVec;
+use smallvec::SmallVec;
 use rustc_data_structures::sync::{Lrc, Lock};
 use std::env;
 use std::hash::Hash;
@@ -1025,7 +1025,7 @@ fn complete_eval_always_task(&mut self, key: DepNode, task: OpenTask) -> DepNode
         } = task {
             debug_assert_eq!(node, key);
             let krate_idx = self.node_to_node_index[&DepNode::new_no_params(DepKind::Krate)];
-            self.alloc_node(node, SmallVec::one(krate_idx))
+            self.alloc_node(node, smallvec![krate_idx])
         } else {
             bug!("complete_eval_always_task() - Expected eval always task to be popped");
         }
index 4a14223eb88f78b4b6b23f90e6c3e24270a471b2..b10f4785f16377d3e08cef3fdd7d12928e845048 100644 (file)
@@ -53,7 +53,7 @@ pub enum Def {
     Existential(DefId),
     /// `type Foo = Bar;`
     TyAlias(DefId),
-    TyForeign(DefId),
+    ForeignTy(DefId),
     TraitAlias(DefId),
     AssociatedTy(DefId),
     /// `existential type Foo: Bar;`
@@ -68,7 +68,7 @@ pub enum Def {
     Const(DefId),
     Static(DefId, bool /* is_mutbl */),
     StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor
-    VariantCtor(DefId, CtorKind),
+    VariantCtor(DefId, CtorKind), // DefId refers to the enum variant
     Method(DefId),
     AssociatedConst(DefId),
 
@@ -272,7 +272,7 @@ pub fn def_id(&self) -> DefId {
             Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
             Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
             Def::AssociatedConst(id) | Def::Macro(id, ..) |
-            Def::Existential(id) | Def::AssociatedExistential(id) | Def::TyForeign(id) => {
+            Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) => {
                 id
             }
 
@@ -311,7 +311,7 @@ pub fn kind_name(&self) -> &'static str {
             Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
             Def::Union(..) => "union",
             Def::Trait(..) => "trait",
-            Def::TyForeign(..) => "foreign type",
+            Def::ForeignTy(..) => "foreign type",
             Def::Method(..) => "method",
             Def::Const(..) => "constant",
             Def::AssociatedConst(..) => "associated constant",
index 7acfe6839540b5ebd2c57e676a63c6d5724ad9f3..be37ea18457f16a90cff2aeb4e222f3b06dbd9ca 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use ty;
-
+use hir::map::definitions::FIRST_FREE_HIGH_DEF_INDEX;
 use rustc_data_structures::indexed_vec::Idx;
 use serialize;
 use std::fmt;
@@ -125,15 +125,25 @@ pub fn from_array_index(i: usize, address_space: DefIndexAddressSpace) -> DefInd
     // index of the macro in the CrateMetadata::proc_macros array) to the
     // corresponding DefIndex.
     pub fn from_proc_macro_index(proc_macro_index: usize) -> DefIndex {
-        let def_index = DefIndex::from_array_index(proc_macro_index,
-                                                   DefIndexAddressSpace::High);
+        // DefIndex for proc macros start from FIRST_FREE_HIGH_DEF_INDEX,
+        // because the first FIRST_FREE_HIGH_DEF_INDEX indexes are reserved
+        // for internal use.
+        let def_index = DefIndex::from_array_index(
+            proc_macro_index.checked_add(FIRST_FREE_HIGH_DEF_INDEX)
+                .expect("integer overflow adding `proc_macro_index`"),
+            DefIndexAddressSpace::High);
         assert!(def_index != CRATE_DEF_INDEX);
         def_index
     }
 
     // This function is the reverse of from_proc_macro_index() above.
     pub fn to_proc_macro_index(self: DefIndex) -> usize {
-        self.as_array_index()
+        assert_eq!(self.address_space(), DefIndexAddressSpace::High);
+
+        self.as_array_index().checked_sub(FIRST_FREE_HIGH_DEF_INDEX)
+            .unwrap_or_else(|| {
+                bug!("using local index {:?} as proc-macro index", self)
+            })
     }
 
     // Don't use this if you don't know about the DefIndex encoding.
@@ -150,7 +160,7 @@ pub fn as_raw_u32(&self) -> u32 {
 impl serialize::UseSpecializedEncodable for DefIndex {}
 impl serialize::UseSpecializedDecodable for DefIndex {}
 
-#[derive(Copy, Clone, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub enum DefIndexAddressSpace {
     Low = 0,
     High = 1,
index bb4fabf1c3e5e07b899b0ad187d0c2061ad8d72f..34b3eb0a8c8bf64d1fd595377f2f028d89dcaf3f 100644 (file)
@@ -50,6 +50,7 @@
 use lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
                     ELIDED_LIFETIMES_IN_PATHS};
 use middle::cstore::CrateStore;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::small_vec::OneVector;
 use rustc_data_structures::thin_vec::ThinVec;
@@ -57,7 +58,7 @@
 use util::common::FN_OUTPUT_NAME;
 use util::nodemap::{DefIdMap, NodeMap};
 
-use std::collections::{BTreeMap, HashSet};
+use std::collections::BTreeMap;
 use std::fmt::Debug;
 use std::iter;
 use std::mem;
@@ -1186,7 +1187,7 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext) -> hir::Ty {
                     }
                     ImplTraitContext::Universal(in_band_ty_params) => {
                         self.lower_node_id(def_node_id);
-                        // Add a definition for the in-band TyParam
+                        // Add a definition for the in-band Param
                         let def_index = self
                             .resolver
                             .definitions()
@@ -1345,7 +1346,7 @@ struct ImplTraitLifetimeCollector<'r, 'a: 'r> {
             exist_ty_id: NodeId,
             collect_elided_lifetimes: bool,
             currently_bound_lifetimes: Vec<hir::LifetimeName>,
-            already_defined_lifetimes: HashSet<hir::LifetimeName>,
+            already_defined_lifetimes: FxHashSet<hir::LifetimeName>,
             output_lifetimes: Vec<hir::GenericArg>,
             output_lifetime_params: Vec<hir::GenericParam>,
         }
@@ -1479,7 +1480,7 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
             exist_ty_id,
             collect_elided_lifetimes: true,
             currently_bound_lifetimes: Vec::new(),
-            already_defined_lifetimes: HashSet::new(),
+            already_defined_lifetimes: FxHashSet::default(),
             output_lifetimes: Vec::new(),
             output_lifetime_params: Vec::new(),
         };
@@ -3181,18 +3182,18 @@ fn visit_path_segment(
     fn lower_item_id(&mut self, i: &Item) -> OneVector<hir::ItemId> {
         match i.node {
             ItemKind::Use(ref use_tree) => {
-                let mut vec = OneVector::one(hir::ItemId { id: i.id });
+                let mut vec = smallvec![hir::ItemId { id: i.id }];
                 self.lower_item_id_use_tree(use_tree, i.id, &mut vec);
                 vec
             }
             ItemKind::MacroDef(..) => OneVector::new(),
             ItemKind::Fn(ref decl, ref header, ..) => {
-                let mut ids = OneVector::one(hir::ItemId { id: i.id });
+                let mut ids = smallvec![hir::ItemId { id: i.id }];
                 self.lower_impl_trait_ids(decl, header, &mut ids);
                 ids
             },
             ItemKind::Impl(.., None, _, ref items) => {
-                let mut ids = OneVector::one(hir::ItemId { id: i.id });
+                let mut ids = smallvec![hir::ItemId { id: i.id }];
                 for item in items {
                     if let ImplItemKind::Method(ref sig, _) = item.node {
                         self.lower_impl_trait_ids(&sig.decl, &sig.header, &mut ids);
@@ -3200,7 +3201,7 @@ fn lower_item_id(&mut self, i: &Item) -> OneVector<hir::ItemId> {
                 }
                 ids
             },
-            _ => OneVector::one(hir::ItemId { id: i.id }),
+            _ => smallvec![hir::ItemId { id: i.id }],
         }
     }
 
@@ -3616,10 +3617,10 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     hir::LoopSource::Loop,
                 )
             }),
-            ExprKind::Catch(ref body) => {
+            ExprKind::TryBlock(ref body) => {
                 self.with_catch_scope(body.id, |this| {
                     let unstable_span =
-                        this.allow_internal_unstable(CompilerDesugaringKind::Catch, body.span);
+                        this.allow_internal_unstable(CompilerDesugaringKind::TryBlock, body.span);
                     let mut block = this.lower_block(body, true).into_inner();
                     let tail = block.expr.take().map_or_else(
                         || {
@@ -4300,7 +4301,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
     }
 
     fn lower_stmt(&mut self, s: &Stmt) -> OneVector<hir::Stmt> {
-        OneVector::one(match s.node {
+        smallvec![match s.node {
             StmtKind::Local(ref l) => Spanned {
                 node: hir::StmtKind::Decl(
                     P(Spanned {
@@ -4339,7 +4340,7 @@ fn lower_stmt(&mut self, s: &Stmt) -> OneVector<hir::Stmt> {
                 span: s.span,
             },
             StmtKind::Mac(..) => panic!("Shouldn't exist here"),
-        })
+        }]
     }
 
     fn lower_capture_clause(&mut self, c: CaptureBy) -> hir::CaptureClause {
index f2f7f95426ab827e977cab992111d409df00bfa5..eeb41682601f5798125be49567f819665b2f1ab2 100644 (file)
@@ -22,8 +22,8 @@
 //! for the `Code` associated with a particular NodeId.
 
 use hir as ast;
-use hir::map::{self, Node};
-use hir::{Expr, FnDecl};
+use hir::map;
+use hir::{Expr, FnDecl, Node};
 use hir::intravisit::FnKind;
 use syntax::ast::{Attribute, Ident, Name, NodeId};
 use syntax_pos::Span;
@@ -39,7 +39,7 @@
 ///
 /// To construct one, use the `Code::from_node` function.
 #[derive(Copy, Clone, Debug)]
-pub struct FnLikeNode<'a> { node: map::Node<'a> }
+pub struct FnLikeNode<'a> { node: Node<'a> }
 
 /// MaybeFnLike wraps a method that indicates if an object
 /// corresponds to some FnLikeNode.
@@ -95,11 +95,11 @@ pub fn id(&self) -> NodeId {
     /// Attempts to construct a Code from presumed FnLike or Expr node input.
     pub fn from_node(map: &map::Map<'a>, id: NodeId) -> Option<Code<'a>> {
         match map.get(id) {
-            map::NodeBlock(_) => {
+            map::Node::Block(_) => {
                 //  Use the parent, hopefully an expression node.
                 Code::from_node(map, map.get_parent_node(id))
             }
-            map::NodeExpr(expr) => Some(Code::Expr(expr)),
+            map::Node::Expr(expr) => Some(Code::Expr(expr)),
             node => FnLikeNode::from_node(node).map(Code::FnLike)
         }
     }
@@ -145,10 +145,10 @@ impl<'a> FnLikeNode<'a> {
     /// Attempts to construct a FnLikeNode from presumed FnLike node input.
     pub fn from_node(node: Node) -> Option<FnLikeNode> {
         let fn_like = match node {
-            map::NodeItem(item) => item.is_fn_like(),
-            map::NodeTraitItem(tm) => tm.is_fn_like(),
-            map::NodeImplItem(it) => it.is_fn_like(),
-            map::NodeExpr(e) => e.is_fn_like(),
+            map::Node::Item(item) => item.is_fn_like(),
+            map::Node::TraitItem(tm) => tm.is_fn_like(),
+            map::Node::ImplItem(it) => it.is_fn_like(),
+            map::Node::Expr(e) => e.is_fn_like(),
             _ => false
         };
         if fn_like {
@@ -234,7 +234,7 @@ fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
         C: FnOnce(ClosureParts<'a>) -> A,
     {
         match self.node {
-            map::NodeItem(i) => match i.node {
+            map::Node::Item(i) => match i.node {
                 ast::ItemKind::Fn(ref decl, header, ref generics, block) =>
                     item_fn(ItemFnParts {
                         id: i.id,
@@ -249,13 +249,13 @@ 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 {
+            map::Node::TraitItem(ti) => match ti.node {
                 ast::TraitItemKind::Method(ref sig, ast::TraitMethod::Provided(body)) => {
                     method(ti.id, ti.ident, sig, None, body, ti.span, &ti.attrs)
                 }
                 _ => bug!("trait method FnLikeNode that is not fn-like"),
             },
-            map::NodeImplItem(ii) => {
+            map::Node::ImplItem(ii) => {
                 match ii.node {
                     ast::ImplItemKind::Method(ref sig, body) => {
                         method(ii.id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs)
@@ -265,7 +265,7 @@ fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
                     }
                 }
             },
-            map::NodeExpr(e) => match e.node {
+            map::Node::Expr(e) => match e.node {
                 ast::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) =>
                     closure(ClosureParts::new(&decl, block, e.id, e.span, &e.attrs)),
                 _ => bug!("expr FnLikeNode that is not fn-like"),
index a14745a1381273d38bebe104520838dcb86cf6d5..30441c331e4cfea71cf9eabb835ff7b6ecb9d5fc 100644 (file)
@@ -29,7 +29,7 @@ pub(super) struct NodeCollector<'a, 'hir> {
     /// The crate
     krate: &'hir Crate,
     /// The node map
-    map: Vec<MapEntry<'hir>>,
+    map: Vec<Option<Entry<'hir>>>,
     /// The parent of this node
     parent_node: NodeId,
 
@@ -114,7 +114,11 @@ pub(super) fn root(krate: &'hir Crate,
             hcx,
             hir_body_nodes,
         };
-        collector.insert_entry(CRATE_NODE_ID, RootCrate(root_mod_sig_dep_index));
+        collector.insert_entry(CRATE_NODE_ID, Entry {
+            parent: CRATE_NODE_ID,
+            dep_node: root_mod_sig_dep_index,
+            node: Node::Crate,
+        });
 
         collector
     }
@@ -124,9 +128,8 @@ pub(super) fn finalize_and_compute_crate_hash(mut self,
                                                   cstore: &dyn CrateStore,
                                                   source_map: &SourceMap,
                                                   commandline_args_hash: u64)
-                                                  -> (Vec<MapEntry<'hir>>, Svh) {
-        self
-            .hir_body_nodes
+                                                  -> (Vec<Option<Entry<'hir>>>, Svh) {
+        self.hir_body_nodes
             .sort_unstable_by(|&(ref d1, _), &(ref d2, _)| d1.cmp(d2));
 
         let node_hashes = self
@@ -178,44 +181,24 @@ pub(super) fn finalize_and_compute_crate_hash(mut self,
         (self.map, svh)
     }
 
-    fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'hir>) {
+    fn insert_entry(&mut self, id: NodeId, entry: Entry<'hir>) {
         debug!("hir_map: {:?} => {:?}", id, entry);
         let len = self.map.len();
         if id.as_usize() >= len {
-            self.map.extend(repeat(NotPresent).take(id.as_usize() - len + 1));
+            self.map.extend(repeat(None).take(id.as_usize() - len + 1));
         }
-        self.map[id.as_usize()] = entry;
+        self.map[id.as_usize()] = Some(entry);
     }
 
     fn insert(&mut self, id: NodeId, node: Node<'hir>) {
-        let parent = self.parent_node;
-        let dep_node_index = if self.currently_in_body {
-            self.current_full_dep_index
-        } else {
-            self.current_signature_dep_index
-        };
-
-        let entry = match node {
-            NodeItem(n) => EntryItem(parent, dep_node_index, n),
-            NodeForeignItem(n) => EntryForeignItem(parent, dep_node_index, n),
-            NodeTraitItem(n) => EntryTraitItem(parent, dep_node_index, n),
-            NodeImplItem(n) => EntryImplItem(parent, dep_node_index, n),
-            NodeVariant(n) => EntryVariant(parent, dep_node_index, n),
-            NodeField(n) => EntryField(parent, dep_node_index, n),
-            NodeAnonConst(n) => EntryAnonConst(parent, dep_node_index, n),
-            NodeExpr(n) => EntryExpr(parent, dep_node_index, n),
-            NodeStmt(n) => EntryStmt(parent, dep_node_index, n),
-            NodeTy(n) => EntryTy(parent, dep_node_index, n),
-            NodeTraitRef(n) => EntryTraitRef(parent, dep_node_index, n),
-            NodeBinding(n) => EntryBinding(parent, dep_node_index, n),
-            NodePat(n) => EntryPat(parent, dep_node_index, n),
-            NodeBlock(n) => EntryBlock(parent, dep_node_index, n),
-            NodeStructCtor(n) => EntryStructCtor(parent, dep_node_index, n),
-            NodeLifetime(n) => EntryLifetime(parent, dep_node_index, n),
-            NodeGenericParam(n) => EntryGenericParam(parent, dep_node_index, n),
-            NodeVisibility(n) => EntryVisibility(parent, dep_node_index, n),
-            NodeLocal(n) => EntryLocal(parent, dep_node_index, n),
-            NodeMacroDef(n) => EntryMacroDef(dep_node_index, n),
+        let entry = Entry {
+            parent: self.parent_node,
+            dep_node: if self.currently_in_body {
+                self.current_full_dep_index
+            } else {
+                self.current_signature_dep_index
+            },
+            node,
         };
 
         // Make sure that the DepNode of some node coincides with the HirId
@@ -326,13 +309,13 @@ fn visit_item(&mut self, i: &'hir Item) {
         debug_assert_eq!(i.hir_id.owner,
                          self.definitions.opt_def_index(i.id).unwrap());
         self.with_dep_node_owner(i.hir_id.owner, i, |this| {
-            this.insert(i.id, NodeItem(i));
+            this.insert(i.id, Node::Item(i));
             this.with_parent(i.id, |this| {
                 match i.node {
                     ItemKind::Struct(ref struct_def, _) => {
                         // If this is a tuple-like struct, register the constructor.
                         if !struct_def.is_struct() {
-                            this.insert(struct_def.id(), NodeStructCtor(struct_def));
+                            this.insert(struct_def.id(), Node::StructCtor(struct_def));
                         }
                     }
                     _ => {}
@@ -343,7 +326,7 @@ fn visit_item(&mut self, i: &'hir Item) {
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem) {
-        self.insert(foreign_item.id, NodeForeignItem(foreign_item));
+        self.insert(foreign_item.id, Node::ForeignItem(foreign_item));
 
         self.with_parent(foreign_item.id, |this| {
             intravisit::walk_foreign_item(this, foreign_item);
@@ -351,7 +334,7 @@ fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem) {
     }
 
     fn visit_generic_param(&mut self, param: &'hir GenericParam) {
-        self.insert(param.id, NodeGenericParam(param));
+        self.insert(param.id, Node::GenericParam(param));
         intravisit::walk_generic_param(self, param);
     }
 
@@ -359,7 +342,7 @@ fn visit_trait_item(&mut self, ti: &'hir TraitItem) {
         debug_assert_eq!(ti.hir_id.owner,
                          self.definitions.opt_def_index(ti.id).unwrap());
         self.with_dep_node_owner(ti.hir_id.owner, ti, |this| {
-            this.insert(ti.id, NodeTraitItem(ti));
+            this.insert(ti.id, Node::TraitItem(ti));
 
             this.with_parent(ti.id, |this| {
                 intravisit::walk_trait_item(this, ti);
@@ -371,7 +354,7 @@ fn visit_impl_item(&mut self, ii: &'hir ImplItem) {
         debug_assert_eq!(ii.hir_id.owner,
                          self.definitions.opt_def_index(ii.id).unwrap());
         self.with_dep_node_owner(ii.hir_id.owner, ii, |this| {
-            this.insert(ii.id, NodeImplItem(ii));
+            this.insert(ii.id, Node::ImplItem(ii));
 
             this.with_parent(ii.id, |this| {
                 intravisit::walk_impl_item(this, ii);
@@ -381,9 +364,9 @@ fn visit_impl_item(&mut self, ii: &'hir ImplItem) {
 
     fn visit_pat(&mut self, pat: &'hir Pat) {
         let node = if let PatKind::Binding(..) = pat.node {
-            NodeBinding(pat)
+            Node::Binding(pat)
         } else {
-            NodePat(pat)
+            Node::Pat(pat)
         };
         self.insert(pat.id, node);
 
@@ -393,7 +376,7 @@ fn visit_pat(&mut self, pat: &'hir Pat) {
     }
 
     fn visit_anon_const(&mut self, constant: &'hir AnonConst) {
-        self.insert(constant.id, NodeAnonConst(constant));
+        self.insert(constant.id, Node::AnonConst(constant));
 
         self.with_parent(constant.id, |this| {
             intravisit::walk_anon_const(this, constant);
@@ -401,7 +384,7 @@ fn visit_anon_const(&mut self, constant: &'hir AnonConst) {
     }
 
     fn visit_expr(&mut self, expr: &'hir Expr) {
-        self.insert(expr.id, NodeExpr(expr));
+        self.insert(expr.id, Node::Expr(expr));
 
         self.with_parent(expr.id, |this| {
             intravisit::walk_expr(this, expr);
@@ -410,7 +393,7 @@ fn visit_expr(&mut self, expr: &'hir Expr) {
 
     fn visit_stmt(&mut self, stmt: &'hir Stmt) {
         let id = stmt.node.id();
-        self.insert(id, NodeStmt(stmt));
+        self.insert(id, Node::Stmt(stmt));
 
         self.with_parent(id, |this| {
             intravisit::walk_stmt(this, stmt);
@@ -418,7 +401,7 @@ fn visit_stmt(&mut self, stmt: &'hir Stmt) {
     }
 
     fn visit_ty(&mut self, ty: &'hir Ty) {
-        self.insert(ty.id, NodeTy(ty));
+        self.insert(ty.id, Node::Ty(ty));
 
         self.with_parent(ty.id, |this| {
             intravisit::walk_ty(this, ty);
@@ -426,7 +409,7 @@ fn visit_ty(&mut self, ty: &'hir Ty) {
     }
 
     fn visit_trait_ref(&mut self, tr: &'hir TraitRef) {
-        self.insert(tr.ref_id, NodeTraitRef(tr));
+        self.insert(tr.ref_id, Node::TraitRef(tr));
 
         self.with_parent(tr.ref_id, |this| {
             intravisit::walk_trait_ref(this, tr);
@@ -440,21 +423,21 @@ fn visit_fn(&mut self, fk: intravisit::FnKind<'hir>, fd: &'hir FnDecl,
     }
 
     fn visit_block(&mut self, block: &'hir Block) {
-        self.insert(block.id, NodeBlock(block));
+        self.insert(block.id, Node::Block(block));
         self.with_parent(block.id, |this| {
             intravisit::walk_block(this, block);
         });
     }
 
     fn visit_local(&mut self, l: &'hir Local) {
-        self.insert(l.id, NodeLocal(l));
+        self.insert(l.id, Node::Local(l));
         self.with_parent(l.id, |this| {
             intravisit::walk_local(this, l)
         })
     }
 
     fn visit_lifetime(&mut self, lifetime: &'hir Lifetime) {
-        self.insert(lifetime.id, NodeLifetime(lifetime));
+        self.insert(lifetime.id, Node::Lifetime(lifetime));
     }
 
     fn visit_vis(&mut self, visibility: &'hir Visibility) {
@@ -463,7 +446,7 @@ fn visit_vis(&mut self, visibility: &'hir Visibility) {
             VisibilityKind::Crate(_) |
             VisibilityKind::Inherited => {}
             VisibilityKind::Restricted { id, .. } => {
-                self.insert(id, NodeVisibility(visibility));
+                self.insert(id, Node::Visibility(visibility));
                 self.with_parent(id, |this| {
                     intravisit::walk_vis(this, visibility);
                 });
@@ -475,20 +458,20 @@ fn visit_macro_def(&mut self, macro_def: &'hir MacroDef) {
         let def_index = self.definitions.opt_def_index(macro_def.id).unwrap();
 
         self.with_dep_node_owner(def_index, macro_def, |this| {
-            this.insert(macro_def.id, NodeMacroDef(macro_def));
+            this.insert(macro_def.id, Node::MacroDef(macro_def));
         });
     }
 
     fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: NodeId) {
         let id = v.node.data.id();
-        self.insert(id, NodeVariant(v));
+        self.insert(id, Node::Variant(v));
         self.with_parent(id, |this| {
             intravisit::walk_variant(this, v, g, item_id);
         });
     }
 
     fn visit_struct_field(&mut self, field: &'hir StructField) {
-        self.insert(field.id, NodeField(field));
+        self.insert(field.id, Node::Field(field));
         self.with_parent(field.id, |this| {
             intravisit::walk_struct_field(this, field);
         });
index 7ecbf7ebbaff07f63520365a79e33fee18ed05db..0b7fb5603cc40baf38a17236c025b1ae5ce265b7 100644 (file)
@@ -380,6 +380,17 @@ fn borrow(&self) -> &Fingerprint {
 
 impl Definitions {
     /// Create new empty definition map.
+    ///
+    /// The DefIndex returned from a new Definitions are as follows:
+    /// 1. At DefIndexAddressSpace::Low,
+    ///     CRATE_ROOT has index 0:0, and then new indexes are allocated in
+    ///     ascending order.
+    /// 2. At DefIndexAddressSpace::High,
+    ///     the first FIRST_FREE_HIGH_DEF_INDEX indexes are reserved for
+    ///     internal use, then 1:FIRST_FREE_HIGH_DEF_INDEX are allocated in
+    ///     ascending order.
+    ///
+    /// FIXME: there is probably a better place to put this comment.
     pub fn new() -> Definitions {
         Definitions {
             table: DefPathTable {
@@ -665,6 +676,11 @@ pub fn to_string(&self) -> String {
     }
 }
 
+macro_rules! count {
+    () => (0usize);
+    ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
+}
+
 // We define the GlobalMetaDataKind enum with this macro because we want to
 // make sure that we exhaustively iterate over all variants when registering
 // the corresponding DefIndices in the DefTable.
@@ -678,6 +694,7 @@ pub enum GlobalMetaDataKind {
         }
 
         const GLOBAL_MD_ADDRESS_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::High;
+        pub const FIRST_FREE_HIGH_DEF_INDEX: usize = count!($($variant)*);
 
         impl GlobalMetaDataKind {
             fn allocate_def_indices(definitions: &mut Definitions) {
index ebda91cb7b0775269fb586d87237da406adf1c89..6fffde7cab50cdc578839693e0cde37c8b8028c6 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::Node::*;
-use self::MapEntry::*;
 use self::collector::NodeCollector;
 pub use self::def_collector::{DefCollector, MacroInvocationData};
 pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
 pub mod definitions;
 mod hir_id_validator;
 
-
 pub const ITEM_LIKE_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::Low;
 pub const REGULAR_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::High;
 
+/// Represents an entry and its parent NodeId.
 #[derive(Copy, Clone, Debug)]
-pub enum Node<'hir> {
-    NodeItem(&'hir Item),
-    NodeForeignItem(&'hir ForeignItem),
-    NodeTraitItem(&'hir TraitItem),
-    NodeImplItem(&'hir ImplItem),
-    NodeVariant(&'hir Variant),
-    NodeField(&'hir StructField),
-    NodeAnonConst(&'hir AnonConst),
-    NodeExpr(&'hir Expr),
-    NodeStmt(&'hir Stmt),
-    NodeTy(&'hir Ty),
-    NodeTraitRef(&'hir TraitRef),
-    NodeBinding(&'hir Pat),
-    NodePat(&'hir Pat),
-    NodeBlock(&'hir Block),
-    NodeLocal(&'hir Local),
-    NodeMacroDef(&'hir MacroDef),
-
-    /// NodeStructCtor represents a tuple struct.
-    NodeStructCtor(&'hir VariantData),
-
-    NodeLifetime(&'hir Lifetime),
-    NodeGenericParam(&'hir GenericParam),
-    NodeVisibility(&'hir Visibility),
-}
-
-/// Represents an entry and its parent NodeID.
-/// The odd layout is to bring down the total size.
-#[derive(Copy, Debug)]
-enum MapEntry<'hir> {
-    /// Placeholder for holes in the map.
-    NotPresent,
-
-    /// All the node types, with a parent ID.
-    EntryItem(NodeId, DepNodeIndex, &'hir Item),
-    EntryForeignItem(NodeId, DepNodeIndex, &'hir ForeignItem),
-    EntryTraitItem(NodeId, DepNodeIndex, &'hir TraitItem),
-    EntryImplItem(NodeId, DepNodeIndex, &'hir ImplItem),
-    EntryVariant(NodeId, DepNodeIndex, &'hir Variant),
-    EntryField(NodeId, DepNodeIndex, &'hir StructField),
-    EntryAnonConst(NodeId, DepNodeIndex, &'hir AnonConst),
-    EntryExpr(NodeId, DepNodeIndex, &'hir Expr),
-    EntryStmt(NodeId, DepNodeIndex, &'hir Stmt),
-    EntryTy(NodeId, DepNodeIndex, &'hir Ty),
-    EntryTraitRef(NodeId, DepNodeIndex, &'hir TraitRef),
-    EntryBinding(NodeId, DepNodeIndex, &'hir Pat),
-    EntryPat(NodeId, DepNodeIndex, &'hir Pat),
-    EntryBlock(NodeId, DepNodeIndex, &'hir Block),
-    EntryStructCtor(NodeId, DepNodeIndex, &'hir VariantData),
-    EntryLifetime(NodeId, DepNodeIndex, &'hir Lifetime),
-    EntryGenericParam(NodeId, DepNodeIndex, &'hir GenericParam),
-    EntryVisibility(NodeId, DepNodeIndex, &'hir Visibility),
-    EntryLocal(NodeId, DepNodeIndex, &'hir Local),
-
-    EntryMacroDef(DepNodeIndex, &'hir MacroDef),
-
-    /// Roots for node trees. The DepNodeIndex is the dependency node of the
-    /// crate's root module.
-    RootCrate(DepNodeIndex),
-}
-
-impl<'hir> Clone for MapEntry<'hir> {
-    fn clone(&self) -> MapEntry<'hir> {
-        *self
-    }
+pub struct Entry<'hir> {
+    parent: NodeId,
+    dep_node: DepNodeIndex,
+    node: Node<'hir>,
 }
 
-impl<'hir> MapEntry<'hir> {
+impl<'hir> Entry<'hir> {
     fn parent_node(self) -> Option<NodeId> {
-        Some(match self {
-            EntryItem(id, _, _) => id,
-            EntryForeignItem(id, _, _) => id,
-            EntryTraitItem(id, _, _) => id,
-            EntryImplItem(id, _, _) => id,
-            EntryVariant(id, _, _) => id,
-            EntryField(id, _, _) => id,
-            EntryAnonConst(id, _, _) => id,
-            EntryExpr(id, _, _) => id,
-            EntryStmt(id, _, _) => id,
-            EntryTy(id, _, _) => id,
-            EntryTraitRef(id, _, _) => id,
-            EntryBinding(id, _, _) => id,
-            EntryPat(id, _, _) => id,
-            EntryBlock(id, _, _) => id,
-            EntryStructCtor(id, _, _) => id,
-            EntryLifetime(id, _, _) => id,
-            EntryGenericParam(id, _, _) => id,
-            EntryVisibility(id, _, _) => id,
-            EntryLocal(id, _, _) => id,
-
-            NotPresent |
-            EntryMacroDef(..) |
-            RootCrate(_) => return None,
-        })
-    }
-
-    fn to_node(self) -> Option<Node<'hir>> {
-        Some(match self {
-            EntryItem(_, _, n) => NodeItem(n),
-            EntryForeignItem(_, _, n) => NodeForeignItem(n),
-            EntryTraitItem(_, _, n) => NodeTraitItem(n),
-            EntryImplItem(_, _, n) => NodeImplItem(n),
-            EntryVariant(_, _, n) => NodeVariant(n),
-            EntryField(_, _, n) => NodeField(n),
-            EntryAnonConst(_, _, n) => NodeAnonConst(n),
-            EntryExpr(_, _, n) => NodeExpr(n),
-            EntryStmt(_, _, n) => NodeStmt(n),
-            EntryTy(_, _, n) => NodeTy(n),
-            EntryTraitRef(_, _, n) => NodeTraitRef(n),
-            EntryBinding(_, _, n) => NodeBinding(n),
-            EntryPat(_, _, n) => NodePat(n),
-            EntryBlock(_, _, n) => NodeBlock(n),
-            EntryStructCtor(_, _, n) => NodeStructCtor(n),
-            EntryLifetime(_, _, n) => NodeLifetime(n),
-            EntryGenericParam(_, _, n) => NodeGenericParam(n),
-            EntryVisibility(_, _, n) => NodeVisibility(n),
-            EntryLocal(_, _, n) => NodeLocal(n),
-            EntryMacroDef(_, n) => NodeMacroDef(n),
-
-            NotPresent |
-            RootCrate(_) => return None
-        })
+        match self.node {
+            Node::Crate | Node::MacroDef(_) => None,
+            _ => Some(self.parent),
+        }
     }
 
     fn fn_decl(&self) -> Option<&FnDecl> {
-        match self {
-            EntryItem(_, _, ref item) => {
+        match self.node {
+            Node::Item(ref item) => {
                 match item.node {
                     ItemKind::Fn(ref fn_decl, _, _, _) => Some(&fn_decl),
                     _ => None,
                 }
             }
 
-            EntryTraitItem(_, _, ref item) => {
+            Node::TraitItem(ref item) => {
                 match item.node {
                     TraitItemKind::Method(ref method_sig, _) => Some(&method_sig.decl),
                     _ => None
                 }
             }
 
-            EntryImplItem(_, _, ref item) => {
+            Node::ImplItem(ref item) => {
                 match item.node {
                     ImplItemKind::Method(ref method_sig, _) => Some(&method_sig.decl),
                     _ => None,
                 }
             }
 
-            EntryExpr(_, _, ref expr) => {
+            Node::Expr(ref expr) => {
                 match expr.node {
                     ExprKind::Closure(_, ref fn_decl, ..) => Some(&fn_decl),
                     _ => None,
                 }
             }
 
-            _ => None
+            _ => None,
         }
     }
 
     fn associated_body(self) -> Option<BodyId> {
-        match self {
-            EntryItem(_, _, item) => {
+        match self.node {
+            Node::Item(item) => {
                 match item.node {
                     ItemKind::Const(_, body) |
                     ItemKind::Static(.., body) |
@@ -216,7 +104,7 @@ fn associated_body(self) -> Option<BodyId> {
                 }
             }
 
-            EntryTraitItem(_, _, item) => {
+            Node::TraitItem(item) => {
                 match item.node {
                     TraitItemKind::Const(_, Some(body)) |
                     TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body),
@@ -224,7 +112,7 @@ fn associated_body(self) -> Option<BodyId> {
                 }
             }
 
-            EntryImplItem(_, _, item) => {
+            Node::ImplItem(item) => {
                 match item.node {
                     ImplItemKind::Const(_, body) |
                     ImplItemKind::Method(_, body) => Some(body),
@@ -232,9 +120,9 @@ fn associated_body(self) -> Option<BodyId> {
                 }
             }
 
-            EntryAnonConst(_, _, constant) => Some(constant.body),
+            Node::AnonConst(constant) => Some(constant.body),
 
-            EntryExpr(_, _, expr) => {
+            Node::Expr(expr) => {
                 match expr.node {
                     ExprKind::Closure(.., body, _, _) => Some(body),
                     _ => None,
@@ -287,16 +175,16 @@ pub struct Map<'hir> {
     /// The SVH of the local crate.
     pub crate_hash: Svh,
 
-    /// NodeIds are sequential integers from 0, so we can be
+    /// `NodeId`s are sequential integers from 0, so we can be
     /// super-compact by storing them in a vector. Not everything with
-    /// a NodeId is in the map, but empirically the occupancy is about
+    /// a `NodeId` is in the map, but empirically the occupancy is about
     /// 75-80%, so there's not too much overhead (certainly less than
     /// a hashmap, since they (at the time of writing) have a maximum
     /// of 75% occupancy).
     ///
     /// Also, indexing is pretty quick when you've got a vector and
     /// plain old integers.
-    map: Vec<MapEntry<'hir>>,
+    map: Vec<Option<Entry<'hir>>>,
 
     definitions: &'hir Definitions,
 
@@ -313,34 +201,10 @@ impl<'hir> Map<'hir> {
     /// read recorded). If the function just returns a DefId or
     /// NodeId, no actual content was returned, so no read is needed.
     pub fn read(&self, id: NodeId) {
-        let entry = self.map[id.as_usize()];
-        match entry {
-            EntryItem(_, dep_node_index, _) |
-            EntryTraitItem(_, dep_node_index, _) |
-            EntryImplItem(_, dep_node_index, _) |
-            EntryVariant(_, dep_node_index, _) |
-            EntryForeignItem(_, dep_node_index, _) |
-            EntryField(_, dep_node_index, _) |
-            EntryStmt(_, dep_node_index, _) |
-            EntryTy(_, dep_node_index, _) |
-            EntryTraitRef(_, dep_node_index, _) |
-            EntryBinding(_, dep_node_index, _) |
-            EntryPat(_, dep_node_index, _) |
-            EntryBlock(_, dep_node_index, _) |
-            EntryStructCtor(_, dep_node_index, _) |
-            EntryLifetime(_, dep_node_index, _) |
-            EntryGenericParam(_, dep_node_index, _) |
-            EntryVisibility(_, dep_node_index, _) |
-            EntryAnonConst(_, dep_node_index, _) |
-            EntryExpr(_, dep_node_index, _) |
-            EntryLocal(_, dep_node_index, _) |
-            EntryMacroDef(dep_node_index, _) |
-            RootCrate(dep_node_index) => {
-                self.dep_graph.read_index(dep_node_index);
-            }
-            NotPresent => {
-                bug!("called HirMap::read() with invalid NodeId")
-            }
+        if let Some(entry) = self.map[id.as_usize()] {
+            self.dep_graph.read_index(entry.dep_node);
+        } else {
+            bug!("called `HirMap::read()` with invalid `NodeId`")
         }
     }
 
@@ -421,7 +285,7 @@ pub fn describe_def(&self, node_id: NodeId) -> Option<Def> {
         };
 
         match node {
-            NodeItem(item) => {
+            Node::Item(item) => {
                 let def_id = || {
                     self.local_def_id(item.id)
                 };
@@ -448,15 +312,15 @@ pub fn describe_def(&self, node_id: NodeId) -> Option<Def> {
                     ItemKind::Impl(..) => None,
                 }
             }
-            NodeForeignItem(item) => {
+            Node::ForeignItem(item) => {
                 let def_id = self.local_def_id(item.id);
                 match item.node {
                     ForeignItemKind::Fn(..) => Some(Def::Fn(def_id)),
                     ForeignItemKind::Static(_, m) => Some(Def::Static(def_id, m)),
-                    ForeignItemKind::Type => Some(Def::TyForeign(def_id)),
+                    ForeignItemKind::Type => Some(Def::ForeignTy(def_id)),
                 }
             }
-            NodeTraitItem(item) => {
+            Node::TraitItem(item) => {
                 let def_id = self.local_def_id(item.id);
                 match item.node {
                     TraitItemKind::Const(..) => Some(Def::AssociatedConst(def_id)),
@@ -464,7 +328,7 @@ pub fn describe_def(&self, node_id: NodeId) -> Option<Def> {
                     TraitItemKind::Type(..) => Some(Def::AssociatedTy(def_id)),
                 }
             }
-            NodeImplItem(item) => {
+            Node::ImplItem(item) => {
                 let def_id = self.local_def_id(item.id);
                 match item.node {
                     ImplItemKind::Const(..) => Some(Def::AssociatedConst(def_id)),
@@ -473,30 +337,31 @@ pub fn describe_def(&self, node_id: NodeId) -> Option<Def> {
                     ImplItemKind::Existential(..) => Some(Def::AssociatedExistential(def_id)),
                 }
             }
-            NodeVariant(variant) => {
+            Node::Variant(variant) => {
                 let def_id = self.local_def_id(variant.node.data.id());
                 Some(Def::Variant(def_id))
             }
-            NodeField(_) |
-            NodeAnonConst(_) |
-            NodeExpr(_) |
-            NodeStmt(_) |
-            NodeTy(_) |
-            NodeTraitRef(_) |
-            NodePat(_) |
-            NodeBinding(_) |
-            NodeStructCtor(_) |
-            NodeLifetime(_) |
-            NodeVisibility(_) |
-            NodeBlock(_) => None,
-            NodeLocal(local) => {
+            Node::Field(_) |
+            Node::AnonConst(_) |
+            Node::Expr(_) |
+            Node::Stmt(_) |
+            Node::Ty(_) |
+            Node::TraitRef(_) |
+            Node::Pat(_) |
+            Node::Binding(_) |
+            Node::StructCtor(_) |
+            Node::Lifetime(_) |
+            Node::Visibility(_) |
+            Node::Block(_) |
+            Node::Crate => None,
+            Node::Local(local) => {
                 Some(Def::Local(local.id))
             }
-            NodeMacroDef(macro_def) => {
+            Node::MacroDef(macro_def) => {
                 Some(Def::Macro(self.local_def_id(macro_def.id),
                                 MacroKind::Bang))
             }
-            NodeGenericParam(param) => {
+            Node::GenericParam(param) => {
                 Some(match param.kind {
                     GenericParamKind::Lifetime { .. } => Def::Local(param.id),
                     GenericParamKind::Type { .. } => Def::TyParam(self.local_def_id(param.id)),
@@ -509,8 +374,8 @@ fn entry_count(&self) -> usize {
         self.map.len()
     }
 
-    fn find_entry(&self, id: NodeId) -> Option<MapEntry<'hir>> {
-        self.map.get(id.as_usize()).cloned()
+    fn find_entry(&self, id: NodeId) -> Option<Entry<'hir>> {
+        self.map.get(id.as_usize()).cloned().unwrap_or(None)
     }
 
     pub fn krate(&self) -> &'hir Crate {
@@ -554,7 +419,7 @@ pub fn fn_decl(&self, node_id: ast::NodeId) -> Option<FnDecl> {
     /// item (possibly associated), a closure, or a `hir::AnonConst`.
     pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId {
         let parent = self.get_parent_node(node_id);
-        assert!(self.map[parent.as_usize()].is_body_owner(node_id));
+        assert!(self.map[parent.as_usize()].map_or(false, |e| e.is_body_owner(node_id)));
         parent
     }
 
@@ -588,13 +453,13 @@ pub fn body_owned_by(&self, id: NodeId) -> BodyId {
 
     pub fn body_owner_kind(&self, id: NodeId) -> BodyOwnerKind {
         match self.get(id) {
-            NodeItem(&Item { node: ItemKind::Const(..), .. }) |
-            NodeTraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) |
-            NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) |
-            NodeAnonConst(_) => {
+            Node::Item(&Item { node: ItemKind::Const(..), .. }) |
+            Node::TraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) |
+            Node::ImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) |
+            Node::AnonConst(_) => {
                 BodyOwnerKind::Const
             }
-            NodeItem(&Item { node: ItemKind::Static(_, m, _), .. }) => {
+            Node::Item(&Item { node: ItemKind::Static(_, m, _), .. }) => {
                 BodyOwnerKind::Static(m)
             }
             // Default to function if it's not a constant or static.
@@ -604,8 +469,8 @@ pub fn body_owner_kind(&self, id: NodeId) -> BodyOwnerKind {
 
     pub fn ty_param_owner(&self, id: NodeId) -> NodeId {
         match self.get(id) {
-            NodeItem(&Item { node: ItemKind::Trait(..), .. }) => id,
-            NodeGenericParam(_) => self.get_parent_node(id),
+            Node::Item(&Item { node: ItemKind::Trait(..), .. }) => id,
+            Node::GenericParam(_) => self.get_parent_node(id),
             _ => {
                 bug!("ty_param_owner: {} not a type parameter",
                     self.node_to_string(id))
@@ -615,10 +480,10 @@ pub fn ty_param_owner(&self, id: NodeId) -> NodeId {
 
     pub fn ty_param_name(&self, id: NodeId) -> Name {
         match self.get(id) {
-            NodeItem(&Item { node: ItemKind::Trait(..), .. }) => {
+            Node::Item(&Item { node: ItemKind::Trait(..), .. }) => {
                 keywords::SelfType.name()
             }
-            NodeGenericParam(param) => param.name.ident().name,
+            Node::GenericParam(param) => param.name.ident().name,
             _ => bug!("ty_param_name: {} not a type parameter", self.node_to_string(id)),
         }
     }
@@ -669,9 +534,9 @@ pub fn get_if_local(&self, id: DefId) -> Option<Node<'hir>> {
     pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics> {
         self.get_if_local(id).and_then(|node| {
             match node {
-                NodeImplItem(ref impl_item) => Some(&impl_item.generics),
-                NodeTraitItem(ref trait_item) => Some(&trait_item.generics),
-                NodeItem(ref item) => {
+                Node::ImplItem(ref impl_item) => Some(&impl_item.generics),
+                Node::TraitItem(ref trait_item) => Some(&trait_item.generics),
+                Node::Item(ref item) => {
                     match item.node {
                         ItemKind::Fn(_, _, ref generics, _) |
                         ItemKind::Ty(_, ref generics) |
@@ -696,7 +561,13 @@ pub fn get_generics_span(&self, id: DefId) -> Option<Span> {
     /// Retrieve the Node corresponding to `id`, returning None if
     /// cannot be found.
     pub fn find(&self, id: NodeId) -> Option<Node<'hir>> {
-        let result = self.find_entry(id).and_then(|x| x.to_node());
+        let result = self.find_entry(id).and_then(|entry| {
+            if let Node::Crate = entry.node {
+                None
+            } else {
+                Some(entry.node)
+            }
+        });
         if result.is_some() {
             self.read(id);
         }
@@ -727,14 +598,14 @@ pub fn get_parent_node(&self, id: NodeId) -> NodeId {
     /// immediate parent is an item or a closure.
     pub fn is_argument(&self, id: NodeId) -> bool {
         match self.find(id) {
-            Some(NodeBinding(_)) => (),
+            Some(Node::Binding(_)) => (),
             _ => return false,
         }
         match self.find(self.get_parent_node(id)) {
-            Some(NodeItem(_)) |
-            Some(NodeTraitItem(_)) |
-            Some(NodeImplItem(_)) => true,
-            Some(NodeExpr(e)) => {
+            Some(Node::Item(_)) |
+            Some(Node::TraitItem(_)) |
+            Some(Node::ImplItem(_)) => true,
+            Some(Node::Expr(e)) => {
                 match e.node {
                     ExprKind::Closure(..) => true,
                     _ => false,
@@ -766,24 +637,19 @@ fn walk_parent_nodes<F, F2>(&self,
                 return Err(id);
             }
 
-            let node = self.find_entry(parent_node);
-            if node.is_none() {
-                return Err(id);
-            }
-            let node = node.unwrap().to_node();
-            match node {
-                Some(ref node) => {
-                    if found(node) {
-                        return Ok(parent_node);
-                    } else if bail_early(node) {
-                        return Err(parent_node);
-                    }
+            if let Some(entry) = self.find_entry(parent_node) {
+                if let Node::Crate = entry.node {
+                    return Err(id);
                 }
-                None => {
+                if found(&entry.node) {
+                    return Ok(parent_node);
+                } else if bail_early(&entry.node) {
                     return Err(parent_node);
                 }
+                id = parent_node;
+            } else {
+                return Err(id);
             }
-            id = parent_node;
         }
     }
 
@@ -812,16 +678,16 @@ fn walk_parent_nodes<F, F2>(&self,
     pub fn get_return_block(&self, id: NodeId) -> Option<NodeId> {
         let match_fn = |node: &Node| {
             match *node {
-                NodeItem(_) |
-                NodeForeignItem(_) |
-                NodeTraitItem(_) |
-                NodeImplItem(_) => true,
+                Node::Item(_) |
+                Node::ForeignItem(_) |
+                Node::TraitItem(_) |
+                Node::ImplItem(_) => true,
                 _ => false,
             }
         };
         let match_non_returning_block = |node: &Node| {
             match *node {
-                NodeExpr(ref expr) => {
+                Node::Expr(ref expr) => {
                     match expr.node {
                         ExprKind::While(..) | ExprKind::Loop(..) => true,
                         _ => false,
@@ -843,10 +709,10 @@ pub fn get_return_block(&self, id: NodeId) -> Option<NodeId> {
     /// in a module, trait, or impl.
     pub fn get_parent(&self, id: NodeId) -> NodeId {
         match self.walk_parent_nodes(id, |node| match *node {
-            NodeItem(_) |
-            NodeForeignItem(_) |
-            NodeTraitItem(_) |
-            NodeImplItem(_) => true,
+            Node::Item(_) |
+            Node::ForeignItem(_) |
+            Node::TraitItem(_) |
+            Node::ImplItem(_) => true,
             _ => false,
         }, |_| false) {
             Ok(id) => id,
@@ -858,7 +724,7 @@ pub fn get_parent(&self, id: NodeId) -> NodeId {
     /// module parent is in this map.
     pub fn get_module_parent(&self, id: NodeId) -> DefId {
         let id = match self.walk_parent_nodes(id, |node| match *node {
-            NodeItem(&Item { node: ItemKind::Mod(_), .. }) => true,
+            Node::Item(&Item { node: ItemKind::Mod(_), .. }) => true,
             _ => false,
         }, |_| false) {
             Ok(id) => id,
@@ -873,11 +739,11 @@ pub fn get_module_parent(&self, id: NodeId) -> DefId {
     /// regard should be expected to be highly unstable.
     pub fn get_enclosing_scope(&self, id: NodeId) -> Option<NodeId> {
         match self.walk_parent_nodes(id, |node| match *node {
-            NodeItem(_) |
-            NodeForeignItem(_) |
-            NodeTraitItem(_) |
-            NodeImplItem(_) |
-            NodeBlock(_) => true,
+            Node::Item(_) |
+            Node::ForeignItem(_) |
+            Node::TraitItem(_) |
+            Node::ImplItem(_) |
+            Node::Block(_) => true,
             _ => false,
         }, |_| false) {
             Ok(id) => Some(id),
@@ -891,49 +757,43 @@ pub fn get_parent_did(&self, id: NodeId) -> DefId {
 
     pub fn get_foreign_abi(&self, id: NodeId) -> Abi {
         let parent = self.get_parent(id);
-        let abi = match self.find_entry(parent) {
-            Some(EntryItem(_, _, i)) => {
-                match i.node {
-                    ItemKind::ForeignMod(ref nm) => Some(nm.abi),
-                    _ => None
+        if let Some(entry) = self.find_entry(parent) {
+            match entry {
+                Entry { node: Node::Item(Item { node: ItemKind::ForeignMod(ref nm), .. }), .. }
+                    => {
+                    self.read(id); // reveals some of the content of a node
+                    return nm.abi;
                 }
+                _ => {}
             }
-            _ => None
-        };
-        match abi {
-            Some(abi) => {
-                self.read(id); // reveals some of the content of a node
-                abi
-            }
-            None => bug!("expected foreign mod or inlined parent, found {}",
-                          self.node_to_string(parent))
         }
+        bug!("expected foreign mod or inlined parent, found {}", self.node_to_string(parent))
     }
 
     pub fn expect_item(&self, id: NodeId) -> &'hir Item {
         match self.find(id) { // read recorded by `find`
-            Some(NodeItem(item)) => item,
+            Some(Node::Item(item)) => item,
             _ => bug!("expected item, found {}", self.node_to_string(id))
         }
     }
 
     pub fn expect_impl_item(&self, id: NodeId) -> &'hir ImplItem {
         match self.find(id) {
-            Some(NodeImplItem(item)) => item,
+            Some(Node::ImplItem(item)) => item,
             _ => bug!("expected impl item, found {}", self.node_to_string(id))
         }
     }
 
     pub fn expect_trait_item(&self, id: NodeId) -> &'hir TraitItem {
         match self.find(id) {
-            Some(NodeTraitItem(item)) => item,
+            Some(Node::TraitItem(item)) => item,
             _ => bug!("expected trait item, found {}", self.node_to_string(id))
         }
     }
 
     pub fn expect_variant_data(&self, id: NodeId) -> &'hir VariantData {
         match self.find(id) {
-            Some(NodeItem(i)) => {
+            Some(Node::Item(i)) => {
                 match i.node {
                     ItemKind::Struct(ref struct_def, _) |
                     ItemKind::Union(ref struct_def, _) => struct_def,
@@ -943,8 +803,8 @@ pub fn expect_variant_data(&self, id: NodeId) -> &'hir VariantData {
                     }
                 }
             }
-            Some(NodeStructCtor(data)) => data,
-            Some(NodeVariant(variant)) => &variant.node.data,
+            Some(Node::StructCtor(data)) => data,
+            Some(Node::Variant(variant)) => &variant.node.data,
             _ => {
                 bug!("expected struct or variant, found {}",
                      self.node_to_string(id));
@@ -954,21 +814,21 @@ pub fn expect_variant_data(&self, id: NodeId) -> &'hir VariantData {
 
     pub fn expect_variant(&self, id: NodeId) -> &'hir Variant {
         match self.find(id) {
-            Some(NodeVariant(variant)) => variant,
+            Some(Node::Variant(variant)) => variant,
             _ => bug!("expected variant, found {}", self.node_to_string(id)),
         }
     }
 
     pub fn expect_foreign_item(&self, id: NodeId) -> &'hir ForeignItem {
         match self.find(id) {
-            Some(NodeForeignItem(item)) => item,
+            Some(Node::ForeignItem(item)) => item,
             _ => bug!("expected foreign item, found {}", self.node_to_string(id))
         }
     }
 
     pub fn expect_expr(&self, id: NodeId) -> &'hir Expr {
         match self.find(id) { // read recorded by find
-            Some(NodeExpr(expr)) => expr,
+            Some(Node::Expr(expr)) => expr,
             _ => bug!("expected expr, found {}", self.node_to_string(id))
         }
     }
@@ -976,16 +836,16 @@ pub fn expect_expr(&self, id: NodeId) -> &'hir Expr {
     /// Returns the name associated with the given NodeId's AST.
     pub fn name(&self, id: NodeId) -> Name {
         match self.get(id) {
-            NodeItem(i) => i.name,
-            NodeForeignItem(i) => i.name,
-            NodeImplItem(ii) => ii.ident.name,
-            NodeTraitItem(ti) => ti.ident.name,
-            NodeVariant(v) => v.node.name,
-            NodeField(f) => f.ident.name,
-            NodeLifetime(lt) => lt.name.ident().name,
-            NodeGenericParam(param) => param.name.ident().name,
-            NodeBinding(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.name,
-            NodeStructCtor(_) => self.name(self.get_parent(id)),
+            Node::Item(i) => i.name,
+            Node::ForeignItem(i) => i.name,
+            Node::ImplItem(ii) => ii.ident.name,
+            Node::TraitItem(ti) => ti.ident.name,
+            Node::Variant(v) => v.node.name,
+            Node::Field(f) => f.ident.name,
+            Node::Lifetime(lt) => lt.name.ident().name,
+            Node::GenericParam(param) => param.name.ident().name,
+            Node::Binding(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.name,
+            Node::StructCtor(_) => self.name(self.get_parent(id)),
             _ => bug!("no name for {}", self.node_to_string(id))
         }
     }
@@ -995,18 +855,18 @@ pub fn name(&self, id: NodeId) -> Name {
     pub fn attrs(&self, id: NodeId) -> &'hir [ast::Attribute] {
         self.read(id); // reveals attributes on the node
         let attrs = match self.find(id) {
-            Some(NodeItem(i)) => Some(&i.attrs[..]),
-            Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]),
-            Some(NodeTraitItem(ref ti)) => Some(&ti.attrs[..]),
-            Some(NodeImplItem(ref ii)) => Some(&ii.attrs[..]),
-            Some(NodeVariant(ref v)) => Some(&v.node.attrs[..]),
-            Some(NodeField(ref f)) => Some(&f.attrs[..]),
-            Some(NodeExpr(ref e)) => Some(&*e.attrs),
-            Some(NodeStmt(ref s)) => Some(s.node.attrs()),
-            Some(NodeGenericParam(param)) => Some(&param.attrs[..]),
+            Some(Node::Item(i)) => Some(&i.attrs[..]),
+            Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]),
+            Some(Node::TraitItem(ref ti)) => Some(&ti.attrs[..]),
+            Some(Node::ImplItem(ref ii)) => Some(&ii.attrs[..]),
+            Some(Node::Variant(ref v)) => Some(&v.node.attrs[..]),
+            Some(Node::Field(ref f)) => Some(&f.attrs[..]),
+            Some(Node::Expr(ref e)) => Some(&*e.attrs),
+            Some(Node::Stmt(ref s)) => Some(s.node.attrs()),
+            Some(Node::GenericParam(param)) => Some(&param.attrs[..]),
             // unit/tuple structs take the attributes straight from
             // the struct definition.
-            Some(NodeStructCtor(_)) => {
+            Some(Node::StructCtor(_)) => {
                 return self.attrs(self.get_parent(id));
             }
             _ => None
@@ -1033,35 +893,33 @@ pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String])
 
     pub fn span(&self, id: NodeId) -> Span {
         self.read(id); // reveals span from node
-        match self.find_entry(id) {
-            Some(EntryItem(_, _, item)) => item.span,
-            Some(EntryForeignItem(_, _, foreign_item)) => foreign_item.span,
-            Some(EntryTraitItem(_, _, trait_method)) => trait_method.span,
-            Some(EntryImplItem(_, _, impl_item)) => impl_item.span,
-            Some(EntryVariant(_, _, variant)) => variant.span,
-            Some(EntryField(_, _, field)) => field.span,
-            Some(EntryAnonConst(_, _, constant)) => self.body(constant.body).value.span,
-            Some(EntryExpr(_, _, expr)) => expr.span,
-            Some(EntryStmt(_, _, stmt)) => stmt.span,
-            Some(EntryTy(_, _, ty)) => ty.span,
-            Some(EntryTraitRef(_, _, tr)) => tr.path.span,
-            Some(EntryBinding(_, _, pat)) => pat.span,
-            Some(EntryPat(_, _, pat)) => pat.span,
-            Some(EntryBlock(_, _, block)) => block.span,
-            Some(EntryStructCtor(_, _, _)) => self.expect_item(self.get_parent(id)).span,
-            Some(EntryLifetime(_, _, lifetime)) => lifetime.span,
-            Some(EntryGenericParam(_, _, param)) => param.span,
-            Some(EntryVisibility(_, _, &Spanned {
+        match self.find_entry(id).map(|entry| entry.node) {
+            Some(Node::Item(item)) => item.span,
+            Some(Node::ForeignItem(foreign_item)) => foreign_item.span,
+            Some(Node::TraitItem(trait_method)) => trait_method.span,
+            Some(Node::ImplItem(impl_item)) => impl_item.span,
+            Some(Node::Variant(variant)) => variant.span,
+            Some(Node::Field(field)) => field.span,
+            Some(Node::AnonConst(constant)) => self.body(constant.body).value.span,
+            Some(Node::Expr(expr)) => expr.span,
+            Some(Node::Stmt(stmt)) => stmt.span,
+            Some(Node::Ty(ty)) => ty.span,
+            Some(Node::TraitRef(tr)) => tr.path.span,
+            Some(Node::Binding(pat)) => pat.span,
+            Some(Node::Pat(pat)) => pat.span,
+            Some(Node::Block(block)) => block.span,
+            Some(Node::StructCtor(_)) => self.expect_item(self.get_parent(id)).span,
+            Some(Node::Lifetime(lifetime)) => lifetime.span,
+            Some(Node::GenericParam(param)) => param.span,
+            Some(Node::Visibility(&Spanned {
                 node: VisibilityKind::Restricted { ref path, .. }, ..
             })) => path.span,
-            Some(EntryVisibility(_, _, v)) => bug!("unexpected Visibility {:?}", v),
-            Some(EntryLocal(_, _, local)) => local.span,
-            Some(EntryMacroDef(_, macro_def)) => macro_def.span,
+            Some(Node::Visibility(v)) => bug!("unexpected Visibility {:?}", v),
+            Some(Node::Local(local)) => local.span,
+            Some(Node::MacroDef(macro_def)) => macro_def.span,
 
-            Some(RootCrate(_)) => self.forest.krate.span,
-            Some(NotPresent) | None => {
-                bug!("hir::map::Map::span: id not in map: {:?}", id)
-            }
+            Some(Node::Crate) => self.forest.krate.span,
+            None => bug!("hir::map::Map::span: id not in map: {:?}", id),
         }
     }
 
@@ -1119,7 +977,7 @@ fn suffix_matches(&self, parent: NodeId) -> bool {
         fn find_first_mod_parent<'a>(map: &'a Map, mut id: NodeId) -> Option<(NodeId, Name)> {
             loop {
                 match map.find(id)? {
-                    NodeItem(item) if item_is_mod(&item) =>
+                    Node::Item(item) if item_is_mod(&item) =>
                         return Some((id, item.name)),
                     _ => {}
                 }
@@ -1154,13 +1012,13 @@ fn next(&mut self) -> Option<NodeId> {
                 return None;
             }
             self.idx = NodeId::from_u32(self.idx.as_u32() + 1);
-            let name = match self.map.find_entry(idx) {
-                Some(EntryItem(_, _, n))       => n.name(),
-                Some(EntryForeignItem(_, _, n))=> n.name(),
-                Some(EntryTraitItem(_, _, n))  => n.name(),
-                Some(EntryImplItem(_, _, n))   => n.name(),
-                Some(EntryVariant(_, _, n))    => n.name(),
-                Some(EntryField(_, _, n))      => n.name(),
+            let name = match self.map.find_entry(idx).map(|entry| entry.node) {
+                Some(Node::Item(n)) => n.name(),
+                Some(Node::ForeignItem(n)) => n.name(),
+                Some(Node::TraitItem(n)) => n.name(),
+                Some(Node::ImplItem(n)) => n.name(),
+                Some(Node::Variant(n)) => n.name(),
+                Some(Node::Field(n)) => n.name(),
                 _ => continue,
             };
             if self.matches_names(self.map.get_parent(idx), name) {
@@ -1209,12 +1067,8 @@ pub fn map_crate<'hir>(sess: &::session::Session,
     if log_enabled!(::log::Level::Debug) {
         // This only makes sense for ordered stores; note the
         // enumerate to count the number of entries.
-        let (entries_less_1, _) = map.iter().filter(|&x| {
-            match *x {
-                NotPresent => false,
-                _ => true
-            }
-        }).enumerate().last().expect("AST map was empty after folding?");
+        let (entries_less_1, _) = map.iter().filter_map(|x| *x).enumerate().last()
+            .expect("AST map was empty after folding?");
 
         let entries = entries_less_1 + 1;
         let vector_length = map.len();
@@ -1257,19 +1111,19 @@ fn nested(&self, state: &mut print::State, nested: print::Nested) -> io::Result<
 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),
-            NodeImplItem(a)     => self.print_impl_item(a),
-            NodeVariant(a)      => self.print_variant(&a),
-            NodeAnonConst(a)    => self.print_anon_const(&a),
-            NodeExpr(a)         => self.print_expr(&a),
-            NodeStmt(a)         => self.print_stmt(&a),
-            NodeTy(a)           => self.print_type(&a),
-            NodeTraitRef(a)     => self.print_trait_ref(&a),
-            NodeBinding(a)       |
-            NodePat(a)          => self.print_pat(&a),
-            NodeBlock(a)        => {
+            Node::Item(a)         => self.print_item(&a),
+            Node::ForeignItem(a)  => self.print_foreign_item(&a),
+            Node::TraitItem(a)    => self.print_trait_item(a),
+            Node::ImplItem(a)     => self.print_impl_item(a),
+            Node::Variant(a)      => self.print_variant(&a),
+            Node::AnonConst(a)    => self.print_anon_const(&a),
+            Node::Expr(a)         => self.print_expr(&a),
+            Node::Stmt(a)         => self.print_stmt(&a),
+            Node::Ty(a)           => self.print_type(&a),
+            Node::TraitRef(a)     => self.print_trait_ref(&a),
+            Node::Binding(a)      |
+            Node::Pat(a)          => self.print_pat(&a),
+            Node::Block(a)        => {
                 use syntax::print::pprust::PrintState;
 
                 // containing cbox, will be closed by print-block at }
@@ -1278,16 +1132,17 @@ pub fn print_node(&mut self, node: Node) -> io::Result<()> {
                 self.ibox(0)?;
                 self.print_block(&a)
             }
-            NodeLifetime(a)     => self.print_lifetime(&a),
-            NodeVisibility(a)   => self.print_visibility(&a),
-            NodeGenericParam(_) => bug!("cannot print NodeGenericParam"),
-            NodeField(_)        => bug!("cannot print StructField"),
+            Node::Lifetime(a)     => self.print_lifetime(&a),
+            Node::Visibility(a)   => self.print_visibility(&a),
+            Node::GenericParam(_) => bug!("cannot print Node::GenericParam"),
+            Node::Field(_)        => bug!("cannot print StructField"),
             // these cases do not carry enough information in the
             // hir_map to reconstruct their full structure for pretty
             // printing.
-            NodeStructCtor(_)   => bug!("cannot print isolated StructCtor"),
-            NodeLocal(a)        => self.print_local_decl(&a),
-            NodeMacroDef(_)     => bug!("cannot print MacroDef"),
+            Node::StructCtor(_)   => bug!("cannot print isolated StructCtor"),
+            Node::Local(a)        => self.print_local_decl(&a),
+            Node::MacroDef(_)     => bug!("cannot print MacroDef"),
+            Node::Crate     => bug!("cannot print Crate"),
         }
     }
 }
@@ -1313,7 +1168,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
     };
 
     match map.find(id) {
-        Some(NodeItem(item)) => {
+        Some(Node::Item(item)) => {
             let item_str = match item.node {
                 ItemKind::ExternCrate(..) => "extern crate",
                 ItemKind::Use(..) => "use",
@@ -1334,10 +1189,10 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
             };
             format!("{} {}{}", item_str, path_str(), id_str)
         }
-        Some(NodeForeignItem(_)) => {
+        Some(Node::ForeignItem(_)) => {
             format!("foreign item {}{}", path_str(), id_str)
         }
-        Some(NodeImplItem(ii)) => {
+        Some(Node::ImplItem(ii)) => {
             match ii.node {
                 ImplItemKind::Const(..) => {
                     format!("assoc const {} in {}{}", ii.ident, path_str(), id_str)
@@ -1353,7 +1208,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
                 }
             }
         }
-        Some(NodeTraitItem(ti)) => {
+        Some(Node::TraitItem(ti)) => {
             let kind = match ti.node {
                 TraitItemKind::Const(..) => "assoc constant",
                 TraitItemKind::Method(..) => "trait method",
@@ -1362,61 +1217,60 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
 
             format!("{} {} in {}{}", kind, ti.ident, path_str(), id_str)
         }
-        Some(NodeVariant(ref variant)) => {
+        Some(Node::Variant(ref variant)) => {
             format!("variant {} in {}{}",
                     variant.node.name,
                     path_str(), id_str)
         }
-        Some(NodeField(ref field)) => {
+        Some(Node::Field(ref field)) => {
             format!("field {} in {}{}",
                     field.ident,
                     path_str(), id_str)
         }
-        Some(NodeAnonConst(_)) => {
+        Some(Node::AnonConst(_)) => {
             format!("const {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeExpr(_)) => {
+        Some(Node::Expr(_)) => {
             format!("expr {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeStmt(_)) => {
+        Some(Node::Stmt(_)) => {
             format!("stmt {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeTy(_)) => {
+        Some(Node::Ty(_)) => {
             format!("type {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeTraitRef(_)) => {
+        Some(Node::TraitRef(_)) => {
             format!("trait_ref {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeBinding(_)) => {
+        Some(Node::Binding(_)) => {
             format!("local {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodePat(_)) => {
+        Some(Node::Pat(_)) => {
             format!("pat {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeBlock(_)) => {
+        Some(Node::Block(_)) => {
             format!("block {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeLocal(_)) => {
+        Some(Node::Local(_)) => {
             format!("local {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeStructCtor(_)) => {
+        Some(Node::StructCtor(_)) => {
             format!("struct_ctor {}{}", path_str(), id_str)
         }
-        Some(NodeLifetime(_)) => {
+        Some(Node::Lifetime(_)) => {
             format!("lifetime {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeGenericParam(ref param)) => {
+        Some(Node::GenericParam(ref param)) => {
             format!("generic_param {:?}{}", param, id_str)
         }
-        Some(NodeVisibility(ref vis)) => {
+        Some(Node::Visibility(ref vis)) => {
             format!("visibility {:?}{}", vis, id_str)
         }
-        Some(NodeMacroDef(_)) => {
+        Some(Node::MacroDef(_)) => {
             format!("macro {}{}",  path_str(), id_str)
         }
-        None => {
-            format!("unknown node{}", id_str)
-        }
+        Some(Node::Crate) => format!("root_crate"),
+        None => format!("unknown node{}", id_str),
     }
 }
 
index a4806502ab38361e37ca8a8b489c9fea52d5b701..1b3103578737190b2c32a3886806940a6022af92 100644 (file)
@@ -1677,12 +1677,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 /// Not represented directly in the AST, referred to by name through a ty_path.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum PrimTy {
-    TyInt(IntTy),
-    TyUint(UintTy),
-    TyFloat(FloatTy),
-    TyStr,
-    TyBool,
-    TyChar,
+    Int(IntTy),
+    Uint(UintTy),
+    Float(FloatTy),
+    Str,
+    Bool,
+    Char,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
@@ -2292,25 +2292,59 @@ pub fn provide(providers: &mut Providers) {
 #[derive(Clone, RustcEncodable, RustcDecodable)]
 pub struct CodegenFnAttrs {
     pub flags: CodegenFnAttrFlags,
+    /// Parsed representation of the `#[inline]` attribute
     pub inline: InlineAttr,
+    /// The `#[export_name = "..."]` attribute, indicating a custom symbol a
+    /// function should be exported under
     pub export_name: Option<Symbol>,
+    /// The `#[link_name = "..."]` attribute, indicating a custom symbol an
+    /// imported function should be imported as. Note that `export_name`
+    /// probably isn't set when this is set, this is for foreign items while
+    /// `#[export_name]` is for Rust-defined functions.
+    pub link_name: Option<Symbol>,
+    /// The `#[target_feature(enable = "...")]` attribute and the enabled
+    /// features (only enabled features are supported right now).
     pub target_features: Vec<Symbol>,
+    /// The `#[linkage = "..."]` attribute and the value we found.
     pub linkage: Option<Linkage>,
+    /// The `#[link_section = "..."]` attribute, or what executable section this
+    /// should be placed in.
     pub link_section: Option<Symbol>,
 }
 
 bitflags! {
     #[derive(RustcEncodable, RustcDecodable)]
     pub struct CodegenFnAttrFlags: u32 {
+        /// #[cold], a hint to LLVM that this function, when called, is never on
+        /// the hot path
         const COLD                      = 1 << 0;
+        /// #[allocator], a hint to LLVM that the pointer returned from this
+        /// function is never null
         const ALLOCATOR                 = 1 << 1;
+        /// #[unwind], an indicator that this function may unwind despite what
+        /// its ABI signature may otherwise imply
         const UNWIND                    = 1 << 2;
+        /// #[rust_allocator_nounwind], an indicator that an imported FFI
+        /// function will never unwind. Probably obsolete by recent changes with
+        /// #[unwind], but hasn't been removed/migrated yet
         const RUSTC_ALLOCATOR_NOUNWIND  = 1 << 3;
+        /// #[naked], indicates to LLVM that no function prologue/epilogue
+        /// should be generated
         const NAKED                     = 1 << 4;
+        /// #[no_mangle], the function's name should be the same as its symbol
         const NO_MANGLE                 = 1 << 5;
+        /// #[rustc_std_internal_symbol], and indicator that this symbol is a
+        /// "weird symbol" for the standard library in that it has slightly
+        /// different linkage, visibility, and reachability rules.
         const RUSTC_STD_INTERNAL_SYMBOL = 1 << 6;
+        /// #[no_debug], indicates that no debugging information should be
+        /// generated for this function by LLVM
         const NO_DEBUG                  = 1 << 7;
+        /// #[thread_local], indicates a static is actually a thread local
+        /// piece of memory
         const THREAD_LOCAL              = 1 << 8;
+        /// #[used], indicates that LLVM can't eliminate this function (but the
+        /// linker can!)
         const USED                      = 1 << 9;
     }
 }
@@ -2321,6 +2355,7 @@ pub fn new() -> CodegenFnAttrs {
             flags: CodegenFnAttrFlags::empty(),
             inline: InlineAttr::None,
             export_name: None,
+            link_name: None,
             target_features: vec![],
             linkage: None,
             link_section: None,
@@ -2340,3 +2375,32 @@ pub fn contains_extern_indicator(&self) -> bool {
         self.flags.contains(CodegenFnAttrFlags::NO_MANGLE) || self.export_name.is_some()
     }
 }
+
+#[derive(Copy, Clone, Debug)]
+pub enum Node<'hir> {
+    Item(&'hir Item),
+    ForeignItem(&'hir ForeignItem),
+    TraitItem(&'hir TraitItem),
+    ImplItem(&'hir ImplItem),
+    Variant(&'hir Variant),
+    Field(&'hir StructField),
+    AnonConst(&'hir AnonConst),
+    Expr(&'hir Expr),
+    Stmt(&'hir Stmt),
+    Ty(&'hir Ty),
+    TraitRef(&'hir TraitRef),
+    Binding(&'hir Pat),
+    Pat(&'hir Pat),
+    Block(&'hir Block),
+    Local(&'hir Local),
+    MacroDef(&'hir MacroDef),
+
+    /// StructCtor represents a tuple struct.
+    StructCtor(&'hir VariantData),
+
+    Lifetime(&'hir Lifetime),
+    GenericParam(&'hir GenericParam),
+    Visibility(&'hir Visibility),
+
+    Crate,
+}
index 193fff1f5b68e27c9ab87a2185414f30106a4d87..55357095fb7596f10b6281af5f268493dab500bd 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::AnnNode::*;
-
 use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax::source_map::{SourceMap, Spanned};
 use std::vec;
 
 pub enum AnnNode<'a> {
-    NodeName(&'a ast::Name),
-    NodeBlock(&'a hir::Block),
-    NodeItem(&'a hir::Item),
-    NodeSubItem(ast::NodeId),
-    NodeExpr(&'a hir::Expr),
-    NodePat(&'a hir::Pat),
+    Name(&'a ast::Name),
+    Block(&'a hir::Block),
+    Item(&'a hir::Item),
+    SubItem(ast::NodeId),
+    Expr(&'a hir::Expr),
+    Pat(&'a hir::Pat),
 }
 
 pub enum Nested {
@@ -529,7 +527,7 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
         self.hardbreak_if_not_bol()?;
         self.maybe_print_comment(item.span.lo())?;
         self.print_outer_attributes(&item.attrs)?;
-        self.ann.pre(self, NodeItem(item))?;
+        self.ann.pre(self, AnnNode::Item(item))?;
         match item.node {
             hir::ItemKind::ExternCrate(orig_name) => {
                 self.head(&visibility_qualified(&item.vis, "extern crate"))?;
@@ -768,7 +766,7 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 self.s.word(";")?;
             }
         }
-        self.ann.post(self, NodeItem(item))
+        self.ann.post(self, AnnNode::Item(item))
     }
 
     pub fn print_trait_ref(&mut self, t: &hir::TraitRef) -> io::Result<()> {
@@ -933,7 +931,7 @@ pub fn print_method_sig(&mut self,
     }
 
     pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
-        self.ann.pre(self, NodeSubItem(ti.id))?;
+        self.ann.pre(self, AnnNode::SubItem(ti.id))?;
         self.hardbreak_if_not_bol()?;
         self.maybe_print_comment(ti.span.lo())?;
         self.print_outer_attributes(&ti.attrs)?;
@@ -965,11 +963,11 @@ pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
                                            default.as_ref().map(|ty| &**ty))?;
             }
         }
-        self.ann.post(self, NodeSubItem(ti.id))
+        self.ann.post(self, AnnNode::SubItem(ti.id))
     }
 
     pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
-        self.ann.pre(self, NodeSubItem(ii.id))?;
+        self.ann.pre(self, AnnNode::SubItem(ii.id))?;
         self.hardbreak_if_not_bol()?;
         self.maybe_print_comment(ii.span.lo())?;
         self.print_outer_attributes(&ii.attrs)?;
@@ -995,7 +993,7 @@ pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
                 self.print_associated_type(ii.ident, Some(bounds), None)?;
             }
         }
-        self.ann.post(self, NodeSubItem(ii.id))
+        self.ann.post(self, AnnNode::SubItem(ii.id))
     }
 
     pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> {
@@ -1055,7 +1053,7 @@ pub fn print_block_maybe_unclosed(&mut self,
             hir::DefaultBlock => (),
         }
         self.maybe_print_comment(blk.span.lo())?;
-        self.ann.pre(self, NodeBlock(blk))?;
+        self.ann.pre(self, AnnNode::Block(blk))?;
         self.bopen()?;
 
         self.print_inner_attributes(attrs)?;
@@ -1072,7 +1070,7 @@ pub fn print_block_maybe_unclosed(&mut self,
             _ => (),
         }
         self.bclose_maybe_open(blk.span, indented, close_box)?;
-        self.ann.post(self, NodeBlock(blk))
+        self.ann.post(self, AnnNode::Block(blk))
     }
 
     fn print_else(&mut self, els: Option<&hir::Expr>) -> io::Result<()> {
@@ -1321,7 +1319,7 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
         self.maybe_print_comment(expr.span.lo())?;
         self.print_outer_attributes(&expr.attrs)?;
         self.ibox(indent_unit)?;
-        self.ann.pre(self, NodeExpr(expr))?;
+        self.ann.pre(self, AnnNode::Expr(expr))?;
         match expr.node {
             hir::ExprKind::Box(ref expr) => {
                 self.word_space("box")?;
@@ -1559,7 +1557,7 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
                 self.print_expr_maybe_paren(&expr, parser::PREC_JUMP)?;
             }
         }
-        self.ann.post(self, NodeExpr(expr))?;
+        self.ann.post(self, AnnNode::Expr(expr))?;
         self.end()
     }
 
@@ -1606,7 +1604,7 @@ pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
         } else {
             self.s.word(&ident.as_str())?;
         }
-        self.ann.post(self, NodeName(&ident.name))
+        self.ann.post(self, AnnNode::Name(&ident.name))
     }
 
     pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> {
@@ -1774,7 +1772,7 @@ fn print_generic_args(&mut self,
 
     pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> {
         self.maybe_print_comment(pat.span.lo())?;
-        self.ann.pre(self, NodePat(pat))?;
+        self.ann.pre(self, AnnNode::Pat(pat))?;
         // Pat isn't normalized, but the beauty of it
         // is that it doesn't matter
         match pat.node {
@@ -1928,7 +1926,7 @@ pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> {
                 self.s.word("]")?;
             }
         }
-        self.ann.post(self, NodePat(pat))
+        self.ann.post(self, AnnNode::Pat(pat))
     }
 
     fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> {
index f03ad98c7dee4e9bb454fda317521e819a9448d4..371f631737c9871001536c5f4e964f2f0a012736 100644 (file)
@@ -34,8 +34,8 @@
 use rustc_data_structures::stable_hasher::{HashStable,
                                            StableHasher, StableHasherResult,
                                            ToStableHashKey};
-use rustc_data_structures::accumulate_vec::AccumulateVec;
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
+use smallvec::SmallVec;
 
 fn compute_ignored_attr_names() -> FxHashSet<Symbol> {
     debug_assert!(ich::IGNORED_ATTRIBUTES.len() > 0);
@@ -405,7 +405,7 @@ pub fn hash_stable_trait_impls<'a, 'gcx, W, R>(
           R: std_hash::BuildHasher,
 {
     {
-        let mut blanket_impls: AccumulateVec<[_; 8]> = blanket_impls
+        let mut blanket_impls: SmallVec<[_; 8]> = blanket_impls
             .iter()
             .map(|&def_id| hcx.def_path_hash(def_id))
             .collect();
@@ -418,7 +418,7 @@ pub fn hash_stable_trait_impls<'a, 'gcx, W, R>(
     }
 
     {
-        let mut keys: AccumulateVec<[_; 8]> =
+        let mut keys: SmallVec<[_; 8]> =
             non_blanket_impls.keys()
                              .map(|k| (k, k.map_def(|d| hcx.def_path_hash(d))))
                              .collect();
@@ -426,7 +426,7 @@ pub fn hash_stable_trait_impls<'a, 'gcx, W, R>(
         keys.len().hash_stable(hcx, hasher);
         for (key, ref stable_key) in keys {
             stable_key.hash_stable(hcx, hasher);
-            let mut impls : AccumulateVec<[_; 8]> = non_blanket_impls[key]
+            let mut impls : SmallVec<[_; 8]> = non_blanket_impls[key]
                 .iter()
                 .map(|&impl_id| hcx.def_path_hash(impl_id))
                 .collect();
index c780ede75a42f9080b416b2bb61e7ea92f40d47a..3f1899bc54fb4c2e1e34b1c548cb51fcc3726e6b 100644 (file)
@@ -308,12 +308,12 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl_stable_hash_for!(enum hir::PrimTy {
-    TyInt(int_ty),
-    TyUint(uint_ty),
-    TyFloat(float_ty),
-    TyStr,
-    TyBool,
-    TyChar
+    Int(int_ty),
+    Uint(uint_ty),
+    Float(float_ty),
+    Str,
+    Bool,
+    Char
 });
 
 impl_stable_hash_for!(struct hir::BareFnTy {
@@ -1016,7 +1016,7 @@ fn to_stable_hash_key(&self,
     PrimTy(prim_ty),
     TyParam(def_id),
     SelfTy(trait_def_id, impl_def_id),
-    TyForeign(def_id),
+    ForeignTy(def_id),
     Fn(def_id),
     Const(def_id),
     Static(def_id, is_mutbl),
@@ -1140,6 +1140,7 @@ fn to_stable_hash_key(&self,
     flags,
     inline,
     export_name,
+    link_name,
     target_features,
     linkage,
     link_section,
index 38ea536b4ee729dccce470a78f5699b918a8c4d2..f11e4487964624d74ce17abd7aa57a3d0b0846e9 100644 (file)
@@ -65,6 +65,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 
         match *self {
             mir::UnsafetyViolationKind::General => {}
+            mir::UnsafetyViolationKind::MinConstFn => {}
             mir::UnsafetyViolationKind::ExternStatic(lint_node_id) |
             mir::UnsafetyViolationKind::BorrowPacked(lint_node_id) => {
                 lint_node_id.hash_stable(hcx, hasher);
@@ -479,10 +480,11 @@ fn hash_stable<W: StableHasherResult>(&self,
             mir::AggregateKind::Array(t) => {
                 t.hash_stable(hcx, hasher);
             }
-            mir::AggregateKind::Adt(adt_def, idx, substs, active_field) => {
+            mir::AggregateKind::Adt(adt_def, idx, substs, user_substs, active_field) => {
                 adt_def.hash_stable(hcx, hasher);
                 idx.hash_stable(hcx, hasher);
                 substs.hash_stable(hcx, hasher);
+                user_substs.hash_stable(hcx, hasher);
                 active_field.hash_stable(hcx, hasher);
             }
             mir::AggregateKind::Closure(def_id, ref substs) => {
@@ -528,7 +530,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     SizeOf
 });
 
-impl_stable_hash_for!(struct mir::Constant<'tcx> { span, ty, literal });
+impl_stable_hash_for!(struct mir::Constant<'tcx> { span, ty, user_ty, literal });
 
 impl_stable_hash_for!(struct mir::Location { block, statement_index });
 
index 65b84ce4a82251b9864c19eca07aeab1b822dd46..a15411c7d83698c115b8bb5dc8f8a5531e22a0ae 100644 (file)
@@ -25,9 +25,9 @@
 
 use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
 
+use smallvec::SmallVec;
 use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
                                            StableHasher, StableHasherResult};
-use rustc_data_structures::accumulate_vec::AccumulateVec;
 
 impl<'a> HashStable<StableHashingContext<'a>> for InternedString {
     #[inline]
@@ -130,7 +130,7 @@ fn to_stable_hash_key(&self,
     level,
     feature,
     rustc_depr,
-    rustc_const_unstable
+    const_stability
 });
 
 impl<'a> HashStable<StableHashingContext<'a>>
@@ -161,7 +161,6 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason });
-impl_stable_hash_for!(struct ::syntax::attr::RustcConstUnstable { feature });
 
 
 impl_stable_hash_for!(enum ::syntax::attr::IntType {
@@ -207,7 +206,7 @@ fn hash_stable<W: StableHasherResult>(&self,
         }
 
         // Some attributes are always ignored during hashing.
-        let filtered: AccumulateVec<[&ast::Attribute; 8]> = self
+        let filtered: SmallVec<[&ast::Attribute; 8]> = self
             .iter()
             .filter(|attr| {
                 !attr.is_sugared_doc && !hcx.is_ignored_attr(attr.name())
@@ -412,7 +411,7 @@ fn hash_token<'a, 'gcx, W: StableHasherResult>(
     QuestionMark,
     ExistentialReturnType,
     ForLoop,
-    Catch
+    TryBlock
 });
 
 impl_stable_hash_for!(enum ::syntax_pos::FileName {
index f13e26fee3ee460aa80a5c1201ea50dd86094af3..6250e12f43043beac2ba90a37fb0e8d286733542 100644 (file)
@@ -25,7 +25,7 @@
 use mir;
 
 impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>>
-for &'gcx ty::Slice<T>
+for &'gcx ty::List<T>
     where T: HashStable<StableHashingContext<'a>> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
@@ -53,7 +53,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
-impl<'a, 'gcx, T> ToStableHashKey<StableHashingContext<'a>> for &'gcx ty::Slice<T>
+impl<'a, 'gcx, T> ToStableHashKey<StableHashingContext<'a>> for &'gcx ty::List<T>
     where T: HashStable<StableHashingContext<'a>>
 {
     type KeyType = Fingerprint;
@@ -384,7 +384,8 @@ fn hash_stable<W: StableHasherResult>(&self,
                 a.hash_stable(hcx, hasher);
                 b.hash_stable(hcx, hasher);
             }
-            ByRef(alloc, offset) => {
+            ByRef(id, alloc, offset) => {
+                id.hash_stable(hcx, hasher);
                 alloc.hash_stable(hcx, hasher);
                 offset.hash_stable(hcx, hasher);
             }
@@ -397,12 +398,6 @@ fn hash_stable<W: StableHasherResult>(&self,
     Undef
 });
 
-impl_stable_hash_for!(enum mir::interpret::Value {
-    Scalar(v),
-    ScalarPair(a, b),
-    ByRef(ptr, align)
-});
-
 impl_stable_hash_for!(struct mir::interpret::Pointer {
     alloc_id,
     offset
@@ -452,7 +447,7 @@ fn hash_stable<W: StableHasherResult>(
         }
         self.undef_mask.hash_stable(hcx, hasher);
         self.align.hash_stable(hcx, hasher);
-        self.runtime_mutability.hash_stable(hcx, hasher);
+        self.mutability.hash_stable(hcx, hasher);
     }
 }
 
@@ -517,12 +512,12 @@ fn hash_stable<W: StableHasherResult>(&self,
         mem::discriminant(&self).hash_stable(hcx, hasher);
 
         match *self {
+            FunctionArgCountMismatch |
             DanglingPointerDeref |
             DoubleFree |
             InvalidMemoryAccess |
             InvalidFunctionPointer |
             InvalidBool |
-            InvalidDiscriminant |
             InvalidNullPointerUsage |
             ReadPointerAsBytes |
             ReadBytesAsPointer |
@@ -542,7 +537,6 @@ fn hash_stable<W: StableHasherResult>(&self,
             DeallocateNonBasePtr |
             HeapAllocZeroBytes |
             Unreachable |
-            Panic |
             ReadFromReturnPointer |
             UnimplementedTraitSelection |
             TypeckError |
@@ -556,9 +550,20 @@ fn hash_stable<W: StableHasherResult>(&self,
             GeneratorResumedAfterReturn |
             GeneratorResumedAfterPanic |
             InfiniteLoop => {}
+            InvalidDiscriminant(val) => val.hash_stable(hcx, hasher),
+            Panic { ref msg, ref file, line, col } => {
+                msg.hash_stable(hcx, hasher);
+                file.hash_stable(hcx, hasher);
+                line.hash_stable(hcx, hasher);
+                col.hash_stable(hcx, hasher);
+            },
             ReferencedConstant(ref err) => err.hash_stable(hcx, hasher),
             MachineError(ref err) => err.hash_stable(hcx, hasher),
-            FunctionPointerTyMismatch(a, b) => {
+            FunctionAbiMismatch(a, b) => {
+                a.hash_stable(hcx, hasher);
+                b.hash_stable(hcx, hasher)
+            },
+            FunctionArgMismatch(a, b) => {
                 a.hash_stable(hcx, hasher);
                 b.hash_stable(hcx, hasher)
             },
@@ -803,90 +808,90 @@ fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope {
 });
 
 impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
-for ty::TypeVariants<'gcx>
+for ty::TyKind<'gcx>
 {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
-        use ty::TypeVariants::*;
+        use ty::TyKind::*;
 
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
-            TyBool  |
-            TyChar  |
-            TyStr   |
-            TyError |
-            TyNever => {
+            Bool  |
+            Char  |
+            Str   |
+            Error |
+            Never => {
                 // Nothing more to hash.
             }
-            TyInt(int_ty) => {
+            Int(int_ty) => {
                 int_ty.hash_stable(hcx, hasher);
             }
-            TyUint(uint_ty) => {
+            Uint(uint_ty) => {
                 uint_ty.hash_stable(hcx, hasher);
             }
-            TyFloat(float_ty)  => {
+            Float(float_ty)  => {
                 float_ty.hash_stable(hcx, hasher);
             }
-            TyAdt(adt_def, substs) => {
+            Adt(adt_def, substs) => {
                 adt_def.hash_stable(hcx, hasher);
                 substs.hash_stable(hcx, hasher);
             }
-            TyArray(inner_ty, len) => {
+            Array(inner_ty, len) => {
                 inner_ty.hash_stable(hcx, hasher);
                 len.hash_stable(hcx, hasher);
             }
-            TySlice(inner_ty) => {
+            Slice(inner_ty) => {
                 inner_ty.hash_stable(hcx, hasher);
             }
-            TyRawPtr(pointee_ty) => {
+            RawPtr(pointee_ty) => {
                 pointee_ty.hash_stable(hcx, hasher);
             }
-            TyRef(region, pointee_ty, mutbl) => {
+            Ref(region, pointee_ty, mutbl) => {
                 region.hash_stable(hcx, hasher);
                 pointee_ty.hash_stable(hcx, hasher);
                 mutbl.hash_stable(hcx, hasher);
             }
-            TyFnDef(def_id, substs) => {
+            FnDef(def_id, substs) => {
                 def_id.hash_stable(hcx, hasher);
                 substs.hash_stable(hcx, hasher);
             }
-            TyFnPtr(ref sig) => {
+            FnPtr(ref sig) => {
                 sig.hash_stable(hcx, hasher);
             }
-            TyDynamic(ref existential_predicates, region) => {
+            Dynamic(ref existential_predicates, region) => {
                 existential_predicates.hash_stable(hcx, hasher);
                 region.hash_stable(hcx, hasher);
             }
-            TyClosure(def_id, closure_substs) => {
+            Closure(def_id, closure_substs) => {
                 def_id.hash_stable(hcx, hasher);
                 closure_substs.hash_stable(hcx, hasher);
             }
-            TyGenerator(def_id, generator_substs, movability) => {
+            Generator(def_id, generator_substs, movability) => {
                 def_id.hash_stable(hcx, hasher);
                 generator_substs.hash_stable(hcx, hasher);
                 movability.hash_stable(hcx, hasher);
             }
-            TyGeneratorWitness(types) => {
+            GeneratorWitness(types) => {
                 types.hash_stable(hcx, hasher)
             }
-            TyTuple(inner_tys) => {
+            Tuple(inner_tys) => {
                 inner_tys.hash_stable(hcx, hasher);
             }
-            TyProjection(ref projection_ty) => {
+            Projection(ref projection_ty) => {
                 projection_ty.hash_stable(hcx, hasher);
             }
-            TyAnon(def_id, substs) => {
+            Anon(def_id, substs) => {
                 def_id.hash_stable(hcx, hasher);
                 substs.hash_stable(hcx, hasher);
             }
-            TyParam(param_ty) => {
+            Param(param_ty) => {
                 param_ty.hash_stable(hcx, hasher);
             }
-            TyForeign(def_id) => {
+            Foreign(def_id) => {
                 def_id.hash_stable(hcx, hasher);
             }
-            TyInfer(infer_ty) => {
+            Infer(infer_ty) => {
                 infer_ty.hash_stable(hcx, hasher);
             }
         }
@@ -911,7 +916,7 @@ fn hash_stable<W: StableHasherResult>(&self,
                                           _hasher: &mut StableHasher<W>) {
         // TyVid values are confined to an inference context and hence
         // should not be hashed.
-        bug!("ty::TypeVariants::hash_stable() - can't hash a TyVid {:?}.", *self)
+        bug!("ty::TyKind::hash_stable() - can't hash a TyVid {:?}.", *self)
     }
 }
 
@@ -923,7 +928,7 @@ fn hash_stable<W: StableHasherResult>(&self,
                                           _hasher: &mut StableHasher<W>) {
         // IntVid values are confined to an inference context and hence
         // should not be hashed.
-        bug!("ty::TypeVariants::hash_stable() - can't hash an IntVid {:?}.", *self)
+        bug!("ty::TyKind::hash_stable() - can't hash an IntVid {:?}.", *self)
     }
 }
 
@@ -935,7 +940,7 @@ fn hash_stable<W: StableHasherResult>(&self,
                                           _hasher: &mut StableHasher<W>) {
         // FloatVid values are confined to an inference context and hence
         // should not be hashed.
-        bug!("ty::TypeVariants::hash_stable() - can't hash a FloatVid {:?}.", *self)
+        bug!("ty::TyKind::hash_stable() - can't hash a FloatVid {:?}.", *self)
     }
 }
 
@@ -1092,6 +1097,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 });
 
 impl_stable_hash_for!(enum ::middle::privacy::AccessLevel {
+    ReachableFromImplTrait,
     Reachable,
     Exported,
     Public
index 205f8c5ad068caee0ab33b171f14b2aa715f0762..8eab07ece05ef24219901d3e0ddab8eca7931b1e 100644 (file)
@@ -10,6 +10,7 @@
 
 use hir::def_id::DefId;
 use hir;
+use hir::Node;
 use infer::{self, InferCtxt, InferOk, TypeVariableOrigin};
 use infer::outlives::free_region_map::FreeRegionRelations;
 use rustc_data_structures::fx::FxHashMap;
@@ -592,7 +593,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         match ty.sty {
-            ty::TyClosure(def_id, substs) => {
+            ty::Closure(def_id, substs) => {
                 // I am a horrible monster and I pray for death. When
                 // we encounter a closure here, it is always a closure
                 // from within the function that we are currently
@@ -655,7 +656,7 @@ fn instantiate_anon_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: &T) ->
             tcx,
             reg_op: |reg| reg,
             fldop: |ty| {
-                if let ty::TyAnon(def_id, substs) = ty.sty {
+                if let ty::Anon(def_id, substs) = ty.sty {
                     // Check that this is `impl Trait` type is
                     // declared by `parent_def_id` -- i.e., one whose
                     // value we are inferring.  At present, this is
@@ -679,7 +680,7 @@ fn instantiate_anon_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: &T) ->
                     // ```
                     //
                     // Here, the return type of `foo` references a
-                    // `TyAnon` indeed, but not one whose value is
+                    // `Anon` indeed, but not one whose value is
                     // presently being inferred. You can get into a
                     // similar situation with closure return types
                     // today:
@@ -697,7 +698,7 @@ fn instantiate_anon_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: &T) ->
                             parent_def_id == tcx.hir.local_def_id(anon_parent_node_id)
                         };
                         let in_definition_scope = match tcx.hir.find(anon_node_id) {
-                            Some(hir::map::NodeItem(item)) => match item.node {
+                            Some(Node::Item(item)) => match item.node {
                                 // impl trait
                                 hir::ItemKind::Existential(hir::ExistTy {
                                     impl_trait_fn: Some(parent),
@@ -714,7 +715,7 @@ fn instantiate_anon_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: &T) ->
                                 ),
                                 _ => def_scope_default(),
                             },
-                            Some(hir::map::NodeImplItem(item)) => match item.node {
+                            Some(Node::ImplItem(item)) => match item.node {
                                 hir::ImplItemKind::Existential(_) => may_define_existential_type(
                                     tcx,
                                     self.parent_def_id,
@@ -755,11 +756,11 @@ fn fold_anon_ty(
         let tcx = infcx.tcx;
 
         debug!(
-            "instantiate_anon_types: TyAnon(def_id={:?}, substs={:?})",
+            "instantiate_anon_types: Anon(def_id={:?}, substs={:?})",
             def_id, substs
         );
 
-        // Use the same type variable if the exact same TyAnon appears more
+        // Use the same type variable if the exact same Anon appears more
         // than once in the return type (e.g. if it's passed to a type alias).
         if let Some(anon_defn) = self.anon_types.get(&def_id) {
             return anon_defn.concrete_ty;
@@ -805,7 +806,7 @@ fn fold_anon_ty(
 
         for predicate in bounds.predicates {
             // Change the predicate to refer to the type variable,
-            // which will be the concrete type, instead of the TyAnon.
+            // which will be the concrete type, instead of the Anon.
             // This also instantiates nested `impl Trait`.
             let predicate = self.instantiate_anon_types_in_map(&predicate);
 
index c4de95c60bff5f624178305e29d14cc76c1424aa..fbe9165ae97fa590c463241c63c0bd9746e6f4c2 100644 (file)
 use std::sync::atomic::Ordering;
 use ty::fold::{TypeFoldable, TypeFolder};
 use ty::subst::Kind;
-use ty::{self, CanonicalVar, Lift, Slice, Ty, TyCtxt, TypeFlags};
+use ty::{self, CanonicalVar, Lift, List, Ty, TyCtxt, TypeFlags};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
-use rustc_data_structures::small_vec::SmallVec;
+use smallvec::SmallVec;
 
 impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
     /// Canonicalizes a query value `V`. When we canonicalize a query,
@@ -246,46 +246,46 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match t.sty {
-            ty::TyInfer(ty::TyVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::General, t),
+            ty::Infer(ty::TyVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::General, t),
 
-            ty::TyInfer(ty::IntVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Int, t),
+            ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Int, t),
 
-            ty::TyInfer(ty::FloatVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Float, t),
+            ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Float, t),
 
-            ty::TyInfer(ty::FreshTy(_))
-            | ty::TyInfer(ty::FreshIntTy(_))
-            | ty::TyInfer(ty::FreshFloatTy(_)) => {
+            ty::Infer(ty::FreshTy(_))
+            | ty::Infer(ty::FreshIntTy(_))
+            | ty::Infer(ty::FreshFloatTy(_)) => {
                 bug!("encountered a fresh type during canonicalization")
             }
 
-            ty::TyInfer(ty::CanonicalTy(_)) => {
+            ty::Infer(ty::CanonicalTy(_)) => {
                 bug!("encountered a canonical type during canonicalization")
             }
 
-            ty::TyClosure(..)
-            | ty::TyGenerator(..)
-            | ty::TyGeneratorWitness(..)
-            | ty::TyBool
-            | ty::TyChar
-            | ty::TyInt(..)
-            | ty::TyUint(..)
-            | ty::TyFloat(..)
-            | ty::TyAdt(..)
-            | ty::TyStr
-            | ty::TyError
-            | ty::TyArray(..)
-            | ty::TySlice(..)
-            | ty::TyRawPtr(..)
-            | ty::TyRef(..)
-            | ty::TyFnDef(..)
-            | ty::TyFnPtr(_)
-            | ty::TyDynamic(..)
-            | ty::TyNever
-            | ty::TyTuple(..)
-            | ty::TyProjection(..)
-            | ty::TyForeign(..)
-            | ty::TyParam(..)
-            | ty::TyAnon(..) => {
+            ty::Closure(..)
+            | ty::Generator(..)
+            | ty::GeneratorWitness(..)
+            | ty::Bool
+            | ty::Char
+            | ty::Int(..)
+            | ty::Uint(..)
+            | ty::Float(..)
+            | ty::Adt(..)
+            | ty::Str
+            | ty::Error
+            | ty::Array(..)
+            | ty::Slice(..)
+            | ty::RawPtr(..)
+            | ty::Ref(..)
+            | ty::FnDef(..)
+            | ty::FnPtr(_)
+            | ty::Dynamic(..)
+            | ty::Never
+            | ty::Tuple(..)
+            | ty::Projection(..)
+            | ty::Foreign(..)
+            | ty::Param(..)
+            | ty::Anon(..) => {
                 if t.flags.intersects(self.needs_canonical_flags) {
                     t.super_fold_with(self)
                 } else {
@@ -327,7 +327,7 @@ fn canonicalize<V>(
         if !value.has_type_flags(needs_canonical_flags) {
             let out_value = gcx.lift(value).unwrap();
             let canon_value = Canonical {
-                variables: Slice::empty(),
+                variables: List::empty(),
                 value: out_value,
             };
             return canon_value;
@@ -380,7 +380,7 @@ fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> Canonic
         // avoid allocations in those cases. We also don't use `indices` to
         // determine if a kind has been seen before until the limit of 8 has
         // been exceeded, to also avoid allocations for `indices`.
-        if var_values.is_array() {
+        if !var_values.spilled() {
             // `var_values` is stack-allocated. `indices` isn't used yet. Do a
             // direct linear search of `var_values`.
             if let Some(idx) = var_values.iter().position(|&k| k == kind) {
@@ -395,7 +395,7 @@ fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> Canonic
 
                 // If `var_values` has become big enough to be heap-allocated,
                 // fill up `indices` to facilitate subsequent lookups.
-                if !var_values.is_array() {
+                if var_values.spilled() {
                     assert!(indices.is_empty());
                     *indices =
                         var_values.iter()
index 9b25727112cdf682900c5cb455f012295f36dcb8..85aa4f62f214c24f6e477c4d021586fc0beca513 100644 (file)
 
 use infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin};
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_data_structures::small_vec::SmallVec;
+use smallvec::SmallVec;
 use rustc_data_structures::sync::Lrc;
 use serialize::UseSpecializedDecodable;
 use std::ops::Index;
 use syntax::source_map::Span;
 use ty::fold::TypeFoldable;
 use ty::subst::Kind;
-use ty::{self, CanonicalVar, Lift, Region, Slice, TyCtxt};
+use ty::{self, CanonicalVar, Lift, Region, List, TyCtxt};
 
 mod canonicalizer;
 
@@ -49,7 +49,7 @@
 mod substitute;
 
 /// A "canonicalized" type `V` is one where all free inference
-/// variables have been rewriten to "canonical vars". These are
+/// variables have been rewritten to "canonical vars". These are
 /// numbered starting from 0 in order of first appearance.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
 pub struct Canonical<'gcx, V> {
@@ -57,7 +57,7 @@ pub struct Canonical<'gcx, V> {
     pub value: V,
 }
 
-pub type CanonicalVarInfos<'gcx> = &'gcx Slice<CanonicalVarInfo>;
+pub type CanonicalVarInfos<'gcx> = &'gcx List<CanonicalVarInfo>;
 
 impl<'gcx> UseSpecializedDecodable for CanonicalVarInfos<'gcx> {}
 
@@ -188,6 +188,36 @@ pub fn is_ambiguous(&self) -> bool {
     }
 }
 
+impl<'gcx, V> Canonical<'gcx, V> {
+    /// Allows you to map the `value` of a canonical while keeping the
+    /// same set of bound variables.
+    ///
+    /// **WARNING:** This function is very easy to mis-use, hence the
+    /// name!  In particular, the new value `W` must use all **the
+    /// same type/region variables** in **precisely the same order**
+    /// as the original! (The ordering is defined by the
+    /// `TypeFoldable` implementation of the type in question.)
+    ///
+    /// An example of a **correct** use of this:
+    ///
+    /// ```rust,ignore (not real code)
+    /// let a: Canonical<'_, T> = ...;
+    /// let b: Canonical<'_, (T,)> = a.unchecked_map(|v| (v, ));
+    /// ```
+    ///
+    /// An example of an **incorrect** use of this:
+    ///
+    /// ```rust,ignore (not real code)
+    /// let a: Canonical<'tcx, T> = ...;
+    /// let ty: Ty<'tcx> = ...;
+    /// let b: Canonical<'tcx, (T, Ty<'tcx>)> = a.unchecked_map(|v| (v, ty));
+    /// ```
+    pub fn unchecked_map<W>(self, map_op: impl FnOnce(V) -> W) -> Canonical<'gcx, W> {
+        let Canonical { variables, value } = self;
+        Canonical { variables, value: map_op(value) }
+    }
+}
+
 pub type QueryRegionConstraint<'tcx> = ty::Binder<ty::OutlivesPredicate<Kind<'tcx>, Region<'tcx>>>;
 
 impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
@@ -221,7 +251,7 @@ pub fn instantiate_canonical_with_fresh_inference_vars<T>(
     fn fresh_inference_vars_for_canonical_vars(
         &self,
         span: Span,
-        variables: &Slice<CanonicalVarInfo>,
+        variables: &List<CanonicalVarInfo>,
     ) -> CanonicalVarValues<'tcx> {
         let var_values: IndexVec<CanonicalVar, Kind<'tcx>> = variables
             .iter()
index f0b6d25e9dae8a9be8a846028db373873af127fc..65d42c0888d5d85ce08056353b4054498fcdc4a5 100644 (file)
 };
 use infer::region_constraints::{Constraint, RegionConstraintData};
 use infer::InferCtxtBuilder;
-use infer::{InferCtxt, InferOk, InferResult, RegionObligation};
+use infer::{InferCtxt, InferOk, InferResult};
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::sync::Lrc;
 use std::fmt::Debug;
-use syntax::ast;
 use syntax_pos::DUMMY_SP;
 use traits::query::{Fallible, NoSolution};
 use traits::{FulfillmentContext, TraitEngine};
 use traits::{Obligation, ObligationCause, PredicateObligation};
 use ty::fold::TypeFoldable;
 use ty::subst::{Kind, UnpackedKind};
-use ty::{self, CanonicalVar, Lift, TyCtxt};
+use ty::{self, CanonicalVar, Lift, Ty, TyCtxt};
 
 impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> {
     /// The "main method" for a canonicalized trait query. Given the
@@ -157,7 +156,12 @@ fn make_query_result<T>(
 
         let region_obligations = self.take_registered_region_obligations();
         let region_constraints = self.with_region_constraints(|region_constraints| {
-            make_query_outlives(tcx, region_obligations, region_constraints)
+            make_query_outlives(
+                tcx,
+                region_obligations
+                    .iter()
+                    .map(|(_, r_o)| (r_o.sup_type, r_o.sub_region)),
+                region_constraints)
         });
 
         let certainty = if ambig_errors.is_empty() {
@@ -421,7 +425,7 @@ fn query_result_substitution_guess<R>(
             match result_value.unpack() {
                 UnpackedKind::Type(result_value) => {
                     // e.g., here `result_value` might be `?0` in the example above...
-                    if let ty::TyInfer(ty::InferTy::CanonicalTy(index)) = result_value.sty {
+                    if let ty::Infer(ty::InferTy::CanonicalTy(index)) = result_value.sty {
                         // in which case we would set `canonical_vars[0]` to `Some(?U)`.
                         opt_values[index] = Some(*original_value);
                     }
@@ -567,7 +571,7 @@ fn unify_canonical_vars(
 /// creates query region constraints.
 pub fn make_query_outlives<'tcx>(
     tcx: TyCtxt<'_, '_, 'tcx>,
-    region_obligations: Vec<(ast::NodeId, RegionObligation<'tcx>)>,
+    outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>)>,
     region_constraints: &RegionConstraintData<'tcx>,
 ) -> Vec<QueryRegionConstraint<'tcx>> {
     let RegionConstraintData {
@@ -600,9 +604,8 @@ pub fn make_query_outlives<'tcx>(
             .collect();
 
     outlives.extend(
-        region_obligations
-            .into_iter()
-            .map(|(_, r_o)| ty::OutlivesPredicate(r_o.sup_type.into(), r_o.sub_region))
+        outlives_obligations
+            .map(|(ty, r)| ty::OutlivesPredicate(ty.into(), r))
             .map(ty::Binder::dummy), // no bound regions in the code above
     );
 
index 679829f43c529d6c64093f1973f0d7c00d8ad15c..f3fe01d5fd121659b064b389ac35e240fb200034 100644 (file)
@@ -85,7 +85,7 @@ fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match t.sty {
-            ty::TyInfer(ty::InferTy::CanonicalTy(c)) => {
+            ty::Infer(ty::InferTy::CanonicalTy(c)) => {
                 match self.var_values.var_values[c].unpack() {
                     UnpackedKind::Type(ty) => ty,
                     r => bug!("{:?} is a type but value is {:?}", c, r),
index ccba5a09cf6cc92433f3430288ad30cb567d4389..4738a03cbd3ec4177f2ecf1a7905b6a334aaf5b1 100644 (file)
@@ -76,44 +76,44 @@ pub fn super_combine_tys<R>(&self,
 
         match (&a.sty, &b.sty) {
             // Relate integral variables to other types
-            (&ty::TyInfer(ty::IntVar(a_id)), &ty::TyInfer(ty::IntVar(b_id))) => {
+            (&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => {
                 self.int_unification_table
                     .borrow_mut()
                     .unify_var_var(a_id, b_id)
                     .map_err(|e| int_unification_error(a_is_expected, e))?;
                 Ok(a)
             }
-            (&ty::TyInfer(ty::IntVar(v_id)), &ty::TyInt(v)) => {
+            (&ty::Infer(ty::IntVar(v_id)), &ty::Int(v)) => {
                 self.unify_integral_variable(a_is_expected, v_id, IntType(v))
             }
-            (&ty::TyInt(v), &ty::TyInfer(ty::IntVar(v_id))) => {
+            (&ty::Int(v), &ty::Infer(ty::IntVar(v_id))) => {
                 self.unify_integral_variable(!a_is_expected, v_id, IntType(v))
             }
-            (&ty::TyInfer(ty::IntVar(v_id)), &ty::TyUint(v)) => {
+            (&ty::Infer(ty::IntVar(v_id)), &ty::Uint(v)) => {
                 self.unify_integral_variable(a_is_expected, v_id, UintType(v))
             }
-            (&ty::TyUint(v), &ty::TyInfer(ty::IntVar(v_id))) => {
+            (&ty::Uint(v), &ty::Infer(ty::IntVar(v_id))) => {
                 self.unify_integral_variable(!a_is_expected, v_id, UintType(v))
             }
 
             // Relate floating-point variables to other types
-            (&ty::TyInfer(ty::FloatVar(a_id)), &ty::TyInfer(ty::FloatVar(b_id))) => {
+            (&ty::Infer(ty::FloatVar(a_id)), &ty::Infer(ty::FloatVar(b_id))) => {
                 self.float_unification_table
                     .borrow_mut()
                     .unify_var_var(a_id, b_id)
                     .map_err(|e| float_unification_error(relation.a_is_expected(), e))?;
                 Ok(a)
             }
-            (&ty::TyInfer(ty::FloatVar(v_id)), &ty::TyFloat(v)) => {
+            (&ty::Infer(ty::FloatVar(v_id)), &ty::Float(v)) => {
                 self.unify_float_variable(a_is_expected, v_id, v)
             }
-            (&ty::TyFloat(v), &ty::TyInfer(ty::FloatVar(v_id))) => {
+            (&ty::Float(v), &ty::Infer(ty::FloatVar(v_id))) => {
                 self.unify_float_variable(!a_is_expected, v_id, v)
             }
 
             // All other cases of inference are errors
-            (&ty::TyInfer(_), _) |
-            (_, &ty::TyInfer(_)) => {
+            (&ty::Infer(_), _) |
+            (_, &ty::Infer(_)) => {
                 Err(TypeError::Sorts(ty::relate::expected_found(relation, &a, &b)))
             }
 
@@ -393,7 +393,7 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         // subtyping. This is basically our "occurs check", preventing
         // us from creating infinitely sized types.
         match t.sty {
-            ty::TyInfer(ty::TyVar(vid)) => {
+            ty::Infer(ty::TyVar(vid)) => {
                 let mut variables = self.infcx.type_variables.borrow_mut();
                 let vid = variables.root_var(vid);
                 let sub_vid = variables.sub_root_var(vid);
@@ -433,8 +433,8 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                     }
                 }
             }
-            ty::TyInfer(ty::IntVar(_)) |
-            ty::TyInfer(ty::FloatVar(_)) => {
+            ty::Infer(ty::IntVar(_)) |
+            ty::Infer(ty::FloatVar(_)) => {
                 // No matter what mode we are in,
                 // integer/floating-point types must be equal to be
                 // relatable.
index 2ae8f8ae9335711f41a9d693f764b4bf30c82e86..26eb2ffbf6aba763e12245a9d92c53d3fa52ba96 100644 (file)
@@ -75,17 +75,17 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         let a = infcx.type_variables.borrow_mut().replace_if_possible(a);
         let b = infcx.type_variables.borrow_mut().replace_if_possible(b);
         match (&a.sty, &b.sty) {
-            (&ty::TyInfer(TyVar(a_id)), &ty::TyInfer(TyVar(b_id))) => {
+            (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => {
                 infcx.type_variables.borrow_mut().equate(a_id, b_id);
                 Ok(a)
             }
 
-            (&ty::TyInfer(TyVar(a_id)), _) => {
+            (&ty::Infer(TyVar(a_id)), _) => {
                 self.fields.instantiate(b, RelationDir::EqTo, a_id, self.a_is_expected)?;
                 Ok(a)
             }
 
-            (_, &ty::TyInfer(TyVar(b_id))) => {
+            (_, &ty::Infer(TyVar(b_id))) => {
                 self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?;
                 Ok(a)
             }
index d2987119e299647d870450d078f962dc88305e31..cf0d0ceadca910b68e2c029698f1ed86af7b819c 100644 (file)
 
 use std::{cmp, fmt};
 use hir;
-use hir::map as hir_map;
+use hir::Node;
 use hir::def_id::DefId;
 use middle::region;
 use traits::{ObligationCause, ObligationCauseCode};
-use ty::{self, subst::Subst, Region, Ty, TyCtxt, TypeFoldable, TypeVariants};
+use ty::{self, subst::Subst, Region, Ty, TyCtxt, TypeFoldable, TyKind};
 use ty::error::TypeError;
 use syntax::ast::DUMMY_NODE_ID;
 use syntax_pos::{Pos, Span};
@@ -100,8 +100,8 @@ pub fn note_and_explain_region(
                 };
                 let span = scope.span(self, region_scope_tree);
                 let tag = match self.hir.find(scope.node_id(self, region_scope_tree)) {
-                    Some(hir_map::NodeBlock(_)) => "block",
-                    Some(hir_map::NodeExpr(expr)) => match expr.node {
+                    Some(Node::Block(_)) => "block",
+                    Some(Node::Expr(expr)) => match expr.node {
                         hir::ExprKind::Call(..) => "call",
                         hir::ExprKind::MethodCall(..) => "method call",
                         hir::ExprKind::Match(.., hir::MatchSource::IfLetDesugar { .. }) => "if let",
@@ -110,10 +110,10 @@ pub fn note_and_explain_region(
                         hir::ExprKind::Match(..) => "match",
                         _ => "expression",
                     },
-                    Some(hir_map::NodeStmt(_)) => "statement",
-                    Some(hir_map::NodeItem(it)) => Self::item_scope_tag(&it),
-                    Some(hir_map::NodeTraitItem(it)) => Self::trait_item_scope_tag(&it),
-                    Some(hir_map::NodeImplItem(it)) => Self::impl_item_scope_tag(&it),
+                    Some(Node::Stmt(_)) => "statement",
+                    Some(Node::Item(it)) => Self::item_scope_tag(&it),
+                    Some(Node::TraitItem(it)) => Self::trait_item_scope_tag(&it),
+                    Some(Node::ImplItem(it)) => Self::impl_item_scope_tag(&it),
                     Some(_) | None => {
                         err.span_note(span, &unknown_scope());
                         return;
@@ -194,10 +194,10 @@ fn msg_span_from_early_bound_and_free_regions(
         let scope = region.free_region_binding_scope(self);
         let node = self.hir.as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID);
         let tag = match self.hir.find(node) {
-            Some(hir_map::NodeBlock(_)) | Some(hir_map::NodeExpr(_)) => "body",
-            Some(hir_map::NodeItem(it)) => Self::item_scope_tag(&it),
-            Some(hir_map::NodeTraitItem(it)) => Self::trait_item_scope_tag(&it),
-            Some(hir_map::NodeImplItem(it)) => Self::impl_item_scope_tag(&it),
+            Some(Node::Block(_)) | Some(Node::Expr(_)) => "body",
+            Some(Node::Item(it)) => Self::item_scope_tag(&it),
+            Some(Node::TraitItem(it)) => Self::trait_item_scope_tag(&it),
+            Some(Node::ImplItem(it)) => Self::impl_item_scope_tag(&it),
             _ => unreachable!()
         };
         let (prefix, span) = match *region {
@@ -484,7 +484,7 @@ fn check_and_note_conflicting_crates(
                 // if they are both "path types", there's a chance of ambiguity
                 // due to different versions of the same crate
                 match (&exp_found.expected.sty, &exp_found.found.sty) {
-                    (&ty::TyAdt(exp_adt, _), &ty::TyAdt(found_adt, _)) => {
+                    (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) => {
                         report_path_match(err, exp_adt.did, found_adt.did);
                     }
                     _ => (),
@@ -561,7 +561,7 @@ fn highlight_outer(
             value.push_highlighted("<");
         }
 
-        // Output the lifetimes fot the first type
+        // Output the lifetimes for the first type
         let lifetimes = sub.regions()
             .map(|lifetime| {
                 let s = lifetime.to_string();
@@ -636,7 +636,7 @@ fn cmp_type_arg(
                 self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
                 return Some(());
             }
-            if let &ty::TyAdt(def, _) = &ta.sty {
+            if let &ty::Adt(def, _) = &ta.sty {
                 let path_ = self.tcx.item_path_str(def.did.clone());
                 if path_ == other_path {
                     self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
@@ -704,14 +704,14 @@ fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagnosticStyledString, Diagnostic
         fn equals<'tcx>(a: &Ty<'tcx>, b: &Ty<'tcx>) -> bool {
             match (&a.sty, &b.sty) {
                 (a, b) if *a == *b => true,
-                (&ty::TyInt(_), &ty::TyInfer(ty::InferTy::IntVar(_)))
-                | (&ty::TyInfer(ty::InferTy::IntVar(_)), &ty::TyInt(_))
-                | (&ty::TyInfer(ty::InferTy::IntVar(_)), &ty::TyInfer(ty::InferTy::IntVar(_)))
-                | (&ty::TyFloat(_), &ty::TyInfer(ty::InferTy::FloatVar(_)))
-                | (&ty::TyInfer(ty::InferTy::FloatVar(_)), &ty::TyFloat(_))
+                (&ty::Int(_), &ty::Infer(ty::InferTy::IntVar(_)))
+                | (&ty::Infer(ty::InferTy::IntVar(_)), &ty::Int(_))
+                | (&ty::Infer(ty::InferTy::IntVar(_)), &ty::Infer(ty::InferTy::IntVar(_)))
+                | (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_)))
+                | (&ty::Infer(ty::InferTy::FloatVar(_)), &ty::Float(_))
                 | (
-                    &ty::TyInfer(ty::InferTy::FloatVar(_)),
-                    &ty::TyInfer(ty::InferTy::FloatVar(_)),
+                    &ty::Infer(ty::InferTy::FloatVar(_)),
+                    &ty::Infer(ty::InferTy::FloatVar(_)),
                 ) => true,
                 _ => false,
             }
@@ -738,7 +738,7 @@ fn push_ty_ref<'tcx>(
         }
 
         match (&t1.sty, &t2.sty) {
-            (&ty::TyAdt(def1, sub1), &ty::TyAdt(def2, sub2)) => {
+            (&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
                 let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1);
                 let sub_no_defaults_2 = self.strip_generic_default_params(def2.did, sub2);
                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
@@ -877,13 +877,13 @@ fn lifetime_display(lifetime: Region) -> String {
             }
 
             // When finding T != &T, highlight only the borrow
-            (&ty::TyRef(r1, ref_ty1, mutbl1), _) if equals(&ref_ty1, &t2) => {
+            (&ty::Ref(r1, ref_ty1, mutbl1), _) if equals(&ref_ty1, &t2) => {
                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
                 push_ty_ref(&r1, ref_ty1, mutbl1, &mut values.0);
                 values.1.push_normal(t2.to_string());
                 values
             }
-            (_, &ty::TyRef(r2, ref_ty2, mutbl2)) if equals(&t1, &ref_ty2) => {
+            (_, &ty::Ref(r2, ref_ty2, mutbl2)) if equals(&t1, &ref_ty2) => {
                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
                 values.0.push_normal(t1.to_string());
                 push_ty_ref(&r2, ref_ty2, mutbl2, &mut values.1);
@@ -891,8 +891,8 @@ fn lifetime_display(lifetime: Region) -> String {
             }
 
             // When encountering &T != &mut T, highlight only the borrow
-            (&ty::TyRef(r1, ref_ty1, mutbl1),
-             &ty::TyRef(r2, ref_ty2, mutbl2)) if equals(&ref_ty1, &ref_ty2) => {
+            (&ty::Ref(r1, ref_ty1, mutbl1),
+             &ty::Ref(r2, ref_ty2, mutbl2)) if equals(&ref_ty1, &ref_ty2) => {
                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
                 push_ty_ref(&r1, ref_ty1, mutbl1, &mut values.0);
                 push_ty_ref(&r2, ref_ty2, mutbl2, &mut values.1);
@@ -979,14 +979,14 @@ pub fn note_type_err(
                 (_, false, _) => {
                     if let Some(exp_found) = exp_found {
                         let (def_id, ret_ty) = match exp_found.found.sty {
-                            TypeVariants::TyFnDef(def, _) => {
+                            TyKind::FnDef(def, _) => {
                                 (Some(def), Some(self.tcx.fn_sig(def).output()))
                             }
                             _ => (None, None),
                         };
 
                         let exp_is_struct = match exp_found.expected.sty {
-                            TypeVariants::TyAdt(def, _) => def.is_struct(),
+                            TyKind::Adt(def, _) => def.is_struct(),
                             _ => false,
                         };
 
@@ -1123,11 +1123,11 @@ pub fn construct_generic_bound_failure(
                         let type_param = generics.type_param(param, self.tcx);
                         let hir = &self.tcx.hir;
                         hir.as_local_node_id(type_param.def_id).map(|id| {
-                            // Get the `hir::TyParam` to verify whether it already has any bounds.
+                            // Get the `hir::Param` to verify whether it already has any bounds.
                             // We do this to avoid suggesting code that ends up as `T: 'a'b`,
                             // instead we suggest `T: 'a + 'b` in that case.
                             let mut has_bounds = false;
-                            if let hir_map::NodeGenericParam(ref param) = hir.get(id) {
+                            if let Node::GenericParam(ref param) = hir.get(id) {
                                 has_bounds = !param.bounds.is_empty();
                             }
                             let sp = hir.span(id);
@@ -1330,7 +1330,7 @@ fn report_inference_failure(
             s
         };
         let var_description = match var_origin {
-            infer::MiscVariable(_) => "".to_string(),
+            infer::MiscVariable(_) => String::new(),
             infer::PatternRegion(_) => " for pattern".to_string(),
             infer::AddrOfRegion(_) => " for borrow expression".to_string(),
             infer::Autoref(_) => " for autoref".to_string(),
index bd2c81c7fb64f4174a5addb700a13be437885de0..505b1bc032d2021b9dbe6457c07b8015b460c049 100644 (file)
@@ -12,7 +12,7 @@
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use infer::InferCtxt;
 use infer::type_variable::TypeVariableOrigin;
-use ty::{self, Ty, TyInfer, TyVar};
+use ty::{self, Ty, Infer, TyVar};
 use syntax::source_map::CompilerDesugaringKind;
 use syntax_pos::Span;
 use errors::DiagnosticBuilder;
@@ -35,7 +35,7 @@ fn node_matches_type(&mut self, node_id: HirId) -> bool {
                 let ty = self.infcx.resolve_type_vars_if_possible(&ty);
                 ty.walk().any(|inner_ty| {
                     inner_ty == *self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) {
-                        (&TyInfer(TyVar(a_vid)), &TyInfer(TyVar(b_vid))) => {
+                        (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
                             self.infcx
                                 .type_variables
                                 .borrow_mut()
@@ -75,7 +75,7 @@ fn visit_body(&mut self, body: &'gcx Body) {
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     pub fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String {
-        if let ty::TyInfer(ty::TyVar(ty_vid)) = (*ty).sty {
+        if let ty::Infer(ty::TyVar(ty_vid)) = (*ty).sty {
             let ty_vars = self.type_variables.borrow();
             if let TypeVariableOrigin::TypeParameterDefinition(_, name) =
                 *ty_vars.var_origin(ty_vid) {
index 21be09b0ba193f0d30e7e42b89cb8776aa948a47..e3faf755672a10c55916cd51f101faddd15de726 100644 (file)
@@ -10,7 +10,7 @@
 
 use hir;
 use ty::{self, Region, TyCtxt};
-use hir::map as hir_map;
+use hir::Node;
 use middle::resolve_lifetime as rl;
 use hir::intravisit::{self, NestedVisitorMap, Visitor};
 use infer::error_reporting::nice_region_error::NiceRegionError;
@@ -40,15 +40,15 @@ pub(super) fn find_anon_type(
             let def_id = anon_reg.def_id;
             if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
                 let fndecl = match self.tcx.hir.get(node_id) {
-                    hir_map::NodeItem(&hir::Item {
+                    Node::Item(&hir::Item {
                         node: hir::ItemKind::Fn(ref fndecl, ..),
                         ..
                     }) => &fndecl,
-                    hir_map::NodeTraitItem(&hir::TraitItem {
+                    Node::TraitItem(&hir::TraitItem {
                         node: hir::TraitItemKind::Method(ref m, ..),
                         ..
                     })
-                    | hir_map::NodeImplItem(&hir::ImplItem {
+                    | Node::ImplItem(&hir::ImplItem {
                         node: hir::ImplItemKind::Method(ref m, ..),
                         ..
                     }) => &m.decl,
index f4ef197e5b4223c53e1ee9b1d9068159674f4a88..5c27cdb6fb55392198cb30678f1895d81b4ff040 100644 (file)
@@ -15,7 +15,7 @@
 use infer::SubregionOrigin;
 use ty::RegionKind;
 use hir::{Expr, ExprKind::Closure};
-use hir::map::NodeExpr;
+use hir::Node;
 use util::common::ErrorReported;
 use infer::lexical_region_resolve::RegionResolutionError::SubSupConflict;
 
@@ -59,7 +59,7 @@ pub(super) fn try_report_outlives_closure(&self) -> Option<ErrorReported> {
                 let hir = &self.tcx.hir;
                 if let Some(node_id) = hir.as_local_node_id(free_region.scope) {
                     match hir.get(node_id) {
-                        NodeExpr(Expr {
+                        Node::Expr(Expr {
                             node: Closure(_, _, _, closure_span, None),
                             ..
                         }) => {
index 28320ce3ad1ba8392e4805952c0d591209fc2ac9..30406f1fec55cd208ce6c56779f64c84deaa17b4 100644 (file)
 
 //! Helper functions corresponding to lifetime errors due to
 //! anonymous regions.
+
 use hir;
 use infer::error_reporting::nice_region_error::NiceRegionError;
 use ty::{self, Region, Ty};
 use hir::def_id::DefId;
-use hir::map as hir_map;
+use hir::Node;
 use syntax_pos::Span;
 
 // The struct contains the information about the anonymous region
@@ -137,8 +138,8 @@ pub(super) fn is_suitable_region(&self, region: Region<'tcx>) -> Option<FreeRegi
             .as_local_node_id(suitable_region_binding_scope)
             .unwrap();
         let is_impl_item = match self.tcx.hir.find(node_id) {
-            Some(hir_map::NodeItem(..)) | Some(hir_map::NodeTraitItem(..)) => false,
-            Some(hir_map::NodeImplItem(..)) => {
+            Some(Node::Item(..)) | Some(Node::TraitItem(..)) => false,
+            Some(Node::ImplItem(..)) => {
                 self.is_bound_region_in_impl_item(suitable_region_binding_scope)
             }
             _ => return None,
@@ -162,7 +163,7 @@ pub(super) fn is_return_type_anon(
     ) -> Option<Span> {
         let ret_ty = self.tcx.type_of(scope_def_id);
         match ret_ty.sty {
-            ty::TyFnDef(_, _) => {
+            ty::FnDef(_, _) => {
                 let sig = ret_ty.fn_sig(self.tcx);
                 let late_bound_regions = self.tcx
                     .collect_referenced_late_bound_regions(&sig.output());
@@ -181,7 +182,7 @@ pub(super) fn is_return_type_impl_trait(
     ) -> bool {
         let ret_ty = self.tcx.type_of(scope_def_id);
         match ret_ty.sty {
-            ty::TyFnDef(_, _) => {
+            ty::FnDef(_, _) => {
                 let sig = ret_ty.fn_sig(self.tcx);
                 let output = self.tcx.erase_late_bound_regions(&sig.output());
                 return output.is_impl_trait();
index 6074bfd083d46dc82a0f1d8e5080ea8a85d6230e..4673aac1872ffb94fef08677e182cee5462e0c4c 100644 (file)
@@ -133,7 +133,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         let tcx = self.infcx.tcx;
 
         match t.sty {
-            ty::TyInfer(ty::TyVar(v)) => {
+            ty::Infer(ty::TyVar(v)) => {
                 let opt_ty = self.infcx.type_variables.borrow_mut().probe(v).known();
                 self.freshen(
                     opt_ty,
@@ -141,7 +141,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                     ty::FreshTy)
             }
 
-            ty::TyInfer(ty::IntVar(v)) => {
+            ty::Infer(ty::IntVar(v)) => {
                 self.freshen(
                     self.infcx.int_unification_table.borrow_mut()
                                                     .probe_value(v)
@@ -150,7 +150,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                     ty::FreshIntTy)
             }
 
-            ty::TyInfer(ty::FloatVar(v)) => {
+            ty::Infer(ty::FloatVar(v)) => {
                 self.freshen(
                     self.infcx.float_unification_table.borrow_mut()
                                                       .probe_value(v)
@@ -159,9 +159,9 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                     ty::FreshFloatTy)
             }
 
-            ty::TyInfer(ty::FreshTy(c)) |
-            ty::TyInfer(ty::FreshIntTy(c)) |
-            ty::TyInfer(ty::FreshFloatTy(c)) => {
+            ty::Infer(ty::FreshTy(c)) |
+            ty::Infer(ty::FreshIntTy(c)) |
+            ty::Infer(ty::FreshFloatTy(c)) => {
                 if c >= self.freshen_count {
                     bug!("Encountered a freshend type with id {} \
                           but our counter is only at {}",
@@ -171,33 +171,33 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                 t
             }
 
-            ty::TyInfer(ty::CanonicalTy(..)) =>
+            ty::Infer(ty::CanonicalTy(..)) =>
                 bug!("encountered canonical ty during freshening"),
 
-            ty::TyGenerator(..) |
-            ty::TyBool |
-            ty::TyChar |
-            ty::TyInt(..) |
-            ty::TyUint(..) |
-            ty::TyFloat(..) |
-            ty::TyAdt(..) |
-            ty::TyStr |
-            ty::TyError |
-            ty::TyArray(..) |
-            ty::TySlice(..) |
-            ty::TyRawPtr(..) |
-            ty::TyRef(..) |
-            ty::TyFnDef(..) |
-            ty::TyFnPtr(_) |
-            ty::TyDynamic(..) |
-            ty::TyNever |
-            ty::TyTuple(..) |
-            ty::TyProjection(..) |
-            ty::TyForeign(..) |
-            ty::TyParam(..) |
-            ty::TyClosure(..) |
-            ty::TyGeneratorWitness(..) |
-            ty::TyAnon(..) => {
+            ty::Generator(..) |
+            ty::Bool |
+            ty::Char |
+            ty::Int(..) |
+            ty::Uint(..) |
+            ty::Float(..) |
+            ty::Adt(..) |
+            ty::Str |
+            ty::Error |
+            ty::Array(..) |
+            ty::Slice(..) |
+            ty::RawPtr(..) |
+            ty::Ref(..) |
+            ty::FnDef(..) |
+            ty::FnPtr(_) |
+            ty::Dynamic(..) |
+            ty::Never |
+            ty::Tuple(..) |
+            ty::Projection(..) |
+            ty::Foreign(..) |
+            ty::Param(..) |
+            ty::Closure(..) |
+            ty::GeneratorWitness(..) |
+            ty::Anon(..) => {
                 t.super_fold_with(self)
             }
         }
index 961dd70a4685204b927909c1738f9f3463b73b6b..39dc24b86e72a8851c08aa06894eefb91f4fb3df 100644 (file)
@@ -123,7 +123,7 @@ fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         match ty.sty {
-            ty::TyInfer(ty::InferTy::TyVar(vid)) => {
+            ty::Infer(ty::InferTy::TyVar(vid)) => {
                 match self.type_variables.get(&vid) {
                     None => {
                         // This variable was created before the
index cb4e1ab65e7590995546a5f711e0b365f7d0718e..bb1c9448132c117b72656f91fe0e871c36d1e555 100644 (file)
@@ -527,7 +527,7 @@ fn region_vars_confined_to_snapshot(&self,
          * we're not careful, it will succeed.
          *
          * The reason is that when we walk through the subtyping
-         * algorith, we begin by replacing `'a` with a skolemized
+         * algorithm, we begin by replacing `'a` with a skolemized
          * variable `'1`. We then have `fn(_#0t) <: fn(&'1 int)`. This
          * can be made true by unifying `_#0t` with `&'1 int`. In the
          * process, we create a fresh variable for the skolemized
index 28aba51ab372468b403f4ff62525bb9d176db1c4..6848c625b5a1ff7fe6bac250f2b27aef24bcb905 100644 (file)
@@ -88,12 +88,12 @@ pub fn super_lattice_tys<'a, 'gcx, 'tcx, L>(this: &mut L,
         // is (e.g.) `Box<i32>`. A more obvious solution might be to
         // iterate on the subtype obligations that are returned, but I
         // think this suffices. -nmatsakis
-        (&ty::TyInfer(TyVar(..)), _) => {
+        (&ty::Infer(TyVar(..)), _) => {
             let v = infcx.next_ty_var(TypeVariableOrigin::LatticeVariable(this.cause().span));
             this.relate_bound(v, b, a)?;
             Ok(v)
         }
-        (_, &ty::TyInfer(TyVar(..))) => {
+        (_, &ty::Infer(TyVar(..))) => {
             let v = infcx.next_ty_var(TypeVariableOrigin::LatticeVariable(this.cause().span));
             this.relate_bound(v, a, b)?;
             Ok(v)
index eed6215150fdbf829eafa24d7b22fcf7d54d1e0b..a379438275d897f5b2e7079ed3ca31027be9c220 100644 (file)
@@ -546,7 +546,7 @@ pub fn freshen<T:TypeFoldable<'tcx>>(&self, t: T) -> T {
 
     pub fn type_var_diverges(&'a self, ty: Ty) -> bool {
         match ty.sty {
-            ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().var_diverges(vid),
+            ty::Infer(ty::TyVar(vid)) => self.type_variables.borrow().var_diverges(vid),
             _ => false
         }
     }
@@ -559,14 +559,14 @@ pub fn type_is_unconstrained_numeric(&'a self, ty: Ty) -> UnconstrainedNumeric {
         use ty::error::UnconstrainedNumeric::Neither;
         use ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
         match ty.sty {
-            ty::TyInfer(ty::IntVar(vid)) => {
+            ty::Infer(ty::IntVar(vid)) => {
                 if self.int_unification_table.borrow_mut().probe_value(vid).is_some() {
                     Neither
                 } else {
                     UnconstrainedInt
                 }
             },
-            ty::TyInfer(ty::FloatVar(vid)) => {
+            ty::Infer(ty::FloatVar(vid)) => {
                 if self.float_unification_table.borrow_mut().probe_value(vid).is_some() {
                     Neither
                 } else {
@@ -1116,9 +1116,13 @@ pub fn trait_ref_to_string(&self, t: &ty::TraitRef<'tcx>) -> String {
         self.resolve_type_vars_if_possible(t).to_string()
     }
 
-    pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
+    // We have this force-inlined variant of shallow_resolve() for the one
+    // callsite that is extremely hot. All other callsites use the normal
+    // variant.
+    #[inline(always)]
+    pub fn inlined_shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
         match typ.sty {
-            ty::TyInfer(ty::TyVar(v)) => {
+            ty::Infer(ty::TyVar(v)) => {
                 // Not entirely obvious: if `typ` is a type variable,
                 // it can be resolved to an int/float variable, which
                 // can then be recursively resolved, hence the
@@ -1135,7 +1139,7 @@ pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
                                    .unwrap_or(typ)
             }
 
-            ty::TyInfer(ty::IntVar(v)) => {
+            ty::Infer(ty::IntVar(v)) => {
                 self.int_unification_table
                     .borrow_mut()
                     .probe_value(v)
@@ -1143,7 +1147,7 @@ pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
                     .unwrap_or(typ)
             }
 
-            ty::TyInfer(ty::FloatVar(v)) => {
+            ty::Infer(ty::FloatVar(v)) => {
                 self.float_unification_table
                     .borrow_mut()
                     .probe_value(v)
@@ -1157,6 +1161,10 @@ pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
         }
     }
 
+    pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
+        self.inlined_shallow_resolve(typ)
+    }
+
     pub fn resolve_type_vars_if_possible<T>(&self, value: &T) -> T
         where T: TypeFoldable<'tcx>
     {
@@ -1210,12 +1218,12 @@ pub fn fully_resolve<T:TypeFoldable<'tcx>>(&self, value: &T) -> FixupResult<T> {
     }
 
     // [Note-Type-error-reporting]
-    // An invariant is that anytime the expected or actual type is TyError (the special
+    // An invariant is that anytime the expected or actual type is Error (the special
     // error type, meaning that an error occurred when typechecking this expression),
     // this is a derived error. The error cascaded from another error (that was already
     // reported), so it's not useful to display it to the user.
     // The following methods implement this logic.
-    // They check if either the actual or expected type is TyError, and don't print the error
+    // They check if either the actual or expected type is Error, and don't print the error
     // in this case. The typechecker should only ever report type errors involving mismatched
     // types using one of these methods, and should not call span_err directly for such
     // errors.
@@ -1230,7 +1238,7 @@ pub fn type_error_struct_with_diag<M>(&self,
         let actual_ty = self.resolve_type_vars_if_possible(&actual_ty);
         debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty);
 
-        // Don't report an error if actual type is TyError.
+        // Don't report an error if actual type is Error.
         if actual_ty.references_error() {
             return self.tcx.sess.diagnostic().struct_dummy();
         }
index 3598d66060bf227363a3277073369dd30b21f7fc..817280b97e0315f8997e76e31c95dc70352eefbd 100644 (file)
@@ -450,8 +450,8 @@ fn projection_must_outlive(
 
     fn type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
         match ty.sty {
-            ty::TyParam(p) => self.param_bound(p),
-            ty::TyProjection(data) => {
+            ty::Param(p) => self.param_bound(p),
+            ty::Projection(data) => {
                 let declared_bounds = self.projection_declared_bounds(data);
                 self.projection_bound(declared_bounds, data)
             }
index 77b722c5695f86803465b0586d96ec7c2360c666..be13fb9a2a5ebf8818925001a71e5d0bea08e7e4 100644 (file)
@@ -104,7 +104,7 @@ impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'gcx, 'tcx>
     fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
         let t = self.infcx.shallow_resolve(t);
         if t.has_infer_types() {
-            if let ty::TyInfer(_) = t.sty {
+            if let ty::Infer(_) = t.sty {
                 // Since we called `shallow_resolve` above, this must
                 // be an (as yet...) unresolved inference variable.
                 true
@@ -158,19 +158,19 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         } else {
             let t = self.infcx.shallow_resolve(t);
             match t.sty {
-                ty::TyInfer(ty::TyVar(vid)) => {
+                ty::Infer(ty::TyVar(vid)) => {
                     self.err = Some(FixupError::UnresolvedTy(vid));
                     self.tcx().types.err
                 }
-                ty::TyInfer(ty::IntVar(vid)) => {
+                ty::Infer(ty::IntVar(vid)) => {
                     self.err = Some(FixupError::UnresolvedIntTy(vid));
                     self.tcx().types.err
                 }
-                ty::TyInfer(ty::FloatVar(vid)) => {
+                ty::Infer(ty::FloatVar(vid)) => {
                     self.err = Some(FixupError::UnresolvedFloatTy(vid));
                     self.tcx().types.err
                 }
-                ty::TyInfer(_) => {
+                ty::Infer(_) => {
                     bug!("Unexpected type in full type resolver: {:?}", t);
                 }
                 _ => {
index 58eae5e6a5b9409d00f28928ab588a6580ab5e56..048810c042722f552de6844b3e5862f1d13b9a53 100644 (file)
@@ -80,7 +80,7 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         let a = infcx.type_variables.borrow_mut().replace_if_possible(a);
         let b = infcx.type_variables.borrow_mut().replace_if_possible(b);
         match (&a.sty, &b.sty) {
-            (&ty::TyInfer(TyVar(a_vid)), &ty::TyInfer(TyVar(b_vid))) => {
+            (&ty::Infer(TyVar(a_vid)), &ty::Infer(TyVar(b_vid))) => {
                 // Shouldn't have any LBR here, so we can safely put
                 // this under a binder below without fear of accidental
                 // capture.
@@ -106,17 +106,17 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
 
                 Ok(a)
             }
-            (&ty::TyInfer(TyVar(a_id)), _) => {
+            (&ty::Infer(TyVar(a_id)), _) => {
                 self.fields
                     .instantiate(b, RelationDir::SupertypeOf, a_id, !self.a_is_expected)?;
                 Ok(a)
             }
-            (_, &ty::TyInfer(TyVar(b_id))) => {
+            (_, &ty::Infer(TyVar(b_id))) => {
                 self.fields.instantiate(a, RelationDir::SubtypeOf, b_id, self.a_is_expected)?;
                 Ok(a)
             }
 
-            (&ty::TyError, _) | (_, &ty::TyError) => {
+            (&ty::Error, _) | (_, &ty::Error) => {
                 infcx.set_tainted_by_errors();
                 Ok(self.tcx().types.err)
             }
index d40e1b3760f0361a2bcf62877c1f528d46159269..b1e4fc7c7fc7b1127e9192bf3dcbbd72162ceb17 100644 (file)
@@ -245,7 +245,7 @@ pub fn probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> {
     /// instantiated. Otherwise, returns `t`.
     pub fn replace_if_possible(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match t.sty {
-            ty::TyInfer(ty::TyVar(v)) => {
+            ty::Infer(ty::TyVar(v)) => {
                 match self.probe(v) {
                     TypeVariableValue::Unknown { .. } => t,
                     TypeVariableValue::Known { value } => value,
index b6f4bd6dc408c9ffb4dfa10b2b7a935ad741434c..d79281666d63914e7f137927c04100b96ec02368 100644 (file)
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(const_fn)]
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(min_const_fn))]
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
-#![feature(iterator_find_map)]
 #![cfg_attr(windows, feature(libc))]
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 #![feature(never_type)]
 #![feature(exhaustive_patterns)]
 #![feature(extern_types)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(non_exhaustive)]
 #![feature(proc_macro_internals)]
 #![feature(quote)]
@@ -65,7 +66,6 @@
 #![feature(trace_macros)]
 #![feature(trusted_len)]
 #![feature(vec_remove_item)]
-#![feature(catch_expr)]
 #![feature(step_trait)]
 #![feature(integer_atomics)]
 #![feature(test)]
 extern crate byteorder;
 extern crate backtrace;
 
+#[macro_use]
+extern crate smallvec;
+
 // Note that librustc doesn't actually depend on these crates, see the note in
 // `Cargo.toml` for this crate about why these are here.
 #[allow(unused_extern_crates)]
index 015f755e97d161ae235c3cb560c48d5054337f90..6783415619f983c1bdd3b0808d913b69c2cb1a72 100644 (file)
      via the module system"
 }
 
+declare_lint! {
+    pub MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
+    Deny,
+    "macro-expanded `macro_export` macros from the current crate \
+     cannot be referred to by absolute paths"
+}
+
 /// Some lints that are buffered from `libsyntax`. See `syntax::early_buffered_lints`.
 pub mod parser {
     declare_lint! {
@@ -398,6 +405,7 @@ fn get_lints(&self) -> LintArray {
             WHERE_CLAUSES_OBJECT_SAFETY,
             PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
             MACRO_USE_EXTERN_CRATE,
+            MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
             parser::QUESTION_MARK_MACRO_SEP,
         )
     }
@@ -412,6 +420,7 @@ pub enum BuiltinLintDiagnostics {
     AbsPathWithModule(Span),
     DuplicatedMacroExports(ast::Ident, Span, Span),
     ProcMacroDeriveResolutionFallback(Span),
+    MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
     ElidedLifetimesInPaths(usize, Span, bool, Span, String),
 }
 
@@ -453,6 +462,9 @@ pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder) {
                 db.span_label(span, "names from parent modules are not \
                                      accessible without an explicit import");
             }
+            BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
+                db.span_note(span_def, "the macro is defined here");
+            }
             BuiltinLintDiagnostics::ElidedLifetimesInPaths(
                 n, path_span, incl_angl_brckt, insertion_span, anon_lts
             ) => {
index 315ed38ad07703fc14566a3efe808490d6253826..d5247b4ce9de85b68b7543ed19dafa09e656cc46 100644 (file)
@@ -67,9 +67,10 @@ pub struct LintStore {
     /// Lints indexed by name.
     by_name: FxHashMap<String, TargetLint>,
 
-    /// Map of registered lint groups to what lints they expand to. The bool
-    /// is true if the lint group was added by a plugin.
-    lint_groups: FxHashMap<&'static str, (Vec<LintId>, bool)>,
+    /// Map of registered lint groups to what lints they expand to. The first
+    /// bool is true if the lint group was added by a plugin. The optional string
+    /// is used to store the new names of deprecated lint group names.
+    lint_groups: FxHashMap<&'static str, (Vec<LintId>, bool, Option<&'static str>)>,
 
     /// Extra info for future incompatibility lints, describing the
     /// issue or RFC that caused the incompatibility.
@@ -138,7 +139,7 @@ pub enum CheckLintNameResult<'a> {
     /// compiled with the tool and therefore the lint was never
     /// added to the `LintStore`. Otherwise the `LintId` will be
     /// returned as if it where a rustc lint.
-    Tool(Option<&'a [LintId]>),
+    Tool(Result<&'a [LintId], (Option<&'a [LintId]>, String)>),
 }
 
 impl LintStore {
@@ -221,7 +222,7 @@ pub fn register_future_incompatible(&mut self,
             let lints = lints.iter().filter(|f| f.edition == Some(*edition)).map(|f| f.id)
                              .collect::<Vec<_>>();
             if !lints.is_empty() {
-                self.register_group(sess, false, edition.lint_name(), lints)
+                self.register_group(sess, false, edition.lint_name(), None, lints)
             }
         }
 
@@ -231,19 +232,35 @@ pub fn register_future_incompatible(&mut self,
             self.future_incompatible.insert(lint.id, lint);
         }
 
-        self.register_group(sess, false, "future_incompatible", future_incompatible);
-
-
+        self.register_group(
+            sess,
+            false,
+            "future_incompatible",
+            None,
+            future_incompatible,
+        );
     }
 
     pub fn future_incompatible(&self, id: LintId) -> Option<&FutureIncompatibleInfo> {
         self.future_incompatible.get(&id)
     }
 
-    pub fn register_group(&mut self, sess: Option<&Session>,
-                          from_plugin: bool, name: &'static str,
-                          to: Vec<LintId>) {
-        let new = self.lint_groups.insert(name, (to, from_plugin)).is_none();
+    pub fn register_group(
+        &mut self,
+        sess: Option<&Session>,
+        from_plugin: bool,
+        name: &'static str,
+        deprecated_name: Option<&'static str>,
+        to: Vec<LintId>,
+    ) {
+        let new = self
+            .lint_groups
+            .insert(name, (to, from_plugin, None))
+            .is_none();
+        if let Some(deprecated) = deprecated_name {
+            self.lint_groups
+                .insert(deprecated, (vec![], from_plugin, Some(name)));
+        }
 
         if !new {
             let msg = format!("duplicate specification of lint group {}", name);
@@ -336,13 +353,14 @@ pub fn check_lint_name(
         } else {
             lint_name.to_string()
         };
+        // If the lint was scoped with `tool::` check if the tool lint exists
         if let Some(_) = tool_name {
             match self.by_name.get(&complete_name) {
                 None => match self.lint_groups.get(&*complete_name) {
-                    None => return CheckLintNameResult::Tool(None),
-                    Some(ids) => return CheckLintNameResult::Tool(Some(&ids.0)),
+                    None => return CheckLintNameResult::Tool(Err((None, String::new()))),
+                    Some(ids) => return CheckLintNameResult::Tool(Ok(&ids.0)),
                 },
-                Some(&Id(ref id)) => return CheckLintNameResult::Tool(Some(slice::from_ref(id))),
+                Some(&Id(ref id)) => return CheckLintNameResult::Tool(Ok(slice::from_ref(id))),
                 // If the lint was registered as removed or renamed by the lint tool, we don't need
                 // to treat tool_lints and rustc lints different and can use the code below.
                 _ => {}
@@ -350,20 +368,64 @@ pub fn check_lint_name(
         }
         match self.by_name.get(&complete_name) {
             Some(&Renamed(ref new_name, _)) => CheckLintNameResult::Warning(
-                format!("lint `{}` has been renamed to `{}`", lint_name, new_name),
+                format!(
+                    "lint `{}` has been renamed to `{}`",
+                    complete_name, new_name
+                ),
                 Some(new_name.to_owned()),
             ),
             Some(&Removed(ref reason)) => CheckLintNameResult::Warning(
-                format!("lint `{}` has been removed: `{}`", lint_name, reason),
+                format!("lint `{}` has been removed: `{}`", complete_name, reason),
                 None,
             ),
             None => match self.lint_groups.get(&*complete_name) {
-                None => CheckLintNameResult::NoLint,
-                Some(ids) => CheckLintNameResult::Ok(&ids.0),
+                // If neither the lint, nor the lint group exists check if there is a `clippy::`
+                // variant of this lint
+                None => self.check_tool_name_for_backwards_compat(&complete_name, "clippy"),
+                Some(ids) => {
+                    // Check if the lint group name is deprecated
+                    if let Some(new_name) = ids.2 {
+                        let lint_ids = self.lint_groups.get(new_name).unwrap();
+                        return CheckLintNameResult::Tool(Err((
+                            Some(&lint_ids.0),
+                            new_name.to_string(),
+                        )));
+                    }
+                    CheckLintNameResult::Ok(&ids.0)
+                }
             },
             Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::from_ref(id)),
         }
     }
+
+    fn check_tool_name_for_backwards_compat(
+        &self,
+        lint_name: &str,
+        tool_name: &str,
+    ) -> CheckLintNameResult {
+        let complete_name = format!("{}::{}", tool_name, lint_name);
+        match self.by_name.get(&complete_name) {
+            None => match self.lint_groups.get(&*complete_name) {
+                // Now we are sure, that this lint exists nowhere
+                None => CheckLintNameResult::NoLint,
+                Some(ids) => {
+                    // Reaching this would be weird, but lets cover this case anyway
+                    if let Some(new_name) = ids.2 {
+                        let lint_ids = self.lint_groups.get(new_name).unwrap();
+                        return CheckLintNameResult::Tool(Err((
+                            Some(&lint_ids.0),
+                            new_name.to_string(),
+                        )));
+                    }
+                    CheckLintNameResult::Tool(Err((Some(&ids.0), complete_name)))
+                }
+            },
+            Some(&Id(ref id)) => {
+                CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name)))
+            }
+            _ => CheckLintNameResult::NoLint,
+        }
+    }
 }
 
 /// Context for lint checking after type checking.
@@ -1046,7 +1108,7 @@ fn visit_mac_def(&mut self, mac: &'a ast::MacroDef, id: ast::NodeId) {
         self.check_id(id);
     }
 
-    fn visit_mac(&mut self, mac: &'ast ast::Mac) {
+    fn visit_mac(&mut self, mac: &'a ast::Mac) {
         run_lints!(self, check_mac, mac);
     }
 }
index 5b9ddabf21c1b36fa16681c5ba1eb72c73046338..336ebe79d33abd7276eb6d20f6f427be9f82b04b 100644 (file)
@@ -231,12 +231,13 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                     let gate_feature = !self.sess.features_untracked().tool_lints;
                     let known_tool = attr::is_known_lint_tool(lint_tool);
                     if gate_feature {
-                        feature_gate::emit_feature_err(&sess.parse_sess,
-                                                       "tool_lints",
-                                                       word.span,
-                                                       feature_gate::GateIssue::Language,
-                                                       &format!("scoped lint `{}` is experimental",
-                                                                word.ident));
+                        feature_gate::emit_feature_err(
+                            &sess.parse_sess,
+                            "tool_lints",
+                            word.span,
+                            feature_gate::GateIssue::Language,
+                            &format!("scoped lint `{}` is experimental", word.ident),
+                        );
                     }
                     if !known_tool {
                         span_err!(
@@ -249,7 +250,7 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                     }
 
                     if gate_feature || !known_tool {
-                        continue
+                        continue;
                     }
 
                     Some(lint_tool.as_str())
@@ -266,17 +267,52 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                     }
 
                     CheckLintNameResult::Tool(result) => {
-                        if let Some(ids) = result {
-                            let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
-                            let src = LintSource::Node(Symbol::intern(complete_name), li.span);
-                            for id in ids {
-                                specs.insert(*id, (level, src));
+                        match result {
+                            Ok(ids) => {
+                                let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
+                                let src = LintSource::Node(Symbol::intern(complete_name), li.span);
+                                for id in ids {
+                                    specs.insert(*id, (level, src));
+                                }
+                            }
+                            Err((Some(ids), new_lint_name)) => {
+                                let lint = builtin::RENAMED_AND_REMOVED_LINTS;
+                                let (lvl, src) =
+                                    self.sets
+                                        .get_lint_level(lint, self.cur, Some(&specs), &sess);
+                                let msg = format!(
+                                    "lint name `{}` is deprecated \
+                                     and may not have an effect in the future. \
+                                     Also `cfg_attr(cargo-clippy)` won't be necessary anymore",
+                                    name
+                                );
+                                let mut err = lint::struct_lint_level(
+                                    self.sess,
+                                    lint,
+                                    lvl,
+                                    src,
+                                    Some(li.span.into()),
+                                    &msg,
+                                );
+                                err.span_suggestion_with_applicability(
+                                    li.span,
+                                    "change it to",
+                                    new_lint_name.to_string(),
+                                    Applicability::MachineApplicable,
+                                ).emit();
+
+                                let src = LintSource::Node(Symbol::intern(&new_lint_name), li.span);
+                                for id in ids {
+                                    specs.insert(*id, (level, src));
+                                }
+                            }
+                            Err((None, _)) => {
+                                // If Tool(Err(None, _)) is returned, then either the lint does not
+                                // exist in the tool or the code was not compiled with the tool and
+                                // therefore the lint was never added to the `LintStore`. To detect
+                                // this is the responsibility of the lint tool.
                             }
                         }
-                        // If Tool(None) is returned, then either the lint does not exist in the
-                        // tool or the code was not compiled with the tool and therefore the lint
-                        // was never added to the `LintStore`. To detect this is the responsibility
-                        // of the lint tool.
                     }
 
                     _ if !self.warn_about_weird_lints => {}
index 5872440c36250c9148e1930b7ac25a6d7f0e00b0..cc0548c0dffcd4acc3eadea3caff5b8112665356 100644 (file)
@@ -266,7 +266,7 @@ fn check_struct_def_post(
 
 macro_rules! expand_lint_pass_methods {
     ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
-        $(#[inline(always)] fn $name(&mut self, $context, $(_: $arg),*) {})*
+        $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
     )
 }
 
index b91a9644b211a3a73d3bc75c917c3c9978b78443..f4b44043389615d2c2540f4b692bf198ae3bd2c3 100644 (file)
 
 // lonely orphan structs and enums looking for a better home
 
-#[derive(Clone, Debug, Copy)]
-pub struct LinkMeta {
-    pub crate_hash: Svh,
-}
-
 /// Where a crate came from on the local filesystem. One of these three options
 /// must be non-None.
 #[derive(PartialEq, Clone, Debug)]
@@ -233,8 +228,7 @@ pub trait CrateStore {
 
     // utility functions
     fn encode_metadata<'a, 'tcx>(&self,
-                                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                 link_meta: &LinkMeta)
+                                 tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                  -> EncodedMetadata;
     fn metadata_encoding_version(&self) -> &[u8];
 }
index 8c4c54ec954d0d946367c1852c09a17234d49b6d..d320173f9f47d01d95361323f5e58db16819f902 100644 (file)
@@ -12,7 +12,7 @@
 // closely. The idea is that all reachable symbols are live, codes called
 // from live codes are live, and everything else is dead.
 
-use hir::map as hir_map;
+use hir::Node;
 use hir::{self, PatKind};
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use hir::itemlikevisit::ItemLikeVisitor;
 use syntax_pos;
 
 // Any local node that may call something in its body block should be
-// explored. For example, if it's a live NodeItem that is a
+// explored. For example, if it's a live Node::Item that is a
 // function, then we should explore its block to check for codes that
 // may need to be marked as live.
 fn should_explore<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             node_id: ast::NodeId) -> bool {
     match tcx.hir.find(node_id) {
-        Some(hir_map::NodeItem(..)) |
-        Some(hir_map::NodeImplItem(..)) |
-        Some(hir_map::NodeForeignItem(..)) |
-        Some(hir_map::NodeTraitItem(..)) =>
+        Some(Node::Item(..)) |
+        Some(Node::ImplItem(..)) |
+        Some(Node::ForeignItem(..)) |
+        Some(Node::TraitItem(..)) =>
             true,
         _ =>
             false
@@ -105,11 +105,11 @@ fn lookup_and_handle_method(&mut self, id: hir::HirId) {
 
     fn handle_field_access(&mut self, lhs: &hir::Expr, node_id: ast::NodeId) {
         match self.tables.expr_ty_adjusted(lhs).sty {
-            ty::TyAdt(def, _) => {
+            ty::Adt(def, _) => {
                 let index = self.tcx.field_index(node_id, self.tables);
                 self.insert_def_id(def.non_enum_variant().fields[index].did);
             }
-            ty::TyTuple(..) => {}
+            ty::Tuple(..) => {}
             _ => span_bug!(lhs.span, "named field access on non-ADT"),
         }
     }
@@ -117,7 +117,7 @@ fn handle_field_access(&mut self, lhs: &hir::Expr, node_id: ast::NodeId) {
     fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, def: Def,
                                   pats: &[source_map::Spanned<hir::FieldPat>]) {
         let variant = match self.tables.node_id_to_type(lhs.hir_id).sty {
-            ty::TyAdt(adt, _) => adt.variant_of_def(def),
+            ty::Adt(adt, _) => adt.variant_of_def(def),
             _ => span_bug!(lhs.span, "non-ADT in struct pattern")
         };
         for pat in pats {
@@ -145,13 +145,13 @@ fn mark_live_symbols(&mut self) {
         }
     }
 
-    fn visit_node(&mut self, node: &hir_map::Node<'tcx>) {
+    fn visit_node(&mut self, node: &Node<'tcx>) {
         let had_repr_c = self.repr_has_repr_c;
         self.repr_has_repr_c = false;
         let had_inherited_pub_visibility = self.inherited_pub_visibility;
         self.inherited_pub_visibility = false;
         match *node {
-            hir_map::NodeItem(item) => {
+            Node::Item(item) => {
                 match item.node {
                     hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
                         let def_id = self.tcx.hir.local_def_id(item.id);
@@ -173,13 +173,13 @@ fn visit_node(&mut self, node: &hir_map::Node<'tcx>) {
                     _ => ()
                 }
             }
-            hir_map::NodeTraitItem(trait_item) => {
+            Node::TraitItem(trait_item) => {
                 intravisit::walk_trait_item(self, trait_item);
             }
-            hir_map::NodeImplItem(impl_item) => {
+            Node::ImplItem(impl_item) => {
                 intravisit::walk_impl_item(self, impl_item);
             }
-            hir_map::NodeForeignItem(foreign_item) => {
+            Node::ForeignItem(foreign_item) => {
                 intravisit::walk_foreign_item(self, &foreign_item);
             }
             _ => ()
@@ -236,7 +236,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
                 self.handle_field_access(&lhs, expr.id);
             }
             hir::ExprKind::Struct(_, ref fields, _) => {
-                if let ty::TypeVariants::TyAdt(ref adt, _) = self.tables.expr_ty(expr).sty {
+                if let ty::Adt(ref adt, _) = self.tables.expr_ty(expr).sty {
                     self.mark_as_used_if_union(adt, fields);
                 }
             }
@@ -293,7 +293,9 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt,
     }
 
     // (To be) stable attribute for #[lang = "panic_impl"]
-    if attr::contains_name(attrs, "panic_implementation") {
+    if attr::contains_name(attrs, "panic_implementation") ||
+        attr::contains_name(attrs, "panic_handler")
+    {
         return true;
     }
 
index 705237aa832f0bc422aa1d3a8bde140a4145abf5..356992b22146d67b02d63c409b07787c93b46774 100644 (file)
@@ -457,7 +457,7 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) {
                 // make sure that the thing we are pointing out stays valid
                 // for the lifetime `scope_r` of the resulting ptr:
                 let expr_ty = return_if_err!(self.mc.expr_ty(expr));
-                if let ty::TyRef(r, _, _) = expr_ty.sty {
+                if let ty::Ref(r, _, _) = expr_ty.sty {
                     let bk = ty::BorrowKind::from_mutbl(m);
                     self.borrow_expr(&base, r, bk, AddrOf);
                 }
@@ -551,10 +551,10 @@ fn walk_callee(&mut self, call: &hir::Expr, callee: &hir::Expr) {
         debug!("walk_callee: callee={:?} callee_ty={:?}",
                callee, callee_ty);
         match callee_ty.sty {
-            ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+            ty::FnDef(..) | ty::FnPtr(_) => {
                 self.consume_expr(callee);
             }
-            ty::TyError => { }
+            ty::Error => { }
             _ => {
                 if let Some(def) = self.mc.tables.type_dependent_defs().get(call.hir_id) {
                     let def_id = def.def_id();
@@ -659,7 +659,7 @@ fn walk_struct_expr(&mut self,
         // Select just those fields of the `with`
         // expression that will actually be used
         match with_cmt.ty.sty {
-            ty::TyAdt(adt, substs) if adt.is_struct() => {
+            ty::Adt(adt, substs) if adt.is_struct() => {
                 // Consume those fields of the with expression that are needed.
                 for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() {
                     let is_mentioned = fields.iter().any(|f| {
@@ -869,7 +869,7 @@ fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: Mat
                     // It is also a borrow or copy/move of the value being matched.
                     match bm {
                         ty::BindByReference(m) => {
-                            if let ty::TyRef(r, _, _) = pat_ty.sty {
+                            if let ty::Ref(r, _, _) = pat_ty.sty {
                                 let bk = ty::BorrowKind::from_mutbl(m);
                                 delegate.borrow(pat.id, pat.span, &cmt_pat, r, bk, RefBinding);
                             }
index 8e4fb547d41642e2e9155aeecb057770912966d9..8058f3dde668d8fd23f44eef940ecb1f15b929ed 100644 (file)
@@ -41,7 +41,7 @@ fn unpack_option_like<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 ty: Ty<'tcx>)
                                 -> Ty<'tcx> {
     let (def, substs) = match ty.sty {
-        ty::TyAdt(def, substs) => (def, substs),
+        ty::Adt(def, substs) => (def, substs),
         _ => return ty
     };
 
@@ -83,7 +83,7 @@ fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) {
             // Special-case transmutting from `typeof(function)` and
             // `Option<typeof(function)>` to present a clearer error.
             let from = unpack_option_like(self.tcx.global_tcx(), from);
-            if let (&ty::TyFnDef(..), SizeSkeleton::Known(size_to)) = (&from.sty, sk_to) {
+            if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (&from.sty, sk_to) {
                 if size_to == Pointer.size(self.tcx) {
                     struct_span_err!(self.tcx.sess, span, E0591,
                                      "can't transmute zero-sized type")
index cf94a0fb4b4ba618b59c3cabc2400c1fcd39a59f..d92f856fa4dbff90445e78b1276bd011d5255b9b 100644 (file)
@@ -185,7 +185,9 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
             if let Some(value) = attribute.value_str() {
                 return Some((value, attribute.span));
             }
-        } else if attribute.check_name("panic_implementation") {
+        } else if attribute.check_name("panic_implementation") ||
+            attribute.check_name("panic_handler")
+        {
             return Some((Symbol::intern("panic_impl"), attribute.span))
         } else if attribute.check_name("alloc_error_handler") {
             return Some((Symbol::intern("oom"), attribute.span))
@@ -305,6 +307,8 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
     PanicBoundsCheckFnLangItem,      "panic_bounds_check",      panic_bounds_check_fn;
     PanicInfoLangItem,               "panic_info",              panic_info;
     PanicImplLangItem,               "panic_impl",              panic_impl;
+    // Libstd panic entry point. Necessary for const eval to be able to catch it
+    BeginPanicFnLangItem,            "begin_panic",             begin_panic_fn;
 
     ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
     BoxFreeFnLangItem,               "box_free",                box_free_fn;
index c21ac6218031df84f321d082e792494a93c559e3..ec618de677318a613953bb3283ad4a7a9a35164d 100644 (file)
@@ -17,7 +17,7 @@
 use ty::TyCtxt;
 use syntax::symbol::Symbol;
 use syntax::ast::{Attribute, MetaItem, MetaItemKind};
-use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::Span;
 use hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use errors::DiagnosticId;
@@ -152,11 +152,6 @@ fn visit_attribute(&mut self, attr: &'tcx Attribute) {
 
 pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LibFeatures {
     let mut collector = LibFeatureCollector::new(tcx);
-    for &cnum in tcx.crates().iter() {
-        for &(feature, since) in tcx.defined_lib_features(cnum).iter() {
-            collector.collect_feature(feature, since, DUMMY_SP);
-        }
-    }
     intravisit::walk_crate(&mut collector, tcx.hir.krate());
     collector.lib_features
 }
index 9850e2e8b1c577163d1c90eab4c6e36b9227cb56..c34a0a654e6a9f7c1964b39b3fa0c4e411391010 100644 (file)
 //!   only dead if the end of the function's block can never be reached.
 //!   It is the responsibility of typeck to ensure that there are no
 //!   `return` expressions in a function declared as diverging.
+
 use self::LoopKind::*;
 use self::LiveNodeKind::*;
 use self::VarKind::*;
 
 use hir::def::*;
+use hir::Node;
 use ty::{self, TyCtxt};
 use lint;
 use errors::Applicability;
@@ -362,7 +364,7 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
     // Don't run unused pass for #[derive()]
     if let FnKind::Method(..) = fk {
         let parent = ir.tcx.hir.get_parent(id);
-        if let Some(hir::map::Node::NodeItem(i)) = ir.tcx.hir.find(parent) {
+        if let Some(Node::Item(i)) = ir.tcx.hir.find(parent) {
             if i.attrs.iter().any(|a| a.check_name("automatically_derived")) {
                 return;
             }
index 8feefdf5a1ddb3b1c11f974191c2faedf3f16958..b63cde0f205f78031363d851a4e6d718291f8620 100644 (file)
@@ -70,7 +70,7 @@
 
 use middle::region;
 use hir::def_id::{DefId, LocalDefId};
-use hir::map as hir_map;
+use hir::Node;
 use infer::InferCtxt;
 use hir::def::{Def, CtorKind};
 use ty::adjustment;
@@ -214,8 +214,8 @@ impl<'tcx> cmt_<'tcx> {
     fn resolve_field(&self, field_index: usize) -> Option<(&'tcx ty::AdtDef, &'tcx ty::FieldDef)>
     {
         let adt_def = match self.ty.sty {
-            ty::TyAdt(def, _) => def,
-            ty::TyTuple(..) => return None,
+            ty::Adt(def, _) => def,
+            ty::Tuple(..) => return None,
             // closures get `Categorization::Upvar` rather than `Categorization::Interior`
             _ =>  bug!("interior cmt {:?} is not an ADT", self)
         };
@@ -343,7 +343,7 @@ fn from_pointer_kind(base_mutbl: MutabilityCategory,
 
     fn from_local(tcx: TyCtxt, tables: &ty::TypeckTables, id: ast::NodeId) -> MutabilityCategory {
         let ret = match tcx.hir.get(id) {
-            hir_map::NodeBinding(p) => match p.node {
+            Node::Binding(p) => match p.node {
                 PatKind::Binding(..) => {
                     let bm = *tables.pat_binding_modes()
                                     .get(p.hir_id)
@@ -783,8 +783,8 @@ fn cat_upvar(&self,
         // FnOnce         | copied               | upvar -> &'up bk
 
         let kind = match self.node_ty(fn_hir_id)?.sty {
-            ty::TyGenerator(..) => ty::ClosureKind::FnOnce,
-            ty::TyClosure(closure_def_id, closure_substs) => {
+            ty::Generator(..) => ty::ClosureKind::FnOnce,
+            ty::Closure(closure_def_id, closure_substs) => {
                 match self.infcx {
                     // During upvar inference we may not know the
                     // closure kind, just use the LATTICE_BOTTOM value.
@@ -893,7 +893,7 @@ fn env_deref(&self,
         // that the above is actually immutable and
         // has a ref type.  However, nothing should
         // actually look at the type, so we can get
-        // away with stuffing a `TyError` in there
+        // away with stuffing a `Error` in there
         // instead of bothering to construct a proper
         // one.
         let cmt_result = cmt_ {
@@ -956,7 +956,7 @@ pub fn cat_rvalue_node(&self,
 
         // Always promote `[T; 0]` (even when e.g. borrowed mutably).
         let promotable = match expr_ty.sty {
-            ty::TyArray(_, len) if len.assert_usize(self.tcx) == Some(0) => true,
+            ty::Array(_, len) if len.assert_usize(self.tcx) == Some(0) => true,
             _ => promotable,
         };
 
@@ -1035,7 +1035,7 @@ fn cat_overloaded_place(
         let base_ty = self.expr_ty_adjusted(base)?;
 
         let (region, mutbl) = match base_ty.sty {
-            ty::TyRef(region, _, mutbl) => (region, mutbl),
+            ty::Ref(region, _, mutbl) => (region, mutbl),
             _ => {
                 span_bug!(expr.span, "cat_overloaded_place: base is not a reference")
             }
@@ -1068,9 +1068,9 @@ pub fn cat_deref(
         };
 
         let ptr = match base_cmt.ty.sty {
-            ty::TyAdt(def, ..) if def.is_box() => Unique,
-            ty::TyRawPtr(ref mt) => UnsafePtr(mt.mutbl),
-            ty::TyRef(r, _, mutbl) => {
+            ty::Adt(def, ..) if def.is_box() => Unique,
+            ty::RawPtr(ref mt) => UnsafePtr(mt.mutbl),
+            ty::Ref(r, _, mutbl) => {
                 let bk = ty::BorrowKind::from_mutbl(mutbl);
                 BorrowedPtr(bk, r)
             }
@@ -1290,7 +1290,7 @@ fn cat_pattern_<F>(&self, mut cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McR
                 }
                 Def::StructCtor(_, CtorKind::Fn) => {
                     match self.pat_ty_unadjusted(&pat)?.sty {
-                        ty::TyAdt(adt_def, _) => {
+                        ty::Adt(adt_def, _) => {
                             (cmt, adt_def.non_enum_variant().fields.len())
                         }
                         ref ty => {
@@ -1343,7 +1343,7 @@ fn cat_pattern_<F>(&self, mut cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McR
           PatKind::Tuple(ref subpats, ddpos) => {
             // (p1, ..., pN)
             let expected_len = match self.pat_ty_unadjusted(&pat)?.sty {
-                ty::TyTuple(ref tys) => tys.len(),
+                ty::Tuple(ref tys) => tys.len(),
                 ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty),
             };
             for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
index e2de0b6bd013d939c4a002837f1c67bf3771de14..70fed9af92128367700c4fc9b8a8aebf84436cd7 100644 (file)
@@ -21,6 +21,8 @@
 // Accessibility levels, sorted in ascending order
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
 pub enum AccessLevel {
+    // Superset of Reachable used to mark impl Trait items.
+    ReachableFromImplTrait,
     // Exported items + items participating in various kinds of public interfaces,
     // but not directly nameable. For example, if function `fn f() -> T {...}` is
     // public, then type `T` is reachable. Its values can be obtained by other crates
@@ -40,7 +42,7 @@ pub struct AccessLevels<Id = NodeId> {
 
 impl<Id: Hash + Eq> AccessLevels<Id> {
     pub fn is_reachable(&self, id: Id) -> bool {
-        self.map.contains_key(&id)
+        self.map.get(&id) >= Some(&AccessLevel::Reachable)
     }
     pub fn is_exported(&self, id: Id) -> bool {
         self.map.get(&id) >= Some(&AccessLevel::Exported)
index 3d8bb6b825b38ec40e599a6086ae1d053c75e0a7..55ee8987e8ad54ccbe49313878ef403d7888e3b8 100644 (file)
@@ -16,7 +16,7 @@
 // reachable as well.
 
 use hir::{CodegenFnAttrs, CodegenFnAttrFlags};
-use hir::map as hir_map;
+use hir::Node;
 use hir::def::Def;
 use hir::def_id::{DefId, CrateNum};
 use rustc_data_structures::sync::Lrc;
@@ -64,7 +64,7 @@ fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
     if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_src) {
         match tcx.hir.find(impl_node_id) {
-            Some(hir_map::NodeItem(item)) =>
+            Some(Node::Item(item)) =>
                 item_might_be_inlined(tcx, &item, codegen_fn_attrs),
             Some(..) | None =>
                 span_bug!(impl_item.span, "impl did is not an item")
@@ -156,14 +156,14 @@ fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
         };
 
         match self.tcx.hir.find(node_id) {
-            Some(hir_map::NodeItem(item)) => {
+            Some(Node::Item(item)) => {
                 match item.node {
                     hir::ItemKind::Fn(..) =>
                         item_might_be_inlined(self.tcx, &item, self.tcx.codegen_fn_attrs(def_id)),
                     _ => false,
                 }
             }
-            Some(hir_map::NodeTraitItem(trait_method)) => {
+            Some(Node::TraitItem(trait_method)) => {
                 match trait_method.node {
                     hir::TraitItemKind::Const(_, ref default) => default.is_some(),
                     hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => true,
@@ -171,7 +171,7 @@ fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
                     hir::TraitItemKind::Type(..) => false,
                 }
             }
-            Some(hir_map::NodeImplItem(impl_item)) => {
+            Some(Node::ImplItem(impl_item)) => {
                 match impl_item.node {
                     hir::ImplItemKind::Const(..) => true,
                     hir::ImplItemKind::Method(..) => {
@@ -219,20 +219,23 @@ fn propagate(&mut self) {
         }
     }
 
-    fn propagate_node(&mut self, node: &hir_map::Node<'tcx>,
+    fn propagate_node(&mut self, node: &Node<'tcx>,
                       search_item: ast::NodeId) {
         if !self.any_library {
             // If we are building an executable, only explicitly extern
             // types need to be exported.
-            if let hir_map::NodeItem(item) = *node {
+            if let Node::Item(item) = *node {
                 let reachable = if let hir::ItemKind::Fn(_, header, ..) = item.node {
                     header.abi != Abi::Rust
                 } else {
                     false
                 };
                 let def_id = self.tcx.hir.local_def_id(item.id);
-                let is_extern = self.tcx.codegen_fn_attrs(def_id).contains_extern_indicator();
-                if reachable || is_extern {
+                let codegen_attrs = self.tcx.codegen_fn_attrs(def_id);
+                let is_extern = codegen_attrs.contains_extern_indicator();
+                let std_internal = codegen_attrs.flags.contains(
+                    CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
+                if reachable || is_extern || std_internal {
                     self.reachable_symbols.insert(search_item);
                 }
             }
@@ -245,7 +248,7 @@ fn propagate_node(&mut self, node: &hir_map::Node<'tcx>,
         }
 
         match *node {
-            hir_map::NodeItem(item) => {
+            Node::Item(item) => {
                 match item.node {
                     hir::ItemKind::Fn(.., body) => {
                         let def_id = self.tcx.hir.local_def_id(item.id);
@@ -282,7 +285,7 @@ fn propagate_node(&mut self, node: &hir_map::Node<'tcx>,
                     hir::ItemKind::GlobalAsm(..) => {}
                 }
             }
-            hir_map::NodeTraitItem(trait_method) => {
+            Node::TraitItem(trait_method) => {
                 match trait_method.node {
                     hir::TraitItemKind::Const(_, None) |
                     hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => {
@@ -295,7 +298,7 @@ fn propagate_node(&mut self, node: &hir_map::Node<'tcx>,
                     hir::TraitItemKind::Type(..) => {}
                 }
             }
-            hir_map::NodeImplItem(impl_item) => {
+            Node::ImplItem(impl_item) => {
                 match impl_item.node {
                     hir::ImplItemKind::Const(_, body) => {
                         self.visit_nested_body(body);
@@ -310,16 +313,16 @@ fn propagate_node(&mut self, node: &hir_map::Node<'tcx>,
                     hir::ImplItemKind::Type(_) => {}
                 }
             }
-            hir_map::NodeExpr(&hir::Expr { node: hir::ExprKind::Closure(.., body, _, _), .. }) => {
+            Node::Expr(&hir::Expr { node: hir::ExprKind::Closure(.., body, _, _), .. }) => {
                 self.visit_nested_body(body);
             }
             // Nothing to recurse on for these
-            hir_map::NodeForeignItem(_) |
-            hir_map::NodeVariant(_) |
-            hir_map::NodeStructCtor(_) |
-            hir_map::NodeField(_) |
-            hir_map::NodeTy(_) |
-            hir_map::NodeMacroDef(_) => {}
+            Node::ForeignItem(_) |
+            Node::Variant(_) |
+            Node::StructCtor(_) |
+            Node::Field(_) |
+            Node::Ty(_) |
+            Node::MacroDef(_) => {}
             _ => {
                 bug!("found unexpected thingy in worklist: {}",
                      self.tcx.hir.node_to_string(search_item))
@@ -434,6 +437,8 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) ->
     // Step 2: Mark all symbols that the symbols on the worklist touch.
     reachable_context.propagate();
 
+    debug!("Inline reachability shows: {:?}", reachable_context.reachable_symbols);
+
     // Return the set of reachable symbols.
     ReachableSet(Lrc::new(reachable_context.reachable_symbols))
 }
index 5302bc806c721d55ca7e36f8be7f38fba7a0b53a..e281cbf94889394198e3e8e5d982b70b43bfab81 100644 (file)
@@ -30,6 +30,7 @@
 use ty::query::Providers;
 
 use hir;
+use hir::Node;
 use hir::def_id::DefId;
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local};
@@ -257,7 +258,7 @@ pub fn span(&self, tcx: TyCtxt, scope_tree: &ScopeTree) -> Span {
         }
         let span = tcx.hir.span(node_id);
         if let ScopeData::Remainder(r) = self.data() {
-            if let hir::map::NodeBlock(ref blk) = tcx.hir.get(node_id) {
+            if let Node::Block(ref blk) = tcx.hir.get(node_id) {
                 // Want span for scope starting after the
                 // indexed statement and ending at end of
                 // `blk`; reuse span of `blk` and shift `lo`
@@ -1422,8 +1423,8 @@ fn region_scope_tree<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
         // record its impl/trait parent, as it can also have
         // lifetime parameters free in this body.
         match tcx.hir.get(id) {
-            hir::map::NodeImplItem(_) |
-            hir::map::NodeTraitItem(_) => {
+            Node::ImplItem(_) |
+            Node::TraitItem(_) => {
                 visitor.scope_tree.root_parent = Some(tcx.hir.get_parent(id));
             }
             _ => {}
index 379f4df11fa7b4881da1c7b488278bb6350b4262..d0f801e661b438d56bbff0798e8768a27b450e86 100644 (file)
@@ -18,7 +18,7 @@
 use hir::def::Def;
 use hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use hir::map::Map;
-use hir::{GenericArg, GenericParam, ItemLocalId, LifetimeName, ParamName};
+use hir::{GenericArg, GenericParam, ItemLocalId, LifetimeName, ParamName, Node};
 use ty::{self, TyCtxt, GenericParamDefKind};
 
 use errors::DiagnosticBuilder;
@@ -1440,10 +1440,10 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
                     let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
                     debug!("node id first={:?}", node_id);
                     if let Some((id, span, name)) = match self.tcx.hir.get(node_id) {
-                        hir::map::NodeLifetime(hir_lifetime) => {
+                        Node::Lifetime(hir_lifetime) => {
                             Some((hir_lifetime.id, hir_lifetime.span, hir_lifetime.name.ident()))
                         }
-                        hir::map::NodeGenericParam(param) => {
+                        Node::GenericParam(param) => {
                             Some((param.id, param.span, param.name.ident()))
                         }
                         _ => None,
@@ -1466,10 +1466,10 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
                 None => {
                     let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
                     if let Some((id, span, name)) = match self.tcx.hir.get(node_id) {
-                        hir::map::NodeLifetime(hir_lifetime) => {
+                        Node::Lifetime(hir_lifetime) => {
                             Some((hir_lifetime.id, hir_lifetime.span, hir_lifetime.name.ident()))
                         }
-                        hir::map::NodeGenericParam(param) => {
+                        Node::GenericParam(param) => {
                             Some((param.id, param.span, param.name.ident()))
                         }
                         _ => None,
@@ -1643,15 +1643,15 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
             } else if let Some(body_id) = outermost_body {
                 let fn_id = self.tcx.hir.body_owner(body_id);
                 match self.tcx.hir.get(fn_id) {
-                    hir::map::NodeItem(&hir::Item {
+                    Node::Item(&hir::Item {
                         node: hir::ItemKind::Fn(..),
                         ..
                     })
-                    | hir::map::NodeTraitItem(&hir::TraitItem {
+                    | Node::TraitItem(&hir::TraitItem {
                         node: hir::TraitItemKind::Method(..),
                         ..
                     })
-                    | hir::map::NodeImplItem(&hir::ImplItem {
+                    | Node::ImplItem(&hir::ImplItem {
                         node: hir::ImplItemKind::Method(..),
                         ..
                     }) => {
@@ -1868,12 +1868,12 @@ fn visit_fn_like_elision(
         let parent = self.tcx.hir.get_parent_node(output.id);
         let body = match self.tcx.hir.get(parent) {
             // `fn` definitions and methods.
-            hir::map::NodeItem(&hir::Item {
+            Node::Item(&hir::Item {
                 node: hir::ItemKind::Fn(.., body),
                 ..
             }) => Some(body),
 
-            hir::map::NodeTraitItem(&hir::TraitItem {
+            Node::TraitItem(&hir::TraitItem {
                 node: hir::TraitItemKind::Method(_, ref m),
                 ..
             }) => {
@@ -1896,7 +1896,7 @@ fn visit_fn_like_elision(
                 }
             }
 
-            hir::map::NodeImplItem(&hir::ImplItem {
+            Node::ImplItem(&hir::ImplItem {
                 node: hir::ImplItemKind::Method(_, body),
                 ..
             }) => {
@@ -1918,7 +1918,7 @@ fn visit_fn_like_elision(
             }
 
             // Foreign functions, `fn(...) -> R` and `Trait(...) -> R` (both types and bounds).
-            hir::map::NodeForeignItem(_) | hir::map::NodeTy(_) | hir::map::NodeTraitRef(_) => None,
+            Node::ForeignItem(_) | Node::Ty(_) | Node::TraitRef(_) => None,
             // Everything else (only closures?) doesn't
             // actually enjoy elision in return types.
             _ => {
index efd568b03ab1f3a200d23a907ba65886a09ed0b2..f237c5b397bd5263722c7ab089f0760ac12a605f 100644 (file)
@@ -440,7 +440,7 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Index<'tcx> {
                     },
                     feature: Symbol::intern("rustc_private"),
                     rustc_depr: None,
-                    rustc_const_unstable: None,
+                    const_stability: None,
                 });
                 annotator.parent_stab = Some(stability);
             }
@@ -846,14 +846,34 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     remaining_lib_features.remove(&Symbol::intern("libc"));
     remaining_lib_features.remove(&Symbol::intern("test"));
 
-    for (feature, stable) in tcx.lib_features().to_vec() {
-        if let Some(since) = stable {
-            if let Some(span) = remaining_lib_features.get(&feature) {
-                // Warn if the user has enabled an already-stable lib feature.
-                unnecessary_stable_feature_lint(tcx, *span, feature, since);
+    let check_features =
+        |remaining_lib_features: &mut FxHashMap<_, _>, defined_features: &Vec<_>| {
+            for &(feature, since) in defined_features {
+                if let Some(since) = since {
+                    if let Some(span) = remaining_lib_features.get(&feature) {
+                        // Warn if the user has enabled an already-stable lib feature.
+                        unnecessary_stable_feature_lint(tcx, *span, feature, since);
+                    }
+                }
+                remaining_lib_features.remove(&feature);
+                if remaining_lib_features.is_empty() {
+                    break;
+                }
+            }
+        };
+
+    // We always collect the lib features declared in the current crate, even if there are
+    // no unknown features, because the collection also does feature attribute validation.
+    let local_defined_features = tcx.lib_features().to_vec();
+    if !remaining_lib_features.is_empty() {
+        check_features(&mut remaining_lib_features, &local_defined_features);
+
+        for &cnum in &*tcx.crates() {
+            if remaining_lib_features.is_empty() {
+                break;
             }
+            check_features(&mut remaining_lib_features, &tcx.defined_lib_features(cnum));
         }
-        remaining_lib_features.remove(&feature);
     }
 
     for (feature, span) in remaining_lib_features {
index e8431ce3e109b4d9505fd0d96acd225d0c29fb2b..cbf6722c0fd375dbcbfbac29a7dd1862098ef168 100644 (file)
@@ -13,6 +13,7 @@
 use session::config;
 use middle::lang_items;
 
+use rustc_data_structures::fx::FxHashSet;
 use rustc_target::spec::PanicStrategy;
 use syntax::ast;
 use syntax::symbol::Symbol;
@@ -23,8 +24,6 @@
 use hir;
 use ty::TyCtxt;
 
-use std::collections::HashSet;
-
 macro_rules! weak_lang_items {
     ($($name:ident, $item:ident, $sym:ident;)*) => (
 
@@ -101,7 +100,7 @@ fn verify<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return
     }
 
-    let mut missing = HashSet::new();
+    let mut missing = FxHashSet::default();
     for &cnum in tcx.crates().iter() {
         for &item in tcx.missing_lang_items(cnum).iter() {
             missing.insert(item);
@@ -113,7 +112,7 @@ fn verify<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            !whitelisted(tcx, lang_items::$item) &&
            items.$name().is_none() {
             if lang_items::$item == lang_items::PanicImplLangItem {
-                tcx.sess.err(&format!("`#[panic_implementation]` function required, \
+                tcx.sess.err(&format!("`#[panic_handler]` function required, \
                                         but not found"));
             } else if lang_items::$item == lang_items::OomLangItem {
                 tcx.sess.err(&format!("`#[alloc_error_handler]` function required, \
index 1e9584bc55bdf0f05e1f044f0db2d7be4899c876..84d55c84ce154b8e23dd643c5f571ca3e53c55d3 100644 (file)
@@ -1,9 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
 use std::{fmt, env};
 
 use mir;
-use ty::{FnSig, Ty, layout};
+use ty::{Ty, layout};
 use ty::layout::{Size, Align};
 use rustc_data_structures::sync::Lrc;
+use rustc_target::spec::abi::Abi;
 
 use super::{
     Pointer, Lock, AccessKind
@@ -17,6 +28,7 @@
 
 use syntax_pos::Span;
 use syntax::ast;
+use syntax::symbol::Symbol;
 
 pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>>;
 
@@ -171,7 +183,10 @@ pub enum EvalErrorKind<'tcx, O> {
     /// This variant is used by machines to signal their own errors that do not
     /// match an existing variant
     MachineError(String),
-    FunctionPointerTyMismatch(FnSig<'tcx>, FnSig<'tcx>),
+
+    FunctionAbiMismatch(Abi, Abi),
+    FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
+    FunctionArgCountMismatch,
     NoMirFor(String),
     UnterminatedCString(Pointer),
     DanglingPointerDeref,
@@ -179,7 +194,7 @@ pub enum EvalErrorKind<'tcx, O> {
     InvalidMemoryAccess,
     InvalidFunctionPointer,
     InvalidBool,
-    InvalidDiscriminant,
+    InvalidDiscriminant(u128),
     PointerOutOfBounds {
         ptr: Pointer,
         access: bool,
@@ -250,7 +265,12 @@ pub enum EvalErrorKind<'tcx, O> {
     HeapAllocZeroBytes,
     HeapAllocNonPowerOfTwoAlignment(u64),
     Unreachable,
-    Panic,
+    Panic {
+        msg: Symbol,
+        line: u32,
+        col: u32,
+        file: Symbol,
+    },
     ReadFromReturnPointer,
     PathNotFound(Vec<String>),
     UnimplementedTraitSelection,
@@ -274,8 +294,8 @@ pub fn description(&self) -> &str {
         use self::EvalErrorKind::*;
         match *self {
             MachineError(ref inner) => inner,
-            FunctionPointerTyMismatch(..) =>
-                "tried to call a function through a function pointer of a different type",
+            FunctionAbiMismatch(..) | FunctionArgMismatch(..) | FunctionArgCountMismatch =>
+                "tried to call a function through a function pointer of incompatible type",
             InvalidMemoryAccess =>
                 "tried to access memory through an invalid pointer",
             DanglingPointerDeref =>
@@ -286,7 +306,7 @@ pub fn description(&self) -> &str {
                 "tried to use a function pointer after offsetting it",
             InvalidBool =>
                 "invalid boolean value read",
-            InvalidDiscriminant =>
+            InvalidDiscriminant(..) =>
                 "invalid enum discriminant value read",
             PointerOutOfBounds { .. } =>
                 "pointer offset outside bounds of allocation",
@@ -309,7 +329,8 @@ pub fn description(&self) -> &str {
             ReadForeignStatic =>
                 "tried to read from foreign (extern) static",
             InvalidPointerMath =>
-                "attempted to do invalid arithmetic on pointers that would leak base addresses, e.g. comparing pointers into different allocations",
+                "attempted to do invalid arithmetic on pointers that would leak base addresses, \
+                e.g. comparing pointers into different allocations",
             ReadUndefBytes =>
                 "attempted to read undefined bytes",
             DeadLocal =>
@@ -363,14 +384,16 @@ pub fn description(&self) -> &str {
             Layout(_) =>
                 "rustc layout computation failed",
             UnterminatedCString(_) =>
-                "attempted to get length of a null terminated string, but no null found before end of allocation",
+                "attempted to get length of a null terminated string, but no null found before end \
+                of allocation",
             HeapAllocZeroBytes =>
                 "tried to re-, de- or allocate zero bytes on the heap",
             HeapAllocNonPowerOfTwoAlignment(_) =>
-                "tried to re-, de-, or allocate heap memory with alignment that is not a power of two",
+                "tried to re-, de-, or allocate heap memory with alignment that is not a power of \
+                two",
             Unreachable =>
                 "entered unreachable code",
-            Panic =>
+            Panic { .. } =>
                 "the evaluated program panicked",
             ReadFromReturnPointer =>
                 "tried to read from the return pointer",
@@ -429,8 +452,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                        kind, ptr, len, lock)
             }
             InvalidMemoryLockRelease { ptr, len, frame, ref lock } => {
-                write!(f, "frame {} tried to release memory write lock at {:?}, size {}, but cannot release lock {:?}",
-                       frame, ptr, len, lock)
+                write!(f, "frame {} tried to release memory write lock at {:?}, size {}, but \
+                       cannot release lock {:?}", frame, ptr, len, lock)
             }
             DeallocatedLockedMemory { ptr, ref lock } => {
                 write!(f, "tried to deallocate memory at {:?} in conflict with lock {:?}",
@@ -440,8 +463,15 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 write!(f, "type validation failed: {}", err)
             }
             NoMirFor(ref func) => write!(f, "no mir for `{}`", func),
-            FunctionPointerTyMismatch(sig, got) =>
-                write!(f, "tried to call a function with sig {} through a function pointer of type {}", sig, got),
+            FunctionAbiMismatch(caller_abi, callee_abi) =>
+                write!(f, "tried to call a function with ABI {:?} using caller ABI {:?}",
+                    callee_abi, caller_abi),
+            FunctionArgMismatch(caller_ty, callee_ty) =>
+                write!(f, "tried to call a function with argument of type {:?} \
+                           passing data of type {:?}",
+                    callee_ty, caller_ty),
+            FunctionArgCountMismatch =>
+                write!(f, "tried to call a function with incorrect number of arguments"),
             BoundsCheck { ref len, ref index } =>
                 write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index),
             ReallocatedWrongMemoryKind(ref old, ref new) =>
@@ -464,7 +494,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             MachineError(ref inner) =>
                 write!(f, "{}", inner),
             IncorrectAllocationInformation(size, size2, align, align2) =>
-                write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and align {}", size.bytes(), align.abi(), size2.bytes(), align2.abi()),
+                write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and \
+                       align {}", size.bytes(), align.abi(), size2.bytes(), align2.abi()),
+            Panic { ref msg, line, col, ref file } =>
+                write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col),
+            InvalidDiscriminant(val) =>
+                write!(f, "encountered invalid enum discriminant {}", val),
             _ => write!(f, "{}", self.description()),
         }
     }
index a0980b06230c8a05b4bdf5428e7962b1934ee81a..d40dbae09d2cb60f8b27420e38b9453aeb39ec21 100644 (file)
@@ -1,3 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
 //! An interpreter for MIR used in CTFE and by miri
 
 #[macro_export]
@@ -13,7 +23,7 @@ macro_rules! err {
     FrameInfo, ConstEvalResult,
 };
 
-pub use self::value::{Scalar, Value, ConstValue, ScalarMaybeUndef};
+pub use self::value::{Scalar, ConstValue, ScalarMaybeUndef};
 
 use std::fmt;
 use mir;
@@ -40,7 +50,8 @@ macro_rules! err {
 pub enum Lock {
     NoLock,
     WriteLock(DynamicLifetime),
-    /// This should never be empty -- that would be a read lock held and nobody there to release it...
+    /// This should never be empty -- that would be a read lock held and nobody
+    /// there to release it...
     ReadLock(Vec<DynamicLifetime>),
 }
 
@@ -74,9 +85,14 @@ pub struct GlobalId<'tcx> {
 pub trait PointerArithmetic: layout::HasDataLayout {
     // These are not supposed to be overridden.
 
+    #[inline(always)]
+    fn pointer_size(self) -> Size {
+        self.data_layout().pointer_size
+    }
+
     //// Trunace the given value to the pointer size; also return whether there was an overflow
     fn truncate_to_ptr(self, val: u128) -> (u64, bool) {
-        let max_ptr_plus_1 = 1u128 << self.data_layout().pointer_size.bits();
+        let max_ptr_plus_1 = 1u128 << self.pointer_size().bits();
         ((val % max_ptr_plus_1) as u64, val >= max_ptr_plus_1)
     }
 
@@ -135,7 +151,7 @@ pub fn new(alloc_id: AllocId, offset: Size) -> Self {
         Pointer { alloc_id, offset }
     }
 
-    pub(crate) fn wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> Self {
+    pub fn wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> Self {
         Pointer::new(
             self.alloc_id,
             Size::from_bytes(cx.data_layout().wrapping_signed_offset(self.offset.bytes(), i)),
@@ -147,7 +163,7 @@ pub fn overflowing_signed_offset<C: HasDataLayout>(self, i: i128, cx: C) -> (Sel
         (Pointer::new(self.alloc_id, Size::from_bytes(res)), over)
     }
 
-    pub(crate) fn signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> {
+    pub fn signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> {
         Ok(Pointer::new(
             self.alloc_id,
             Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?),
@@ -382,7 +398,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 pub enum AllocType<'tcx, M> {
     /// The alloc id is used as a function pointer
     Function(Instance<'tcx>),
-    /// The alloc id points to a static variable
+    /// The alloc id points to a "lazy" static variable that did not get computed (yet).
+    /// This is also used to break the cycle in recursive statics.
     Static(DefId),
     /// The alloc id points to memory
     Memory(M)
@@ -479,19 +496,22 @@ pub struct Allocation {
     /// Note that the bytes of a pointer represent the offset of the pointer
     pub bytes: Vec<u8>,
     /// Maps from byte addresses to allocations.
-    /// Only the first byte of a pointer is inserted into the map.
+    /// Only the first byte of a pointer is inserted into the map; i.e.,
+    /// every entry in this map applies to `pointer_size` consecutive bytes starting
+    /// at the given offset.
     pub relocations: Relocations,
     /// Denotes undefined memory. Reading from undefined memory is forbidden in miri
     pub undef_mask: UndefMask,
     /// The alignment of the allocation to detect unaligned reads.
     pub align: Align,
-    /// Whether the allocation (of a static) should be put into mutable memory when codegenning
-    ///
-    /// Only happens for `static mut` or `static` with interior mutability
-    pub runtime_mutability: Mutability,
+    /// Whether the allocation is mutable.
+    /// Also used by codegen to determine if a static should be put into mutable memory,
+    /// which happens for `static mut` and `static` with interior mutability.
+    pub mutability: Mutability,
 }
 
 impl Allocation {
+    /// Creates a read-only allocation initialized by the given bytes
     pub fn from_bytes(slice: &[u8], align: Align) -> Self {
         let mut undef_mask = UndefMask::new(Size::ZERO);
         undef_mask.grow(Size::from_bytes(slice.len() as u64), true);
@@ -500,7 +520,7 @@ pub fn from_bytes(slice: &[u8], align: Align) -> Self {
             relocations: Relocations::new(),
             undef_mask,
             align,
-            runtime_mutability: Mutability::Immutable,
+            mutability: Mutability::Immutable,
         }
     }
 
@@ -515,7 +535,7 @@ pub fn undef(size: Size, align: Align) -> Self {
             relocations: Relocations::new(),
             undef_mask: UndefMask::new(size),
             align,
-            runtime_mutability: Mutability::Immutable,
+            mutability: Mutability::Mutable,
         }
     }
 }
@@ -567,18 +587,6 @@ pub fn write_target_uint(
     }
 }
 
-pub fn write_target_int(
-    endianness: layout::Endian,
-    mut target: &mut [u8],
-    data: i128,
-) -> Result<(), io::Error> {
-    let len = target.len();
-    match endianness {
-        layout::Endian::Little => target.write_int128::<LittleEndian>(data, len),
-        layout::Endian::Big => target.write_int128::<BigEndian>(data, len),
-    }
-}
-
 pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result<u128, io::Error> {
     match endianness {
         layout::Endian::Little => source.read_uint128::<LittleEndian>(source.len()),
@@ -586,6 +594,26 @@ pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// Methods to faciliate working with signed integers stored in a u128
+////////////////////////////////////////////////////////////////////////////////
+
+pub fn sign_extend(value: u128, size: Size) -> u128 {
+    let size = size.bits();
+    // sign extend
+    let shift = 128 - size;
+    // shift the unsigned value to the left
+    // and back to the right as signed (essentially fills with FF on the left)
+    (((value << shift) as i128) >> shift) as u128
+}
+
+pub fn truncate(value: u128, size: Size) -> u128 {
+    let size = size.bits();
+    let shift = 128 - size;
+    // truncate (shift left to drop out leftover values, shift right to fill with zeroes)
+    (value << shift) >> shift
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Undefined byte tracking
 ////////////////////////////////////////////////////////////////////////////////
index f569f4def143f8dd6af8c2b71b4cbc27ae4a6219..11a4f8b884e7f1b46d3fa910e801f3e807563053 100644 (file)
@@ -1,14 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
 #![allow(unknown_lints)]
 
-use ty::layout::{Align, HasDataLayout, Size};
-use ty;
+use ty::layout::{HasDataLayout, Size};
 use ty::subst::Substs;
 use hir::def_id::DefId;
 
-use super::{EvalResult, Pointer, PointerArithmetic, Allocation};
+use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
 
 /// Represents a constant value in Rust. Scalar and ScalarPair are optimizations which
-/// matches Value's optimizations for easy conversions between these two types
+/// matches the LocalValue optimizations for easy conversions between Value and ConstValue.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
 pub enum ConstValue<'tcx> {
     /// Never returned from the `const_eval` query, but the HIR contains these frequently in order
@@ -16,35 +25,19 @@ pub enum ConstValue<'tcx> {
     /// evaluation
     Unevaluated(DefId, &'tcx Substs<'tcx>),
     /// Used only for types with layout::abi::Scalar ABI and ZSTs
+    ///
+    /// Not using the enum `Value` to encode that this must not be `Undef`
     Scalar(Scalar),
     /// Used only for types with layout::abi::ScalarPair
     ///
     /// The second field may be undef in case of `Option<usize>::None`
     ScalarPair(Scalar, ScalarMaybeUndef),
-    /// Used only for the remaining cases. An allocation + offset into the allocation
-    ByRef(&'tcx Allocation, Size),
+    /// Used only for the remaining cases. An allocation + offset into the allocation.
+    /// Invariant: The AllocId matches the allocation.
+    ByRef(AllocId, &'tcx Allocation, Size),
 }
 
 impl<'tcx> ConstValue<'tcx> {
-    #[inline]
-    pub fn from_byval_value(val: Value) -> EvalResult<'static, Self> {
-        Ok(match val {
-            Value::ByRef(..) => bug!(),
-            Value::ScalarPair(a, b) => ConstValue::ScalarPair(a.unwrap_or_err()?, b),
-            Value::Scalar(val) => ConstValue::Scalar(val.unwrap_or_err()?),
-        })
-    }
-
-    #[inline]
-    pub fn to_byval_value(&self) -> Option<Value> {
-        match *self {
-            ConstValue::Unevaluated(..) |
-            ConstValue::ByRef(..) => None,
-            ConstValue::ScalarPair(a, b) => Some(Value::ScalarPair(a.into(), b)),
-            ConstValue::Scalar(val) => Some(Value::Scalar(val.into())),
-        }
-    }
-
     #[inline]
     pub fn try_to_scalar(&self) -> Option<Scalar> {
         match *self {
@@ -56,58 +49,49 @@ pub fn try_to_scalar(&self) -> Option<Scalar> {
     }
 
     #[inline]
-    pub fn to_bits(&self, size: Size) -> Option<u128> {
+    pub fn try_to_bits(&self, size: Size) -> Option<u128> {
         self.try_to_scalar()?.to_bits(size).ok()
     }
 
     #[inline]
-    pub fn to_ptr(&self) -> Option<Pointer> {
+    pub fn try_to_ptr(&self) -> Option<Pointer> {
         self.try_to_scalar()?.to_ptr().ok()
     }
-}
-
-/// A `Value` represents a single self-contained Rust value.
-///
-/// A `Value` can either refer to a block of memory inside an allocation (`ByRef`) or to a primitve
-/// value held directly, outside of any allocation (`Scalar`).  For `ByRef`-values, we remember
-/// whether the pointer is supposed to be aligned or not (also see Place).
-///
-/// For optimization of a few very common cases, there is also a representation for a pair of
-/// primitive values (`ScalarPair`). It allows Miri to avoid making allocations for checked binary
-/// operations and fat pointers. This idea was taken from rustc's codegen.
-#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
-pub enum Value {
-    ByRef(Scalar, Align),
-    Scalar(ScalarMaybeUndef),
-    ScalarPair(ScalarMaybeUndef, ScalarMaybeUndef),
-}
 
-impl<'tcx> ty::TypeFoldable<'tcx> for Value {
-    fn super_fold_with<'gcx: 'tcx, F: ty::fold::TypeFolder<'gcx, 'tcx>>(&self, _: &mut F) -> Self {
-        *self
+    #[inline]
+    pub fn new_slice(
+        val: Scalar,
+        len: u64,
+        cx: impl HasDataLayout
+    ) -> Self {
+        ConstValue::ScalarPair(val, Scalar::Bits {
+            bits: len as u128,
+            size: cx.data_layout().pointer_size.bytes() as u8,
+        }.into())
     }
-    fn super_visit_with<V: ty::fold::TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
-        false
+
+    #[inline]
+    pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self {
+        ConstValue::ScalarPair(val, Scalar::Ptr(vtable).into())
     }
 }
 
 impl<'tcx> Scalar {
-    pub fn ptr_null<C: HasDataLayout>(cx: C) -> Self {
+    #[inline]
+    pub fn ptr_null(cx: impl HasDataLayout) -> Self {
         Scalar::Bits {
             bits: 0,
             size: cx.data_layout().pointer_size.bytes() as u8,
         }
     }
 
-    pub fn to_value_with_len<C: HasDataLayout>(self, len: u64, cx: C) -> Value {
-        ScalarMaybeUndef::Scalar(self).to_value_with_len(len, cx)
-    }
-
-    pub fn to_value_with_vtable(self, vtable: Pointer) -> Value {
-        ScalarMaybeUndef::Scalar(self).to_value_with_vtable(vtable)
+    #[inline]
+    pub fn zst() -> Self {
+        Scalar::Bits { bits: 0, size: 0 }
     }
 
-    pub fn ptr_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> {
+    #[inline]
+    pub fn ptr_signed_offset(self, i: i64, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
         let layout = cx.data_layout();
         match self {
             Scalar::Bits { bits, size } => {
@@ -121,7 +105,8 @@ pub fn ptr_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'t
         }
     }
 
-    pub fn ptr_offset<C: HasDataLayout>(self, i: Size, cx: C) -> EvalResult<'tcx, Self> {
+    #[inline]
+    pub fn ptr_offset(self, i: Size, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
         let layout = cx.data_layout();
         match self {
             Scalar::Bits { bits, size } => {
@@ -135,7 +120,8 @@ pub fn ptr_offset<C: HasDataLayout>(self, i: Size, cx: C) -> EvalResult<'tcx, Se
         }
     }
 
-    pub fn ptr_wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> Self {
+    #[inline]
+    pub fn ptr_wrapping_signed_offset(self, i: i64, cx: impl HasDataLayout) -> Self {
         let layout = cx.data_layout();
         match self {
             Scalar::Bits { bits, size } => {
@@ -149,7 +135,8 @@ pub fn ptr_wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> Self
         }
     }
 
-    pub fn is_null_ptr<C: HasDataLayout>(self, cx: C) -> bool {
+    #[inline]
+    pub fn is_null_ptr(self, cx: impl HasDataLayout) -> bool {
         match self {
             Scalar::Bits { bits, size } =>  {
                 assert_eq!(size as u64, cx.data_layout().pointer_size.bytes());
@@ -159,12 +146,176 @@ pub fn is_null_ptr<C: HasDataLayout>(self, cx: C) -> bool {
         }
     }
 
-    pub fn to_value(self) -> Value {
-        Value::Scalar(ScalarMaybeUndef::Scalar(self))
+    #[inline]
+    pub fn is_null(self) -> bool {
+        match self {
+            Scalar::Bits { bits, .. } => bits == 0,
+            Scalar::Ptr(_) => false
+        }
+    }
+
+    #[inline]
+    pub fn from_bool(b: bool) -> Self {
+        Scalar::Bits { bits: b as u128, size: 1 }
+    }
+
+    #[inline]
+    pub fn from_char(c: char) -> Self {
+        Scalar::Bits { bits: c as u128, size: 4 }
+    }
+
+    #[inline]
+    pub fn from_uint(i: impl Into<u128>, size: Size) -> Self {
+        let i = i.into();
+        debug_assert_eq!(truncate(i, size), i,
+                    "Unsigned value {} does not fit in {} bits", i, size.bits());
+        Scalar::Bits { bits: i, size: size.bytes() as u8 }
+    }
+
+    #[inline]
+    pub fn from_int(i: impl Into<i128>, size: Size) -> Self {
+        let i = i.into();
+        // `into` performed sign extension, we have to truncate
+        let truncated = truncate(i as u128, size);
+        debug_assert_eq!(sign_extend(truncated, size) as i128, i,
+                    "Signed value {} does not fit in {} bits", i, size.bits());
+        Scalar::Bits { bits: truncated, size: size.bytes() as u8 }
+    }
+
+    #[inline]
+    pub fn from_f32(f: f32) -> Self {
+        Scalar::Bits { bits: f.to_bits() as u128, size: 4 }
+    }
+
+    #[inline]
+    pub fn from_f64(f: f64) -> Self {
+        Scalar::Bits { bits: f.to_bits() as u128, size: 8 }
+    }
+
+    #[inline]
+    pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
+        match self {
+            Scalar::Bits { bits, size } => {
+                assert_eq!(target_size.bytes(), size as u64);
+                assert_ne!(size, 0, "to_bits cannot be used with zsts");
+                Ok(bits)
+            }
+            Scalar::Ptr(_) => err!(ReadPointerAsBytes),
+        }
+    }
+
+    #[inline]
+    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
+        match self {
+            Scalar::Bits { bits: 0, .. } => err!(InvalidNullPointerUsage),
+            Scalar::Bits { .. } => err!(ReadBytesAsPointer),
+            Scalar::Ptr(p) => Ok(p),
+        }
+    }
+
+    #[inline]
+    pub fn is_bits(self) -> bool {
+        match self {
+            Scalar::Bits { .. } => true,
+            _ => false,
+        }
+    }
+
+    #[inline]
+    pub fn is_ptr(self) -> bool {
+        match self {
+            Scalar::Ptr(_) => true,
+            _ => false,
+        }
+    }
+
+    pub fn to_bool(self) -> EvalResult<'tcx, bool> {
+        match self {
+            Scalar::Bits { bits: 0, size: 1 } => Ok(false),
+            Scalar::Bits { bits: 1, size: 1 } => Ok(true),
+            _ => err!(InvalidBool),
+        }
+    }
+
+    pub fn to_char(self) -> EvalResult<'tcx, char> {
+        let val = self.to_u32()?;
+        match ::std::char::from_u32(val) {
+            Some(c) => Ok(c),
+            None => err!(InvalidChar(val as u128)),
+        }
+    }
+
+    pub fn to_u8(self) -> EvalResult<'static, u8> {
+        let sz = Size::from_bits(8);
+        let b = self.to_bits(sz)?;
+        assert_eq!(b as u8 as u128, b);
+        Ok(b as u8)
+    }
+
+    pub fn to_u32(self) -> EvalResult<'static, u32> {
+        let sz = Size::from_bits(32);
+        let b = self.to_bits(sz)?;
+        assert_eq!(b as u32 as u128, b);
+        Ok(b as u32)
+    }
+
+    pub fn to_u64(self) -> EvalResult<'static, u64> {
+        let sz = Size::from_bits(64);
+        let b = self.to_bits(sz)?;
+        assert_eq!(b as u64 as u128, b);
+        Ok(b as u64)
+    }
+
+    pub fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64> {
+        let b = self.to_bits(cx.data_layout().pointer_size)?;
+        assert_eq!(b as u64 as u128, b);
+        Ok(b as u64)
+    }
+
+    pub fn to_i8(self) -> EvalResult<'static, i8> {
+        let sz = Size::from_bits(8);
+        let b = self.to_bits(sz)?;
+        let b = sign_extend(b, sz) as i128;
+        assert_eq!(b as i8 as i128, b);
+        Ok(b as i8)
+    }
+
+    pub fn to_i32(self) -> EvalResult<'static, i32> {
+        let sz = Size::from_bits(32);
+        let b = self.to_bits(sz)?;
+        let b = sign_extend(b, sz) as i128;
+        assert_eq!(b as i32 as i128, b);
+        Ok(b as i32)
+    }
+
+    pub fn to_i64(self) -> EvalResult<'static, i64> {
+        let sz = Size::from_bits(64);
+        let b = self.to_bits(sz)?;
+        let b = sign_extend(b, sz) as i128;
+        assert_eq!(b as i64 as i128, b);
+        Ok(b as i64)
+    }
+
+    pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64> {
+        let b = self.to_bits(cx.data_layout().pointer_size)?;
+        let b = sign_extend(b, cx.data_layout().pointer_size) as i128;
+        assert_eq!(b as i64 as i128, b);
+        Ok(b as i64)
+    }
+
+    #[inline]
+    pub fn to_f32(self) -> EvalResult<'static, f32> {
+        Ok(f32::from_bits(self.to_u32()?))
+    }
+
+    #[inline]
+    pub fn to_f64(self) -> EvalResult<'static, f64> {
+        Ok(f64::from_bits(self.to_u64()?))
     }
 }
 
 impl From<Pointer> for Scalar {
+    #[inline(always)]
     fn from(ptr: Pointer) -> Self {
         Scalar::Ptr(ptr)
     }
@@ -179,7 +330,7 @@ pub enum Scalar {
     /// The raw bytes of a simple value.
     Bits {
         /// The first `size` bytes are the value.
-        /// Do not try to read less or more bytes that that
+        /// Do not try to read less or more bytes that that. The remaining bytes must be 0.
         size: u8,
         bits: u128,
     },
@@ -197,86 +348,88 @@ pub enum ScalarMaybeUndef {
 }
 
 impl From<Scalar> for ScalarMaybeUndef {
+    #[inline(always)]
     fn from(s: Scalar) -> Self {
         ScalarMaybeUndef::Scalar(s)
     }
 }
 
-impl ScalarMaybeUndef {
-    pub fn unwrap_or_err(self) -> EvalResult<'static, Scalar> {
+impl<'tcx> ScalarMaybeUndef {
+    #[inline]
+    pub fn not_undef(self) -> EvalResult<'static, Scalar> {
         match self {
             ScalarMaybeUndef::Scalar(scalar) => Ok(scalar),
             ScalarMaybeUndef::Undef => err!(ReadUndefBytes),
         }
     }
 
-    pub fn to_value_with_len<C: HasDataLayout>(self, len: u64, cx: C) -> Value {
-        Value::ScalarPair(self, Scalar::Bits {
-            bits: len as u128,
-            size: cx.data_layout().pointer_size.bytes() as u8,
-        }.into())
+    #[inline(always)]
+    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
+        self.not_undef()?.to_ptr()
     }
 
-    pub fn to_value_with_vtable(self, vtable: Pointer) -> Value {
-        Value::ScalarPair(self, Scalar::Ptr(vtable).into())
+    #[inline(always)]
+    pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
+        self.not_undef()?.to_bits(target_size)
     }
 
-    pub fn ptr_offset<C: HasDataLayout>(self, i: Size, cx: C) -> EvalResult<'tcx, Self> {
-        match self {
-            ScalarMaybeUndef::Scalar(scalar) => {
-                scalar.ptr_offset(i, cx).map(ScalarMaybeUndef::Scalar)
-            },
-            ScalarMaybeUndef::Undef => Ok(ScalarMaybeUndef::Undef)
-        }
+    #[inline(always)]
+    pub fn to_bool(self) -> EvalResult<'tcx, bool> {
+        self.not_undef()?.to_bool()
     }
-}
 
-impl<'tcx> Scalar {
-    pub fn from_bool(b: bool) -> Self {
-        Scalar::Bits { bits: b as u128, size: 1 }
+    #[inline(always)]
+    pub fn to_char(self) -> EvalResult<'tcx, char> {
+        self.not_undef()?.to_char()
     }
 
-    pub fn from_char(c: char) -> Self {
-        Scalar::Bits { bits: c as u128, size: 4 }
+    #[inline(always)]
+    pub fn to_f32(self) -> EvalResult<'tcx, f32> {
+        self.not_undef()?.to_f32()
     }
 
-    pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
-        match self {
-            Scalar::Bits { bits, size } => {
-                assert_eq!(target_size.bytes(), size as u64);
-                assert_ne!(size, 0, "to_bits cannot be used with zsts");
-                Ok(bits)
-            }
-            Scalar::Ptr(_) => err!(ReadPointerAsBytes),
-        }
+    #[inline(always)]
+    pub fn to_f64(self) -> EvalResult<'tcx, f64> {
+        self.not_undef()?.to_f64()
     }
 
-    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
-        match self {
-            Scalar::Bits {..} => err!(ReadBytesAsPointer),
-            Scalar::Ptr(p) => Ok(p),
-        }
+    #[inline(always)]
+    pub fn to_u8(self) -> EvalResult<'tcx, u8> {
+        self.not_undef()?.to_u8()
     }
 
-    pub fn is_bits(self) -> bool {
-        match self {
-            Scalar::Bits { .. } => true,
-            _ => false,
-        }
+    #[inline(always)]
+    pub fn to_u32(self) -> EvalResult<'tcx, u32> {
+        self.not_undef()?.to_u32()
     }
 
-    pub fn is_ptr(self) -> bool {
-        match self {
-            Scalar::Ptr(_) => true,
-            _ => false,
-        }
+    #[inline(always)]
+    pub fn to_u64(self) -> EvalResult<'tcx, u64> {
+        self.not_undef()?.to_u64()
     }
 
-    pub fn to_bool(self) -> EvalResult<'tcx, bool> {
-        match self {
-            Scalar::Bits { bits: 0, size: 1 } => Ok(false),
-            Scalar::Bits { bits: 1, size: 1 } => Ok(true),
-            _ => err!(InvalidBool),
-        }
+    #[inline(always)]
+    pub fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, u64> {
+        self.not_undef()?.to_usize(cx)
+    }
+
+    #[inline(always)]
+    pub fn to_i8(self) -> EvalResult<'tcx, i8> {
+        self.not_undef()?.to_i8()
+    }
+
+    #[inline(always)]
+    pub fn to_i32(self) -> EvalResult<'tcx, i32> {
+        self.not_undef()?.to_i32()
+    }
+
+    #[inline(always)]
+    pub fn to_i64(self) -> EvalResult<'tcx, i64> {
+        self.not_undef()?.to_i64()
+    }
+
+    #[inline(always)]
+    pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, i64> {
+        self.not_undef()?.to_isize(cx)
     }
 }
index 8ceff303774b596a265af6a1dfac05a09589914c..44730c19dd3e8a52a5e5bd0002ce6d934f15c7fb 100644 (file)
 use hir::def_id::DefId;
 use hir::{self, HirId, InlineAsm};
 use middle::region;
-use mir::interpret::{EvalErrorKind, Scalar, Value, ScalarMaybeUndef};
+use mir::interpret::{ConstValue, EvalErrorKind, Scalar, ScalarMaybeUndef};
 use mir::visit::MirVisitable;
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
 use rustc_data_structures::graph::dominators::{dominators, Dominators};
 use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
-use rustc_data_structures::small_vec::SmallVec;
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::sync::ReadGuard;
 use rustc_serialize as serialize;
+use smallvec::SmallVec;
 use std::borrow::Cow;
 use std::fmt::{self, Debug, Formatter, Write};
 use std::ops::{Index, IndexMut};
@@ -194,15 +194,44 @@ pub fn basic_blocks_and_local_decls_mut(
     }
 
     #[inline]
-    pub fn predecessors(&self) -> ReadGuard<IndexVec<BasicBlock, Vec<BasicBlock>>> {
+    pub fn predecessors(&self) -> ReadGuard<'_, IndexVec<BasicBlock, Vec<BasicBlock>>> {
         self.cache.predecessors(self)
     }
 
     #[inline]
-    pub fn predecessors_for(&self, bb: BasicBlock) -> ReadGuard<Vec<BasicBlock>> {
+    pub fn predecessors_for(&self, bb: BasicBlock) -> ReadGuard<'_, Vec<BasicBlock>> {
         ReadGuard::map(self.predecessors(), |p| &p[bb])
     }
 
+    #[inline]
+    pub fn predecessor_locations(&self, loc: Location) -> impl Iterator<Item = Location> + '_ {
+        let if_zero_locations = if loc.statement_index == 0 {
+            let predecessor_blocks = self.predecessors_for(loc.block);
+            let num_predecessor_blocks = predecessor_blocks.len();
+            Some(
+                (0..num_predecessor_blocks)
+                    .map(move |i| predecessor_blocks[i])
+                    .map(move |bb| self.terminator_loc(bb)),
+            )
+        } else {
+            None
+        };
+
+        let if_not_zero_locations = if loc.statement_index == 0 {
+            None
+        } else {
+            Some(Location {
+                block: loc.block,
+                statement_index: loc.statement_index - 1,
+            })
+        };
+
+        if_zero_locations
+            .into_iter()
+            .flatten()
+            .chain(if_not_zero_locations)
+    }
+
     #[inline]
     pub fn dominators(&self) -> Dominators<BasicBlock> {
         dominators(self)
@@ -328,6 +357,14 @@ pub fn is_sub_scope(&self, mut sub: SourceScope, sup: SourceScope) -> bool {
     pub fn return_ty(&self) -> Ty<'tcx> {
         self.local_decls[RETURN_PLACE].ty
     }
+
+    /// Get the location of the terminator for the given block
+    pub fn terminator_loc(&self, bb: BasicBlock) -> Location {
+        Location {
+            block: bb,
+            statement_index: self[bb].statements.len(),
+        }
+    }
 }
 
 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
@@ -547,13 +584,15 @@ pub enum BindingForm<'tcx> {
 });
 
 mod binding_form_impl {
-    use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
     use ich::StableHashingContext;
+    use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
 
     impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for super::BindingForm<'tcx> {
-        fn hash_stable<W: StableHasherResult>(&self,
-                                            hcx: &mut StableHashingContext<'a>,
-                                            hasher: &mut StableHasher<W>) {
+        fn hash_stable<W: StableHasherResult>(
+            &self,
+            hcx: &mut StableHashingContext<'a>,
+            hasher: &mut StableHasher<W>,
+        ) {
             use super::BindingForm::*;
             ::std::mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -927,11 +966,11 @@ pub enum TerminatorKind<'tcx> {
     ///   Drop(P, goto BB1, unwind BB2)
     /// }
     /// BB1 {
-    ///   // P is now unitialized
+    ///   // P is now uninitialized
     ///   P <- V
     /// }
     /// BB2 {
-    ///   // P is now unitialized -- its dtor panicked
+    ///   // P is now uninitialized -- its dtor panicked
     ///   P <- V
     /// }
     /// ```
@@ -1469,17 +1508,18 @@ pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
                     .iter()
                     .map(|&u| {
                         let mut s = String::new();
-                        print_miri_value(
-                            Scalar::Bits {
-                                bits: u,
-                                size: size.bytes() as u8,
-                            }.to_value(),
-                            switch_ty,
-                            &mut s,
-                        ).unwrap();
+                        let c = ty::Const {
+                            val: ConstValue::Scalar(
+                                Scalar::Bits {
+                                    bits: u,
+                                    size: size.bytes() as u8,
+                                }.into(),
+                            ),
+                            ty: switch_ty,
+                        };
+                        fmt_const_val(&mut s, &c).unwrap();
                         s.into()
-                    })
-                    .chain(iter::once(String::from("otherwise").into()))
+                    }).chain(iter::once(String::from("otherwise").into()))
                     .collect()
             }
             Call {
@@ -1888,12 +1928,15 @@ pub enum Operand<'tcx> {
     /// This implies that the type of the place must be `Copy`; this is true
     /// by construction during build, but also checked by the MIR type checker.
     Copy(Place<'tcx>),
+
     /// Move: The value (including old borrows of it) will not be used again.
     ///
     /// Safe for values of all types (modulo future developments towards `?Move`).
     /// Correct usage patterns are enforced by the borrow checker for safe code.
     /// `Copy` may be converted to `Move` to enable "last-use" optimizations.
     Move(Place<'tcx>),
+
+    /// Synthesizes a constant value.
     Constant(Box<Constant<'tcx>>),
 }
 
@@ -1909,6 +1952,9 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
 }
 
 impl<'tcx> Operand<'tcx> {
+    /// Convenience helper to make a constant that refers to the fn
+    /// with given def-id and substs. Since this is used to synthesize
+    /// MIR, assumes `user_ty` is None.
     pub fn function_handle<'a>(
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         def_id: DefId,
@@ -1919,6 +1965,7 @@ pub fn function_handle<'a>(
         Operand::Constant(box Constant {
             span,
             ty,
+            user_ty: None,
             literal: ty::Const::zero_sized(tcx, ty),
         })
     }
@@ -2002,7 +2049,13 @@ pub enum AggregateKind<'tcx> {
     /// active field number and is present only for union expressions
     /// -- e.g. for a union expression `SomeUnion { c: .. }`, the
     /// active field index would identity the field `c`
-    Adt(&'tcx AdtDef, usize, &'tcx Substs<'tcx>, Option<usize>),
+    Adt(
+        &'tcx AdtDef,
+        usize,
+        &'tcx Substs<'tcx>,
+        Option<CanonicalTy<'tcx>>,
+        Option<usize>,
+    ),
 
     Closure(DefId, ClosureSubsts<'tcx>),
     Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
@@ -2105,7 +2158,7 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
                     region
                 } else {
                     // Do not even print 'static
-                    "".to_owned()
+                    String::new()
                 };
                 write!(fmt, "&{}{}{:?}", region, kind_str, place)
             }
@@ -2128,7 +2181,7 @@ fn fmt_tuple(fmt: &mut Formatter, places: &[Operand]) -> fmt::Result {
                         _ => fmt_tuple(fmt, places),
                     },
 
-                    AggregateKind::Adt(adt_def, variant, substs, _) => {
+                    AggregateKind::Adt(adt_def, variant, substs, _user_ty, _) => {
                         let variant_def = &adt_def.variants[variant];
 
                         ppaux::parameterized(fmt, substs, variant_def.did, &[])?;
@@ -2207,6 +2260,14 @@ fn fmt_tuple(fmt: &mut Formatter, places: &[Operand]) -> fmt::Result {
 pub struct Constant<'tcx> {
     pub span: Span,
     pub ty: Ty<'tcx>,
+
+    /// Optional user-given type: for something like
+    /// `collect::<Vec<_>>`, this would be present and would
+    /// indicate that `Vec<_>` was explicitly specified.
+    ///
+    /// Needed for NLL to impose user-given type constraints.
+    pub user_ty: Option<CanonicalTy<'tcx>>,
+
     pub literal: &'tcx ty::Const<'tcx>,
 }
 
@@ -2220,25 +2281,19 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
 }
 
 /// Write a `ConstValue` in a way closer to the original source code than the `Debug` output.
-pub fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Result {
-    if let Some(value) = const_val.to_byval_value() {
-        print_miri_value(value, const_val.ty, fmt)
-    } else {
-        write!(fmt, "{:?}:{}", const_val.val, const_val.ty)
-    }
-}
-
-pub fn print_miri_value<W: Write>(value: Value, ty: Ty, f: &mut W) -> fmt::Result {
-    use ty::TypeVariants::*;
+pub fn fmt_const_val(f: &mut impl Write, const_val: &ty::Const) -> fmt::Result {
+    use ty::TyKind::*;
+    let value = const_val.val;
+    let ty = const_val.ty;
     // print some primitives
-    if let Value::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits { bits, .. })) = value {
+    if let ConstValue::Scalar(Scalar::Bits { bits, .. }) = value {
         match ty.sty {
-            TyBool if bits == 0 => return write!(f, "false"),
-            TyBool if bits == 1 => return write!(f, "true"),
-            TyFloat(ast::FloatTy::F32) => return write!(f, "{}f32", Single::from_bits(bits)),
-            TyFloat(ast::FloatTy::F64) => return write!(f, "{}f64", Double::from_bits(bits)),
-            TyUint(ui) => return write!(f, "{:?}{}", bits, ui),
-            TyInt(i) => {
+            Bool if bits == 0 => return write!(f, "false"),
+            Bool if bits == 1 => return write!(f, "true"),
+            Float(ast::FloatTy::F32) => return write!(f, "{}f32", Single::from_bits(bits)),
+            Float(ast::FloatTy::F64) => return write!(f, "{}f64", Double::from_bits(bits)),
+            Uint(ui) => return write!(f, "{:?}{}", bits, ui),
+            Int(i) => {
                 let bit_width = ty::tls::with(|tcx| {
                     let ty = tcx.lift_to_global(&ty).unwrap();
                     tcx.layout_of(ty::ParamEnv::empty().and(ty))
@@ -2249,31 +2304,29 @@ pub fn print_miri_value<W: Write>(value: Value, ty: Ty, f: &mut W) -> fmt::Resul
                 let shift = 128 - bit_width;
                 return write!(f, "{:?}{}", ((bits as i128) << shift) >> shift, i);
             }
-            TyChar => return write!(f, "{:?}", ::std::char::from_u32(bits as u32).unwrap()),
-            _ => {},
+            Char => return write!(f, "{:?}", ::std::char::from_u32(bits as u32).unwrap()),
+            _ => {}
         }
     }
     // print function definitons
-    if let TyFnDef(did, _) = ty.sty {
+    if let FnDef(did, _) = ty.sty {
         return write!(f, "{}", item_path_str(did));
     }
     // print string literals
-    if let Value::ScalarPair(ptr, len) = value {
-        if let ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) = ptr {
+    if let ConstValue::ScalarPair(ptr, len) = value {
+        if let Scalar::Ptr(ptr) = ptr {
             if let ScalarMaybeUndef::Scalar(Scalar::Bits { bits: len, .. }) = len {
-                if let TyRef(_, &ty::TyS { sty: TyStr, .. }, _) = ty.sty {
+                if let Ref(_, &ty::TyS { sty: Str, .. }, _) = ty.sty {
                     return ty::tls::with(|tcx| {
                         let alloc = tcx.alloc_map.lock().get(ptr.alloc_id);
                         if let Some(interpret::AllocType::Memory(alloc)) = alloc {
                             assert_eq!(len as usize as u128, len);
-                            let slice = &alloc
-                                .bytes
-                                    [(ptr.offset.bytes() as usize)..]
-                                    [..(len as usize)];
+                            let slice =
+                                &alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
                             let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
                             write!(f, "{:?}", s)
                         } else {
-                             write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len)
+                            write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len)
                         }
                     });
                 }
@@ -2377,6 +2430,8 @@ pub fn dominates(&self, other: Location, dominators: &Dominators<BasicBlock>) ->
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub enum UnsafetyViolationKind {
     General,
+    /// unsafety is not allowed at all in min const fn
+    MinConstFn,
     ExternStatic(ast::NodeId),
     BorrowPacked(ast::NodeId),
 }
@@ -2804,9 +2859,13 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
                 let kind = box match **kind {
                     AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
                     AggregateKind::Tuple => AggregateKind::Tuple,
-                    AggregateKind::Adt(def, v, substs, n) => {
-                        AggregateKind::Adt(def, v, substs.fold_with(folder), n)
-                    }
+                    AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
+                        def,
+                        v,
+                        substs.fold_with(folder),
+                        user_ty.fold_with(folder),
+                        n,
+                    ),
                     AggregateKind::Closure(id, substs) => {
                         AggregateKind::Closure(id, substs.fold_with(folder))
                     }
@@ -2837,7 +2896,9 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
                 (match **kind {
                     AggregateKind::Array(ty) => ty.visit_with(visitor),
                     AggregateKind::Tuple => false,
-                    AggregateKind::Adt(_, _, substs, _) => substs.visit_with(visitor),
+                    AggregateKind::Adt(_, _, substs, user_ty, _) => {
+                        substs.visit_with(visitor) || user_ty.visit_with(visitor)
+                    }
                     AggregateKind::Closure(_, substs) => substs.visit_with(visitor),
                     AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor),
                 }) || fields.visit_with(visitor)
@@ -2908,6 +2969,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
         Constant {
             span: self.span.clone(),
             ty: self.ty.fold_with(folder),
+            user_ty: self.user_ty.fold_with(folder),
             literal: self.literal.fold_with(folder),
         }
     }
index 5991845d265b24a8ce86842d5f10d6d0e34a7dab..c928be4f9df78aa351698ece504e7a22b40b9a80 100644 (file)
@@ -68,12 +68,12 @@ pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                 let ty = self.to_ty(tcx);
                 PlaceTy::Ty {
                     ty: match ty.sty {
-                        ty::TyArray(inner, size) => {
+                        ty::Array(inner, size) => {
                             let size = size.unwrap_usize(tcx);
                             let len = size - (from as u64) - (to as u64);
                             tcx.mk_array(inner, len)
                         }
-                        ty::TySlice(..) => ty,
+                        ty::Slice(..) => ty,
                         _ => {
                             bug!("cannot subslice non-array type: `{:?}`", self)
                         }
@@ -82,7 +82,7 @@ pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
             }
             ProjectionElem::Downcast(adt_def1, index) =>
                 match self.to_ty(tcx).sty {
-                    ty::TyAdt(adt_def, substs) => {
+                    ty::Adt(adt_def, substs) => {
                         assert!(adt_def.is_enum());
                         assert!(index < adt_def.variants.len());
                         assert_eq!(adt_def, adt_def1);
@@ -199,7 +199,7 @@ pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> T
             }
             Rvalue::Discriminant(ref place) => {
                 let ty = place.ty(local_decls, tcx).to_ty(tcx);
-                if let ty::TyAdt(adt_def, _) = ty.sty {
+                if let ty::Adt(adt_def, _) = ty.sty {
                     adt_def.repr.discr_type().to_ty(tcx)
                 } else {
                     // This can only be `0`, for now, so `u8` will suffice.
@@ -216,7 +216,7 @@ pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> T
                     AggregateKind::Tuple => {
                         tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx)))
                     }
-                    AggregateKind::Adt(def, _, substs, _) => {
+                    AggregateKind::Adt(def, _, substs, _, _) => {
                         tcx.type_of(def.did).subst(tcx, substs)
                     }
                     AggregateKind::Closure(did, substs) => {
index c178a9063c9acd09fa1131c52e44831ed6e6ed33..c919793fe3e03c38aeca2e498e5d97f15659e3eb 100644 (file)
@@ -171,7 +171,7 @@ fn traverse_successor(&mut self) {
         //      (A, [C])]
         //
         // Now that the top of the stack has no successors we can traverse, each item will
-        // be popped off during iteration until we get back to `A`. This yeilds [E, D, B].
+        // be popped off during iteration until we get back to `A`. This yields [E, D, B].
         //
         // When we yield `B` and call `traverse_successor`, we push `C` to the stack, but
         // since we've already visited `E`, that child isn't added to the stack. The last
index cab6ed0c122cd88469aab9c5d2553926ad02cdf2..c7723fdf1913710de4b8f742fa93dd756f92e681 100644 (file)
@@ -213,6 +213,10 @@ fn visit_ty(&mut self,
                 self.super_ty(ty);
             }
 
+            fn visit_canonical_ty(&mut self, ty: & $($mutability)* CanonicalTy<'tcx>) {
+                self.super_canonical_ty(ty);
+            }
+
             fn visit_region(&mut self,
                             region: & $($mutability)* ty::Region<'tcx>,
                             _: Location) {
@@ -585,6 +589,7 @@ fn super_rvalue(&mut self,
                             AggregateKind::Adt(_adt_def,
                                                _variant_index,
                                                ref $($mutability)* substs,
+                                               _user_substs,
                                                _active_field_index) => {
                                 self.visit_substs(substs, location);
                             }
@@ -625,9 +630,10 @@ fn super_operand(&mut self,
             }
 
             fn super_user_assert_ty(&mut self,
-                                    _c_ty: & $($mutability)* CanonicalTy<'tcx>,
+                                    c_ty: & $($mutability)* CanonicalTy<'tcx>,
                                     local: & $($mutability)* Local,
                                     location: Location) {
+                self.visit_canonical_ty(c_ty);
                 self.visit_local(local, PlaceContext::Validate, location);
             }
 
@@ -740,11 +746,13 @@ fn super_constant(&mut self,
                 let Constant {
                     ref $($mutability)* span,
                     ref $($mutability)* ty,
+                    ref $($mutability)* user_ty,
                     ref $($mutability)* literal,
                 } = *constant;
 
                 self.visit_span(span);
                 self.visit_ty(ty, TyContext::Location(location));
+                drop(user_ty); // no visit method for this
                 self.visit_const(literal, location);
             }
 
@@ -764,6 +772,9 @@ fn super_source_info(&mut self, source_info: & $($mutability)* SourceInfo) {
                 self.visit_source_scope(scope);
             }
 
+            fn super_canonical_ty(&mut self, _ty: & $($mutability)* CanonicalTy<'tcx>) {
+            }
+
             fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) {
             }
 
index d5946786252880a01c3c03a24ad10d7eb9f6aeb7..ee683e37648f0089c9f316c667d88cbda01639d5 100644 (file)
 use std::collections::btree_map::Keys as BTreeMapKeysIter;
 use std::collections::btree_map::Values as BTreeMapValuesIter;
 
+use rustc_data_structures::fx::FxHashSet;
 use std::{fmt, str};
 use std::hash::Hasher;
 use std::collections::hash_map::DefaultHasher;
-use std::collections::HashSet;
 use std::iter::FromIterator;
 use std::path::{Path, PathBuf};
 
@@ -1051,7 +1051,7 @@ fn parse_cross_lang_lto(slot: &mut CrossLangLto, v: Option<&str>) -> bool {
         "perform LLVM link-time optimizations"),
     target_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
         "select target processor (rustc --print target-cpus for details)"),
-    target_feature: String = ("".to_string(), parse_string, [TRACKED],
+    target_feature: String = (String::new(), parse_string, [TRACKED],
         "target specific attributes (rustc --print target-features for details)"),
     passes: Vec<String> = (Vec::new(), parse_list, [TRACKED],
         "a list of extra LLVM passes to run (space separated)"),
@@ -1085,7 +1085,7 @@ fn parse_cross_lang_lto(slot: &mut CrossLangLto, v: Option<&str>) -> bool {
          "choose the code model to use (rustc --print code-models for details)"),
     metadata: Vec<String> = (Vec::new(), parse_list, [TRACKED],
          "metadata to mangle symbol names with"),
-    extra_filename: String = ("".to_string(), parse_string, [UNTRACKED],
+    extra_filename: String = (String::new(), parse_string, [UNTRACKED],
          "extra data to put in each output filename"),
     codegen_units: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
         "divide crate into N units to optimize in parallel"),
@@ -1373,7 +1373,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
     let max_atomic_width = sess.target.target.max_atomic_width();
     let atomic_cas = sess.target.target.options.atomic_cas;
 
-    let mut ret = HashSet::new();
+    let mut ret = FxHashSet::default();
     // Target bindings.
     ret.insert((Symbol::intern("target_os"), Some(Symbol::intern(os))));
     if let Some(ref fam) = sess.target.target.options.target_family {
@@ -1992,7 +1992,7 @@ pub fn build_session_options_and_crate_config(
     };
     if cg.target_feature == "help" {
         prints.push(PrintRequest::TargetFeatures);
-        cg.target_feature = "".to_string();
+        cg.target_feature = String::new();
     }
     if cg.relocation_model.as_ref().map_or(false, |s| s == "help") {
         prints.push(PrintRequest::RelocationModels);
index 32044fdf2a8cb2fa9df336d949ca3b9fc24d5dce..0de5d3d03d5c37cbb725264079ddc62b10bb42d3 100644 (file)
@@ -12,8 +12,8 @@
 
 pub use self::FileMatch::*;
 
+use rustc_data_structures::fx::FxHashSet;
 use std::borrow::Cow;
-use std::collections::HashSet;
 use std::env;
 use std::fs;
 use std::path::{Path, PathBuf};
@@ -40,7 +40,7 @@ impl<'a> FileSearch<'a> {
     pub fn for_each_lib_search_path<F>(&self, mut f: F) where
         F: FnMut(&Path, PathKind)
     {
-        let mut visited_dirs = HashSet::new();
+        let mut visited_dirs = FxHashSet::default();
 
         for (path, kind) in self.search_paths.iter(self.kind) {
             f(path, kind);
index ef81cd3a4575e9909a50a710ef1cef6dcdac039e..00c5369e0644e371a894db0c8d8befe4e093eaf6 100644 (file)
@@ -47,7 +47,6 @@
 
 use std;
 use std::cell::{self, Cell, RefCell};
-use std::collections::HashMap;
 use std::env;
 use std::fmt;
 use std::io::Write;
@@ -122,7 +121,7 @@ pub struct Session {
     /// Map from imported macro spans (which consist of
     /// the localized span for the macro body) to the
     /// macro name and definition span in the source crate.
-    pub imported_macro_spans: OneThread<RefCell<HashMap<Span, (String, Span)>>>,
+    pub imported_macro_spans: OneThread<RefCell<FxHashMap<Span, (String, Span)>>>,
 
     incr_comp_session: OneThread<RefCell<IncrCompSession>>,
 
@@ -649,13 +648,6 @@ pub fn crt_static_feature(&self) -> bool {
         }
     }
 
-    pub fn target_cpu(&self) -> &str {
-        match self.opts.cg.target_cpu {
-            Some(ref s) => &**s,
-            None => &*self.target.target.options.cpu
-        }
-    }
-
     pub fn must_not_eliminate_frame_pointers(&self) -> bool {
         if let Some(x) = self.opts.cg.force_frame_pointers {
             x
@@ -1129,7 +1121,7 @@ pub fn build_session_(
         injected_allocator: Once::new(),
         allocator_kind: Once::new(),
         injected_panic_runtime: Once::new(),
-        imported_macro_spans: OneThread::new(RefCell::new(HashMap::new())),
+        imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())),
         incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
         self_profiling: Lock::new(SelfProfiler::new()),
         profile_channel: Lock::new(None),
index fd8c2d45e644a6f384db7f9e43c74a08a1b3f44d..ed95aa73078a92f5282e1137fd8a0b24d21fa969 100644 (file)
@@ -264,12 +264,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
     // The core logic responsible for computing the bounds for our synthesized impl.
     //
     // To calculate the bounds, we call SelectionContext.select in a loop. Like FulfillmentContext,
-    // we recursively select the nested obligations of predicates we encounter. However, whenver we
+    // we recursively select the nested obligations of predicates we encounter. However, whenever we
     // encounter an UnimplementedError involving a type parameter, we add it to our ParamEnv. Since
     // our goal is to determine when a particular type implements an auto trait, Unimplemented
     // errors tell us what conditions need to be met.
     //
-    // This method ends up working somewhat similary to FulfillmentContext, but with a few key
+    // This method ends up working somewhat similarly to FulfillmentContext, but with a few key
     // differences. FulfillmentContext works under the assumption that it's dealing with concrete
     // user code. According, it considers all possible ways that a Predicate could be met - which
     // isn't always what we want for a synthesized impl. For example, given the predicate 'T:
@@ -289,11 +289,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
     // we'll pick up any nested bounds, without ever inferring that 'T: IntoIterator' needs to
     // hold.
     //
-    // One additonal consideration is supertrait bounds. Normally, a ParamEnv is only ever
+    // One additional consideration is supertrait bounds. Normally, a ParamEnv is only ever
     // consutrcted once for a given type. As part of the construction process, the ParamEnv will
     // have any supertrait bounds normalized - e.g. if we have a type 'struct Foo<T: Copy>', the
     // ParamEnv will contain 'T: Copy' and 'T: Clone', since 'Copy: Clone'. When we construct our
-    // own ParamEnv, we need to do this outselves, through traits::elaborate_predicates, or else
+    // own ParamEnv, we need to do this ourselves, through traits::elaborate_predicates, or else
     // SelectionContext will choke on the missing predicates. However, this should never show up in
     // the final synthesized generics: we don't want our generated docs page to contain something
     // like 'T: Copy + Clone', as that's redundant. Therefore, we keep track of a separate
@@ -606,8 +606,8 @@ pub fn is_of_param(&self, substs: &Substs) -> bool {
         }
 
         return match substs.type_at(0).sty {
-            ty::TyParam(_) => true,
-            ty::TyProjection(p) => self.is_of_param(p.substs),
+            ty::Param(_) => true,
+            ty::Projection(p) => self.is_of_param(p.substs),
             _ => false,
         };
     }
index 02bfab033efc864150beb2562359bbcb891eb6b8..c283c4d3caba38e9ffe521f09f4c31be069723dd 100644 (file)
@@ -407,7 +407,7 @@ fn uncovered_tys<'tcx>(tcx: TyCtxt, ty: Ty<'tcx>, in_crate: InCrate)
 
 fn is_possibly_remote_type(ty: Ty, _in_crate: InCrate) -> bool {
     match ty.sty {
-        ty::TyProjection(..) | ty::TyParam(..) => true,
+        ty::Projection(..) | ty::Param(..) => true,
         _ => false,
     }
 }
@@ -419,9 +419,9 @@ fn ty_is_local(tcx: TyCtxt, ty: Ty, in_crate: InCrate) -> bool {
 
 fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
     match ty.sty {
-        ty::TyRef(..) => true,
-        ty::TyAdt(def, _) => def.is_fundamental(),
-        ty::TyDynamic(ref data, ..) => {
+        ty::Ref(..) => true,
+        ty::Adt(def, _) => def.is_fundamental(),
+        ty::Dynamic(ref data, ..) => {
             data.principal().map_or(false, |p| tcx.has_attr(p.def_id(), "fundamental"))
         }
         _ => false
@@ -441,49 +441,49 @@ fn ty_is_local_constructor(ty: Ty, in_crate: InCrate) -> bool {
     debug!("ty_is_local_constructor({:?})", ty);
 
     match ty.sty {
-        ty::TyBool |
-        ty::TyChar |
-        ty::TyInt(..) |
-        ty::TyUint(..) |
-        ty::TyFloat(..) |
-        ty::TyStr |
-        ty::TyFnDef(..) |
-        ty::TyFnPtr(_) |
-        ty::TyArray(..) |
-        ty::TySlice(..) |
-        ty::TyRawPtr(..) |
-        ty::TyRef(..) |
-        ty::TyNever |
-        ty::TyTuple(..) |
-        ty::TyParam(..) |
-        ty::TyProjection(..) => {
+        ty::Bool |
+        ty::Char |
+        ty::Int(..) |
+        ty::Uint(..) |
+        ty::Float(..) |
+        ty::Str |
+        ty::FnDef(..) |
+        ty::FnPtr(_) |
+        ty::Array(..) |
+        ty::Slice(..) |
+        ty::RawPtr(..) |
+        ty::Ref(..) |
+        ty::Never |
+        ty::Tuple(..) |
+        ty::Param(..) |
+        ty::Projection(..) => {
             false
         }
 
-        ty::TyInfer(..) => match in_crate {
+        ty::Infer(..) => match in_crate {
             InCrate::Local => false,
             // The inference variable might be unified with a local
             // type in that remote crate.
             InCrate::Remote => true,
         },
 
-        ty::TyAdt(def, _) => def_id_is_local(def.did, in_crate),
-        ty::TyForeign(did) => def_id_is_local(did, in_crate),
+        ty::Adt(def, _) => def_id_is_local(def.did, in_crate),
+        ty::Foreign(did) => def_id_is_local(did, in_crate),
 
-        ty::TyDynamic(ref tt, ..) => {
+        ty::Dynamic(ref tt, ..) => {
             tt.principal().map_or(false, |p| {
                 def_id_is_local(p.def_id(), in_crate)
             })
         }
 
-        ty::TyError => {
+        ty::Error => {
             true
         }
 
-        ty::TyClosure(..) |
-        ty::TyGenerator(..) |
-        ty::TyGeneratorWitness(..) |
-        ty::TyAnon(..) => {
+        ty::Closure(..) |
+        ty::Generator(..) |
+        ty::GeneratorWitness(..) |
+        ty::Anon(..) => {
             bug!("ty_is_local invoked on unexpected type: {:?}", ty)
         }
     }
index 5d45badf49f8d3b17333f584dedf7c5e21fa470a..b34378151ccb32c9ea25a2acfcb7d55cc28eec78 100644 (file)
@@ -29,6 +29,7 @@
 
 use errors::{Applicability, DiagnosticBuilder};
 use hir;
+use hir::Node;
 use hir::def_id::DefId;
 use infer::{self, InferCtxt};
 use infer::type_variable::TypeVariableOrigin;
@@ -244,36 +245,36 @@ fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
         /// if the type can be equated to any type.
         fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> {
             match t.sty {
-                ty::TyBool => Some(0),
-                ty::TyChar => Some(1),
-                ty::TyStr => Some(2),
-                ty::TyInt(..) | ty::TyUint(..) | ty::TyInfer(ty::IntVar(..)) => Some(3),
-                ty::TyFloat(..) | ty::TyInfer(ty::FloatVar(..)) => Some(4),
-                ty::TyRef(..) | ty::TyRawPtr(..) => Some(5),
-                ty::TyArray(..) | ty::TySlice(..) => Some(6),
-                ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7),
-                ty::TyDynamic(..) => Some(8),
-                ty::TyClosure(..) => Some(9),
-                ty::TyTuple(..) => Some(10),
-                ty::TyProjection(..) => Some(11),
-                ty::TyParam(..) => Some(12),
-                ty::TyAnon(..) => Some(13),
-                ty::TyNever => Some(14),
-                ty::TyAdt(adt, ..) => match adt.adt_kind() {
+                ty::Bool => Some(0),
+                ty::Char => Some(1),
+                ty::Str => Some(2),
+                ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
+                ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
+                ty::Ref(..) | ty::RawPtr(..) => Some(5),
+                ty::Array(..) | ty::Slice(..) => Some(6),
+                ty::FnDef(..) | ty::FnPtr(..) => Some(7),
+                ty::Dynamic(..) => Some(8),
+                ty::Closure(..) => Some(9),
+                ty::Tuple(..) => Some(10),
+                ty::Projection(..) => Some(11),
+                ty::Param(..) => Some(12),
+                ty::Anon(..) => Some(13),
+                ty::Never => Some(14),
+                ty::Adt(adt, ..) => match adt.adt_kind() {
                     AdtKind::Struct => Some(15),
                     AdtKind::Union => Some(16),
                     AdtKind::Enum => Some(17),
                 },
-                ty::TyGenerator(..) => Some(18),
-                ty::TyForeign(..) => Some(19),
-                ty::TyGeneratorWitness(..) => Some(20),
-                ty::TyInfer(..) | ty::TyError => None
+                ty::Generator(..) => Some(18),
+                ty::Foreign(..) => Some(19),
+                ty::GeneratorWitness(..) => Some(20),
+                ty::Infer(..) | ty::Error => None
             }
         }
 
         match (type_category(a), type_category(b)) {
             (Some(cat_a), Some(cat_b)) => match (&a.sty, &b.sty) {
-                (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => def_a == def_b,
+                (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
                 _ => cat_a == cat_b
             },
             // infer and error can be equated to all types
@@ -472,7 +473,7 @@ fn report_similar_impl_candidates(&self,
                           if len > 5 {
                               format!("\nand {} others", len - 4)
                           } else {
-                              "".to_owned()
+                              String::new()
                           }
                           ));
     }
@@ -652,7 +653,7 @@ pub fn report_selection_error(&self,
                         }
 
                         // If this error is due to `!: Trait` not implemented but `(): Trait` is
-                        // implemented, and fallback has occured, then it could be due to a
+                        // implemented, and fallback has occurred, then it could be due to a
                         // variable that used to fallback to `()` now falling back to `!`. Issue a
                         // note informing about the change in behaviour.
                         if trait_predicate.skip_binder().self_ty().is_never()
@@ -784,10 +785,10 @@ pub fn report_selection_error(&self,
                 let found_trait_ty = found_trait_ref.self_ty();
 
                 let found_did = match found_trait_ty.sty {
-                    ty::TyClosure(did, _) |
-                    ty::TyForeign(did) |
-                    ty::TyFnDef(did, _) => Some(did),
-                    ty::TyAdt(def, _) => Some(def.did),
+                    ty::Closure(did, _) |
+                    ty::Foreign(did) |
+                    ty::FnDef(did, _) => Some(did),
+                    ty::Adt(def, _) => Some(def.did),
                     _ => None,
                 };
                 let found_span = found_did.and_then(|did| {
@@ -795,14 +796,14 @@ pub fn report_selection_error(&self,
                 }).map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
 
                 let found = match found_trait_ref.skip_binder().substs.type_at(1).sty {
-                    ty::TyTuple(ref tys) => tys.iter()
+                    ty::Tuple(ref tys) => tys.iter()
                         .map(|_| ArgKind::empty()).collect::<Vec<_>>(),
                     _ => vec![ArgKind::empty()],
                 };
                 let expected = match expected_trait_ref.skip_binder().substs.type_at(1).sty {
-                    ty::TyTuple(ref tys) => tys.iter()
+                    ty::Tuple(ref tys) => tys.iter()
                         .map(|t| match t.sty {
-                            ty::TypeVariants::TyTuple(ref tys) => ArgKind::Tuple(
+                            ty::Tuple(ref tys) => ArgKind::Tuple(
                                 Some(span),
                                 tys.iter()
                                     .map(|ty| ("_".to_owned(), ty.sty.to_string()))
@@ -864,7 +865,7 @@ fn suggest_borrow_on_unsized_slice(&self,
                                        err: &mut DiagnosticBuilder<'tcx>) {
         if let &ObligationCauseCode::VariableType(node_id) = code {
             let parent_node = self.tcx.hir.get_parent_node(node_id);
-            if let Some(hir::map::NodeLocal(ref local)) = self.tcx.hir.find(parent_node) {
+            if let Some(Node::Local(ref local)) = self.tcx.hir.find(parent_node) {
                 if let Some(ref expr) = local.init {
                     if let hir::ExprKind::Index(_, _) = expr.node {
                         if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
@@ -899,7 +900,7 @@ fn suggest_remove_reference(&self,
             let mut trait_type = trait_ref.self_ty();
 
             for refs_remaining in 0..refs_number {
-                if let ty::TypeVariants::TyRef(_, t_type, _) = trait_type.sty {
+                if let ty::Ref(_, t_type, _) = trait_type.sty {
                     trait_type = t_type;
 
                     let substs = self.tcx.mk_substs_trait(trait_type, &[]);
@@ -917,7 +918,7 @@ fn suggest_remove_reference(&self,
                                                  remove_refs);
 
                         err.span_suggestion_short_with_applicability(
-                            sp, &format_str, String::from(""), Applicability::MachineApplicable
+                            sp, &format_str, String::new(), Applicability::MachineApplicable
                         );
                         break;
                     }
@@ -932,9 +933,9 @@ fn suggest_remove_reference(&self,
     /// returns a span and `ArgKind` information that describes the
     /// arguments it expects. This can be supplied to
     /// `report_arg_count_mismatch`.
-    pub fn get_fn_like_arguments(&self, node: hir::map::Node) -> (Span, Vec<ArgKind>) {
+    pub fn get_fn_like_arguments(&self, node: Node) -> (Span, Vec<ArgKind>) {
         match node {
-            hir::map::NodeExpr(&hir::Expr {
+            Node::Expr(&hir::Expr {
                 node: hir::ExprKind::Closure(_, ref _decl, id, span, _),
                 ..
             }) => {
@@ -961,17 +962,17 @@ pub fn get_fn_like_arguments(&self, node: hir::map::Node) -> (Span, Vec<ArgKind>
                     })
                     .collect::<Vec<ArgKind>>())
             }
-            hir::map::NodeItem(&hir::Item {
+            Node::Item(&hir::Item {
                 span,
                 node: hir::ItemKind::Fn(ref decl, ..),
                 ..
             }) |
-            hir::map::NodeImplItem(&hir::ImplItem {
+            Node::ImplItem(&hir::ImplItem {
                 span,
                 node: hir::ImplItemKind::Method(hir::MethodSig { ref decl, .. }, _),
                 ..
             }) |
-            hir::map::NodeTraitItem(&hir::TraitItem {
+            Node::TraitItem(&hir::TraitItem {
                 span,
                 node: hir::TraitItemKind::Method(hir::MethodSig { ref decl, .. }, _),
                 ..
@@ -987,7 +988,7 @@ pub fn get_fn_like_arguments(&self, node: hir::map::Node) -> (Span, Vec<ArgKind>
                     _ => ArgKind::Arg("_".to_owned(), "_".to_owned())
                 }).collect::<Vec<ArgKind>>())
             }
-            hir::map::NodeVariant(&hir::Variant {
+            Node::Variant(&hir::Variant {
                 span,
                 node: hir::VariantKind {
                     data: hir::VariantData::Tuple(ref fields, _),
@@ -1000,7 +1001,7 @@ pub fn get_fn_like_arguments(&self, node: hir::map::Node) -> (Span, Vec<ArgKind>
                      ArgKind::Arg(field.ident.to_string(), "_".to_string())
                  }).collect::<Vec<_>>())
             }
-            hir::map::NodeStructCtor(ref variant_data) => {
+            Node::StructCtor(ref variant_data) => {
                 (self.tcx.sess.source_map().def_span(self.tcx.hir.span(variant_data.id())),
                  variant_data.fields()
                     .iter().map(|_| ArgKind::Arg("_".to_owned(), "_".to_owned()))
@@ -1116,7 +1117,7 @@ pub fn report_arg_count_mismatch(
                                         .collect::<Vec<String>>()
                                         .join(", "))
                         } else {
-                            "".to_owned()
+                            String::new()
                         },
                     );
                     err.span_suggestion_with_applicability(
@@ -1143,7 +1144,7 @@ fn report_closure_arg_mismatch(&self,
         fn build_fn_sig_string<'a, 'gcx, 'tcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>,
                                                trait_ref: &ty::TraitRef<'tcx>) -> String {
             let inputs = trait_ref.substs.type_at(1);
-            let sig = if let ty::TyTuple(inputs) = inputs.sty {
+            let sig = if let ty::Tuple(inputs) = inputs.sty {
                 tcx.mk_fn_sig(
                     inputs.iter().map(|&x| x),
                     tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
@@ -1348,7 +1349,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ParamToVarFolder<'a, 'gcx, 'tcx>
             fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx }
 
             fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-                if let ty::TyParam(ty::ParamTy {name, ..}) = ty.sty {
+                if let ty::Param(ty::ParamTy {name, ..}) = ty.sty {
                     let infcx = self.infcx;
                     self.var_map.entry(ty).or_insert_with(||
                         infcx.next_ty_var(
@@ -1594,7 +1595,7 @@ fn empty() -> ArgKind {
     /// argument. This has no name (`_`) and no source spans..
     pub fn from_expected_ty(t: Ty<'_>) -> ArgKind {
         match t.sty {
-            ty::TyTuple(ref tys) => ArgKind::Tuple(
+            ty::Tuple(ref tys) => ArgKind::Tuple(
                 None,
                 tys.iter()
                    .map(|ty| ("_".to_owned(), ty.sty.to_string()))
index 5113f3cde32843b588faee72e8e485fd5d0e2677..9998db4ad1d48569f8ce45bd488d949a5f3b2467 100644 (file)
@@ -269,7 +269,8 @@ fn process_obligation(&mut self,
         // doing more work yet
         if !pending_obligation.stalled_on.is_empty() {
             if pending_obligation.stalled_on.iter().all(|&ty| {
-                let resolved_ty = self.selcx.infcx().shallow_resolve(&ty);
+                // Use the force-inlined variant of shallow_resolve() because this code is hot.
+                let resolved_ty = self.selcx.infcx().inlined_shallow_resolve(&ty);
                 resolved_ty == ty // nothing changed here
             }) {
                 debug!("process_predicate: pending obligation {:?} still stalled on {:?}",
@@ -540,7 +541,7 @@ fn trait_ref_type_vars<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 't
      .map(|t| selcx.infcx().resolve_type_vars_if_possible(&t))
      .filter(|t| t.has_infer_types())
      .flat_map(|t| t.walk())
-     .filter(|t| match t.sty { ty::TyInfer(_) => true, _ => false })
+     .filter(|t| match t.sty { ty::Infer(_) => true, _ => false })
      .collect()
 }
 
index 0ba94b5275cb2e1f90f9ebd5507a52b7e93b7b76..e2dbe88354060b2221957de9398ed8696e392ecd 100644 (file)
@@ -24,7 +24,7 @@
 use middle::region;
 use mir::interpret::ConstEvalErr;
 use ty::subst::Substs;
-use ty::{self, AdtKind, Slice, Ty, TyCtxt, GenericParamDefKind, ToPredicate};
+use ty::{self, AdtKind, List, Ty, TyCtxt, GenericParamDefKind, ToPredicate};
 use ty::error::{ExpectedFound, TypeError};
 use ty::fold::{TypeFolder, TypeFoldable, TypeVisitor};
 use infer::{InferCtxt};
@@ -325,7 +325,7 @@ pub enum Goal<'tcx> {
     CannotProve,
 }
 
-pub type Goals<'tcx> = &'tcx Slice<Goal<'tcx>>;
+pub type Goals<'tcx> = &'tcx List<Goal<'tcx>>;
 
 impl<'tcx> DomainGoal<'tcx> {
     pub fn into_goal(self) -> Goal<'tcx> {
@@ -357,7 +357,7 @@ pub enum Clause<'tcx> {
 }
 
 /// Multiple clauses.
-pub type Clauses<'tcx> = &'tcx Slice<Clause<'tcx>>;
+pub type Clauses<'tcx> = &'tcx List<Clause<'tcx>>;
 
 /// A "program clause" has the form `D :- G1, ..., Gn`. It is saying
 /// that the domain goal `D` is true if `G1...Gn` are provable. This
index aa4f63675d7341dbab16834fc61ecf64c88fc3f5..17d55b77625b2c5cc347cbec2229b5c4d9a9978d 100644 (file)
@@ -371,7 +371,7 @@ fn contains_illegal_self_type_reference(self,
         let mut error = false;
         ty.maybe_walk(|ty| {
             match ty.sty {
-                ty::TyParam(ref param_ty) => {
+                ty::Param(ref param_ty) => {
                     if param_ty.is_self() {
                         error = true;
                     }
@@ -379,7 +379,7 @@ fn contains_illegal_self_type_reference(self,
                     false // no contained types to walk
                 }
 
-                ty::TyProjection(ref data) => {
+                ty::Projection(ref data) => {
                     // This is a projected type `<Foo as SomeTrait>::X`.
 
                     // Compute supertraits of current trait lazily.
index 1224cdd76d85ba4891f1fea429392fd73bab3d62..939ba92c7badfdce7af71823f05079204bc405f2 100644 (file)
@@ -366,7 +366,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
 
         let ty = ty.super_fold_with(self);
         match ty.sty {
-            ty::TyAnon(def_id, substs) if !substs.has_escaping_regions() => { // (*)
+            ty::Anon(def_id, substs) if !substs.has_escaping_regions() => { // (*)
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal {
                     Reveal::UserFacing => ty,
@@ -393,7 +393,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 }
             }
 
-            ty::TyProjection(ref data) if !data.has_escaping_regions() => { // (*)
+            ty::Projection(ref data) if !data.has_escaping_regions() => { // (*)
 
                 // (*) This is kind of hacky -- we need to be able to
                 // handle normalization within binders because
@@ -812,10 +812,10 @@ fn get_paranoid_cache_value_obligation<'a, 'gcx, 'tcx>(
 /// return an associated obligation that, when fulfilled, will lead to
 /// an error.
 ///
-/// Note that we used to return `TyError` here, but that was quite
+/// Note that we used to return `Error` here, but that was quite
 /// dubious -- the premise was that an error would *eventually* be
 /// reported, when the obligation was processed. But in general once
-/// you see a `TyError` you are supposed to be able to assume that an
+/// you see a `Error` you are supposed to be able to assume that an
 /// error *has been* reported, so that you can take whatever heuristic
 /// paths you want to take. To make things worse, it was possible for
 /// cycles to arise, where you basically had a setup like `<MyType<$0>
@@ -983,11 +983,11 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>(
     let tcx = selcx.tcx();
     // Check whether the self-type is itself a projection.
     let (def_id, substs) = match obligation_trait_ref.self_ty().sty {
-        ty::TyProjection(ref data) => {
+        ty::Projection(ref data) => {
             (data.trait_ref(tcx).def_id, data.substs)
         }
-        ty::TyAnon(def_id, substs) => (def_id, substs),
-        ty::TyInfer(ty::TyVar(_)) => {
+        ty::Anon(def_id, substs) => (def_id, substs),
+        ty::Infer(ty::TyVar(_)) => {
             // If the self-type is an inference variable, then it MAY wind up
             // being a projected type, so induce an ambiguity.
             candidate_set.mark_ambiguous();
@@ -1265,7 +1265,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
     debug!("confirm_object_candidate(object_ty={:?})",
            object_ty);
     let data = match object_ty.sty {
-        ty::TyDynamic(ref data, ..) => data,
+        ty::Dynamic(ref data, ..) => data,
         _ => {
             span_bug!(
                 obligation.cause.span,
@@ -1506,7 +1506,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
         // This means that the impl is missing a definition for the
         // associated type. This error will be reported by the type
         // checker method `check_impl_items_against_trait`, so here we
-        // just return TyError.
+        // just return Error.
         debug!("confirm_impl_candidate: no associated type {:?} for {:?}",
                assoc_ty.item.ident,
                obligation.predicate);
index 56484e17777fe46af755c223ecf258651ecbeab2..3a0f7700824097078d16dda4dc19e3270c3ac742 100644 (file)
@@ -10,7 +10,7 @@
 
 use infer::at::At;
 use infer::InferOk;
-use rustc_data_structures::small_vec::SmallVec;
+use smallvec::SmallVec;
 use std::iter::FromIterator;
 use syntax::source_map::Span;
 use ty::subst::Kind;
@@ -82,7 +82,7 @@ pub fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec<Kind<'tcx>>> {
         // Errors and ambiuity in dropck occur in two cases:
         // - unresolved inference variables at the end of typeck
         // - non well-formed types where projections cannot be resolved
-        // Either of these should hvae created an error before.
+        // Either of these should have created an error before.
         tcx.sess
             .delay_span_bug(span, "dtorck encountered internal error");
         return InferOk {
@@ -214,34 +214,34 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
         // None of these types have a destructor and hence they do not
         // require anything in particular to outlive the dtor's
         // execution.
-        ty::TyInfer(ty::FreshIntTy(_))
-        | ty::TyInfer(ty::FreshFloatTy(_))
-        | ty::TyBool
-        | ty::TyInt(_)
-        | ty::TyUint(_)
-        | ty::TyFloat(_)
-        | ty::TyNever
-        | ty::TyFnDef(..)
-        | ty::TyFnPtr(_)
-        | ty::TyChar
-        | ty::TyGeneratorWitness(..)
-        | ty::TyRawPtr(_)
-        | ty::TyRef(..)
-        | ty::TyStr
-        | ty::TyForeign(..)
-        | ty::TyError => true,
+        ty::Infer(ty::FreshIntTy(_))
+        | ty::Infer(ty::FreshFloatTy(_))
+        | ty::Bool
+        | ty::Int(_)
+        | ty::Uint(_)
+        | ty::Float(_)
+        | ty::Never
+        | ty::FnDef(..)
+        | ty::FnPtr(_)
+        | ty::Char
+        | ty::GeneratorWitness(..)
+        | ty::RawPtr(_)
+        | ty::Ref(..)
+        | ty::Str
+        | ty::Foreign(..)
+        | ty::Error => true,
 
         // [T; N] and [T] have same properties as T.
-        ty::TyArray(ty, _) | ty::TySlice(ty) => trivial_dropck_outlives(tcx, ty),
+        ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, ty),
 
         // (T1..Tn) and closures have same properties as T1..Tn --
         // check if *any* of those are trivial.
-        ty::TyTuple(ref tys) => tys.iter().cloned().all(|t| trivial_dropck_outlives(tcx, t)),
-        ty::TyClosure(def_id, ref substs) => substs
+        ty::Tuple(ref tys) => tys.iter().cloned().all(|t| trivial_dropck_outlives(tcx, t)),
+        ty::Closure(def_id, ref substs) => substs
             .upvar_tys(def_id, tcx)
             .all(|t| trivial_dropck_outlives(tcx, t)),
 
-        ty::TyAdt(def, _) => {
+        ty::Adt(def, _) => {
             if Some(def.did) == tcx.lang_items().manually_drop() {
                 // `ManuallyDrop` never has a dtor.
                 true
@@ -255,11 +255,11 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
         }
 
         // The following *might* require a destructor: it would deeper inspection to tell.
-        ty::TyDynamic(..)
-        | ty::TyProjection(..)
-        | ty::TyParam(_)
-        | ty::TyAnon(..)
-        | ty::TyInfer(_)
-        | ty::TyGenerator(..) => false,
+        ty::Dynamic(..)
+        | ty::Projection(..)
+        | ty::Param(_)
+        | ty::Anon(..)
+        | ty::Infer(_)
+        | ty::Generator(..) => false,
     }
 }
index 93fcadceb1655a7af6cd1166fc10d7f622d0f124..6bd92678362544ac62522f02dcfbddd4ef7d8ffb 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use infer::InferCtxt;
-use rustc_data_structures::small_vec::SmallVec;
+use smallvec::SmallVec;
 use traits::{EvaluationResult, PredicateObligation, SelectionContext,
              TraitQueryMode, OverflowError};
 
index fab7289409c4f74d69962fab0611a63e8785dd11..8b4954cc501dd3aeac50a0cd7e22ca4f7eba32ac 100644 (file)
@@ -15,7 +15,7 @@
 use infer::at::At;
 use infer::{InferCtxt, InferOk};
 use mir::interpret::{ConstValue, GlobalId};
-use rustc_data_structures::small_vec::SmallVec;
+use smallvec::SmallVec;
 use traits::project::Normalized;
 use traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
 use ty::fold::{TypeFoldable, TypeFolder};
@@ -99,7 +99,7 @@ fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'tcx> {
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         let ty = ty.super_fold_with(self);
         match ty.sty {
-            ty::TyAnon(def_id, substs) if !substs.has_escaping_regions() => {
+            ty::Anon(def_id, substs) if !substs.has_escaping_regions() => {
                 // (*)
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal {
@@ -121,36 +121,14 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                         let concrete_ty = generic_ty.subst(self.tcx(), substs);
                         self.anon_depth += 1;
                         if concrete_ty == ty {
-                            // The type in question can only be inferred in terms of itself. This
-                            // is likely a user code issue, not a compiler issue. Thus, we will
-                            // induce a cycle error by calling the parent query again on the type.
-                            //
-                            // FIXME: Perhaps a better solution would be to have fold_ty()
-                            // itself be a query. Then, a type fold cycle would be detected
-                            // and reported more naturally as part of the query system, rather
-                            // than forcing it here.
-                            //
-                            // FIXME: Need a better span than just one pointing to the type def.
-                            // Should point to a defining use of the type that results in this
-                            // un-normalizable state.
-                            if let Some(param_env_lifted) =
-                                self.tcx().lift_to_global(&self.param_env)
-                            {
-                                if let Some(ty_lifted) = self.tcx().lift_to_global(&concrete_ty) {
-                                    let span = self.tcx().def_span(def_id);
-                                    self.tcx()
-                                        .global_tcx()
-                                        .at(span)
-                                        .normalize_ty_after_erasing_regions(
-                                            param_env_lifted.and(ty_lifted),
-                                        );
-                                    self.tcx().sess.abort_if_errors();
-                                }
-                            }
-                            // If a cycle error can't be emitted, indicate a NoSolution error
-                            // and let the caller handle it.
-                            self.error = true;
-                            return concrete_ty;
+                            bug!(
+                                "infinite recursion generic_ty: {:#?}, substs: {:#?}, \
+                                 concrete_ty: {:#?}, ty: {:#?}",
+                                generic_ty,
+                                substs,
+                                concrete_ty,
+                                ty
+                            );
                         }
                         let folded_ty = self.fold_ty(concrete_ty);
                         self.anon_depth -= 1;
@@ -159,7 +137,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 }
             }
 
-            ty::TyProjection(ref data) if !data.has_escaping_regions() => {
+            ty::Projection(ref data) if !data.has_escaping_regions() => {
                 // (*)
                 // (*) This is kind of hacky -- we need to be able to
                 // handle normalization within binders because
index 868b8dfc885439389d083b231c5a044dd4838822..47c8ee357fbe846e340ece253e68827e406e6fb4 100644 (file)
@@ -11,7 +11,7 @@
 use infer::InferCtxt;
 use syntax::ast;
 use syntax::source_map::Span;
-use rustc_data_structures::small_vec::SmallVec;
+use smallvec::SmallVec;
 use traits::{FulfillmentContext, ObligationCause, TraitEngine, TraitEngineExt};
 use traits::query::NoSolution;
 use ty::{self, Ty, TyCtxt};
index 737388ad411017541abb3aff5490b4e9b7de896d..6a5ef75a660ba454027c9b9c8749039e6cd7d944 100644 (file)
@@ -102,8 +102,14 @@ fn scrape_region_constraints<'gcx, 'tcx, R>(
 
     let region_constraint_data = infcx.take_and_reset_region_constraints();
 
-    let outlives =
-        query_result::make_query_outlives(infcx.tcx, region_obligations, &region_constraint_data);
+    let outlives = query_result::make_query_outlives(
+        infcx.tcx,
+        region_obligations
+            .iter()
+            .map(|(_, r_o)| (r_o.sup_type, r_o.sub_region))
+            .map(|(ty, r)| (infcx.resolve_type_vars_if_possible(&ty), r)),
+        &region_constraint_data,
+    );
 
     if outlives.is_empty() {
         Ok((value, None))
diff --git a/src/librustc/traits/query/type_op/implied_outlives_bounds.rs b/src/librustc/traits/query/type_op/implied_outlives_bounds.rs
new file mode 100644 (file)
index 0000000..27534bc
--- /dev/null
@@ -0,0 +1,80 @@
+// 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 infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryResult};
+use traits::query::outlives_bounds::OutlivesBound;
+use traits::query::Fallible;
+use ty::{ParamEnvAnd, Ty, TyCtxt};
+
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct ImpliedOutlivesBounds<'tcx> {
+    pub ty: Ty<'tcx>,
+}
+
+impl<'tcx> ImpliedOutlivesBounds<'tcx> {
+    pub fn new(ty: Ty<'tcx>) -> Self {
+        ImpliedOutlivesBounds { ty }
+    }
+}
+
+impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for ImpliedOutlivesBounds<'tcx> {
+    type QueryResult = Vec<OutlivesBound<'tcx>>;
+
+    fn try_fast_path(
+        _tcx: TyCtxt<'_, 'gcx, 'tcx>,
+        _key: &ParamEnvAnd<'tcx, Self>,
+    ) -> Option<Self::QueryResult> {
+        None
+    }
+
+    fn perform_query(
+        tcx: TyCtxt<'_, 'gcx, 'tcx>,
+        canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
+    ) -> Fallible<CanonicalizedQueryResult<'gcx, Self::QueryResult>> {
+        // FIXME the query should take a `ImpliedOutlivesBounds`
+        let Canonical {
+            variables,
+            value:
+                ParamEnvAnd {
+                    param_env,
+                    value: ImpliedOutlivesBounds { ty },
+                },
+        } = canonicalized;
+        let canonicalized = Canonical {
+            variables,
+            value: param_env.and(ty),
+        };
+
+        tcx.implied_outlives_bounds(canonicalized)
+    }
+
+    fn shrink_to_tcx_lifetime(
+        v: &'a CanonicalizedQueryResult<'gcx, Self::QueryResult>,
+    ) -> &'a Canonical<'tcx, QueryResult<'tcx, Self::QueryResult>> {
+        v
+    }
+}
+
+BraceStructTypeFoldableImpl! {
+    impl<'tcx> TypeFoldable<'tcx> for ImpliedOutlivesBounds<'tcx> {
+        ty,
+    }
+}
+
+BraceStructLiftImpl! {
+    impl<'a, 'tcx> Lift<'tcx> for ImpliedOutlivesBounds<'a> {
+        type Lifted = ImpliedOutlivesBounds<'tcx>;
+        ty,
+    }
+}
+
+impl_stable_hash_for! {
+    struct ImpliedOutlivesBounds<'tcx> { ty }
+}
index be5e2838963ee2c906cd448b8f245ef8a8714a85..8e4236d1754c2d820109f3a0128b13e77481ca65 100644 (file)
@@ -11,7 +11,7 @@
 use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryRegionConstraint,
                        QueryResult};
 use infer::{InferCtxt, InferOk};
-use rustc_data_structures::small_vec::SmallVec;
+use smallvec::SmallVec;
 use std::fmt;
 use std::rc::Rc;
 use traits::query::Fallible;
@@ -21,6 +21,7 @@
 
 pub mod custom;
 pub mod eq;
+pub mod implied_outlives_bounds;
 pub mod normalize;
 pub mod outlives;
 pub mod prove_predicate;
index ea96c30502680362db489f3af847504fd2a8cede..69bdeec6eea230099bd209572893ea8542b7753a 100644 (file)
@@ -120,13 +120,13 @@ pub fn intercrate_ambiguity_hint(&self) -> String {
             &IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => {
                 let self_desc = if let &Some(ref ty) = self_desc {
                     format!(" for type `{}`", ty)
-                } else { "".to_string() };
+                } else { String::new() };
                 format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc)
             }
             &IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => {
                 let self_desc = if let &Some(ref ty) = self_desc {
                     format!(" for type `{}`", ty)
-                } else { "".to_string() };
+                } else { String::new() };
                 format!("upstream crates may add new impl of trait `{}`{} \
                          in future versions",
                         trait_desc, self_desc)
@@ -1128,7 +1128,7 @@ fn candidate_from_obligation_no_cache<'o>(&mut self,
                                               -> SelectionResult<'tcx, SelectionCandidate<'tcx>>
     {
         if stack.obligation.predicate.references_error() {
-            // If we encounter a `TyError`, we generally prefer the
+            // If we encounter a `Error`, we generally prefer the
             // most "optimistic" result in response -- that is, the
             // one least likely to report downstream errors. But
             // because this routine is shared by coherence and by
@@ -1492,8 +1492,8 @@ fn assemble_candidates_from_projected_tys(&mut self,
         // before we go into the whole skolemization thing, just
         // quickly check if the self-type is a projection at all.
         match obligation.predicate.skip_binder().trait_ref.self_ty().sty {
-            ty::TyProjection(_) | ty::TyAnon(..) => {}
-            ty::TyInfer(ty::TyVar(_)) => {
+            ty::Projection(_) | ty::Anon(..) => {}
+            ty::Infer(ty::TyVar(_)) => {
                 span_bug!(obligation.cause.span,
                     "Self=_ should have been handled by assemble_candidates");
             }
@@ -1526,9 +1526,9 @@ fn match_projection_obligation_against_definition_bounds(
                skol_map);
 
         let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty {
-            ty::TyProjection(ref data) =>
+            ty::Projection(ref data) =>
                 (data.trait_ref(self.tcx()).def_id, data.substs),
-            ty::TyAnon(def_id, substs) => (def_id, substs),
+            ty::Anon(def_id, substs) => (def_id, substs),
             _ => {
                 span_bug!(
                     obligation.cause.span,
@@ -1661,7 +1661,7 @@ fn assemble_generator_candidates(&mut self,
         // type/region parameters
         let self_ty = *obligation.self_ty().skip_binder();
         match self_ty.sty {
-            ty::TyGenerator(..) => {
+            ty::Generator(..) => {
                 debug!("assemble_generator_candidates: self_ty={:?} obligation={:?}",
                        self_ty,
                        obligation);
@@ -1669,7 +1669,7 @@ fn assemble_generator_candidates(&mut self,
                 candidates.vec.push(GeneratorCandidate);
                 Ok(())
             }
-            ty::TyInfer(ty::TyVar(_)) => {
+            ty::Infer(ty::TyVar(_)) => {
                 debug!("assemble_generator_candidates: ambiguous self-type");
                 candidates.ambiguous = true;
                 return Ok(());
@@ -1698,7 +1698,7 @@ fn assemble_closure_candidates(&mut self,
         // touch bound regions, they just capture the in-scope
         // type/region parameters
         match obligation.self_ty().skip_binder().sty {
-            ty::TyClosure(closure_def_id, closure_substs) => {
+            ty::Closure(closure_def_id, closure_substs) => {
                 debug!("assemble_unboxed_candidates: kind={:?} obligation={:?}",
                        kind, obligation);
                 match self.infcx.closure_kind(closure_def_id, closure_substs) {
@@ -1715,7 +1715,7 @@ fn assemble_closure_candidates(&mut self,
                 };
                 Ok(())
             }
-            ty::TyInfer(ty::TyVar(_)) => {
+            ty::Infer(ty::TyVar(_)) => {
                 debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
                 candidates.ambiguous = true;
                 return Ok(());
@@ -1738,13 +1738,13 @@ fn assemble_fn_pointer_candidates(&mut self,
         // ok to skip binder because what we are inspecting doesn't involve bound regions
         let self_ty = *obligation.self_ty().skip_binder();
         match self_ty.sty {
-            ty::TyInfer(ty::TyVar(_)) => {
+            ty::Infer(ty::TyVar(_)) => {
                 debug!("assemble_fn_pointer_candidates: ambiguous self-type");
                 candidates.ambiguous = true; // could wind up being a fn() type
             }
 
             // provide an impl, but only for suitable `fn` pointers
-            ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+            ty::FnDef(..) | ty::FnPtr(_) => {
                 if let ty::FnSig {
                     unsafety: hir::Unsafety::Normal,
                     abi: Abi::Rust,
@@ -1804,20 +1804,20 @@ fn assemble_candidates_from_auto_impls(&mut self,
 
         if self.tcx().trait_is_auto(def_id) {
             match self_ty.sty {
-                ty::TyDynamic(..) => {
+                ty::Dynamic(..) => {
                     // For object types, we don't know what the closed
                     // over types are. This means we conservatively
                     // say nothing; a candidate may be added by
                     // `assemble_candidates_from_object_ty`.
                 }
-                ty::TyForeign(..) => {
+                ty::Foreign(..) => {
                     // Since the contents of foreign types is unknown,
                     // we don't add any `..` impl. Default traits could
                     // still be provided by a manual implementation for
                     // this trait and type.
                 }
-                ty::TyParam(..) |
-                ty::TyProjection(..) => {
+                ty::Param(..) |
+                ty::Projection(..) => {
                     // In these cases, we don't know what the actual
                     // type is.  Therefore, we cannot break it down
                     // into its constituent types. So we don't
@@ -1832,7 +1832,7 @@ fn assemble_candidates_from_auto_impls(&mut self,
                     // for an example of a test case that exercises
                     // this path.
                 }
-                ty::TyInfer(ty::TyVar(_)) => {
+                ty::Infer(ty::TyVar(_)) => {
                     // the auto impl might apply, we don't know
                     candidates.ambiguous = true;
                 }
@@ -1871,7 +1871,7 @@ fn assemble_candidates_from_object_ty(&mut self,
             // any LBR.
             let self_ty = this.tcx().erase_late_bound_regions(&obligation.self_ty());
             let poly_trait_ref = match self_ty.sty {
-                ty::TyDynamic(ref data, ..) => {
+                ty::Dynamic(ref data, ..) => {
                     if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
                         debug!("assemble_candidates_from_object_ty: matched builtin bound, \
                                     pushing candidate");
@@ -1884,7 +1884,7 @@ fn assemble_candidates_from_object_ty(&mut self,
                         None => return,
                     }
                 }
-                ty::TyInfer(ty::TyVar(_)) => {
+                ty::Infer(ty::TyVar(_)) => {
                     debug!("assemble_candidates_from_object_ty: ambiguous");
                     candidates.ambiguous = true; // could wind up being an object type
                     return;
@@ -1953,7 +1953,7 @@ fn assemble_candidates_for_unsizing(&mut self,
 
         let may_apply = match (&source.sty, &target.sty) {
             // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
-            (&ty::TyDynamic(ref data_a, ..), &ty::TyDynamic(ref data_b, ..)) => {
+            (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
                 // Upcasts permit two things:
                 //
                 // 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo`
@@ -1975,28 +1975,28 @@ fn assemble_candidates_for_unsizing(&mut self,
             }
 
             // T -> Trait.
-            (_, &ty::TyDynamic(..)) => true,
+            (_, &ty::Dynamic(..)) => true,
 
             // Ambiguous handling is below T -> Trait, because inference
             // variables can still implement Unsize<Trait> and nested
             // obligations will have the final say (likely deferred).
-            (&ty::TyInfer(ty::TyVar(_)), _) |
-            (_, &ty::TyInfer(ty::TyVar(_))) => {
+            (&ty::Infer(ty::TyVar(_)), _) |
+            (_, &ty::Infer(ty::TyVar(_))) => {
                 debug!("assemble_candidates_for_unsizing: ambiguous");
                 candidates.ambiguous = true;
                 false
             }
 
             // [T; n] -> [T].
-            (&ty::TyArray(..), &ty::TySlice(_)) => true,
+            (&ty::Array(..), &ty::Slice(_)) => true,
 
             // Struct<T> -> Struct<U>.
-            (&ty::TyAdt(def_id_a, _), &ty::TyAdt(def_id_b, _)) if def_id_a.is_struct() => {
+            (&ty::Adt(def_id_a, _), &ty::Adt(def_id_b, _)) if def_id_a.is_struct() => {
                 def_id_a == def_id_b
             }
 
             // (.., T) -> (.., U).
-            (&ty::TyTuple(tys_a), &ty::TyTuple(tys_b)) => {
+            (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
                 tys_a.len() == tys_b.len()
             }
 
@@ -2179,23 +2179,23 @@ fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>)
             obligation.predicate.skip_binder().self_ty());
 
         match self_ty.sty {
-            ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) |
-            ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
-            ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyRawPtr(..) |
-            ty::TyChar | ty::TyRef(..) | ty::TyGenerator(..) |
-            ty::TyGeneratorWitness(..) | ty::TyArray(..) | ty::TyClosure(..) |
-            ty::TyNever | ty::TyError => {
+            ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) |
+            ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) |
+            ty::FnDef(..) | ty::FnPtr(_) | ty::RawPtr(..) |
+            ty::Char | ty::Ref(..) | ty::Generator(..) |
+            ty::GeneratorWitness(..) | ty::Array(..) | ty::Closure(..) |
+            ty::Never | ty::Error => {
                 // safe for everything
                 Where(ty::Binder::dummy(Vec::new()))
             }
 
-            ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) | ty::TyForeign(..) => None,
+            ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => None,
 
-            ty::TyTuple(tys) => {
+            ty::Tuple(tys) => {
                 Where(ty::Binder::bind(tys.last().into_iter().cloned().collect()))
             }
 
-            ty::TyAdt(def, substs) => {
+            ty::Adt(def, substs) => {
                 let sized_crit = def.sized_constraint(self.tcx());
                 // (*) binder moved here
                 Where(ty::Binder::bind(
@@ -2203,13 +2203,13 @@ fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>)
                 ))
             }
 
-            ty::TyProjection(_) | ty::TyParam(_) | ty::TyAnon(..) => None,
-            ty::TyInfer(ty::TyVar(_)) => Ambiguous,
+            ty::Projection(_) | ty::Param(_) | ty::Anon(..) => None,
+            ty::Infer(ty::TyVar(_)) => Ambiguous,
 
-            ty::TyInfer(ty::CanonicalTy(_)) |
-            ty::TyInfer(ty::FreshTy(_)) |
-            ty::TyInfer(ty::FreshIntTy(_)) |
-            ty::TyInfer(ty::FreshFloatTy(_)) => {
+            ty::Infer(ty::CanonicalTy(_)) |
+            ty::Infer(ty::FreshTy(_)) |
+            ty::Infer(ty::FreshIntTy(_)) |
+            ty::Infer(ty::FreshFloatTy(_)) => {
                 bug!("asked to assemble builtin bounds of unexpected type: {:?}",
                      self_ty);
             }
@@ -2226,35 +2226,35 @@ fn copy_clone_conditions(&mut self, obligation: &TraitObligation<'tcx>)
         use self::BuiltinImplConditions::{Ambiguous, None, Where};
 
         match self_ty.sty {
-            ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) |
-            ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyError => {
+            ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) |
+            ty::FnDef(..) | ty::FnPtr(_) | ty::Error => {
                 Where(ty::Binder::dummy(Vec::new()))
             }
 
-            ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
-            ty::TyChar | ty::TyRawPtr(..) | ty::TyNever |
-            ty::TyRef(_, _, hir::MutImmutable) => {
+            ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) |
+            ty::Char | ty::RawPtr(..) | ty::Never |
+            ty::Ref(_, _, hir::MutImmutable) => {
                 // Implementations provided in libcore
                 None
             }
 
-            ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) |
-            ty::TyGenerator(..) | ty::TyGeneratorWitness(..) | ty::TyForeign(..) |
-            ty::TyRef(_, _, hir::MutMutable) => {
+            ty::Dynamic(..) | ty::Str | ty::Slice(..) |
+            ty::Generator(..) | ty::GeneratorWitness(..) | ty::Foreign(..) |
+            ty::Ref(_, _, hir::MutMutable) => {
                 None
             }
 
-            ty::TyArray(element_ty, _) => {
+            ty::Array(element_ty, _) => {
                 // (*) binder moved here
                 Where(ty::Binder::bind(vec![element_ty]))
             }
 
-            ty::TyTuple(tys) => {
+            ty::Tuple(tys) => {
                 // (*) binder moved here
                 Where(ty::Binder::bind(tys.to_vec()))
             }
 
-            ty::TyClosure(def_id, substs) => {
+            ty::Closure(def_id, substs) => {
                 let trait_id = obligation.predicate.def_id();
                 let is_copy_trait = Some(trait_id) == self.tcx().lang_items().copy_trait();
                 let is_clone_trait = Some(trait_id) == self.tcx().lang_items().clone_trait();
@@ -2265,22 +2265,22 @@ fn copy_clone_conditions(&mut self, obligation: &TraitObligation<'tcx>)
                 }
             }
 
-            ty::TyAdt(..) | ty::TyProjection(..) | ty::TyParam(..) | ty::TyAnon(..) => {
+            ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Anon(..) => {
                 // Fallback to whatever user-defined impls exist in this case.
                 None
             }
 
-            ty::TyInfer(ty::TyVar(_)) => {
+            ty::Infer(ty::TyVar(_)) => {
                 // Unbound type variable. Might or might not have
                 // applicable impls and so forth, depending on what
                 // those type variables wind up being bound to.
                 Ambiguous
             }
 
-            ty::TyInfer(ty::CanonicalTy(_)) |
-            ty::TyInfer(ty::FreshTy(_)) |
-            ty::TyInfer(ty::FreshIntTy(_)) |
-            ty::TyInfer(ty::FreshFloatTy(_)) => {
+            ty::Infer(ty::CanonicalTy(_)) |
+            ty::Infer(ty::FreshTy(_)) |
+            ty::Infer(ty::FreshIntTy(_)) |
+            ty::Infer(ty::FreshFloatTy(_)) => {
                 bug!("asked to assemble builtin bounds of unexpected type: {:?}",
                      self_ty);
             }
@@ -2300,58 +2300,58 @@ fn copy_clone_conditions(&mut self, obligation: &TraitObligation<'tcx>)
     /// ```
     fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
         match t.sty {
-            ty::TyUint(_) |
-            ty::TyInt(_) |
-            ty::TyBool |
-            ty::TyFloat(_) |
-            ty::TyFnDef(..) |
-            ty::TyFnPtr(_) |
-            ty::TyStr |
-            ty::TyError |
-            ty::TyInfer(ty::IntVar(_)) |
-            ty::TyInfer(ty::FloatVar(_)) |
-            ty::TyNever |
-            ty::TyChar => {
+            ty::Uint(_) |
+            ty::Int(_) |
+            ty::Bool |
+            ty::Float(_) |
+            ty::FnDef(..) |
+            ty::FnPtr(_) |
+            ty::Str |
+            ty::Error |
+            ty::Infer(ty::IntVar(_)) |
+            ty::Infer(ty::FloatVar(_)) |
+            ty::Never |
+            ty::Char => {
                 Vec::new()
             }
 
-            ty::TyDynamic(..) |
-            ty::TyParam(..) |
-            ty::TyForeign(..) |
-            ty::TyProjection(..) |
-            ty::TyInfer(ty::CanonicalTy(_)) |
-            ty::TyInfer(ty::TyVar(_)) |
-            ty::TyInfer(ty::FreshTy(_)) |
-            ty::TyInfer(ty::FreshIntTy(_)) |
-            ty::TyInfer(ty::FreshFloatTy(_)) => {
+            ty::Dynamic(..) |
+            ty::Param(..) |
+            ty::Foreign(..) |
+            ty::Projection(..) |
+            ty::Infer(ty::CanonicalTy(_)) |
+            ty::Infer(ty::TyVar(_)) |
+            ty::Infer(ty::FreshTy(_)) |
+            ty::Infer(ty::FreshIntTy(_)) |
+            ty::Infer(ty::FreshFloatTy(_)) => {
                 bug!("asked to assemble constituent types of unexpected type: {:?}",
                      t);
             }
 
-            ty::TyRawPtr(ty::TypeAndMut { ty: element_ty, ..}) |
-            ty::TyRef(_, element_ty, _) => {
+            ty::RawPtr(ty::TypeAndMut { ty: element_ty, ..}) |
+            ty::Ref(_, element_ty, _) => {
                 vec![element_ty]
             },
 
-            ty::TyArray(element_ty, _) | ty::TySlice(element_ty) => {
+            ty::Array(element_ty, _) | ty::Slice(element_ty) => {
                 vec![element_ty]
             }
 
-            ty::TyTuple(ref tys) => {
+            ty::Tuple(ref tys) => {
                 // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
                 tys.to_vec()
             }
 
-            ty::TyClosure(def_id, ref substs) => {
+            ty::Closure(def_id, ref substs) => {
                 substs.upvar_tys(def_id, self.tcx()).collect()
             }
 
-            ty::TyGenerator(def_id, ref substs, _) => {
+            ty::Generator(def_id, ref substs, _) => {
                 let witness = substs.witness(def_id, self.tcx());
                 substs.upvar_tys(def_id, self.tcx()).chain(iter::once(witness)).collect()
             }
 
-            ty::TyGeneratorWitness(types) => {
+            ty::GeneratorWitness(types) => {
                 // This is sound because no regions in the witness can refer to
                 // the binder outside the witness. So we'll effectivly reuse
                 // the implicit binder around the witness.
@@ -2359,17 +2359,17 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
             }
 
             // for `PhantomData<T>`, we pass `T`
-            ty::TyAdt(def, substs) if def.is_phantom_data() => {
+            ty::Adt(def, substs) if def.is_phantom_data() => {
                 substs.types().collect()
             }
 
-            ty::TyAdt(def, substs) => {
+            ty::Adt(def, substs) => {
                 def.all_fields()
                     .map(|f| f.ty(self.tcx(), substs))
                     .collect()
             }
 
-            ty::TyAnon(def_id, substs) => {
+            ty::Anon(def_id, substs) => {
                 // We can resolve the `impl Trait` to its concrete type,
                 // which enforces a DAG between the functions requiring
                 // the auto trait bounds in question.
@@ -2728,7 +2728,7 @@ fn confirm_object_candidate(&mut self,
         // case that results. -nmatsakis
         let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
         let poly_trait_ref = match self_ty.sty {
-            ty::TyDynamic(ref data, ..) => {
+            ty::Dynamic(ref data, ..) => {
                 data.principal().unwrap().with_self_ty(self.tcx(), self_ty)
             }
             _ => {
@@ -2823,7 +2823,7 @@ fn confirm_generator_candidate(&mut self,
         // type/region parameters
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
         let (generator_def_id, substs) = match self_ty.sty {
-            ty::TyGenerator(id, substs, _) => (id, substs),
+            ty::Generator(id, substs, _) => (id, substs),
             _ => bug!("closure candidate for non-closure {:?}", obligation)
         };
 
@@ -2879,7 +2879,7 @@ fn confirm_closure_candidate(&mut self,
         // type/region parameters
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
         let (closure_def_id, substs) = match self_ty.sty {
-            ty::TyClosure(id, substs) => (id, substs),
+            ty::Closure(id, substs) => (id, substs),
             _ => bug!("closure candidate for non-closure {:?}", obligation)
         };
 
@@ -2976,7 +2976,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
         let mut nested = vec![];
         match (&source.sty, &target.sty) {
             // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
-            (&ty::TyDynamic(ref data_a, r_a), &ty::TyDynamic(ref data_b, r_b)) => {
+            (&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
                 // See assemble_candidates_for_unsizing for more info.
                 let existential_predicates = data_a.map_bound(|data_a| {
                     let principal = data_a.principal();
@@ -3005,7 +3005,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
             }
 
             // T -> Trait.
-            (_, &ty::TyDynamic(ref data, r)) => {
+            (_, &ty::Dynamic(ref data, r)) => {
                 let mut object_dids =
                     data.auto_traits().chain(data.principal().map(|p| p.def_id()));
                 if let Some(did) = object_dids.find(|did| {
@@ -3048,7 +3048,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
             }
 
             // [T; n] -> [T].
-            (&ty::TyArray(a, _), &ty::TySlice(b)) => {
+            (&ty::Array(a, _), &ty::Slice(b)) => {
                 let InferOk { obligations, .. } =
                     self.infcx.at(&obligation.cause, obligation.param_env)
                               .eq(b, a)
@@ -3057,7 +3057,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
             }
 
             // Struct<T> -> Struct<U>.
-            (&ty::TyAdt(def, substs_a), &ty::TyAdt(_, substs_b)) => {
+            (&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => {
                 let fields = def
                     .all_fields()
                     .map(|f| tcx.type_of(f.did))
@@ -3072,7 +3072,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 let mut ty_params = BitArray::new(substs_a.types().count());
                 let mut found = false;
                 for ty in field.walk() {
-                    if let ty::TyParam(p) = ty.sty {
+                    if let ty::Param(p) = ty.sty {
                         ty_params.insert(p.idx as usize);
                         found = true;
                     }
@@ -3082,7 +3082,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 }
 
                 // Replace type parameters used in unsizing with
-                // TyError and ensure they do not affect any other fields.
+                // Error and ensure they do not affect any other fields.
                 // This could be checked after type collection for any struct
                 // with a potentially unsized trailing field.
                 let params = substs_a.iter().enumerate().map(|(i, &k)| {
@@ -3130,7 +3130,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
             }
 
             // (.., T) -> (.., U).
-            (&ty::TyTuple(tys_a), &ty::TyTuple(tys_b)) => {
+            (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
                 assert_eq!(tys_a.len(), tys_b.len());
 
                 // The last field of the tuple has to exist.
index caebcbec3903e4569dd029aacd8428d11517fb04..9343eff9e79b4f2f43407ade6b09ea0e74d85a8e 100644 (file)
@@ -90,7 +90,7 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                 .unwrap()
                                 .subst(infcx.tcx, &source_substs);
 
-    // translate the Self and TyParam parts of the substitution, since those
+    // translate the Self and Param parts of the substitution, since those
     // vary across impls
     let target_substs = match target_node {
         specialization_graph::Node::Impl(target_impl) => {
index 9292b42eb525e751a8308c6eb348a9aa4537621e..10e930d1c92d9a58b3f08632f86b97a27db9aa06 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use chalk_engine;
-use rustc_data_structures::accumulate_vec::AccumulateVec;
+use smallvec::SmallVec;
 use traits;
 use traits::project::Normalized;
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
@@ -620,11 +620,11 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Goal<'a> {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<traits::Goal<'tcx>> {
+impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<traits::Goal<'tcx>> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         let v = self.iter()
             .map(|t| t.fold_with(folder))
-            .collect::<AccumulateVec<[_; 8]>>();
+            .collect::<SmallVec<[_; 8]>>();
         folder.tcx().intern_goals(&v)
     }
 
@@ -658,11 +658,11 @@ impl<'tcx> TypeFoldable<'tcx> for traits::Clause<'tcx> {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<traits::Clause<'tcx>> {
+impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<traits::Clause<'tcx>> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         let v = self.iter()
             .map(|t| t.fold_with(folder))
-            .collect::<AccumulateVec<[_; 8]>>();
+            .collect::<SmallVec<[_; 8]>>();
         folder.tcx().intern_clauses(&v)
     }
 
index 047bfcc8c6f59e80f06eefdd57c1b77541113b4b..c9b0e97c9b05c61847e79409a6232055c2ba1647 100644 (file)
@@ -67,18 +67,18 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         if a == b { return Ok(a); }
 
         match (&a.sty, &b.sty) {
-            (_, &ty::TyInfer(ty::FreshTy(_))) |
-            (_, &ty::TyInfer(ty::FreshIntTy(_))) |
-            (_, &ty::TyInfer(ty::FreshFloatTy(_))) => {
+            (_, &ty::Infer(ty::FreshTy(_))) |
+            (_, &ty::Infer(ty::FreshIntTy(_))) |
+            (_, &ty::Infer(ty::FreshFloatTy(_))) => {
                 Ok(a)
             }
 
-            (&ty::TyInfer(_), _) |
-            (_, &ty::TyInfer(_)) => {
+            (&ty::Infer(_), _) |
+            (_, &ty::Infer(_)) => {
                 Err(TypeError::Sorts(relate::expected_found(self, &a, &b)))
             }
 
-            (&ty::TyError, _) | (_, &ty::TyError) => {
+            (&ty::Error, _) | (_, &ty::Error) => {
                 Ok(self.tcx().types.err)
             }
 
index 7593d4ed24e768f71872dad84892d6c79edb1e98..c0861abb774deda27da77623d852da04f2d8f316 100644 (file)
@@ -60,18 +60,18 @@ pub enum CastKind {
 impl<'tcx> CastTy<'tcx> {
     pub fn from_ty(t: Ty<'tcx>) -> Option<CastTy<'tcx>> {
         match t.sty {
-            ty::TyBool => Some(CastTy::Int(IntTy::Bool)),
-            ty::TyChar => Some(CastTy::Int(IntTy::Char)),
-            ty::TyInt(_) => Some(CastTy::Int(IntTy::I)),
-            ty::TyInfer(ty::InferTy::IntVar(_)) => Some(CastTy::Int(IntTy::I)),
-            ty::TyInfer(ty::InferTy::FloatVar(_)) => Some(CastTy::Float),
-            ty::TyUint(u) => Some(CastTy::Int(IntTy::U(u))),
-            ty::TyFloat(_) => Some(CastTy::Float),
-            ty::TyAdt(d,_) if d.is_enum() && d.is_payloadfree() =>
+            ty::Bool => Some(CastTy::Int(IntTy::Bool)),
+            ty::Char => Some(CastTy::Int(IntTy::Char)),
+            ty::Int(_) => Some(CastTy::Int(IntTy::I)),
+            ty::Infer(ty::InferTy::IntVar(_)) => Some(CastTy::Int(IntTy::I)),
+            ty::Infer(ty::InferTy::FloatVar(_)) => Some(CastTy::Float),
+            ty::Uint(u) => Some(CastTy::Int(IntTy::U(u))),
+            ty::Float(_) => Some(CastTy::Float),
+            ty::Adt(d,_) if d.is_enum() && d.is_payloadfree() =>
                 Some(CastTy::Int(IntTy::CEnum)),
-            ty::TyRawPtr(mt) => Some(CastTy::Ptr(mt)),
-            ty::TyRef(_, ty, mutbl) => Some(CastTy::RPtr(ty::TypeAndMut { ty, mutbl })),
-            ty::TyFnPtr(..) => Some(CastTy::FnPtr),
+            ty::RawPtr(mt) => Some(CastTy::Ptr(mt)),
+            ty::Ref(_, ty, mutbl) => Some(CastTy::RPtr(ty::TypeAndMut { ty, mutbl })),
+            ty::FnPtr(..) => Some(CastTy::FnPtr),
             _ => None,
         }
     }
index 967a3324cfb2a92113d202133085d0b80df2d9bb..cc3e8a458a01fe698d75f0697d8cbcce447742e5 100644 (file)
@@ -37,7 +37,7 @@ pub trait EncodableWithShorthand: Clone + Eq + Hash {
 }
 
 impl<'tcx> EncodableWithShorthand for Ty<'tcx> {
-    type Variant = ty::TypeVariants<'tcx>;
+    type Variant = ty::TyKind<'tcx>;
     fn variant(&self) -> &Self::Variant {
         &self.sty
     }
@@ -164,7 +164,7 @@ pub fn decode_ty<'a, 'tcx, D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
         })
     } else {
         let tcx = decoder.tcx();
-        Ok(tcx.mk_ty(ty::TypeVariants::decode(decoder)?))
+        Ok(tcx.mk_ty(ty::TyKind::decode(decoder)?))
     }
 }
 
@@ -212,7 +212,7 @@ pub fn decode_region<'a, 'tcx, D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D
 
 #[inline]
 pub fn decode_ty_slice<'a, 'tcx, D>(decoder: &mut D)
-                                    -> Result<&'tcx ty::Slice<Ty<'tcx>>, D::Error>
+                                    -> Result<&'tcx ty::List<Ty<'tcx>>, D::Error>
     where D: TyDecoder<'a, 'tcx>,
           'tcx: 'a,
 {
@@ -232,7 +232,7 @@ pub fn decode_adt_def<'a, 'tcx, D>(decoder: &mut D)
 
 #[inline]
 pub fn decode_existential_predicate_slice<'a, 'tcx, D>(decoder: &mut D)
-    -> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, D::Error>
+    -> Result<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>, D::Error>
     where D: TyDecoder<'a, 'tcx>,
           'tcx: 'a,
 {
@@ -366,10 +366,10 @@ fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::Slice<ty::Ty<'tcx>>>
+            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List<ty::Ty<'tcx>>>
             for $DecoderName<$($typaram),*> {
                 fn specialized_decode(&mut self)
-                                      -> Result<&'tcx ty::Slice<ty::Ty<'tcx>>, Self::Error> {
+                                      -> Result<&'tcx ty::List<ty::Ty<'tcx>>, Self::Error> {
                     decode_ty_slice(self)
                 }
             }
@@ -381,10 +381,10 @@ fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>
+            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>
                 for $DecoderName<$($typaram),*> {
                 fn specialized_decode(&mut self)
-                    -> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, Self::Error> {
+                    -> Result<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>, Self::Error> {
                     decode_existential_predicate_slice(self)
                 }
             }
index ef363459108c9b13d2090203224631f430481ec6..6981d92f05f00cf9ec4c96acf9e99d4adccf19e9 100644 (file)
 use ich::{StableHashingContext, NodeIdHashingMode};
 use infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
 use infer::outlives::free_region_map::FreeRegionMap;
-use middle::cstore::{CrateStoreDyn, LinkMeta};
+use middle::cstore::CrateStoreDyn;
 use middle::cstore::EncodedMetadata;
 use middle::lang_items;
 use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
 use middle::stability;
 use mir::{self, Mir, interpret};
 use mir::interpret::Allocation;
-use ty::subst::{Kind, Substs, Subst};
+use ty::subst::{CanonicalSubsts, Kind, Substs, Subst};
 use ty::ReprOptions;
 use traits;
 use traits::{Clause, Clauses, Goal, Goals};
 use ty::{self, Ty, TypeAndMut};
-use ty::{TyS, TypeVariants, Slice};
+use ty::{TyS, TyKind, List};
 use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const};
 use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
 use ty::RegionKind;
 use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
-use ty::TypeVariants::*;
+use ty::TyKind::*;
 use ty::GenericParamDefKind;
 use ty::layout::{LayoutDetails, TargetDataLayout};
 use ty::query;
@@ -52,7 +52,7 @@
 use ty::CanonicalTy;
 use util::nodemap::{DefIdSet, ItemLocalMap};
 use util::nodemap::{FxHashMap, FxHashSet};
-use rustc_data_structures::accumulate_vec::AccumulateVec;
+use smallvec::SmallVec;
 use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
                                            StableHasher, StableHasherResult,
                                            StableVec};
@@ -135,15 +135,15 @@ pub struct CtxtInterners<'tcx> {
     /// Specifically use a speedy hash algorithm for these hash sets,
     /// they're accessed quite often.
     type_: InternedSet<'tcx, TyS<'tcx>>,
-    type_list: InternedSet<'tcx, Slice<Ty<'tcx>>>,
+    type_list: InternedSet<'tcx, List<Ty<'tcx>>>,
     substs: InternedSet<'tcx, Substs<'tcx>>,
-    canonical_var_infos: InternedSet<'tcx, Slice<CanonicalVarInfo>>,
+    canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo>>,
     region: InternedSet<'tcx, RegionKind>,
-    existential_predicates: InternedSet<'tcx, Slice<ExistentialPredicate<'tcx>>>,
-    predicates: InternedSet<'tcx, Slice<Predicate<'tcx>>>,
+    existential_predicates: InternedSet<'tcx, List<ExistentialPredicate<'tcx>>>,
+    predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
     const_: InternedSet<'tcx, Const<'tcx>>,
-    clauses: InternedSet<'tcx, Slice<Clause<'tcx>>>,
-    goals: InternedSet<'tcx, Slice<Goal<'tcx>>>,
+    clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
+    goals: InternedSet<'tcx, List<Goal<'tcx>>>,
 }
 
 impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
@@ -167,7 +167,7 @@ fn new(arena: &'tcx SyncDroplessArena) -> CtxtInterners<'tcx> {
     fn intern_ty(
         local: &CtxtInterners<'tcx>,
         global: &CtxtInterners<'gcx>,
-        st: TypeVariants<'tcx>
+        st: TyKind<'tcx>
     ) -> Ty<'tcx> {
         let flags = super::flags::FlagComputation::for_sty(&st);
 
@@ -371,6 +371,18 @@ pub struct TypeckTables<'tcx> {
     /// other items.
     node_substs: ItemLocalMap<&'tcx Substs<'tcx>>,
 
+    /// Stores the substitutions that the user explicitly gave (if any)
+    /// attached to `id`. These will not include any inferred
+    /// values. The canonical form is used to capture things like `_`
+    /// or other unspecified values.
+    ///
+    /// Example:
+    ///
+    /// If the user wrote `foo.collect::<Vec<_>>()`, then the
+    /// canonical substitutions would include only `for<X> { Vec<X>
+    /// }`.
+    user_substs: ItemLocalMap<CanonicalSubsts<'tcx>>,
+
     adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
 
     /// Stores the actual binding mode for all instances of hir::BindingAnnotation.
@@ -444,6 +456,7 @@ pub fn empty(local_id_root: Option<DefId>) -> TypeckTables<'tcx> {
             user_provided_tys: ItemLocalMap(),
             node_types: ItemLocalMap(),
             node_substs: ItemLocalMap(),
+            user_substs: ItemLocalMap(),
             adjustments: ItemLocalMap(),
             pat_binding_modes: ItemLocalMap(),
             pat_adjustments: ItemLocalMap(),
@@ -561,6 +574,18 @@ pub fn node_substs_opt(&self, id: hir::HirId) -> Option<&'tcx Substs<'tcx>> {
         self.node_substs.get(&id.local_id).cloned()
     }
 
+    pub fn user_substs_mut(&mut self) -> LocalTableInContextMut<CanonicalSubsts<'tcx>> {
+        LocalTableInContextMut {
+            local_id_root: self.local_id_root,
+            data: &mut self.user_substs
+        }
+    }
+
+    pub fn user_substs(&self, id: hir::HirId) -> Option<CanonicalSubsts<'tcx>> {
+        validate_hir_id_for_typeck_tables(self.local_id_root, id, false);
+        self.user_substs.get(&id.local_id).cloned()
+    }
+
     // Returns the type of a pattern as a monotype. Like @expr_ty, this function
     // doesn't provide type parameter substitutions.
     pub fn pat_ty(&self, pat: &hir::Pat) -> Ty<'tcx> {
@@ -740,6 +765,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             ref user_provided_tys,
             ref node_types,
             ref node_substs,
+            ref user_substs,
             ref adjustments,
             ref pat_binding_modes,
             ref pat_adjustments,
@@ -762,6 +788,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             user_provided_tys.hash_stable(hcx, hasher);
             node_types.hash_stable(hcx, hasher);
             node_substs.hash_stable(hcx, hasher);
+            user_substs.hash_stable(hcx, hasher);
             adjustments.hash_stable(hcx, hasher);
             pat_binding_modes.hash_stable(hcx, hasher);
             pat_adjustments.hash_stable(hcx, hasher);
@@ -803,7 +830,7 @@ impl<'tcx> CommonTypes<'tcx> {
     fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
         // Ensure our type representation does not grow
         #[cfg(target_pointer_width = "64")]
-        assert!(mem::size_of::<ty::TypeVariants>() <= 24);
+        assert!(mem::size_of::<ty::TyKind>() <= 24);
         #[cfg(target_pointer_width = "64")]
         assert!(mem::size_of::<ty::TyS>() <= 32);
 
@@ -817,24 +844,24 @@ fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
             &*r
         };
         CommonTypes {
-            bool: mk(TyBool),
-            char: mk(TyChar),
-            never: mk(TyNever),
-            err: mk(TyError),
-            isize: mk(TyInt(ast::IntTy::Isize)),
-            i8: mk(TyInt(ast::IntTy::I8)),
-            i16: mk(TyInt(ast::IntTy::I16)),
-            i32: mk(TyInt(ast::IntTy::I32)),
-            i64: mk(TyInt(ast::IntTy::I64)),
-            i128: mk(TyInt(ast::IntTy::I128)),
-            usize: mk(TyUint(ast::UintTy::Usize)),
-            u8: mk(TyUint(ast::UintTy::U8)),
-            u16: mk(TyUint(ast::UintTy::U16)),
-            u32: mk(TyUint(ast::UintTy::U32)),
-            u64: mk(TyUint(ast::UintTy::U64)),
-            u128: mk(TyUint(ast::UintTy::U128)),
-            f32: mk(TyFloat(ast::FloatTy::F32)),
-            f64: mk(TyFloat(ast::FloatTy::F64)),
+            bool: mk(Bool),
+            char: mk(Char),
+            never: mk(Never),
+            err: mk(Error),
+            isize: mk(Int(ast::IntTy::Isize)),
+            i8: mk(Int(ast::IntTy::I8)),
+            i16: mk(Int(ast::IntTy::I16)),
+            i32: mk(Int(ast::IntTy::I32)),
+            i64: mk(Int(ast::IntTy::I64)),
+            i128: mk(Int(ast::IntTy::I128)),
+            usize: mk(Uint(ast::UintTy::Usize)),
+            u8: mk(Uint(ast::UintTy::U8)),
+            u16: mk(Uint(ast::UintTy::U16)),
+            u32: mk(Uint(ast::UintTy::U32)),
+            u64: mk(Uint(ast::UintTy::U64)),
+            u128: mk(Uint(ast::UintTy::U128)),
+            f32: mk(Float(ast::FloatTy::F32)),
+            f64: mk(Float(ast::FloatTy::F64)),
 
             re_empty: mk_region(RegionKind::ReEmpty),
             re_static: mk_region(RegionKind::ReStatic),
@@ -892,7 +919,7 @@ pub struct GlobalCtxt<'tcx> {
 
     pub(crate) queries: query::Queries<'tcx>,
 
-    // Records the free variables refrenced by every closure
+    // Records the free variables referenced by every closure
     // expression. Do not track deps for this, just recompute it from
     // scratch every time.
     freevars: FxHashMap<DefId, Lrc<Vec<hir::Freevar>>>,
@@ -1016,13 +1043,13 @@ pub fn intern_const_alloc(
         }
 
         let interned = self.global_arenas.const_allocs.alloc(alloc);
-        if let Some(prev) = allocs.replace(interned) {
+        if let Some(prev) = allocs.replace(interned) { // insert into interner
             bug!("Tried to overwrite interned Allocation: {:#?}", prev)
         }
         interned
     }
 
-    /// Allocates a byte or string literal for `mir::interpret`
+    /// Allocates a byte or string literal for `mir::interpret`, read-only
     pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
         // create an allocation that just contains these bytes
         let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes);
@@ -1072,6 +1099,37 @@ fn is_global(self) -> bool {
         local as usize == global as usize
     }
 
+    /// Returns true if this function must conform to `min_const_fn`
+    pub fn is_min_const_fn(self, def_id: DefId) -> bool {
+        if self.features().staged_api {
+            // some intrinsics are waved through if called inside the
+            // standard library. Users never need to call them directly
+            if let abi::Abi::RustIntrinsic = self.fn_sig(def_id).abi() {
+                assert!(!self.is_const_fn(def_id));
+                match &self.item_name(def_id).as_str()[..] {
+                    | "size_of"
+                    | "min_align_of"
+                    => return true,
+                    _ => {},
+                }
+            }
+            // in order for a libstd function to be considered min_const_fn
+            // it needs to be stable and have no `rustc_const_unstable` attribute
+            match self.lookup_stability(def_id) {
+                // stable functions with unstable const fn aren't `min_const_fn`
+                Some(&attr::Stability { const_stability: Some(_), .. }) => false,
+                // unstable functions don't need to conform
+                Some(&attr::Stability { ref level, .. }) if level.is_unstable() => false,
+                // everything else needs to conform, because it would be callable from
+                // other `min_const_fn` functions
+                _ => true,
+            }
+        } else {
+            // users enabling the `const_fn` can do what they want
+            !self.sess.features_untracked().const_fn
+        }
+    }
+
     /// Create a type context and call the closure with a `TyCtxt` reference
     /// to the context. The closure enforces that the type context and any interned
     /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
@@ -1490,10 +1548,10 @@ pub fn local_crate_exports_generics(self) -> bool {
 }
 
 impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
-    pub fn encode_metadata(self, link_meta: &LinkMeta)
+    pub fn encode_metadata(self)
         -> EncodedMetadata
     {
-        self.cstore.encode_metadata(self, link_meta)
+        self.cstore.encode_metadata(self)
     }
 }
 
@@ -1540,7 +1598,7 @@ pub fn enter_local<F, R>(
 /// None is returned if the value or one of the components is not part
 /// of the provided context.
 /// For Ty, None can be returned if either the type interner doesn't
-/// contain the TypeVariants key or if the address of the interned
+/// contain the TyKind key or if the address of the interned
 /// pointer differs. The latter case is possible if a primitive type,
 /// e.g. `()` or `u8`, was interned in a different context.
 pub trait Lift<'tcx>: fmt::Debug {
@@ -1593,12 +1651,12 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Goa
     }
 }
 
-impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Goal<'a>> {
-    type Lifted = &'tcx Slice<Goal<'tcx>>;
+impl<'a, 'tcx> Lift<'tcx> for &'a List<Goal<'a>> {
+    type Lifted = &'tcx List<Goal<'tcx>>;
     fn lift_to_tcx<'b, 'gcx>(
         &self,
         tcx: TyCtxt<'b, 'gcx, 'tcx>,
-    ) -> Option<&'tcx Slice<Goal<'tcx>>> {
+    ) -> Option<&'tcx List<Goal<'tcx>>> {
         if tcx.interners.arena.in_arena(*self as *const _) {
             return Some(unsafe { mem::transmute(*self) });
         }
@@ -1611,12 +1669,12 @@ fn lift_to_tcx<'b, 'gcx>(
     }
 }
 
-impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Clause<'a>> {
-    type Lifted = &'tcx Slice<Clause<'tcx>>;
+impl<'a, 'tcx> Lift<'tcx> for &'a List<Clause<'a>> {
+    type Lifted = &'tcx List<Clause<'tcx>>;
     fn lift_to_tcx<'b, 'gcx>(
         &self,
         tcx: TyCtxt<'b, 'gcx, 'tcx>,
-    ) -> Option<&'tcx Slice<Clause<'tcx>>> {
+    ) -> Option<&'tcx List<Clause<'tcx>>> {
         if tcx.interners.arena.in_arena(*self as *const _) {
             return Some(unsafe { mem::transmute(*self) });
         }
@@ -1648,7 +1706,7 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
     type Lifted = &'tcx Substs<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Substs<'tcx>> {
         if self.len() == 0 {
-            return Some(Slice::empty());
+            return Some(List::empty());
         }
         if tcx.interners.arena.in_arena(&self[..] as *const _) {
             return Some(unsafe { mem::transmute(*self) });
@@ -1662,12 +1720,12 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Sub
     }
 }
 
-impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Ty<'a>> {
-    type Lifted = &'tcx Slice<Ty<'tcx>>;
+impl<'a, 'tcx> Lift<'tcx> for &'a List<Ty<'a>> {
+    type Lifted = &'tcx List<Ty<'tcx>>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
-                             -> Option<&'tcx Slice<Ty<'tcx>>> {
+                             -> Option<&'tcx List<Ty<'tcx>>> {
         if self.len() == 0 {
-            return Some(Slice::empty());
+            return Some(List::empty());
         }
         if tcx.interners.arena.in_arena(*self as *const _) {
             return Some(unsafe { mem::transmute(*self) });
@@ -1681,12 +1739,12 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
     }
 }
 
-impl<'a, 'tcx> Lift<'tcx> for &'a Slice<ExistentialPredicate<'a>> {
-    type Lifted = &'tcx Slice<ExistentialPredicate<'tcx>>;
+impl<'a, 'tcx> Lift<'tcx> for &'a List<ExistentialPredicate<'a>> {
+    type Lifted = &'tcx List<ExistentialPredicate<'tcx>>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
-        -> Option<&'tcx Slice<ExistentialPredicate<'tcx>>> {
+        -> Option<&'tcx List<ExistentialPredicate<'tcx>>> {
         if self.is_empty() {
-            return Some(Slice::empty());
+            return Some(List::empty());
         }
         if tcx.interners.arena.in_arena(*self as *const _) {
             return Some(unsafe { mem::transmute(*self) });
@@ -1700,12 +1758,12 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
     }
 }
 
-impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Predicate<'a>> {
-    type Lifted = &'tcx Slice<Predicate<'tcx>>;
+impl<'a, 'tcx> Lift<'tcx> for &'a List<Predicate<'a>> {
+    type Lifted = &'tcx List<Predicate<'tcx>>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
-        -> Option<&'tcx Slice<Predicate<'tcx>>> {
+        -> Option<&'tcx List<Predicate<'tcx>>> {
         if self.is_empty() {
-            return Some(Slice::empty());
+            return Some(List::empty());
         }
         if tcx.interners.arena.in_arena(*self as *const _) {
             return Some(unsafe { mem::transmute(*self) });
@@ -1719,11 +1777,11 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
     }
 }
 
-impl<'a, 'tcx> Lift<'tcx> for &'a Slice<CanonicalVarInfo> {
-    type Lifted = &'tcx Slice<CanonicalVarInfo>;
+impl<'a, 'tcx> Lift<'tcx> for &'a List<CanonicalVarInfo> {
+    type Lifted = &'tcx List<CanonicalVarInfo>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
         if self.len() == 0 {
-            return Some(Slice::empty());
+            return Some(List::empty());
         }
         if tcx.interners.arena.in_arena(*self as *const _) {
             return Some(unsafe { mem::transmute(*self) });
@@ -2035,9 +2093,9 @@ pub fn go(tcx: TyCtxt) {
 
                 for &Interned(t) in tcx.interners.type_.borrow().iter() {
                     let variant = match t.sty {
-                        ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) |
-                            ty::TyFloat(..) | ty::TyStr | ty::TyNever => continue,
-                        ty::TyError => /* unimportant */ continue,
+                        ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
+                            ty::Float(..) | ty::Str | ty::Never => continue,
+                        ty::Error => /* unimportant */ continue,
                         $(ty::$variant(..) => &mut $variant,)*
                     };
                     let region = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
@@ -2076,9 +2134,9 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     pub fn print_debug_stats(self) {
         sty_debug_print!(
             self,
-            TyAdt, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr,
-            TyGenerator, TyGeneratorWitness, TyDynamic, TyClosure, TyTuple,
-            TyParam, TyInfer, TyProjection, TyAnon, TyForeign);
+            Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr,
+            Generator, GeneratorWitness, Dynamic, Closure, Tuple,
+            Param, Infer, Projection, Anon, Foreign);
 
         println!("Substs interner: #{}", self.interners.substs.borrow().len());
         println!("Region interner: #{}", self.interners.region.borrow().len());
@@ -2107,34 +2165,34 @@ fn hash<H: Hasher>(&self, s: &mut H) {
     }
 }
 
-impl<'tcx: 'lcx, 'lcx> Borrow<TypeVariants<'lcx>> for Interned<'tcx, TyS<'tcx>> {
-    fn borrow<'a>(&'a self) -> &'a TypeVariants<'lcx> {
+impl<'tcx: 'lcx, 'lcx> Borrow<TyKind<'lcx>> for Interned<'tcx, TyS<'tcx>> {
+    fn borrow<'a>(&'a self) -> &'a TyKind<'lcx> {
         &self.0.sty
     }
 }
 
-// NB: An Interned<Slice<T>> compares and hashes as its elements.
-impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, Slice<T>> {
-    fn eq(&self, other: &Interned<'tcx, Slice<T>>) -> bool {
+// NB: An Interned<List<T>> compares and hashes as its elements.
+impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, List<T>> {
+    fn eq(&self, other: &Interned<'tcx, List<T>>) -> bool {
         self.0[..] == other.0[..]
     }
 }
 
-impl<'tcx, T: Eq> Eq for Interned<'tcx, Slice<T>> {}
+impl<'tcx, T: Eq> Eq for Interned<'tcx, List<T>> {}
 
-impl<'tcx, T: Hash> Hash for Interned<'tcx, Slice<T>> {
+impl<'tcx, T: Hash> Hash for Interned<'tcx, List<T>> {
     fn hash<H: Hasher>(&self, s: &mut H) {
         self.0[..].hash(s)
     }
 }
 
-impl<'tcx: 'lcx, 'lcx> Borrow<[Ty<'lcx>]> for Interned<'tcx, Slice<Ty<'tcx>>> {
+impl<'tcx: 'lcx, 'lcx> Borrow<[Ty<'lcx>]> for Interned<'tcx, List<Ty<'tcx>>> {
     fn borrow<'a>(&'a self) -> &'a [Ty<'lcx>] {
         &self.0[..]
     }
 }
 
-impl<'tcx: 'lcx, 'lcx> Borrow<[CanonicalVarInfo]> for Interned<'tcx, Slice<CanonicalVarInfo>> {
+impl<'tcx: 'lcx, 'lcx> Borrow<[CanonicalVarInfo]> for Interned<'tcx, List<CanonicalVarInfo>> {
     fn borrow<'a>(&'a self) -> &'a [CanonicalVarInfo] {
         &self.0[..]
     }
@@ -2153,14 +2211,14 @@ fn borrow<'a>(&'a self) -> &'a RegionKind {
 }
 
 impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]>
-    for Interned<'tcx, Slice<ExistentialPredicate<'tcx>>> {
+    for Interned<'tcx, List<ExistentialPredicate<'tcx>>> {
     fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'lcx>] {
         &self.0[..]
     }
 }
 
 impl<'tcx: 'lcx, 'lcx> Borrow<[Predicate<'lcx>]>
-    for Interned<'tcx, Slice<Predicate<'tcx>>> {
+    for Interned<'tcx, List<Predicate<'tcx>>> {
     fn borrow<'a>(&'a self) -> &'a [Predicate<'lcx>] {
         &self.0[..]
     }
@@ -2173,14 +2231,14 @@ fn borrow<'a>(&'a self) -> &'a Const<'lcx> {
 }
 
 impl<'tcx: 'lcx, 'lcx> Borrow<[Clause<'lcx>]>
-for Interned<'tcx, Slice<Clause<'tcx>>> {
+for Interned<'tcx, List<Clause<'tcx>>> {
     fn borrow<'a>(&'a self) -> &'a [Clause<'lcx>] {
         &self.0[..]
     }
 }
 
 impl<'tcx: 'lcx, 'lcx> Borrow<[Goal<'lcx>]>
-for Interned<'tcx, Slice<Goal<'tcx>>> {
+for Interned<'tcx, List<Goal<'tcx>>> {
     fn borrow<'a>(&'a self) -> &'a [Goal<'lcx>] {
         &self.0[..]
     }
@@ -2274,9 +2332,9 @@ macro_rules! slice_interners {
     ($($field:ident: $method:ident($ty:ident)),+) => (
         $(intern_method!( 'tcx, $field: $method(
             &[$ty<'tcx>],
-            |a, v| Slice::from_arena(a, v),
+            |a, v| List::from_arena(a, v),
             Deref::deref,
-            |xs: &[$ty]| xs.iter().any(keep_local)) -> Slice<$ty<'tcx>>);)+
+            |xs: &[$ty]| xs.iter().any(keep_local)) -> List<$ty<'tcx>>);)+
     )
 }
 
@@ -2298,10 +2356,10 @@ macro_rules! slice_interners {
     'tcx,
     canonical_var_infos: _intern_canonical_var_infos(
         &[CanonicalVarInfo],
-        |a, v| Slice::from_arena(a, v),
+        |a, v| List::from_arena(a, v),
         Deref::deref,
         |_xs: &[CanonicalVarInfo]| -> bool { false }
-    ) -> Slice<CanonicalVarInfo>
+    ) -> List<CanonicalVarInfo>
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
@@ -2323,7 +2381,7 @@ pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
     pub fn coerce_closure_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
         let converted_sig = sig.map_bound(|s| {
             let params_iter = match s.inputs()[0].sty {
-                ty::TyTuple(params) => {
+                ty::Tuple(params) => {
                     params.into_iter().cloned()
                 }
                 _ => bug!(),
@@ -2340,7 +2398,7 @@ pub fn coerce_closure_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
         self.mk_fn_ptr(converted_sig)
     }
 
-    pub fn mk_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> {
+    pub fn mk_ty(&self, st: TyKind<'tcx>) -> Ty<'tcx> {
         CtxtInterners::intern_ty(&self.interners, &self.global_interners, st)
     }
 
@@ -2374,7 +2432,7 @@ pub fn mk_mach_float(self, tm: ast::FloatTy) -> Ty<'tcx> {
     }
 
     pub fn mk_str(self) -> Ty<'tcx> {
-        self.mk_ty(TyStr)
+        self.mk_ty(Str)
     }
 
     pub fn mk_static_str(self) -> Ty<'tcx> {
@@ -2383,11 +2441,11 @@ pub fn mk_static_str(self) -> Ty<'tcx> {
 
     pub fn mk_adt(self, def: &'tcx AdtDef, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
         // take a copy of substs so that we own the vectors inside
-        self.mk_ty(TyAdt(def, substs))
+        self.mk_ty(Adt(def, substs))
     }
 
     pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> {
-        self.mk_ty(TyForeign(def_id))
+        self.mk_ty(Foreign(def_id))
     }
 
     pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
@@ -2406,15 +2464,15 @@ pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 }
             }
         });
-        self.mk_ty(TyAdt(adt_def, substs))
+        self.mk_ty(Adt(adt_def, substs))
     }
 
     pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(TyRawPtr(tm))
+        self.mk_ty(RawPtr(tm))
     }
 
     pub fn mk_ref(self, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(TyRef(r, tm.ty, tm.mutbl))
+        self.mk_ty(Ref(r, tm.ty, tm.mutbl))
     }
 
     pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
@@ -2438,19 +2496,19 @@ pub fn mk_nil_ptr(self) -> Ty<'tcx> {
     }
 
     pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
-        self.mk_ty(TyArray(ty, ty::Const::from_usize(self, n)))
+        self.mk_ty(Array(ty, ty::Const::from_usize(self, n)))
     }
 
     pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(TySlice(ty))
+        self.mk_ty(Slice(ty))
     }
 
     pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
-        self.mk_ty(TyTuple(self.intern_type_list(ts)))
+        self.mk_ty(Tuple(self.intern_type_list(ts)))
     }
 
     pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I) -> I::Output {
-        iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts))))
+        iter.intern_with(|ts| self.mk_ty(Tuple(self.intern_type_list(ts))))
     }
 
     pub fn mk_nil(self) -> Ty<'tcx> {
@@ -2466,31 +2524,31 @@ pub fn mk_diverging_default(self) -> Ty<'tcx> {
     }
 
     pub fn mk_bool(self) -> Ty<'tcx> {
-        self.mk_ty(TyBool)
+        self.mk_ty(Bool)
     }
 
     pub fn mk_fn_def(self, def_id: DefId,
                      substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(TyFnDef(def_id, substs))
+        self.mk_ty(FnDef(def_id, substs))
     }
 
     pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(TyFnPtr(fty))
+        self.mk_ty(FnPtr(fty))
     }
 
     pub fn mk_dynamic(
         self,
-        obj: ty::Binder<&'tcx Slice<ExistentialPredicate<'tcx>>>,
+        obj: ty::Binder<&'tcx List<ExistentialPredicate<'tcx>>>,
         reg: ty::Region<'tcx>
     ) -> Ty<'tcx> {
-        self.mk_ty(TyDynamic(obj, reg))
+        self.mk_ty(Dynamic(obj, reg))
     }
 
     pub fn mk_projection(self,
                          item_def_id: DefId,
                          substs: &'tcx Substs<'tcx>)
         -> Ty<'tcx> {
-            self.mk_ty(TyProjection(ProjectionTy {
+            self.mk_ty(Projection(ProjectionTy {
                 item_def_id,
                 substs,
             }))
@@ -2498,7 +2556,7 @@ pub fn mk_projection(self,
 
     pub fn mk_closure(self, closure_id: DefId, closure_substs: ClosureSubsts<'tcx>)
                                           -> Ty<'tcx> {
-        self.mk_ty(TyClosure(closure_id, closure_substs))
+        self.mk_ty(Closure(closure_id, closure_substs))
     }
 
     pub fn mk_generator(self,
@@ -2506,11 +2564,11 @@ pub fn mk_generator(self,
                         generator_substs: GeneratorSubsts<'tcx>,
                         movability: hir::GeneratorMovability)
                         -> Ty<'tcx> {
-        self.mk_ty(TyGenerator(id, generator_substs, movability))
+        self.mk_ty(Generator(id, generator_substs, movability))
     }
 
-    pub fn mk_generator_witness(self, types: ty::Binder<&'tcx Slice<Ty<'tcx>>>) -> Ty<'tcx> {
-        self.mk_ty(TyGeneratorWitness(types))
+    pub fn mk_generator_witness(self, types: ty::Binder<&'tcx List<Ty<'tcx>>>) -> Ty<'tcx> {
+        self.mk_ty(GeneratorWitness(types))
     }
 
     pub fn mk_var(self, v: TyVid) -> Ty<'tcx> {
@@ -2526,13 +2584,13 @@ pub fn mk_float_var(self, v: FloatVid) -> Ty<'tcx> {
     }
 
     pub fn mk_infer(self, it: InferTy) -> Ty<'tcx> {
-        self.mk_ty(TyInfer(it))
+        self.mk_ty(Infer(it))
     }
 
     pub fn mk_ty_param(self,
                     index: u32,
                     name: InternedString) -> Ty<'tcx> {
-        self.mk_ty(TyParam(ParamTy { idx: index, name: name }))
+        self.mk_ty(Param(ParamTy { idx: index, name: name }))
     }
 
     pub fn mk_self_type(self) -> Ty<'tcx> {
@@ -2549,40 +2607,40 @@ pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> Kind<'tcx> {
     }
 
     pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(TyAnon(def_id, substs))
+        self.mk_ty(Anon(def_id, substs))
     }
 
     pub fn intern_existential_predicates(self, eps: &[ExistentialPredicate<'tcx>])
-        -> &'tcx Slice<ExistentialPredicate<'tcx>> {
+        -> &'tcx List<ExistentialPredicate<'tcx>> {
         assert!(!eps.is_empty());
         assert!(eps.windows(2).all(|w| w[0].stable_cmp(self, &w[1]) != Ordering::Greater));
         self._intern_existential_predicates(eps)
     }
 
     pub fn intern_predicates(self, preds: &[Predicate<'tcx>])
-        -> &'tcx Slice<Predicate<'tcx>> {
+        -> &'tcx List<Predicate<'tcx>> {
         // FIXME consider asking the input slice to be sorted to avoid
         // re-interning permutations, in which case that would be asserted
         // here.
         if preds.len() == 0 {
             // The macro-generated method below asserts we don't intern an empty slice.
-            Slice::empty()
+            List::empty()
         } else {
             self._intern_predicates(preds)
         }
     }
 
-    pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx Slice<Ty<'tcx>> {
+    pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
         if ts.len() == 0 {
-            Slice::empty()
+            List::empty()
         } else {
             self._intern_type_list(ts)
         }
     }
 
-    pub fn intern_substs(self, ts: &[Kind<'tcx>]) -> &'tcx Slice<Kind<'tcx>> {
+    pub fn intern_substs(self, ts: &[Kind<'tcx>]) -> &'tcx List<Kind<'tcx>> {
         if ts.len() == 0 {
-            Slice::empty()
+            List::empty()
         } else {
             self._intern_substs(ts)
         }
@@ -2590,7 +2648,7 @@ pub fn intern_substs(self, ts: &[Kind<'tcx>]) -> &'tcx Slice<Kind<'tcx>> {
 
     pub fn intern_canonical_var_infos(self, ts: &[CanonicalVarInfo]) -> CanonicalVarInfos<'gcx> {
         if ts.len() == 0 {
-            Slice::empty()
+            List::empty()
         } else {
             self.global_tcx()._intern_canonical_var_infos(ts)
         }
@@ -2598,7 +2656,7 @@ pub fn intern_canonical_var_infos(self, ts: &[CanonicalVarInfo]) -> CanonicalVar
 
     pub fn intern_clauses(self, ts: &[Clause<'tcx>]) -> Clauses<'tcx> {
         if ts.len() == 0 {
-            Slice::empty()
+            List::empty()
         } else {
             self._intern_clauses(ts)
         }
@@ -2606,7 +2664,7 @@ pub fn intern_clauses(self, ts: &[Clause<'tcx>]) -> Clauses<'tcx> {
 
     pub fn intern_goals(self, ts: &[Goal<'tcx>]) -> Goals<'tcx> {
         if ts.len() == 0 {
-            Slice::empty()
+            List::empty()
         } else {
             self._intern_goals(ts)
         }
@@ -2629,24 +2687,24 @@ pub fn mk_fn_sig<I>(self,
     }
 
     pub fn mk_existential_predicates<I: InternAs<[ExistentialPredicate<'tcx>],
-                                     &'tcx Slice<ExistentialPredicate<'tcx>>>>(self, iter: I)
+                                     &'tcx List<ExistentialPredicate<'tcx>>>>(self, iter: I)
                                      -> I::Output {
         iter.intern_with(|xs| self.intern_existential_predicates(xs))
     }
 
     pub fn mk_predicates<I: InternAs<[Predicate<'tcx>],
-                                     &'tcx Slice<Predicate<'tcx>>>>(self, iter: I)
+                                     &'tcx List<Predicate<'tcx>>>>(self, iter: I)
                                      -> I::Output {
         iter.intern_with(|xs| self.intern_predicates(xs))
     }
 
     pub fn mk_type_list<I: InternAs<[Ty<'tcx>],
-                        &'tcx Slice<Ty<'tcx>>>>(self, iter: I) -> I::Output {
+                        &'tcx List<Ty<'tcx>>>>(self, iter: I) -> I::Output {
         iter.intern_with(|xs| self.intern_type_list(xs))
     }
 
     pub fn mk_substs<I: InternAs<[Kind<'tcx>],
-                     &'tcx Slice<Kind<'tcx>>>>(self, iter: I) -> I::Output {
+                     &'tcx List<Kind<'tcx>>>>(self, iter: I) -> I::Output {
         iter.intern_with(|xs| self.intern_substs(xs))
     }
 
@@ -2813,7 +2871,7 @@ pub trait InternIteratorElement<T, R>: Sized {
 impl<T, R> InternIteratorElement<T, R> for T {
     type Output = R;
     fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output {
-        f(&iter.collect::<AccumulateVec<[_; 8]>>())
+        f(&iter.collect::<SmallVec<[_; 8]>>())
     }
 }
 
@@ -2822,14 +2880,14 @@ impl<'a, T, R> InternIteratorElement<T, R> for &'a T
 {
     type Output = R;
     fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output {
-        f(&iter.cloned().collect::<AccumulateVec<[_; 8]>>())
+        f(&iter.cloned().collect::<SmallVec<[_; 8]>>())
     }
 }
 
 impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
     type Output = Result<R, E>;
     fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output {
-        Ok(f(&iter.collect::<Result<AccumulateVec<[_; 8]>, _>>()?))
+        Ok(f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?))
     }
 }
 
index e23034bde7672ff9d1e5260de0c52feb6744c336..aa6ee420a2162a4b41b93a2bfad48d7773b68612 100644 (file)
@@ -51,7 +51,7 @@ pub enum TypeError<'tcx> {
     CyclicTy(Ty<'tcx>),
     ProjectionMismatched(ExpectedFound<DefId>),
     ProjectionBoundsLength(ExpectedFound<usize>),
-    ExistentialMismatch(ExpectedFound<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>),
+    ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),
 
     OldStyleLUB(Box<TypeError<'tcx>>),
 }
@@ -175,21 +175,21 @@ fn report_maybe_different(f: &mut fmt::Formatter,
 impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
     pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
         match self.sty {
-            ty::TyBool | ty::TyChar | ty::TyInt(_) |
-            ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr | ty::TyNever => self.to_string(),
-            ty::TyTuple(ref tys) if tys.is_empty() => self.to_string(),
+            ty::Bool | ty::Char | ty::Int(_) |
+            ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => self.to_string(),
+            ty::Tuple(ref tys) if tys.is_empty() => self.to_string(),
 
-            ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
-            ty::TyForeign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)),
-            ty::TyArray(_, n) => {
+            ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
+            ty::Foreign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)),
+            ty::Array(_, n) => {
                 match n.assert_usize(tcx) {
                     Some(n) => format!("array of {} elements", n),
                     None => "array".to_string(),
                 }
             }
-            ty::TySlice(_) => "slice".to_string(),
-            ty::TyRawPtr(_) => "*-ptr".to_string(),
-            ty::TyRef(region, ty, mutbl) => {
+            ty::Slice(_) => "slice".to_string(),
+            ty::RawPtr(_) => "*-ptr".to_string(),
+            ty::Ref(region, ty, mutbl) => {
                 let tymut = ty::TypeAndMut { ty, mutbl };
                 let tymut_string = tymut.to_string();
                 if tymut_string == "_" ||         //unknown type name,
@@ -204,33 +204,33 @@ pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
                     format!("&{}", tymut_string)
                 }
             }
-            ty::TyFnDef(..) => "fn item".to_string(),
-            ty::TyFnPtr(_) => "fn pointer".to_string(),
-            ty::TyDynamic(ref inner, ..) => {
+            ty::FnDef(..) => "fn item".to_string(),
+            ty::FnPtr(_) => "fn pointer".to_string(),
+            ty::Dynamic(ref inner, ..) => {
                 inner.principal().map_or_else(|| "trait".to_string(),
                     |p| format!("trait {}", tcx.item_path_str(p.def_id())))
             }
-            ty::TyClosure(..) => "closure".to_string(),
-            ty::TyGenerator(..) => "generator".to_string(),
-            ty::TyGeneratorWitness(..) => "generator witness".to_string(),
-            ty::TyTuple(..) => "tuple".to_string(),
-            ty::TyInfer(ty::TyVar(_)) => "inferred type".to_string(),
-            ty::TyInfer(ty::IntVar(_)) => "integral variable".to_string(),
-            ty::TyInfer(ty::FloatVar(_)) => "floating-point variable".to_string(),
-            ty::TyInfer(ty::CanonicalTy(_)) |
-            ty::TyInfer(ty::FreshTy(_)) => "skolemized type".to_string(),
-            ty::TyInfer(ty::FreshIntTy(_)) => "skolemized integral type".to_string(),
-            ty::TyInfer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(),
-            ty::TyProjection(_) => "associated type".to_string(),
-            ty::TyParam(ref p) => {
+            ty::Closure(..) => "closure".to_string(),
+            ty::Generator(..) => "generator".to_string(),
+            ty::GeneratorWitness(..) => "generator witness".to_string(),
+            ty::Tuple(..) => "tuple".to_string(),
+            ty::Infer(ty::TyVar(_)) => "inferred type".to_string(),
+            ty::Infer(ty::IntVar(_)) => "integral variable".to_string(),
+            ty::Infer(ty::FloatVar(_)) => "floating-point variable".to_string(),
+            ty::Infer(ty::CanonicalTy(_)) |
+            ty::Infer(ty::FreshTy(_)) => "skolemized type".to_string(),
+            ty::Infer(ty::FreshIntTy(_)) => "skolemized integral type".to_string(),
+            ty::Infer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(),
+            ty::Projection(_) => "associated type".to_string(),
+            ty::Param(ref p) => {
                 if p.is_self() {
                     "Self".to_string()
                 } else {
                     "type parameter".to_string()
                 }
             }
-            ty::TyAnon(..) => "anonymized type".to_string(),
-            ty::TyError => "type error".to_string(),
+            ty::Anon(..) => "anonymized type".to_string(),
+            ty::Error => "type error".to_string(),
         }
     }
 }
@@ -251,7 +251,7 @@ pub fn note_and_explain_type_err(self,
                     db.help("consider boxing your closure and/or using it as a trait object");
                 }
                 match (&values.found.sty, &values.expected.sty) { // Issue #53280
-                    (ty::TyInfer(ty::IntVar(_)), ty::TyFloat(_)) => {
+                    (ty::Infer(ty::IntVar(_)), ty::Float(_)) => {
                         if let Ok(snippet) = self.sess.source_map().span_to_snippet(sp) {
                             if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') {
                                 db.span_suggestion_with_applicability(
index cf5e55a59f713e10cd16534bba946745570adaba..567d1c668f7c7d2fbb4e43828043399dc689fdc0 100644 (file)
@@ -68,42 +68,42 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                      -> Option<SimplifiedType>
 {
     match ty.sty {
-        ty::TyBool => Some(BoolSimplifiedType),
-        ty::TyChar => Some(CharSimplifiedType),
-        ty::TyInt(int_type) => Some(IntSimplifiedType(int_type)),
-        ty::TyUint(uint_type) => Some(UintSimplifiedType(uint_type)),
-        ty::TyFloat(float_type) => Some(FloatSimplifiedType(float_type)),
-        ty::TyAdt(def, _) => Some(AdtSimplifiedType(def.did)),
-        ty::TyStr => Some(StrSimplifiedType),
-        ty::TyArray(..) | ty::TySlice(_) => Some(ArraySimplifiedType),
-        ty::TyRawPtr(_) => Some(PtrSimplifiedType),
-        ty::TyDynamic(ref trait_info, ..) => {
+        ty::Bool => Some(BoolSimplifiedType),
+        ty::Char => Some(CharSimplifiedType),
+        ty::Int(int_type) => Some(IntSimplifiedType(int_type)),
+        ty::Uint(uint_type) => Some(UintSimplifiedType(uint_type)),
+        ty::Float(float_type) => Some(FloatSimplifiedType(float_type)),
+        ty::Adt(def, _) => Some(AdtSimplifiedType(def.did)),
+        ty::Str => Some(StrSimplifiedType),
+        ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType),
+        ty::RawPtr(_) => Some(PtrSimplifiedType),
+        ty::Dynamic(ref trait_info, ..) => {
             trait_info.principal().map(|p| TraitSimplifiedType(p.def_id()))
         }
-        ty::TyRef(_, ty, _) => {
+        ty::Ref(_, ty, _) => {
             // since we introduce auto-refs during method lookup, we
             // just treat &T and T as equivalent from the point of
             // view of possibly unifying
             simplify_type(tcx, ty, can_simplify_params)
         }
-        ty::TyFnDef(def_id, _) |
-        ty::TyClosure(def_id, _) => {
+        ty::FnDef(def_id, _) |
+        ty::Closure(def_id, _) => {
             Some(ClosureSimplifiedType(def_id))
         }
-        ty::TyGenerator(def_id, _, _) => {
+        ty::Generator(def_id, _, _) => {
             Some(GeneratorSimplifiedType(def_id))
         }
-        ty::TyGeneratorWitness(ref tys) => {
+        ty::GeneratorWitness(ref tys) => {
             Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len()))
         }
-        ty::TyNever => Some(NeverSimplifiedType),
-        ty::TyTuple(ref tys) => {
+        ty::Never => Some(NeverSimplifiedType),
+        ty::Tuple(ref tys) => {
             Some(TupleSimplifiedType(tys.len()))
         }
-        ty::TyFnPtr(ref f) => {
+        ty::FnPtr(ref f) => {
             Some(FunctionSimplifiedType(f.skip_binder().inputs().len()))
         }
-        ty::TyProjection(_) | ty::TyParam(_) => {
+        ty::Projection(_) | ty::Param(_) => {
             if can_simplify_params {
                 // In normalized types, projections don't unify with
                 // anything. when lazy normalization happens, this
@@ -115,13 +115,13 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                 None
             }
         }
-        ty::TyAnon(def_id, _) => {
+        ty::Anon(def_id, _) => {
             Some(AnonSimplifiedType(def_id))
         }
-        ty::TyForeign(def_id) => {
+        ty::Foreign(def_id) => {
             Some(ForeignSimplifiedType(def_id))
         }
-        ty::TyInfer(_) | ty::TyError => None,
+        ty::Infer(_) | ty::Error => None,
     }
 }
 
index 3718c436b3a0019fa5d42321449c0b1debabf39c..b9371ec39ccdad00a79543eef173301e341bcabd 100644 (file)
@@ -28,7 +28,7 @@ fn new() -> FlagComputation {
         }
     }
 
-    pub fn for_sty(st: &ty::TypeVariants) -> FlagComputation {
+    pub fn for_sty(st: &ty::TyKind) -> FlagComputation {
         let mut result = FlagComputation::new();
         result.add_sty(st);
         result
@@ -67,30 +67,30 @@ fn add_bound_computation(&mut self, computation: &FlagComputation) {
         }
     }
 
-    fn add_sty(&mut self, st: &ty::TypeVariants) {
+    fn add_sty(&mut self, st: &ty::TyKind) {
         match st {
-            &ty::TyBool |
-            &ty::TyChar |
-            &ty::TyInt(_) |
-            &ty::TyFloat(_) |
-            &ty::TyUint(_) |
-            &ty::TyNever |
-            &ty::TyStr |
-            &ty::TyForeign(..) => {
+            &ty::Bool |
+            &ty::Char |
+            &ty::Int(_) |
+            &ty::Float(_) |
+            &ty::Uint(_) |
+            &ty::Never |
+            &ty::Str |
+            &ty::Foreign(..) => {
             }
 
-            // You might think that we could just return TyError for
-            // any type containing TyError as a component, and get
+            // You might think that we could just return Error for
+            // any type containing Error as a component, and get
             // rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with
             // the exception of function types that return bot).
             // But doing so caused sporadic memory corruption, and
             // neither I (tjc) nor nmatsakis could figure out why,
             // so we're doing it this way.
-            &ty::TyError => {
+            &ty::Error => {
                 self.add_flags(TypeFlags::HAS_TY_ERR)
             }
 
-            &ty::TyParam(ref p) => {
+            &ty::Param(ref p) => {
                 self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                 if p.is_self() {
                     self.add_flags(TypeFlags::HAS_SELF);
@@ -99,25 +99,25 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
                 }
             }
 
-            &ty::TyGenerator(_, ref substs, _) => {
+            &ty::Generator(_, ref substs, _) => {
                 self.add_flags(TypeFlags::HAS_TY_CLOSURE);
                 self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                 self.add_substs(&substs.substs);
             }
 
-            &ty::TyGeneratorWitness(ref ts) => {
+            &ty::GeneratorWitness(ref ts) => {
                 let mut computation = FlagComputation::new();
                 computation.add_tys(&ts.skip_binder()[..]);
                 self.add_bound_computation(&computation);
             }
 
-            &ty::TyClosure(_, ref substs) => {
+            &ty::Closure(_, ref substs) => {
                 self.add_flags(TypeFlags::HAS_TY_CLOSURE);
                 self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                 self.add_substs(&substs.substs);
             }
 
-            &ty::TyInfer(infer) => {
+            &ty::Infer(infer) => {
                 self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right?
                 self.add_flags(TypeFlags::HAS_TY_INFER);
                 match infer {
@@ -136,11 +136,11 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
                 }
             }
 
-            &ty::TyAdt(_, substs) => {
+            &ty::Adt(_, substs) => {
                 self.add_substs(substs);
             }
 
-            &ty::TyProjection(ref data) => {
+            &ty::Projection(ref data) => {
                 // currently we can't normalize projections that
                 // include bound regions, so track those separately.
                 if !data.has_escaping_regions() {
@@ -150,12 +150,12 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
                 self.add_projection_ty(data);
             }
 
-            &ty::TyAnon(_, substs) => {
+            &ty::Anon(_, substs) => {
                 self.add_flags(TypeFlags::HAS_PROJECTION);
                 self.add_substs(substs);
             }
 
-            &ty::TyDynamic(ref obj, r) => {
+            &ty::Dynamic(ref obj, r) => {
                 let mut computation = FlagComputation::new();
                 for predicate in obj.skip_binder().iter() {
                     match *predicate {
@@ -172,33 +172,33 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
                 self.add_region(r);
             }
 
-            &ty::TyArray(tt, len) => {
+            &ty::Array(tt, len) => {
                 self.add_ty(tt);
                 self.add_const(len);
             }
 
-            &ty::TySlice(tt) => {
+            &ty::Slice(tt) => {
                 self.add_ty(tt)
             }
 
-            &ty::TyRawPtr(ref m) => {
+            &ty::RawPtr(ref m) => {
                 self.add_ty(m.ty);
             }
 
-            &ty::TyRef(r, ty, _) => {
+            &ty::Ref(r, ty, _) => {
                 self.add_region(r);
                 self.add_ty(ty);
             }
 
-            &ty::TyTuple(ref ts) => {
+            &ty::Tuple(ref ts) => {
                 self.add_tys(&ts[..]);
             }
 
-            &ty::TyFnDef(_, substs) => {
+            &ty::FnDef(_, substs) => {
                 self.add_substs(substs);
             }
 
-            &ty::TyFnPtr(f) => {
+            &ty::FnPtr(f) => {
                 self.add_fn_sig(f);
             }
         }
index e4484041b065ce829306f816f8a7e04e1212482c..26010c3d5f55c0b3b87652734c0a3596ba89aeb7 100644 (file)
@@ -771,7 +771,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
         // in the normalized form
         if self.just_constrained {
             match t.sty {
-                ty::TyProjection(..) | ty::TyAnon(..) => { return false; }
+                ty::Projection(..) | ty::Anon(..) => { return false; }
                 _ => { }
             }
         }
index 3629709e6a48de19a1f0843f26d4b7f88099f353..c152c0fb8e94cea9ccdf9b272929902b93044756 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::mem;
-use rustc_data_structures::small_vec::SmallVec;
+use smallvec::SmallVec;
 use syntax::ast::CRATE_NODE_ID;
 use ty::context::TyCtxt;
 use ty::{DefId, DefIdTree};
@@ -83,14 +83,14 @@ pub fn intersection<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         let mut next_ret = SmallVec::new();
         let mut old_ret: SmallVec<[DefId; 1]> = SmallVec::new();
         for next_forest in iter {
-            for id in ret.root_ids.drain(..) {
+            for id in ret.root_ids.drain() {
                 if next_forest.contains(tcx, id) {
                     next_ret.push(id);
                 } else {
                     old_ret.push(id);
                 }
             }
-            ret.root_ids.extend(old_ret.drain(..));
+            ret.root_ids.extend(old_ret.drain());
 
             for id in next_forest.root_ids {
                 if ret.contains(tcx, id) {
@@ -99,7 +99,7 @@ pub fn intersection<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             }
 
             mem::swap(&mut next_ret, &mut ret.root_ids);
-            next_ret.drain(..);
+            next_ret.drain();
         }
         ret
     }
@@ -112,7 +112,7 @@ pub fn union<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         let mut ret = DefIdForest::empty();
         let mut next_ret = SmallVec::new();
         for next_forest in iter {
-            for id in ret.root_ids.drain(..) {
+            for id in ret.root_ids.drain() {
                 if !next_forest.contains(tcx, id) {
                     next_ret.push(id);
                 }
@@ -125,7 +125,7 @@ pub fn union<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             }
 
             mem::swap(&mut next_ret, &mut ret.root_ids);
-            next_ret.drain(..);
+            next_ret.drain();
         }
         ret
     }
index 0ace44dca77b40f0f996fcf2c9345e21bc9ff369..ef5b2236200322bf7c34ee921899058b2e67030f 100644 (file)
@@ -13,7 +13,7 @@
 use ty::{AdtDef, VariantDef, FieldDef, Ty, TyS};
 use ty::{DefId, Substs};
 use ty::{AdtKind, Visibility};
-use ty::TypeVariants::*;
+use ty::TyKind::*;
 
 pub use self::def_id_forest::DefIdForest;
 
@@ -226,7 +226,7 @@ fn uninhabited_from(
         tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
     {
         match self.sty {
-            TyAdt(def, substs) => {
+            Adt(def, substs) => {
                 {
                     let substs_set = visited.entry(def.did).or_default();
                     if !substs_set.insert(substs) {
@@ -255,13 +255,13 @@ fn uninhabited_from(
                 ret
             },
 
-            TyNever => DefIdForest::full(tcx),
-            TyTuple(ref tys) => {
+            Never => DefIdForest::full(tcx),
+            Tuple(ref tys) => {
                 DefIdForest::union(tcx, tys.iter().map(|ty| {
                     ty.uninhabited_from(visited, tcx)
                 }))
             },
-            TyArray(ty, len) => {
+            Array(ty, len) => {
                 match len.assert_usize(tcx) {
                     // If the array is definitely non-empty, it's uninhabited if
                     // the type of its elements is uninhabited.
@@ -269,7 +269,7 @@ fn uninhabited_from(
                     _ => DefIdForest::empty()
                 }
             }
-            TyRef(_, ty, _) => {
+            Ref(_, ty, _) => {
                 ty.uninhabited_from(visited, tcx)
             }
 
index 7329f4832f2e27022ce4fd8d57bc3bb5d5db22f9..68996f52b867a27adf6fd88dd9c2c264c8a35baa 100644 (file)
@@ -194,7 +194,7 @@ pub fn resolve(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             );
 
             let def = match item_type.sty {
-                ty::TyFnDef(..) if {
+                ty::FnDef(..) if {
                     let f = item_type.fn_sig(tcx);
                     f.abi() == Abi::RustIntrinsic ||
                         f.abi() == Abi::PlatformIntrinsic
index 593470b5d1ecd49f66eb79cdcdc67890da37a06e..e38bb411a14f97bf4531ffd85b7a2272b69a3a03 100644 (file)
@@ -299,7 +299,7 @@ fn push_impl_path<T>(self,
         // impl on `Foo`, but fallback to `<Foo>::bar` if self-type is
         // anything other than a simple path.
         match self_ty.sty {
-            ty::TyAdt(adt_def, substs) => {
+            ty::Adt(adt_def, substs) => {
                 if substs.types().next().is_none() { // ignore regions
                     self.push_item_path(buffer, adt_def.did);
                 } else {
@@ -307,14 +307,14 @@ fn push_impl_path<T>(self,
                 }
             }
 
-            ty::TyForeign(did) => self.push_item_path(buffer, did),
+            ty::Foreign(did) => self.push_item_path(buffer, did),
 
-            ty::TyBool |
-            ty::TyChar |
-            ty::TyInt(_) |
-            ty::TyUint(_) |
-            ty::TyFloat(_) |
-            ty::TyStr => {
+            ty::Bool |
+            ty::Char |
+            ty::Int(_) |
+            ty::Uint(_) |
+            ty::Float(_) |
+            ty::Str => {
                 buffer.push(&self_ty.to_string());
             }
 
@@ -357,40 +357,40 @@ pub fn parent_def_id(self, def_id: DefId) -> Option<DefId> {
 /// decisions and we may want to adjust it later.
 pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
     match ty.sty {
-        ty::TyAdt(adt_def, _) => Some(adt_def.did),
+        ty::Adt(adt_def, _) => Some(adt_def.did),
 
-        ty::TyDynamic(data, ..) => data.principal().map(|p| p.def_id()),
+        ty::Dynamic(data, ..) => data.principal().map(|p| p.def_id()),
 
-        ty::TyArray(subty, _) |
-        ty::TySlice(subty) => characteristic_def_id_of_type(subty),
+        ty::Array(subty, _) |
+        ty::Slice(subty) => characteristic_def_id_of_type(subty),
 
-        ty::TyRawPtr(mt) => characteristic_def_id_of_type(mt.ty),
+        ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty),
 
-        ty::TyRef(_, ty, _) => characteristic_def_id_of_type(ty),
+        ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty),
 
-        ty::TyTuple(ref tys) => tys.iter()
+        ty::Tuple(ref tys) => tys.iter()
                                    .filter_map(|ty| characteristic_def_id_of_type(ty))
                                    .next(),
 
-        ty::TyFnDef(def_id, _) |
-        ty::TyClosure(def_id, _) |
-        ty::TyGenerator(def_id, _, _) |
-        ty::TyForeign(def_id) => Some(def_id),
-
-        ty::TyBool |
-        ty::TyChar |
-        ty::TyInt(_) |
-        ty::TyUint(_) |
-        ty::TyStr |
-        ty::TyFnPtr(_) |
-        ty::TyProjection(_) |
-        ty::TyParam(_) |
-        ty::TyAnon(..) |
-        ty::TyInfer(_) |
-        ty::TyError |
-        ty::TyGeneratorWitness(..) |
-        ty::TyNever |
-        ty::TyFloat(_) => None,
+        ty::FnDef(def_id, _) |
+        ty::Closure(def_id, _) |
+        ty::Generator(def_id, _, _) |
+        ty::Foreign(def_id) => Some(def_id),
+
+        ty::Bool |
+        ty::Char |
+        ty::Int(_) |
+        ty::Uint(_) |
+        ty::Str |
+        ty::FnPtr(_) |
+        ty::Projection(_) |
+        ty::Param(_) |
+        ty::Anon(..) |
+        ty::Infer(_) |
+        ty::Error |
+        ty::GeneratorWitness(..) |
+        ty::Never |
+        ty::Float(_) => None,
     }
 }
 
index 0da4d5ddea2f264a5bea4abb08f7d51866f6ef1a..4524c486272b54e563bd62578b15e777616d4aad 100644 (file)
@@ -470,33 +470,33 @@ enum StructKind {
 
         Ok(match ty.sty {
             // Basic scalars.
-            ty::TyBool => {
+            ty::Bool => {
                 tcx.intern_layout(LayoutDetails::scalar(self, Scalar {
                     value: Int(I8, false),
                     valid_range: 0..=1
                 }))
             }
-            ty::TyChar => {
+            ty::Char => {
                 tcx.intern_layout(LayoutDetails::scalar(self, Scalar {
                     value: Int(I32, false),
                     valid_range: 0..=0x10FFFF
                 }))
             }
-            ty::TyInt(ity) => {
+            ty::Int(ity) => {
                 scalar(Int(Integer::from_attr(dl, attr::SignedInt(ity)), true))
             }
-            ty::TyUint(ity) => {
+            ty::Uint(ity) => {
                 scalar(Int(Integer::from_attr(dl, attr::UnsignedInt(ity)), false))
             }
-            ty::TyFloat(fty) => scalar(Float(fty)),
-            ty::TyFnPtr(_) => {
+            ty::Float(fty) => scalar(Float(fty)),
+            ty::FnPtr(_) => {
                 let mut ptr = scalar_unit(Pointer);
                 ptr.valid_range = 1..=*ptr.valid_range.end();
                 tcx.intern_layout(LayoutDetails::scalar(self, ptr))
             }
 
             // The never type.
-            ty::TyNever => {
+            ty::Never => {
                 tcx.intern_layout(LayoutDetails {
                     variants: Variants::Single { index: 0 },
                     fields: FieldPlacement::Union(0),
@@ -507,8 +507,8 @@ enum StructKind {
             }
 
             // Potentially-fat pointers.
-            ty::TyRef(_, pointee, _) |
-            ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
+            ty::Ref(_, pointee, _) |
+            ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
                 let mut data_ptr = scalar_unit(Pointer);
                 if !ty.is_unsafe_ptr() {
                     data_ptr.valid_range = 1..=*data_ptr.valid_range.end();
@@ -521,13 +521,13 @@ enum StructKind {
 
                 let unsized_part = tcx.struct_tail(pointee);
                 let metadata = match unsized_part.sty {
-                    ty::TyForeign(..) => {
+                    ty::Foreign(..) => {
                         return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr)));
                     }
-                    ty::TySlice(_) | ty::TyStr => {
+                    ty::Slice(_) | ty::Str => {
                         scalar_unit(Int(dl.ptr_sized_integer(), false))
                     }
-                    ty::TyDynamic(..) => {
+                    ty::Dynamic(..) => {
                         let mut vtable = scalar_unit(Pointer);
                         vtable.valid_range = 1..=*vtable.valid_range.end();
                         vtable
@@ -540,7 +540,7 @@ enum StructKind {
             }
 
             // Arrays and slices.
-            ty::TyArray(element, mut count) => {
+            ty::Array(element, mut count) => {
                 if count.has_projections() {
                     count = tcx.normalize_erasing_regions(param_env, count);
                     if count.has_projections() {
@@ -564,7 +564,7 @@ enum StructKind {
                     size
                 })
             }
-            ty::TySlice(element) => {
+            ty::Slice(element) => {
                 let element = self.layout_of(element)?;
                 tcx.intern_layout(LayoutDetails {
                     variants: Variants::Single { index: 0 },
@@ -577,7 +577,7 @@ enum StructKind {
                     size: Size::ZERO
                 })
             }
-            ty::TyStr => {
+            ty::Str => {
                 tcx.intern_layout(LayoutDetails {
                     variants: Variants::Single { index: 0 },
                     fields: FieldPlacement::Array {
@@ -591,10 +591,10 @@ enum StructKind {
             }
 
             // Odd unit types.
-            ty::TyFnDef(..) => {
+            ty::FnDef(..) => {
                 univariant(&[], &ReprOptions::default(), StructKind::AlwaysSized)?
             }
-            ty::TyDynamic(..) | ty::TyForeign(..) => {
+            ty::Dynamic(..) | ty::Foreign(..) => {
                 let mut unit = univariant_uninterned(&[], &ReprOptions::default(),
                   StructKind::AlwaysSized)?;
                 match unit.abi {
@@ -605,21 +605,21 @@ enum StructKind {
             }
 
             // Tuples, generators and closures.
-            ty::TyGenerator(def_id, ref substs, _) => {
+            ty::Generator(def_id, ref substs, _) => {
                 let tys = substs.field_tys(def_id, tcx);
                 univariant(&tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
                     &ReprOptions::default(),
                     StructKind::AlwaysSized)?
             }
 
-            ty::TyClosure(def_id, ref substs) => {
+            ty::Closure(def_id, ref substs) => {
                 let tys = substs.upvar_tys(def_id, tcx);
                 univariant(&tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
                     &ReprOptions::default(),
                     StructKind::AlwaysSized)?
             }
 
-            ty::TyTuple(tys) => {
+            ty::Tuple(tys) => {
                 let kind = if tys.len() == 0 {
                     StructKind::AlwaysSized
                 } else {
@@ -631,7 +631,7 @@ enum StructKind {
             }
 
             // SIMD vector types.
-            ty::TyAdt(def, ..) if def.repr.simd() => {
+            ty::Adt(def, ..) if def.repr.simd() => {
                 let element = self.layout_of(ty.simd_type(tcx))?;
                 let count = ty.simd_size(tcx) as u64;
                 assert!(count > 0);
@@ -664,7 +664,7 @@ enum StructKind {
             }
 
             // ADTs.
-            ty::TyAdt(def, substs) => {
+            ty::Adt(def, substs) => {
                 // Cache the field layouts.
                 let variants = def.variants.iter().map(|v| {
                     v.fields.iter().map(|field| {
@@ -1103,17 +1103,17 @@ enum StructKind {
             }
 
             // Types with no meaningful known layout.
-            ty::TyProjection(_) | ty::TyAnon(..) => {
+            ty::Projection(_) | ty::Anon(..) => {
                 let normalized = tcx.normalize_erasing_regions(param_env, ty);
                 if ty == normalized {
                     return Err(LayoutError::Unknown(ty));
                 }
                 tcx.layout_raw(param_env.and(normalized))?
             }
-            ty::TyGeneratorWitness(..) | ty::TyInfer(_) => {
+            ty::GeneratorWitness(..) | ty::Infer(_) => {
                 bug!("LayoutDetails::compute: unexpected type `{}`", ty)
             }
-            ty::TyParam(_) | ty::TyError => {
+            ty::Param(_) | ty::Error => {
                 return Err(LayoutError::Unknown(ty));
             }
         })
@@ -1153,12 +1153,12 @@ fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) {
         };
 
         let adt_def = match layout.ty.sty {
-            ty::TyAdt(ref adt_def, _) => {
+            ty::Adt(ref adt_def, _) => {
                 debug!("print-type-size t: `{:?}` process adt", layout.ty);
                 adt_def
             }
 
-            ty::TyClosure(..) => {
+            ty::Closure(..) => {
                 debug!("print-type-size t: `{:?}` record closure", layout.ty);
                 record(DataTypeKind::Closure, false, None, vec![]);
                 return;
@@ -1294,12 +1294,12 @@ pub fn compute(ty: Ty<'tcx>,
         };
 
         match ty.sty {
-            ty::TyRef(_, pointee, _) |
-            ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
+            ty::Ref(_, pointee, _) |
+            ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
                 let non_zero = !ty.is_unsafe_ptr();
                 let tail = tcx.struct_tail(pointee);
                 match tail.sty {
-                    ty::TyParam(_) | ty::TyProjection(_) => {
+                    ty::Param(_) | ty::Projection(_) => {
                         debug_assert!(tail.has_param_types() || tail.has_self_ty());
                         Ok(SizeSkeleton::Pointer {
                             non_zero,
@@ -1314,7 +1314,7 @@ pub fn compute(ty: Ty<'tcx>,
                 }
             }
 
-            ty::TyAdt(def, substs) => {
+            ty::Adt(def, substs) => {
                 // Only newtypes and enums w/ nullable pointer optimization.
                 if def.is_union() || def.variants.is_empty() || def.variants.len() > 2 {
                     return Err(err);
@@ -1373,7 +1373,7 @@ pub fn compute(ty: Ty<'tcx>,
                 }
             }
 
-            ty::TyProjection(_) | ty::TyAnon(..) => {
+            ty::Projection(_) | ty::Anon(..) => {
                 let normalized = tcx.normalize_erasing_regions(param_env, ty);
                 if ty == normalized {
                     Err(err)
@@ -1552,7 +1552,7 @@ fn for_variant(this: TyLayout<'tcx>, cx: C, variant_index: usize) -> TyLayout<'t
                 });
 
                 let fields = match this.ty.sty {
-                    ty::TyAdt(def, _) => def.variants[variant_index].fields.len(),
+                    ty::Adt(def, _) => def.variants[variant_index].fields.len(),
                     _ => bug!()
                 };
                 let tcx = cx.tcx();
@@ -1582,23 +1582,23 @@ fn for_variant(this: TyLayout<'tcx>, cx: C, variant_index: usize) -> TyLayout<'t
     fn field(this: TyLayout<'tcx>, cx: C, i: usize) -> C::TyLayout {
         let tcx = cx.tcx();
         cx.layout_of(match this.ty.sty {
-            ty::TyBool |
-            ty::TyChar |
-            ty::TyInt(_) |
-            ty::TyUint(_) |
-            ty::TyFloat(_) |
-            ty::TyFnPtr(_) |
-            ty::TyNever |
-            ty::TyFnDef(..) |
-            ty::TyGeneratorWitness(..) |
-            ty::TyForeign(..) |
-            ty::TyDynamic(..) => {
+            ty::Bool |
+            ty::Char |
+            ty::Int(_) |
+            ty::Uint(_) |
+            ty::Float(_) |
+            ty::FnPtr(_) |
+            ty::Never |
+            ty::FnDef(..) |
+            ty::GeneratorWitness(..) |
+            ty::Foreign(..) |
+            ty::Dynamic(..) => {
                 bug!("TyLayout::field_type({:?}): not applicable", this)
             }
 
             // Potentially-fat pointers.
-            ty::TyRef(_, pointee, _) |
-            ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
+            ty::Ref(_, pointee, _) |
+            ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
                 assert!(i < this.fields.count());
 
                 // Reuse the fat *T type as its own thin pointer data field.
@@ -1619,22 +1619,21 @@ fn field(this: TyLayout<'tcx>, cx: C, i: usize) -> C::TyLayout {
                 }
 
                 match tcx.struct_tail(pointee).sty {
-                    ty::TySlice(_) |
-                    ty::TyStr => tcx.types.usize,
-                    ty::TyDynamic(data, _) => {
-                        let trait_def_id = data.principal().unwrap().def_id();
-                        let num_fns: u64 = crate::traits::supertrait_def_ids(tcx, trait_def_id)
-                            .map(|trait_def_id| {
-                                tcx.associated_items(trait_def_id)
-                                    .filter(|item| item.kind == ty::AssociatedKind::Method)
-                                    .count() as u64
-                            })
-                            .sum();
+                    ty::Slice(_) |
+                    ty::Str => tcx.types.usize,
+                    ty::Dynamic(_, _) => {
                         tcx.mk_imm_ref(
                             tcx.types.re_static,
-                            tcx.mk_array(tcx.types.usize, 3 + num_fns),
+                            tcx.mk_array(tcx.types.usize, 3),
                         )
                         /* FIXME use actual fn pointers
+                        Warning: naively computing the number of entries in the
+                        vtable by counting the methods on the trait + methods on
+                        all parent traits does not work, because some methods can
+                        be not object safe and thus excluded from the vtable.
+                        Increase this counter if you tried to implement this but
+                        failed to do it without duplicating a lot of code from
+                        other places in the compiler: 2
                         tcx.mk_tup(&[
                             tcx.mk_array(tcx.types.usize, 3),
                             tcx.mk_array(Option<fn()>),
@@ -1646,28 +1645,28 @@ fn field(this: TyLayout<'tcx>, cx: C, i: usize) -> C::TyLayout {
             }
 
             // Arrays and slices.
-            ty::TyArray(element, _) |
-            ty::TySlice(element) => element,
-            ty::TyStr => tcx.types.u8,
+            ty::Array(element, _) |
+            ty::Slice(element) => element,
+            ty::Str => tcx.types.u8,
 
             // Tuples, generators and closures.
-            ty::TyClosure(def_id, ref substs) => {
+            ty::Closure(def_id, ref substs) => {
                 substs.upvar_tys(def_id, tcx).nth(i).unwrap()
             }
 
-            ty::TyGenerator(def_id, ref substs, _) => {
+            ty::Generator(def_id, ref substs, _) => {
                 substs.field_tys(def_id, tcx).nth(i).unwrap()
             }
 
-            ty::TyTuple(tys) => tys[i],
+            ty::Tuple(tys) => tys[i],
 
             // SIMD vector types.
-            ty::TyAdt(def, ..) if def.repr.simd() => {
+            ty::Adt(def, ..) if def.repr.simd() => {
                 this.ty.simd_type(tcx)
             }
 
             // ADTs.
-            ty::TyAdt(def, substs) => {
+            ty::Adt(def, substs) => {
                 match this.variants {
                     Variants::Single { index } => {
                         def.variants[index].fields[i].ty(tcx, substs)
@@ -1686,8 +1685,8 @@ fn field(this: TyLayout<'tcx>, cx: C, i: usize) -> C::TyLayout {
                 }
             }
 
-            ty::TyProjection(_) | ty::TyAnon(..) | ty::TyParam(_) |
-            ty::TyInfer(_) | ty::TyError => {
+            ty::Projection(_) | ty::Anon(..) | ty::Param(_) |
+            ty::Infer(_) | ty::Error => {
                 bug!("TyLayout::field_type: unexpected type `{}`", this.ty)
             }
         })
@@ -1749,7 +1748,7 @@ fn find_niche(self, layout: TyLayout<'tcx>) -> Result<Option<Niche>, LayoutError
         // Locals variables which live across yields are stored
         // in the generator type as fields. These may be uninitialized
         // so we don't look for niches there.
-        if let ty::TyGenerator(..) = layout.ty.sty {
+        if let ty::Generator(..) = layout.ty.sty {
             return Ok(None);
         }
 
index f6d21ca5861fbf6c45720f8e92abe368877ce2d5..63308ac46d10f4b7b28eb3a9e77756f6f587a5a0 100644 (file)
@@ -15,6 +15,7 @@
 pub use self::fold::TypeFoldable;
 
 use hir::{map as hir_map, FreevarMap, TraitMap};
+use hir::Node;
 use hir::def::{Def, CtorKind, ExportMap};
 use hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use hir::map::DefPathData;
@@ -55,7 +56,7 @@
 use syntax::symbol::{keywords, Symbol, LocalInternedString, InternedString};
 use syntax_pos::{DUMMY_SP, Span};
 
-use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
+use smallvec;
 use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
                                            HashStable};
 
@@ -65,7 +66,7 @@
 pub use self::sty::{FnSig, GenSig, PolyFnSig, PolyGenSig};
 pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
 pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
-pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef};
+pub use self::sty::{TraitRef, TyKind, PolyTraitRef};
 pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
 pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const};
 pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
@@ -74,7 +75,7 @@
 pub use self::sty::BoundRegion::*;
 pub use self::sty::InferTy::*;
 pub use self::sty::RegionKind::*;
-pub use self::sty::TypeVariants::*;
+pub use self::sty::TyKind::*;
 
 pub use self::binding::BindingMode;
 pub use self::binding::BindingMode::*;
@@ -450,7 +451,7 @@ pub struct TypeFlags: u32 {
         const HAS_FREE_LOCAL_NAMES    = 1 << 10;
 
         // Present if the type belongs in a local type context.
-        // Only set for TyInfer other than Fresh.
+        // Only set for Infer other than Fresh.
         const KEEP_IN_LOCAL_TCX  = 1 << 11;
 
         // Is there a projection that does not involve a bound region?
@@ -490,7 +491,7 @@ pub struct TypeFlags: u32 {
 }
 
 pub struct TyS<'tcx> {
-    pub sty: TypeVariants<'tcx>,
+    pub sty: TyKind<'tcx>,
     pub flags: TypeFlags,
 
     /// This is a kind of confusing thing: it stores the smallest
@@ -542,29 +543,29 @@ fn hash<H: Hasher>(&self, s: &mut H) {
 impl<'tcx> TyS<'tcx> {
     pub fn is_primitive_ty(&self) -> bool {
         match self.sty {
-            TypeVariants::TyBool |
-                TypeVariants::TyChar |
-                TypeVariants::TyInt(_) |
-                TypeVariants::TyUint(_) |
-                TypeVariants::TyFloat(_) |
-                TypeVariants::TyInfer(InferTy::IntVar(_)) |
-                TypeVariants::TyInfer(InferTy::FloatVar(_)) |
-                TypeVariants::TyInfer(InferTy::FreshIntTy(_)) |
-                TypeVariants::TyInfer(InferTy::FreshFloatTy(_)) => true,
-            TypeVariants::TyRef(_, x, _) => x.is_primitive_ty(),
+            TyKind::Bool |
+                TyKind::Char |
+                TyKind::Int(_) |
+                TyKind::Uint(_) |
+                TyKind::Float(_) |
+                TyKind::Infer(InferTy::IntVar(_)) |
+                TyKind::Infer(InferTy::FloatVar(_)) |
+                TyKind::Infer(InferTy::FreshIntTy(_)) |
+                TyKind::Infer(InferTy::FreshFloatTy(_)) => true,
+            TyKind::Ref(_, x, _) => x.is_primitive_ty(),
             _ => false,
         }
     }
 
     pub fn is_suggestable(&self) -> bool {
         match self.sty {
-            TypeVariants::TyAnon(..) |
-            TypeVariants::TyFnDef(..) |
-            TypeVariants::TyFnPtr(..) |
-            TypeVariants::TyDynamic(..) |
-            TypeVariants::TyClosure(..) |
-            TypeVariants::TyInfer(..) |
-            TypeVariants::TyProjection(..) => false,
+            TyKind::Anon(..) |
+            TyKind::FnDef(..) |
+            TyKind::FnPtr(..) |
+            TyKind::Dynamic(..) |
+            TyKind::Closure(..) |
+            TyKind::Infer(..) |
+            TyKind::Projection(..) => false,
             _ => true,
         }
     }
@@ -596,8 +597,8 @@ impl<'tcx> serialize::UseSpecializedDecodable for Ty<'tcx> {}
 pub type CanonicalTy<'gcx> = Canonical<'gcx, Ty<'gcx>>;
 
 extern {
-    /// A dummy type used to force Slice to by unsized without requiring fat pointers
-    type OpaqueSliceContents;
+    /// A dummy type used to force List to by unsized without requiring fat pointers
+    type OpaqueListContents;
 }
 
 /// A wrapper for slices with the additional invariant
@@ -605,18 +606,19 @@ impl<'tcx> serialize::UseSpecializedDecodable for Ty<'tcx> {}
 /// the same contents can exist in the same context.
 /// This means we can use pointer for both
 /// equality comparisons and hashing.
+/// Note: `Slice` was already taken by the `Ty`.
 #[repr(C)]
-pub struct Slice<T> {
+pub struct List<T> {
     len: usize,
     data: [T; 0],
-    opaque: OpaqueSliceContents,
+    opaque: OpaqueListContents,
 }
 
-unsafe impl<T: Sync> Sync for Slice<T> {}
+unsafe impl<T: Sync> Sync for List<T> {}
 
-impl<T: Copy> Slice<T> {
+impl<T: Copy> List<T> {
     #[inline]
-    fn from_arena<'tcx>(arena: &'tcx SyncDroplessArena, slice: &[T]) -> &'tcx Slice<T> {
+    fn from_arena<'tcx>(arena: &'tcx SyncDroplessArena, slice: &[T]) -> &'tcx List<T> {
         assert!(!mem::needs_drop::<T>());
         assert!(mem::size_of::<T>() != 0);
         assert!(slice.len() != 0);
@@ -633,7 +635,7 @@ fn from_arena<'tcx>(arena: &'tcx SyncDroplessArena, slice: &[T]) -> &'tcx Slice<
             size,
             cmp::max(mem::align_of::<T>(), mem::align_of::<usize>()));
         unsafe {
-            let result = &mut *(mem.as_mut_ptr() as *mut Slice<T>);
+            let result = &mut *(mem.as_mut_ptr() as *mut List<T>);
             // Write the length
             result.len = slice.len();
 
@@ -646,51 +648,51 @@ fn from_arena<'tcx>(arena: &'tcx SyncDroplessArena, slice: &[T]) -> &'tcx Slice<
     }
 }
 
-impl<T: fmt::Debug> fmt::Debug for Slice<T> {
+impl<T: fmt::Debug> fmt::Debug for List<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         (**self).fmt(f)
     }
 }
 
-impl<T: Encodable> Encodable for Slice<T> {
+impl<T: Encodable> Encodable for List<T> {
     #[inline]
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         (**self).encode(s)
     }
 }
 
-impl<T> Ord for Slice<T> where T: Ord {
-    fn cmp(&self, other: &Slice<T>) -> Ordering {
+impl<T> Ord for List<T> where T: Ord {
+    fn cmp(&self, other: &List<T>) -> Ordering {
         if self == other { Ordering::Equal } else {
             <[T] as Ord>::cmp(&**self, &**other)
         }
     }
 }
 
-impl<T> PartialOrd for Slice<T> where T: PartialOrd {
-    fn partial_cmp(&self, other: &Slice<T>) -> Option<Ordering> {
+impl<T> PartialOrd for List<T> where T: PartialOrd {
+    fn partial_cmp(&self, other: &List<T>) -> Option<Ordering> {
         if self == other { Some(Ordering::Equal) } else {
             <[T] as PartialOrd>::partial_cmp(&**self, &**other)
         }
     }
 }
 
-impl<T: PartialEq> PartialEq for Slice<T> {
+impl<T: PartialEq> PartialEq for List<T> {
     #[inline]
-    fn eq(&self, other: &Slice<T>) -> bool {
+    fn eq(&self, other: &List<T>) -> bool {
         ptr::eq(self, other)
     }
 }
-impl<T: Eq> Eq for Slice<T> {}
+impl<T: Eq> Eq for List<T> {}
 
-impl<T> Hash for Slice<T> {
+impl<T> Hash for List<T> {
     #[inline]
     fn hash<H: Hasher>(&self, s: &mut H) {
-        (self as *const Slice<T>).hash(s)
+        (self as *const List<T>).hash(s)
     }
 }
 
-impl<T> Deref for Slice<T> {
+impl<T> Deref for List<T> {
     type Target = [T];
     #[inline(always)]
     fn deref(&self) -> &[T] {
@@ -700,7 +702,7 @@ fn deref(&self) -> &[T] {
     }
 }
 
-impl<'a, T> IntoIterator for &'a Slice<T> {
+impl<'a, T> IntoIterator for &'a List<T> {
     type Item = &'a T;
     type IntoIter = <&'a [T] as IntoIterator>::IntoIter;
     #[inline(always)]
@@ -709,17 +711,17 @@ fn into_iter(self) -> Self::IntoIter {
     }
 }
 
-impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice<Ty<'tcx>> {}
+impl<'tcx> serialize::UseSpecializedDecodable for &'tcx List<Ty<'tcx>> {}
 
-impl<T> Slice<T> {
+impl<T> List<T> {
     #[inline(always)]
-    pub fn empty<'a>() -> &'a Slice<T> {
+    pub fn empty<'a>() -> &'a List<T> {
         #[repr(align(64), C)]
         struct EmptySlice([u8; 64]);
         static EMPTY_SLICE: EmptySlice = EmptySlice([0; 64]);
         assert!(mem::align_of::<T>() <= 64);
         unsafe {
-            &*(&EMPTY_SLICE as *const _ as *const Slice<T>)
+            &*(&EMPTY_SLICE as *const _ as *const List<T>)
         }
     }
 }
@@ -1501,7 +1503,7 @@ impl UniverseIndex {
 
     /// Creates a universe index from the given integer.  Not to be
     /// used lightly lest you pick a bad value. But sometimes we
-    /// convert universe indicies into integers and back for various
+    /// convert universe indices into integers and back for various
     /// reasons.
     pub fn from_u32(index: u32) -> Self {
         UniverseIndex(index)
@@ -1556,7 +1558,7 @@ pub struct ParamEnv<'tcx> {
     /// Obligations that the caller must satisfy. This is basically
     /// the set of bounds on the in-scope type parameters, translated
     /// into Obligations, and elaborated and normalized.
-    pub caller_bounds: &'tcx Slice<ty::Predicate<'tcx>>,
+    pub caller_bounds: &'tcx List<ty::Predicate<'tcx>>,
 
     /// Typically, this is `Reveal::UserFacing`, but during codegen we
     /// want `Reveal::All` -- note that this is always paired with an
@@ -1570,7 +1572,7 @@ impl<'tcx> ParamEnv<'tcx> {
     /// Trait`) are left hidden, so this is suitable for ordinary
     /// type-checking.
     pub fn empty() -> Self {
-        Self::new(ty::Slice::empty(), Reveal::UserFacing)
+        Self::new(List::empty(), Reveal::UserFacing)
     }
 
     /// Construct a trait environment with no where clauses in scope
@@ -1581,11 +1583,11 @@ pub fn empty() -> Self {
     /// NB. If you want to have predicates in scope, use `ParamEnv::new`,
     /// or invoke `param_env.with_reveal_all()`.
     pub fn reveal_all() -> Self {
-        Self::new(ty::Slice::empty(), Reveal::All)
+        Self::new(List::empty(), Reveal::All)
     }
 
     /// Construct a trait environment with the given set of predicates.
-    pub fn new(caller_bounds: &'tcx ty::Slice<ty::Predicate<'tcx>>,
+    pub fn new(caller_bounds: &'tcx List<ty::Predicate<'tcx>>,
                reveal: Reveal)
                -> Self {
         ty::ParamEnv { caller_bounds, reveal }
@@ -1603,7 +1605,7 @@ pub fn with_reveal_all(self) -> Self {
 
     /// Returns this same environment but with no caller bounds.
     pub fn without_caller_bounds(self) -> Self {
-        ty::ParamEnv { caller_bounds: ty::Slice::empty(), ..self }
+        ty::ParamEnv { caller_bounds: List::empty(), ..self }
     }
 
     /// Creates a suitable environment in which to perform trait
@@ -2229,30 +2231,30 @@ fn sized_constraint_for_ty(&self,
                                ty: Ty<'tcx>)
                                -> Vec<Ty<'tcx>> {
         let result = match ty.sty {
-            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
-            TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
-            TyArray(..) | TyClosure(..) | TyGenerator(..) | TyNever => {
+            Bool | Char | Int(..) | Uint(..) | Float(..) |
+            RawPtr(..) | Ref(..) | FnDef(..) | FnPtr(_) |
+            Array(..) | Closure(..) | Generator(..) | Never => {
                 vec![]
             }
 
-            TyStr |
-            TyDynamic(..) |
-            TySlice(_) |
-            TyForeign(..) |
-            TyError |
-            TyGeneratorWitness(..) => {
+            Str |
+            Dynamic(..) |
+            Slice(_) |
+            Foreign(..) |
+            Error |
+            GeneratorWitness(..) => {
                 // these are never sized - return the target type
                 vec![ty]
             }
 
-            TyTuple(ref tys) => {
+            Tuple(ref tys) => {
                 match tys.last() {
                     None => vec![],
                     Some(ty) => self.sized_constraint_for_ty(tcx, ty)
                 }
             }
 
-            TyAdt(adt, substs) => {
+            Adt(adt, substs) => {
                 // recursive case
                 let adt_tys = adt.sized_constraint(tcx);
                 debug!("sized_constraint_for_ty({:?}) intermediate = {:?}",
@@ -2263,13 +2265,13 @@ fn sized_constraint_for_ty(&self,
                     .collect()
             }
 
-            TyProjection(..) | TyAnon(..) => {
+            Projection(..) | Anon(..) => {
                 // must calculate explicitly.
                 // FIXME: consider special-casing always-Sized projections
                 vec![ty]
             }
 
-            TyParam(..) => {
+            Param(..) => {
                 // perf hack: if there is a `T: Sized` bound, then
                 // we know that `T` is Sized and do not need to check
                 // it on the impl.
@@ -2290,7 +2292,7 @@ fn sized_constraint_for_ty(&self,
                 }
             }
 
-            TyInfer(..) => {
+            Infer(..) => {
                 bug!("unexpected type `{:?}` in sized_constraint_for_ty",
                      ty)
             }
@@ -2381,7 +2383,7 @@ pub fn walk(&'tcx self) -> TypeWalker<'tcx> {
     /// Iterator that walks the immediate children of `self`.  Hence
     /// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]`
     /// (but not `i32`, like `walk`).
-    pub fn walk_shallow(&'tcx self) -> AccIntoIter<walk::TypeWalkerArray<'tcx>> {
+    pub fn walk_shallow(&'tcx self) -> smallvec::IntoIter<walk::TypeWalkerArray<'tcx>> {
         walk::walk_shallow(self)
     }
 
@@ -2477,7 +2479,7 @@ pub fn par_body_owners<F: Fn(DefId) + sync::Sync + sync::Send>(self, f: F) {
 
     pub fn expr_span(self, id: NodeId) -> Span {
         match self.hir.find(id) {
-            Some(hir_map::NodeExpr(e)) => {
+            Some(Node::Expr(e)) => {
                 e.span
             }
             Some(f) => {
@@ -2504,7 +2506,7 @@ pub fn trait_relevant_for_never(self, did: DefId) -> bool {
     pub fn opt_associated_item(self, def_id: DefId) -> Option<AssociatedItem> {
         let is_associated_item = if let Some(node_id) = self.hir.as_local_node_id(def_id) {
             match self.hir.get(node_id) {
-                hir_map::NodeTraitItem(_) | hir_map::NodeImplItem(_) => true,
+                Node::TraitItem(_) | Node::ImplItem(_) => true,
                 _ => false,
             }
         } else {
@@ -2832,7 +2834,7 @@ fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
 ///     - a type parameter or projection whose Sizedness can't be known
 ///     - a tuple of type parameters or projections, if there are multiple
 ///       such.
-///     - a TyError, if a type contained itself. The representability
+///     - a Error, if a type contained itself. The representability
 ///       check should catch this case.
 fn adt_sized_constraint<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   def_id: DefId)
@@ -2894,7 +2896,7 @@ fn trait_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option
 /// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition
 pub fn is_impl_trait_defn(tcx: TyCtxt, def_id: DefId) -> Option<DefId> {
     if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
-        if let hir::map::NodeItem(item) = tcx.hir.get(node_id) {
+        if let Node::Item(item) = tcx.hir.get(node_id) {
             if let hir::ItemKind::Existential(ref exist_ty) = item.node {
                 return exist_ty.impl_trait_fn;
             }
index ff99a4b7ff63828a17b5fd2d44cd4144e63b7428..5171bfb7e06083e62e1bd58216e5effd65ce7a67 100644 (file)
@@ -72,14 +72,14 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
         // in the `subtys` iterator (e.g., when encountering a
         // projection).
         match ty.sty {
-            ty::TyClosure(def_id, ref substs) => {
+            ty::Closure(def_id, ref substs) => {
 
                 for upvar_ty in substs.upvar_tys(def_id, *self) {
                     self.compute_components(upvar_ty, out);
                 }
             }
 
-            ty::TyGenerator(def_id, ref substs, _) => {
+            ty::Generator(def_id, ref substs, _) => {
                 // Same as the closure case
                 for upvar_ty in substs.upvar_tys(def_id, *self) {
                     self.compute_components(upvar_ty, out);
@@ -90,11 +90,11 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
             }
 
             // All regions are bound inside a witness
-            ty::TyGeneratorWitness(..) => (),
+            ty::GeneratorWitness(..) => (),
 
             // OutlivesTypeParameterEnv -- the actual checking that `X:'a`
             // is implied by the environment is done in regionck.
-            ty::TyParam(p) => {
+            ty::Param(p) => {
                 out.push(Component::Param(p));
             }
 
@@ -106,7 +106,7 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
             // trait-ref. Therefore, if we see any higher-ranke regions,
             // we simply fallback to the most restrictive rule, which
             // requires that `Pi: 'a` for all `i`.
-            ty::TyProjection(ref data) => {
+            ty::Projection(ref data) => {
                 if !data.has_escaping_regions() {
                     // best case: no escaping regions, so push the
                     // projection and skip the subtree (thus generating no
@@ -127,7 +127,7 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
             // We assume that inference variables are fully resolved.
             // So, if we encounter an inference variable, just record
             // the unresolved variable as a component.
-            ty::TyInfer(infer_ty) => {
+            ty::Infer(infer_ty) => {
                 out.push(Component::UnresolvedInferenceVariable(infer_ty));
             }
 
@@ -137,25 +137,25 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
             // the type and then visits the types that are lexically
             // contained within. (The comments refer to relevant rules
             // from RFC1214.)
-            ty::TyBool |            // OutlivesScalar
-            ty::TyChar |            // OutlivesScalar
-            ty::TyInt(..) |         // OutlivesScalar
-            ty::TyUint(..) |        // OutlivesScalar
-            ty::TyFloat(..) |       // OutlivesScalar
-            ty::TyNever |           // ...
-            ty::TyAdt(..) |         // OutlivesNominalType
-            ty::TyAnon(..) |        // OutlivesNominalType (ish)
-            ty::TyForeign(..) |     // OutlivesNominalType
-            ty::TyStr |             // OutlivesScalar (ish)
-            ty::TyArray(..) |       // ...
-            ty::TySlice(..) |       // ...
-            ty::TyRawPtr(..) |      // ...
-            ty::TyRef(..) |         // OutlivesReference
-            ty::TyTuple(..) |       // ...
-            ty::TyFnDef(..) |       // OutlivesFunction (*)
-            ty::TyFnPtr(_) |        // OutlivesFunction (*)
-            ty::TyDynamic(..) |       // OutlivesObject, OutlivesFragment (*)
-            ty::TyError => {
+            ty::Bool |            // OutlivesScalar
+            ty::Char |            // OutlivesScalar
+            ty::Int(..) |         // OutlivesScalar
+            ty::Uint(..) |        // OutlivesScalar
+            ty::Float(..) |       // OutlivesScalar
+            ty::Never |           // ...
+            ty::Adt(..) |         // OutlivesNominalType
+            ty::Anon(..) |        // OutlivesNominalType (ish)
+            ty::Foreign(..) |     // OutlivesNominalType
+            ty::Str |             // OutlivesScalar (ish)
+            ty::Array(..) |       // ...
+            ty::Slice(..) |       // ...
+            ty::RawPtr(..) |      // ...
+            ty::Ref(..) |         // OutlivesReference
+            ty::Tuple(..) |       // ...
+            ty::FnDef(..) |       // OutlivesFunction (*)
+            ty::FnPtr(_) |        // OutlivesFunction (*)
+            ty::Dynamic(..) |       // OutlivesObject, OutlivesFragment (*)
+            ty::Error => {
                 // (*) Bare functions and traits are both binders. In the
                 // RFC, this means we would add the bound regions to the
                 // "bound regions list".  In our representation, no such
index ecf35c1b0da391b7a24558f277f4ea327c1b1d27..d32580181f8dc65cb25376dd46eef0f622f4acb8 100644 (file)
@@ -198,12 +198,6 @@ fn describe(tcx: TyCtxt, def_id: DefId) -> String {
     }
 }
 
-impl<'tcx> QueryDescription<'tcx> for queries::const_value_to_allocation<'tcx> {
-    fn describe(_tcx: TyCtxt, val: &'tcx ty::Const<'tcx>) -> String {
-        format!("converting value `{:?}` to an allocation", val)
-    }
-}
-
 impl<'tcx> QueryDescription<'tcx> for queries::erase_regions_ty<'tcx> {
     fn describe(_tcx: TyCtxt, ty: Ty<'tcx>) -> String {
         format!("erasing regions from `{:?}`", ty)
index 56a8c13a8d3b80864e2e19c29f5767d51f9b1518..d07891fca12aea5144fbe378051805c345a2eb43 100644 (file)
@@ -11,6 +11,7 @@
 #![allow(warnings)]
 
 use std::mem;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::{Lock, LockGuard, Lrc, Weak};
 use rustc_data_structures::OnDrop;
 use syntax_pos::Span;
@@ -21,7 +22,7 @@
 use errors::Diagnostic;
 use std::process;
 use std::{fmt, ptr};
-use std::collections::HashSet;
+
 #[cfg(parallel_queries)]
 use {
     rayon_core,
@@ -262,7 +263,7 @@ fn visit_waiters<'tcx, F>(query: Lrc<QueryJob<'tcx>>, mut visit: F) -> Option<Op
         }
     }
 
-    // Visit the explict waiters which use condvars and are resumable
+    // Visit the explicit waiters which use condvars and are resumable
     for (i, waiter) in query.latch.info.lock().waiters.iter().enumerate() {
         if let Some(ref waiter_query) = waiter.query {
             if visit(waiter.span, waiter_query.clone()).is_some() {
@@ -282,7 +283,7 @@ fn visit_waiters<'tcx, F>(query: Lrc<QueryJob<'tcx>>, mut visit: F) -> Option<Op
 fn cycle_check<'tcx>(query: Lrc<QueryJob<'tcx>>,
                      span: Span,
                      stack: &mut Vec<(Span, Lrc<QueryJob<'tcx>>)>,
-                     visited: &mut HashSet<*const QueryJob<'tcx>>
+                     visited: &mut FxHashSet<*const QueryJob<'tcx>>
 ) -> Option<Option<Waiter<'tcx>>> {
     if visited.contains(&query.as_ptr()) {
         return if let Some(p) = stack.iter().position(|q| q.1.as_ptr() == query.as_ptr()) {
@@ -321,7 +322,7 @@ fn cycle_check<'tcx>(query: Lrc<QueryJob<'tcx>>,
 #[cfg(parallel_queries)]
 fn connected_to_root<'tcx>(
     query: Lrc<QueryJob<'tcx>>,
-    visited: &mut HashSet<*const QueryJob<'tcx>>
+    visited: &mut FxHashSet<*const QueryJob<'tcx>>
 ) -> bool {
     // We already visited this or we're deliberately ignoring it
     if visited.contains(&query.as_ptr()) {
@@ -357,7 +358,7 @@ fn remove_cycle<'tcx>(
     wakelist: &mut Vec<Lrc<QueryWaiter<'tcx>>>,
     tcx: TyCtxt<'_, 'tcx, '_>
 ) -> bool {
-    let mut visited = HashSet::new();
+    let mut visited = FxHashSet::default();
     let mut stack = Vec::new();
     // Look for a cycle starting with the last query in `jobs`
     if let Some(waiter) = cycle_check(jobs.pop().unwrap(),
@@ -389,7 +390,7 @@ fn remove_cycle<'tcx>(
         // connected to queries outside the cycle
         let entry_points: Vec<Lrc<QueryJob<'tcx>>> = stack.iter().filter_map(|query| {
             // Mark all the other queries in the cycle as already visited
-            let mut visited = HashSet::from_iter(stack.iter().filter_map(|q| {
+            let mut visited = FxHashSet::from_iter(stack.iter().filter_map(|q| {
                 if q.1.as_ptr() != query.1.as_ptr() {
                     Some(q.1.as_ptr())
                 } else {
index ef22ebef9d7d4867fd5c79443f48d0f973854d8f..88f599971c7daeab9a4d5c793c2142e6d87b9554 100644 (file)
@@ -30,7 +30,7 @@
 use mir::interpret::ConstEvalResult;
 use mir::mono::{CodegenUnit, Stats};
 use mir;
-use mir::interpret::{GlobalId, Allocation};
+use mir::interpret::GlobalId;
 use session::{CompileResult, CrateDisambiguator};
 use session::config::OutputFilenames;
 use traits::{self, Vtable};
@@ -49,7 +49,7 @@
 use util::common::{ErrorReported};
 use util::profiling::ProfileCategory::*;
 
-use rustc_data_structures::indexed_set::IdxSetBuf;
+use rustc_data_structures::indexed_set::IdxSet;
 use rustc_target::spec::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
         /// Maps DefId's that have an associated Mir to the result
         /// of the MIR qualify_consts pass. The actual meaning of
         /// the value isn't known except to the pass itself.
-        [] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Lrc<IdxSetBuf<mir::Local>>),
+        [] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Lrc<IdxSet<mir::Local>>),
 
         /// Fetch the MIR for a given def-id right after it's built - this includes
         /// unreachable code.
         /// other items (such as enum variant explicit discriminants).
         [] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
             -> ConstEvalResult<'tcx>,
-
-        /// Converts a constant value to an constant allocation
-        [] fn const_value_to_allocation: const_value_to_allocation(
-            &'tcx ty::Const<'tcx>
-        ) -> &'tcx Allocation,
     },
 
     TypeChecking {
@@ -706,12 +701,6 @@ fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> {
     DepConstructor::EraseRegionsTy { ty }
 }
 
-fn const_value_to_allocation<'tcx>(
-    val: &'tcx ty::Const<'tcx>,
-) -> DepConstructor<'tcx> {
-    DepConstructor::ConstValueToAllocation { val }
-}
-
 fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
     DepConstructor::TypeParamPredicates {
         item_id,
index bf721ddd13fc6bd7088bec7612e8cdff78c5cc9f..215fba54499b7e0065f53c78066d565d55191e97 100644 (file)
@@ -718,7 +718,7 @@ pub fn collect_active_jobs(&self) -> Vec<Lrc<QueryJob<$tcx>>> {
             }
         }
 
-        #[allow(bad_style)]
+        #[allow(nonstandard_style)]
         #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
         pub enum Query<$tcx> {
             $($(#[$attr])* $name($K)),*
@@ -775,7 +775,7 @@ fn hash_stable<W: StableHasherResult>(&self,
         pub mod queries {
             use std::marker::PhantomData;
 
-            $(#[allow(bad_style)]
+            $(#[allow(nonstandard_style)]
             pub struct $name<$tcx> {
                 data: PhantomData<&$tcx ()>
             })*
@@ -1062,7 +1062,6 @@ macro_rules! force {
         DepKind::FulfillObligation |
         DepKind::VtableMethods |
         DepKind::EraseRegionsTy |
-        DepKind::ConstValueToAllocation |
         DepKind::NormalizeProjectionTy |
         DepKind::NormalizeTyAfterErasingRegions |
         DepKind::ImpliedOutlivesBounds |
index 4e8f33d6a4a0324ded1ee685a1392138c057dc3b..d72e48c04fed4ed5ea0bb98e6c15ee05b6b0a2d0 100644 (file)
@@ -316,7 +316,7 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
 }
 
 #[derive(Debug, Clone)]
-struct GeneratorWitness<'tcx>(&'tcx ty::Slice<Ty<'tcx>>);
+struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
 
 TupleStructTypeFoldableImpl! {
     impl<'tcx> TypeFoldable<'tcx> for GeneratorWitness<'tcx> {
@@ -363,50 +363,50 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
     let b_sty = &b.sty;
     debug!("super_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty);
     match (a_sty, b_sty) {
-        (&ty::TyInfer(_), _) |
-        (_, &ty::TyInfer(_)) =>
+        (&ty::Infer(_), _) |
+        (_, &ty::Infer(_)) =>
         {
             // The caller should handle these cases!
             bug!("var types encountered in super_relate_tys")
         }
 
-        (&ty::TyError, _) | (_, &ty::TyError) =>
+        (&ty::Error, _) | (_, &ty::Error) =>
         {
             Ok(tcx.types.err)
         }
 
-        (&ty::TyNever, _) |
-        (&ty::TyChar, _) |
-        (&ty::TyBool, _) |
-        (&ty::TyInt(_), _) |
-        (&ty::TyUint(_), _) |
-        (&ty::TyFloat(_), _) |
-        (&ty::TyStr, _)
+        (&ty::Never, _) |
+        (&ty::Char, _) |
+        (&ty::Bool, _) |
+        (&ty::Int(_), _) |
+        (&ty::Uint(_), _) |
+        (&ty::Float(_), _) |
+        (&ty::Str, _)
             if a == b =>
         {
             Ok(a)
         }
 
-        (&ty::TyParam(ref a_p), &ty::TyParam(ref b_p))
+        (&ty::Param(ref a_p), &ty::Param(ref b_p))
             if a_p.idx == b_p.idx =>
         {
             Ok(a)
         }
 
-        (&ty::TyAdt(a_def, a_substs), &ty::TyAdt(b_def, b_substs))
+        (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
             if a_def == b_def =>
         {
             let substs = relation.relate_item_substs(a_def.did, a_substs, b_substs)?;
             Ok(tcx.mk_adt(a_def, substs))
         }
 
-        (&ty::TyForeign(a_id), &ty::TyForeign(b_id))
+        (&ty::Foreign(a_id), &ty::Foreign(b_id))
             if a_id == b_id =>
         {
             Ok(tcx.mk_foreign(a_id))
         }
 
-        (&ty::TyDynamic(ref a_obj, ref a_region), &ty::TyDynamic(ref b_obj, ref b_region)) => {
+        (&ty::Dynamic(ref a_obj, ref a_region), &ty::Dynamic(ref b_obj, ref b_region)) => {
             let region_bound = relation.with_cause(Cause::ExistentialRegionBound,
                                                        |relation| {
                                                            relation.relate_with_variance(
@@ -417,18 +417,18 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound))
         }
 
-        (&ty::TyGenerator(a_id, a_substs, movability),
-         &ty::TyGenerator(b_id, b_substs, _))
+        (&ty::Generator(a_id, a_substs, movability),
+         &ty::Generator(b_id, b_substs, _))
             if a_id == b_id =>
         {
-            // All TyGenerator types with the same id represent
+            // All Generator types with the same id represent
             // the (anonymous) type of the same generator expression. So
             // all of their regions should be equated.
             let substs = relation.relate(&a_substs, &b_substs)?;
             Ok(tcx.mk_generator(a_id, substs, movability))
         }
 
-        (&ty::TyGeneratorWitness(a_types), &ty::TyGeneratorWitness(b_types)) =>
+        (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) =>
         {
             // Wrap our types with a temporary GeneratorWitness struct
             // inside the binder so we can related them
@@ -439,24 +439,24 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             Ok(tcx.mk_generator_witness(types))
         }
 
-        (&ty::TyClosure(a_id, a_substs),
-         &ty::TyClosure(b_id, b_substs))
+        (&ty::Closure(a_id, a_substs),
+         &ty::Closure(b_id, b_substs))
             if a_id == b_id =>
         {
-            // All TyClosure types with the same id represent
+            // All Closure types with the same id represent
             // the (anonymous) type of the same closure expression. So
             // all of their regions should be equated.
             let substs = relation.relate(&a_substs, &b_substs)?;
             Ok(tcx.mk_closure(a_id, substs))
         }
 
-        (&ty::TyRawPtr(ref a_mt), &ty::TyRawPtr(ref b_mt)) =>
+        (&ty::RawPtr(ref a_mt), &ty::RawPtr(ref b_mt)) =>
         {
             let mt = relation.relate(a_mt, b_mt)?;
             Ok(tcx.mk_ptr(mt))
         }
 
-        (&ty::TyRef(a_r, a_ty, a_mutbl), &ty::TyRef(b_r, b_ty, b_mutbl)) =>
+        (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) =>
         {
             let r = relation.relate_with_variance(ty::Contravariant, &a_r, &b_r)?;
             let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl };
@@ -465,7 +465,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             Ok(tcx.mk_ref(r, mt))
         }
 
-        (&ty::TyArray(a_t, sz_a), &ty::TyArray(b_t, sz_b)) =>
+        (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) =>
         {
             let t = relation.relate(&a_t, &b_t)?;
             assert_eq!(sz_a.ty, tcx.types.usize);
@@ -514,26 +514,26 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             match (to_u64(sz_a), to_u64(sz_b)) {
                 (Ok(sz_a_u64), Ok(sz_b_u64)) => {
                     if sz_a_u64 == sz_b_u64 {
-                        Ok(tcx.mk_ty(ty::TyArray(t, sz_a)))
+                        Ok(tcx.mk_ty(ty::Array(t, sz_a)))
                     } else {
                         Err(TypeError::FixedArraySize(
                             expected_found(relation, &sz_a_u64, &sz_b_u64)))
                     }
                 }
-                // We reported an error or will ICE, so we can return TyError.
+                // We reported an error or will ICE, so we can return Error.
                 (Err(ErrorReported), _) | (_, Err(ErrorReported)) => {
                     Ok(tcx.types.err)
                 }
             }
         }
 
-        (&ty::TySlice(a_t), &ty::TySlice(b_t)) =>
+        (&ty::Slice(a_t), &ty::Slice(b_t)) =>
         {
             let t = relation.relate(&a_t, &b_t)?;
             Ok(tcx.mk_slice(t))
         }
 
-        (&ty::TyTuple(as_), &ty::TyTuple(bs)) =>
+        (&ty::Tuple(as_), &ty::Tuple(bs)) =>
         {
             if as_.len() == bs.len() {
                 Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)))?)
@@ -545,26 +545,26 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             }
         }
 
-        (&ty::TyFnDef(a_def_id, a_substs), &ty::TyFnDef(b_def_id, b_substs))
+        (&ty::FnDef(a_def_id, a_substs), &ty::FnDef(b_def_id, b_substs))
             if a_def_id == b_def_id =>
         {
             let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?;
             Ok(tcx.mk_fn_def(a_def_id, substs))
         }
 
-        (&ty::TyFnPtr(a_fty), &ty::TyFnPtr(b_fty)) =>
+        (&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) =>
         {
             let fty = relation.relate(&a_fty, &b_fty)?;
             Ok(tcx.mk_fn_ptr(fty))
         }
 
-        (&ty::TyProjection(ref a_data), &ty::TyProjection(ref b_data)) =>
+        (&ty::Projection(ref a_data), &ty::Projection(ref b_data)) =>
         {
             let projection_ty = relation.relate(a_data, b_data)?;
             Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs))
         }
 
-        (&ty::TyAnon(a_def_id, a_substs), &ty::TyAnon(b_def_id, b_substs))
+        (&ty::Anon(a_def_id, a_substs), &ty::Anon(b_def_id, b_substs))
             if a_def_id == b_def_id =>
         {
             let substs = relate_substs(relation, None, a_substs, b_substs)?;
@@ -578,7 +578,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
     }
 }
 
-impl<'tcx> Relate<'tcx> for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
+impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
     fn relate<'a, 'gcx, R>(relation: &mut R,
                            a: &Self,
                            b: &Self)
index ad29f808285b1ae99d9b6cf3f993b546830e57b1..60b85e8a8eb9aad5c4eed9938a5caeabb07009f6 100644 (file)
@@ -16,8 +16,8 @@
 use mir::interpret::{ConstValue, ConstEvalErr};
 use ty::{self, Lift, Ty, TyCtxt};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
-use rustc_data_structures::accumulate_vec::AccumulateVec;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use smallvec::SmallVec;
 use mir::interpret;
 
 use std::rc::Rc;
@@ -487,10 +487,12 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
         use ::mir::interpret::EvalErrorKind::*;
         Some(match *self {
             MachineError(ref err) => MachineError(err.clone()),
-            FunctionPointerTyMismatch(a, b) => FunctionPointerTyMismatch(
+            FunctionAbiMismatch(a, b) => FunctionAbiMismatch(a, b),
+            FunctionArgMismatch(a, b) => FunctionArgMismatch(
                 tcx.lift(&a)?,
                 tcx.lift(&b)?,
             ),
+            FunctionArgCountMismatch => FunctionArgCountMismatch,
             NoMirFor(ref s) => NoMirFor(s.clone()),
             UnterminatedCString(ptr) => UnterminatedCString(ptr),
             DanglingPointerDeref => DanglingPointerDeref,
@@ -498,7 +500,7 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
             InvalidMemoryAccess => InvalidMemoryAccess,
             InvalidFunctionPointer => InvalidFunctionPointer,
             InvalidBool => InvalidBool,
-            InvalidDiscriminant => InvalidDiscriminant,
+            InvalidDiscriminant(val) => InvalidDiscriminant(val),
             PointerOutOfBounds {
                 ptr,
                 access,
@@ -574,7 +576,11 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
             HeapAllocZeroBytes => HeapAllocZeroBytes,
             HeapAllocNonPowerOfTwoAlignment(n) => HeapAllocNonPowerOfTwoAlignment(n),
             Unreachable => Unreachable,
-            Panic => Panic,
+            Panic { ref msg, ref file, line, col } => Panic {
+                msg: msg.clone(),
+                file: file.clone(),
+                line, col,
+            },
             ReadFromReturnPointer => ReadFromReturnPointer,
             PathNotFound(ref v) => PathNotFound(v.clone()),
             UnimplementedTraitSelection => UnimplementedTraitSelection,
@@ -735,9 +741,9 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     impl<'tcx> TypeFoldable<'tcx> for ty::ParamEnv<'tcx> { reveal, caller_bounds }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
+impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        let v = self.iter().map(|p| p.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>();
+        let v = self.iter().map(|p| p.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
         folder.tcx().intern_existential_predicates(&v)
     }
 
@@ -754,9 +760,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialPredicate<'tcx> {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<Ty<'tcx>> {
+impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        let v = self.iter().map(|t| t.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>();
+        let v = self.iter().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
         folder.tcx().intern_type_list(&v)
     }
 
@@ -836,33 +842,33 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
 impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         let sty = match self.sty {
-            ty::TyRawPtr(tm) => ty::TyRawPtr(tm.fold_with(folder)),
-            ty::TyArray(typ, sz) => ty::TyArray(typ.fold_with(folder), sz.fold_with(folder)),
-            ty::TySlice(typ) => ty::TySlice(typ.fold_with(folder)),
-            ty::TyAdt(tid, substs) => ty::TyAdt(tid, substs.fold_with(folder)),
-            ty::TyDynamic(ref trait_ty, ref region) =>
-                ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)),
-            ty::TyTuple(ts) => ty::TyTuple(ts.fold_with(folder)),
-            ty::TyFnDef(def_id, substs) => {
-                ty::TyFnDef(def_id, substs.fold_with(folder))
+            ty::RawPtr(tm) => ty::RawPtr(tm.fold_with(folder)),
+            ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)),
+            ty::Slice(typ) => ty::Slice(typ.fold_with(folder)),
+            ty::Adt(tid, substs) => ty::Adt(tid, substs.fold_with(folder)),
+            ty::Dynamic(ref trait_ty, ref region) =>
+                ty::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder)),
+            ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)),
+            ty::FnDef(def_id, substs) => {
+                ty::FnDef(def_id, substs.fold_with(folder))
             }
-            ty::TyFnPtr(f) => ty::TyFnPtr(f.fold_with(folder)),
-            ty::TyRef(ref r, ty, mutbl) => {
-                ty::TyRef(r.fold_with(folder), ty.fold_with(folder), mutbl)
+            ty::FnPtr(f) => ty::FnPtr(f.fold_with(folder)),
+            ty::Ref(ref r, ty, mutbl) => {
+                ty::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl)
             }
-            ty::TyGenerator(did, substs, movability) => {
-                ty::TyGenerator(
+            ty::Generator(did, substs, movability) => {
+                ty::Generator(
                     did,
                     substs.fold_with(folder),
                     movability)
             }
-            ty::TyGeneratorWitness(types) => ty::TyGeneratorWitness(types.fold_with(folder)),
-            ty::TyClosure(did, substs) => ty::TyClosure(did, substs.fold_with(folder)),
-            ty::TyProjection(ref data) => ty::TyProjection(data.fold_with(folder)),
-            ty::TyAnon(did, substs) => ty::TyAnon(did, substs.fold_with(folder)),
-            ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
-            ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
-            ty::TyParam(..) | ty::TyNever | ty::TyForeign(..) => return self
+            ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)),
+            ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)),
+            ty::Projection(ref data) => ty::Projection(data.fold_with(folder)),
+            ty::Anon(did, substs) => ty::Anon(did, substs.fold_with(folder)),
+            ty::Bool | ty::Char | ty::Str | ty::Int(_) |
+            ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) |
+            ty::Param(..) | ty::Never | ty::Foreign(..) => return self
         };
 
         if self.sty == sty {
@@ -878,26 +884,26 @@ fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Se
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         match self.sty {
-            ty::TyRawPtr(ref tm) => tm.visit_with(visitor),
-            ty::TyArray(typ, sz) => typ.visit_with(visitor) || sz.visit_with(visitor),
-            ty::TySlice(typ) => typ.visit_with(visitor),
-            ty::TyAdt(_, substs) => substs.visit_with(visitor),
-            ty::TyDynamic(ref trait_ty, ref reg) =>
+            ty::RawPtr(ref tm) => tm.visit_with(visitor),
+            ty::Array(typ, sz) => typ.visit_with(visitor) || sz.visit_with(visitor),
+            ty::Slice(typ) => typ.visit_with(visitor),
+            ty::Adt(_, substs) => substs.visit_with(visitor),
+            ty::Dynamic(ref trait_ty, ref reg) =>
                 trait_ty.visit_with(visitor) || reg.visit_with(visitor),
-            ty::TyTuple(ts) => ts.visit_with(visitor),
-            ty::TyFnDef(_, substs) => substs.visit_with(visitor),
-            ty::TyFnPtr(ref f) => f.visit_with(visitor),
-            ty::TyRef(r, ty, _) => r.visit_with(visitor) || ty.visit_with(visitor),
-            ty::TyGenerator(_did, ref substs, _) => {
+            ty::Tuple(ts) => ts.visit_with(visitor),
+            ty::FnDef(_, substs) => substs.visit_with(visitor),
+            ty::FnPtr(ref f) => f.visit_with(visitor),
+            ty::Ref(r, ty, _) => r.visit_with(visitor) || ty.visit_with(visitor),
+            ty::Generator(_did, ref substs, _) => {
                 substs.visit_with(visitor)
             }
-            ty::TyGeneratorWitness(ref types) => types.visit_with(visitor),
-            ty::TyClosure(_did, ref substs) => substs.visit_with(visitor),
-            ty::TyProjection(ref data) => data.visit_with(visitor),
-            ty::TyAnon(_, ref substs) => substs.visit_with(visitor),
-            ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
-            ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
-            ty::TyParam(..) | ty::TyNever | ty::TyForeign(..) => false,
+            ty::GeneratorWitness(ref types) => types.visit_with(visitor),
+            ty::Closure(_did, ref substs) => substs.visit_with(visitor),
+            ty::Projection(ref data) => data.visit_with(visitor),
+            ty::Anon(_, ref substs) => substs.visit_with(visitor),
+            ty::Bool | ty::Char | ty::Str | ty::Int(_) |
+            ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) |
+            ty::Param(..) | ty::Never | ty::Foreign(..) => false,
         }
     }
 
@@ -1010,9 +1016,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<ty::Predicate<'tcx>> {
+impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        let v = self.iter().map(|p| p.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>();
+        let v = self.iter().map(|p| p.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
         folder.tcx().intern_predicates(&v)
     }
 
@@ -1135,7 +1141,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
         match *self {
             ConstValue::Scalar(v) => ConstValue::Scalar(v),
             ConstValue::ScalarPair(a, b) => ConstValue::ScalarPair(a, b),
-            ConstValue::ByRef(alloc, offset) => ConstValue::ByRef(alloc, offset),
+            ConstValue::ByRef(id, alloc, offset) => ConstValue::ByRef(id, alloc, offset),
             ConstValue::Unevaluated(def_id, substs) => {
                 ConstValue::Unevaluated(def_id, substs.fold_with(folder))
             }
@@ -1146,7 +1152,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         match *self {
             ConstValue::Scalar(_) |
             ConstValue::ScalarPair(_, _) |
-            ConstValue::ByRef(_, _) => false,
+            ConstValue::ByRef(_, _, _) => false,
             ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor),
         }
     }
index 226388c9efa483595aa111a7c32cddc14033cbb4..7c7ee9b330ecccce65f1e55853b91c57f33cb5d5 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! This module contains TypeVariants and its major components
+//! This module contains TyKind and its major components
 
 use hir::def_id::DefId;
 
@@ -18,9 +18,9 @@
 use rustc_data_structures::indexed_vec::Idx;
 use ty::subst::{Substs, Subst, Kind, UnpackedKind};
 use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
-use ty::{Slice, TyS, ParamEnvAnd, ParamEnv};
+use ty::{List, TyS, ParamEnvAnd, ParamEnv};
 use util::captures::Captures;
-use mir::interpret::{Scalar, Pointer, Value};
+use mir::interpret::{Scalar, Pointer};
 
 use std::iter;
 use std::cmp::Ordering;
@@ -33,7 +33,7 @@
 use hir;
 
 use self::InferTy::*;
-use self::TypeVariants::*;
+use self::TyKind::*;
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub struct TypeAndMut<'tcx> {
@@ -82,80 +82,80 @@ pub fn is_named(&self) -> bool {
 /// NB: If you change this, you'll probably want to change the corresponding
 /// AST structure in libsyntax/ast.rs as well.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
-pub enum TypeVariants<'tcx> {
+pub enum TyKind<'tcx> {
     /// The primitive boolean type. Written as `bool`.
-    TyBool,
+    Bool,
 
     /// The primitive character type; holds a Unicode scalar value
     /// (a non-surrogate code point).  Written as `char`.
-    TyChar,
+    Char,
 
     /// A primitive signed integer type. For example, `i32`.
-    TyInt(ast::IntTy),
+    Int(ast::IntTy),
 
     /// A primitive unsigned integer type. For example, `u32`.
-    TyUint(ast::UintTy),
+    Uint(ast::UintTy),
 
     /// A primitive floating-point type. For example, `f64`.
-    TyFloat(ast::FloatTy),
+    Float(ast::FloatTy),
 
     /// Structures, enumerations and unions.
     ///
-    /// Substs here, possibly against intuition, *may* contain `TyParam`s.
+    /// Substs here, possibly against intuition, *may* contain `Param`s.
     /// That is, even after substitution it is possible that there are type
-    /// variables. This happens when the `TyAdt` corresponds to an ADT
+    /// variables. This happens when the `Adt` corresponds to an ADT
     /// definition and not a concrete use of it.
-    TyAdt(&'tcx AdtDef, &'tcx Substs<'tcx>),
+    Adt(&'tcx AdtDef, &'tcx Substs<'tcx>),
 
-    TyForeign(DefId),
+    Foreign(DefId),
 
     /// The pointee of a string slice. Written as `str`.
-    TyStr,
+    Str,
 
     /// An array with the given length. Written as `[T; n]`.
-    TyArray(Ty<'tcx>, &'tcx ty::Const<'tcx>),
+    Array(Ty<'tcx>, &'tcx ty::Const<'tcx>),
 
     /// The pointee of an array slice.  Written as `[T]`.
-    TySlice(Ty<'tcx>),
+    Slice(Ty<'tcx>),
 
     /// A raw pointer. Written as `*mut T` or `*const T`
-    TyRawPtr(TypeAndMut<'tcx>),
+    RawPtr(TypeAndMut<'tcx>),
 
     /// A reference; a pointer with an associated lifetime. Written as
     /// `&'a mut T` or `&'a T`.
-    TyRef(Region<'tcx>, Ty<'tcx>, hir::Mutability),
+    Ref(Region<'tcx>, Ty<'tcx>, hir::Mutability),
 
     /// The anonymous type of a function declaration/definition. Each
     /// function has a unique type.
-    TyFnDef(DefId, &'tcx Substs<'tcx>),
+    FnDef(DefId, &'tcx Substs<'tcx>),
 
     /// A pointer to a function.  Written as `fn() -> i32`.
-    TyFnPtr(PolyFnSig<'tcx>),
+    FnPtr(PolyFnSig<'tcx>),
 
     /// A trait, defined with `trait`.
-    TyDynamic(Binder<&'tcx Slice<ExistentialPredicate<'tcx>>>, ty::Region<'tcx>),
+    Dynamic(Binder<&'tcx List<ExistentialPredicate<'tcx>>>, ty::Region<'tcx>),
 
     /// The anonymous type of a closure. Used to represent the type of
     /// `|a| a`.
-    TyClosure(DefId, ClosureSubsts<'tcx>),
+    Closure(DefId, ClosureSubsts<'tcx>),
 
     /// The anonymous type of a generator. Used to represent the type of
     /// `|a| yield a`.
-    TyGenerator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
+    Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
 
     /// A type representin the types stored inside a generator.
     /// This should only appear in GeneratorInteriors.
-    TyGeneratorWitness(Binder<&'tcx Slice<Ty<'tcx>>>),
+    GeneratorWitness(Binder<&'tcx List<Ty<'tcx>>>),
 
     /// The never type `!`
-    TyNever,
+    Never,
 
     /// A tuple type.  For example, `(i32, bool)`.
-    TyTuple(&'tcx Slice<Ty<'tcx>>),
+    Tuple(&'tcx List<Ty<'tcx>>),
 
     /// The projection of an associated type.  For example,
     /// `<T as Trait<..>>::N`.
-    TyProjection(ProjectionTy<'tcx>),
+    Projection(ProjectionTy<'tcx>),
 
     /// Anonymized (`impl Trait`) type found in a return type.
     /// The DefId comes either from
@@ -163,17 +163,17 @@ pub enum TypeVariants<'tcx> {
     /// * or the `existential type` declaration
     /// The substitutions are for the generics of the function in question.
     /// After typeck, the concrete type can be found in the `types` map.
-    TyAnon(DefId, &'tcx Substs<'tcx>),
+    Anon(DefId, &'tcx Substs<'tcx>),
 
     /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
-    TyParam(ParamTy),
+    Param(ParamTy),
 
     /// A type variable used during type-checking.
-    TyInfer(InferTy),
+    Infer(InferTy),
 
     /// A placeholder for a type which could not be computed; this is
     /// propagated to avoid useless error messages.
-    TyError,
+    Error,
 }
 
 /// A closure can be modeled as a struct that looks like:
@@ -348,7 +348,7 @@ pub fn closure_kind(self, def_id: DefId, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> ty::Clo
     /// If you have an inference context, use `infcx.closure_sig()`.
     pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> ty::PolyFnSig<'tcx> {
         match self.closure_sig_ty(def_id, tcx).sty {
-            ty::TyFnPtr(sig) => sig,
+            ty::FnPtr(sig) => sig,
             ref t => bug!("closure_sig_ty is not a fn-ptr: {:?}", t),
         }
     }
@@ -536,9 +536,9 @@ pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>)
     }
 }
 
-impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice<ExistentialPredicate<'tcx>> {}
+impl<'tcx> serialize::UseSpecializedDecodable for &'tcx List<ExistentialPredicate<'tcx>> {}
 
-impl<'tcx> Slice<ExistentialPredicate<'tcx>> {
+impl<'tcx> List<ExistentialPredicate<'tcx>> {
     pub fn principal(&self) -> Option<ExistentialTraitRef<'tcx>> {
         match self.get(0) {
             Some(&ExistentialPredicate::Trait(tr)) => Some(tr),
@@ -568,7 +568,7 @@ pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item=DefId> + 'a {
     }
 }
 
-impl<'tcx> Binder<&'tcx Slice<ExistentialPredicate<'tcx>>> {
+impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
     pub fn principal(&self) -> Option<PolyExistentialTraitRef<'tcx>> {
         self.skip_binder().principal().map(Binder::bind)
     }
@@ -918,7 +918,7 @@ pub fn return_ty(&self) -> ty::Binder<Ty<'tcx>> {
 /// - `variadic` indicates whether this is a variadic function. (only true for foreign fns)
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
 pub struct FnSig<'tcx> {
-    pub inputs_and_output: &'tcx Slice<Ty<'tcx>>,
+    pub inputs_and_output: &'tcx List<Ty<'tcx>>,
     pub variadic: bool,
     pub unsafety: hir::Unsafety,
     pub abi: abi::Abi,
@@ -943,7 +943,7 @@ pub fn inputs(&self) -> Binder<&'tcx [Ty<'tcx>]> {
     pub fn input(&self, index: usize) -> ty::Binder<Ty<'tcx>> {
         self.map_bound_ref(|fn_sig| fn_sig.inputs()[index])
     }
-    pub fn inputs_and_output(&self) -> ty::Binder<&'tcx Slice<Ty<'tcx>>> {
+    pub fn inputs_and_output(&self) -> ty::Binder<&'tcx List<Ty<'tcx>>> {
         self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output)
     }
     pub fn output(&self) -> ty::Binder<Ty<'tcx>> {
@@ -1058,7 +1058,7 @@ pub fn is_self(&self) -> bool {
 /// the likes of `liberate_late_bound_regions`. The distinction exists
 /// because higher-ranked lifetimes aren't supported in all places. See [1][2].
 ///
-/// Unlike TyParam-s, bound regions are not supposed to exist "in the wild"
+/// Unlike Param-s, bound regions are not supposed to exist "in the wild"
 /// outside their binder, e.g. in types passed to type inference, and
 /// should first be substituted (by skolemized regions, free regions,
 /// or region variables).
@@ -1469,67 +1469,67 @@ pub fn free_region_binding_scope(&self, tcx: TyCtxt<'_, '_, '_>) -> DefId {
 impl<'a, 'gcx, 'tcx> TyS<'tcx> {
     pub fn is_nil(&self) -> bool {
         match self.sty {
-            TyTuple(ref tys) => tys.is_empty(),
+            Tuple(ref tys) => tys.is_empty(),
             _ => false,
         }
     }
 
     pub fn is_never(&self) -> bool {
         match self.sty {
-            TyNever => true,
+            Never => true,
             _ => false,
         }
     }
 
     pub fn is_primitive(&self) -> bool {
         match self.sty {
-            TyBool | TyChar | TyInt(_) | TyUint(_) | TyFloat(_) => true,
+            Bool | Char | Int(_) | Uint(_) | Float(_) => true,
             _ => false,
         }
     }
 
     pub fn is_ty_var(&self) -> bool {
         match self.sty {
-            TyInfer(TyVar(_)) => true,
+            Infer(TyVar(_)) => true,
             _ => false,
         }
     }
 
     pub fn is_ty_infer(&self) -> bool {
         match self.sty {
-            TyInfer(_) => true,
+            Infer(_) => true,
             _ => false,
         }
     }
 
     pub fn is_phantom_data(&self) -> bool {
-        if let TyAdt(def, _) = self.sty {
+        if let Adt(def, _) = self.sty {
             def.is_phantom_data()
         } else {
             false
         }
     }
 
-    pub fn is_bool(&self) -> bool { self.sty == TyBool }
+    pub fn is_bool(&self) -> bool { self.sty == Bool }
 
     pub fn is_param(&self, index: u32) -> bool {
         match self.sty {
-            ty::TyParam(ref data) => data.idx == index,
+            ty::Param(ref data) => data.idx == index,
             _ => false,
         }
     }
 
     pub fn is_self(&self) -> bool {
         match self.sty {
-            TyParam(ref p) => p.is_self(),
+            Param(ref p) => p.is_self(),
             _ => false,
         }
     }
 
     pub fn is_slice(&self) -> bool {
         match self.sty {
-            TyRawPtr(TypeAndMut { ty, .. }) | TyRef(_, ty, _) => match ty.sty {
-                TySlice(_) | TyStr => true,
+            RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => match ty.sty {
+                Slice(_) | Str => true,
                 _ => false,
             },
             _ => false
@@ -1539,22 +1539,22 @@ pub fn is_slice(&self) -> bool {
     #[inline]
     pub fn is_simd(&self) -> bool {
         match self.sty {
-            TyAdt(def, _) => def.repr.simd(),
+            Adt(def, _) => def.repr.simd(),
             _ => false,
         }
     }
 
     pub fn sequence_element_type(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
         match self.sty {
-            TyArray(ty, _) | TySlice(ty) => ty,
-            TyStr => tcx.mk_mach_uint(ast::UintTy::U8),
+            Array(ty, _) | Slice(ty) => ty,
+            Str => tcx.mk_mach_uint(ast::UintTy::U8),
             _ => bug!("sequence_element_type called on non-sequence value: {}", self),
         }
     }
 
     pub fn simd_type(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
         match self.sty {
-            TyAdt(def, substs) => {
+            Adt(def, substs) => {
                 def.non_enum_variant().fields[0].ty(tcx, substs)
             }
             _ => bug!("simd_type called on invalid type")
@@ -1563,36 +1563,36 @@ pub fn simd_type(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
 
     pub fn simd_size(&self, _cx: TyCtxt) -> usize {
         match self.sty {
-            TyAdt(def, _) => def.non_enum_variant().fields.len(),
+            Adt(def, _) => def.non_enum_variant().fields.len(),
             _ => bug!("simd_size called on invalid type")
         }
     }
 
     pub fn is_region_ptr(&self) -> bool {
         match self.sty {
-            TyRef(..) => true,
+            Ref(..) => true,
             _ => false,
         }
     }
 
     pub fn is_mutable_pointer(&self) -> bool {
         match self.sty {
-            TyRawPtr(TypeAndMut { mutbl: hir::Mutability::MutMutable, .. }) |
-            TyRef(_, _, hir::Mutability::MutMutable) => true,
+            RawPtr(TypeAndMut { mutbl: hir::Mutability::MutMutable, .. }) |
+            Ref(_, _, hir::Mutability::MutMutable) => true,
             _ => false
         }
     }
 
     pub fn is_unsafe_ptr(&self) -> bool {
         match self.sty {
-            TyRawPtr(_) => return true,
+            RawPtr(_) => return true,
             _ => return false,
         }
     }
 
     pub fn is_box(&self) -> bool {
         match self.sty {
-            TyAdt(def, _) => def.is_box(),
+            Adt(def, _) => def.is_box(),
             _ => false,
         }
     }
@@ -1600,19 +1600,19 @@ pub fn is_box(&self) -> bool {
     /// panics if called on any type other than `Box<T>`
     pub fn boxed_ty(&self) -> Ty<'tcx> {
         match self.sty {
-            TyAdt(def, substs) if def.is_box() => substs.type_at(0),
+            Adt(def, substs) if def.is_box() => substs.type_at(0),
             _ => bug!("`boxed_ty` is called on non-box type {:?}", self),
         }
     }
 
     /// A scalar type is one that denotes an atomic datum, with no sub-components.
-    /// (A TyRawPtr is scalar because it represents a non-managed pointer, so its
+    /// (A RawPtr is scalar because it represents a non-managed pointer, so its
     /// contents are abstract to rustc.)
     pub fn is_scalar(&self) -> bool {
         match self.sty {
-            TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) |
-            TyInfer(IntVar(_)) | TyInfer(FloatVar(_)) |
-            TyFnDef(..) | TyFnPtr(_) | TyRawPtr(_) => true,
+            Bool | Char | Int(_) | Float(_) | Uint(_) |
+            Infer(IntVar(_)) | Infer(FloatVar(_)) |
+            FnDef(..) | FnPtr(_) | RawPtr(_) => true,
             _ => false
         }
     }
@@ -1620,22 +1620,22 @@ pub fn is_scalar(&self) -> bool {
     /// Returns true if this type is a floating point type and false otherwise.
     pub fn is_floating_point(&self) -> bool {
         match self.sty {
-            TyFloat(_) |
-            TyInfer(FloatVar(_)) => true,
+            Float(_) |
+            Infer(FloatVar(_)) => true,
             _ => false,
         }
     }
 
     pub fn is_trait(&self) -> bool {
         match self.sty {
-            TyDynamic(..) => true,
+            Dynamic(..) => true,
             _ => false,
         }
     }
 
     pub fn is_enum(&self) -> bool {
         match self.sty {
-            TyAdt(adt_def, _) => {
+            Adt(adt_def, _) => {
                 adt_def.is_enum()
             }
             _ => false,
@@ -1644,51 +1644,51 @@ pub fn is_enum(&self) -> bool {
 
     pub fn is_closure(&self) -> bool {
         match self.sty {
-            TyClosure(..) => true,
+            Closure(..) => true,
             _ => false,
         }
     }
 
     pub fn is_generator(&self) -> bool {
         match self.sty {
-            TyGenerator(..) => true,
+            Generator(..) => true,
             _ => false,
         }
     }
 
     pub fn is_integral(&self) -> bool {
         match self.sty {
-            TyInfer(IntVar(_)) | TyInt(_) | TyUint(_) => true,
+            Infer(IntVar(_)) | Int(_) | Uint(_) => true,
             _ => false
         }
     }
 
     pub fn is_fresh_ty(&self) -> bool {
         match self.sty {
-            TyInfer(FreshTy(_)) => true,
+            Infer(FreshTy(_)) => true,
             _ => false,
         }
     }
 
     pub fn is_fresh(&self) -> bool {
         match self.sty {
-            TyInfer(FreshTy(_)) => true,
-            TyInfer(FreshIntTy(_)) => true,
-            TyInfer(FreshFloatTy(_)) => true,
+            Infer(FreshTy(_)) => true,
+            Infer(FreshIntTy(_)) => true,
+            Infer(FreshFloatTy(_)) => true,
             _ => false,
         }
     }
 
     pub fn is_char(&self) -> bool {
         match self.sty {
-            TyChar => true,
+            Char => true,
             _ => false,
         }
     }
 
     pub fn is_fp(&self) -> bool {
         match self.sty {
-            TyInfer(FloatVar(_)) | TyFloat(_) => true,
+            Infer(FloatVar(_)) | Float(_) => true,
             _ => false
         }
     }
@@ -1699,22 +1699,22 @@ pub fn is_numeric(&self) -> bool {
 
     pub fn is_signed(&self) -> bool {
         match self.sty {
-            TyInt(_) => true,
+            Int(_) => true,
             _ => false,
         }
     }
 
     pub fn is_machine(&self) -> bool {
         match self.sty {
-            TyInt(ast::IntTy::Isize) | TyUint(ast::UintTy::Usize) => false,
-            TyInt(..) | TyUint(..) | TyFloat(..) => true,
+            Int(ast::IntTy::Isize) | Uint(ast::UintTy::Usize) => false,
+            Int(..) | Uint(..) | Float(..) => true,
             _ => false,
         }
     }
 
     pub fn has_concrete_skeleton(&self) -> bool {
         match self.sty {
-            TyParam(_) | TyInfer(_) | TyError => false,
+            Param(_) | Infer(_) | Error => false,
             _ => true,
         }
     }
@@ -1725,14 +1725,14 @@ pub fn has_concrete_skeleton(&self) -> bool {
     /// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
     pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut<'tcx>> {
         match self.sty {
-            TyAdt(def, _) if def.is_box() => {
+            Adt(def, _) if def.is_box() => {
                 Some(TypeAndMut {
                     ty: self.boxed_ty(),
                     mutbl: hir::MutImmutable,
                 })
             },
-            TyRef(_, ty, mutbl) => Some(TypeAndMut { ty, mutbl }),
-            TyRawPtr(mt) if explicit => Some(mt),
+            Ref(_, ty, mutbl) => Some(TypeAndMut { ty, mutbl }),
+            RawPtr(mt) if explicit => Some(mt),
             _ => None,
         }
     }
@@ -1740,38 +1740,38 @@ pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut<'tcx>> {
     /// Returns the type of `ty[i]`.
     pub fn builtin_index(&self) -> Option<Ty<'tcx>> {
         match self.sty {
-            TyArray(ty, _) | TySlice(ty) => Some(ty),
+            Array(ty, _) | Slice(ty) => Some(ty),
             _ => None,
         }
     }
 
     pub fn fn_sig(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PolyFnSig<'tcx> {
         match self.sty {
-            TyFnDef(def_id, substs) => {
+            FnDef(def_id, substs) => {
                 tcx.fn_sig(def_id).subst(tcx, substs)
             }
-            TyFnPtr(f) => f,
+            FnPtr(f) => f,
             _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self)
         }
     }
 
     pub fn is_fn(&self) -> bool {
         match self.sty {
-            TyFnDef(..) | TyFnPtr(_) => true,
+            FnDef(..) | FnPtr(_) => true,
             _ => false,
         }
     }
 
     pub fn is_impl_trait(&self) -> bool {
         match self.sty {
-            TyAnon(..) => true,
+            Anon(..) => true,
             _ => false,
         }
     }
 
     pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> {
         match self.sty {
-            TyAdt(adt, _) => Some(adt),
+            Adt(adt, _) => Some(adt),
             _ => None,
         }
     }
@@ -1781,44 +1781,44 @@ pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> {
     /// ignores late-bound regions binders.
     pub fn regions(&self) -> Vec<ty::Region<'tcx>> {
         match self.sty {
-            TyRef(region, _, _) => {
+            Ref(region, _, _) => {
                 vec![region]
             }
-            TyDynamic(ref obj, region) => {
+            Dynamic(ref obj, region) => {
                 let mut v = vec![region];
                 if let Some(p) = obj.principal() {
                     v.extend(p.skip_binder().substs.regions());
                 }
                 v
             }
-            TyAdt(_, substs) | TyAnon(_, substs) => {
+            Adt(_, substs) | Anon(_, substs) => {
                 substs.regions().collect()
             }
-            TyClosure(_, ClosureSubsts { ref substs }) |
-            TyGenerator(_, GeneratorSubsts { ref substs }, _) => {
+            Closure(_, ClosureSubsts { ref substs }) |
+            Generator(_, GeneratorSubsts { ref substs }, _) => {
                 substs.regions().collect()
             }
-            TyProjection(ref data) => {
+            Projection(ref data) => {
                 data.substs.regions().collect()
             }
-            TyFnDef(..) |
-            TyFnPtr(_) |
-            TyGeneratorWitness(..) |
-            TyBool |
-            TyChar |
-            TyInt(_) |
-            TyUint(_) |
-            TyFloat(_) |
-            TyStr |
-            TyArray(..) |
-            TySlice(_) |
-            TyRawPtr(_) |
-            TyNever |
-            TyTuple(..) |
-            TyForeign(..) |
-            TyParam(_) |
-            TyInfer(_) |
-            TyError => {
+            FnDef(..) |
+            FnPtr(_) |
+            GeneratorWitness(..) |
+            Bool |
+            Char |
+            Int(_) |
+            Uint(_) |
+            Float(_) |
+            Str |
+            Array(..) |
+            Slice(_) |
+            RawPtr(_) |
+            Never |
+            Tuple(..) |
+            Foreign(..) |
+            Param(_) |
+            Infer(_) |
+            Error => {
                 vec![]
             }
         }
@@ -1838,16 +1838,16 @@ pub fn regions(&self) -> Vec<ty::Region<'tcx>> {
     /// is complete, that type variable will be unified.
     pub fn to_opt_closure_kind(&self) -> Option<ty::ClosureKind> {
         match self.sty {
-            TyInt(int_ty) => match int_ty {
+            Int(int_ty) => match int_ty {
                 ast::IntTy::I8 => Some(ty::ClosureKind::Fn),
                 ast::IntTy::I16 => Some(ty::ClosureKind::FnMut),
                 ast::IntTy::I32 => Some(ty::ClosureKind::FnOnce),
                 _ => bug!("cannot convert type `{:?}` to a closure kind", self),
             },
 
-            TyInfer(_) => None,
+            Infer(_) => None,
 
-            TyError => Some(ty::ClosureKind::Fn),
+            Error => Some(ty::ClosureKind::Fn),
 
             _ => bug!("cannot convert type `{:?}` to a closure kind", self),
         }
@@ -1859,31 +1859,31 @@ pub fn to_opt_closure_kind(&self) -> Option<ty::ClosureKind> {
     /// `false` means nothing -- could be sized, might not be.
     pub fn is_trivially_sized(&self, tcx: TyCtxt<'_, '_, 'tcx>) -> bool {
         match self.sty {
-            ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) |
-            ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
-            ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyRawPtr(..) |
-            ty::TyChar | ty::TyRef(..) | ty::TyGenerator(..) |
-            ty::TyGeneratorWitness(..) | ty::TyArray(..) | ty::TyClosure(..) |
-            ty::TyNever | ty::TyError =>
+            ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) |
+            ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) |
+            ty::FnDef(..) | ty::FnPtr(_) | ty::RawPtr(..) |
+            ty::Char | ty::Ref(..) | ty::Generator(..) |
+            ty::GeneratorWitness(..) | ty::Array(..) | ty::Closure(..) |
+            ty::Never | ty::Error =>
                 true,
 
-            ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) | ty::TyForeign(..) =>
+            ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) =>
                 false,
 
-            ty::TyTuple(tys) =>
+            ty::Tuple(tys) =>
                 tys.iter().all(|ty| ty.is_trivially_sized(tcx)),
 
-            ty::TyAdt(def, _substs) =>
+            ty::Adt(def, _substs) =>
                 def.sized_constraint(tcx).is_empty(),
 
-            ty::TyProjection(_) | ty::TyParam(_) | ty::TyAnon(..) => false,
+            ty::Projection(_) | ty::Param(_) | ty::Anon(..) => false,
 
-            ty::TyInfer(ty::TyVar(_)) => false,
+            ty::Infer(ty::TyVar(_)) => false,
 
-            ty::TyInfer(ty::CanonicalTy(_)) |
-            ty::TyInfer(ty::FreshTy(_)) |
-            ty::TyInfer(ty::FreshIntTy(_)) |
-            ty::TyInfer(ty::FreshFloatTy(_)) =>
+            ty::Infer(ty::CanonicalTy(_)) |
+            ty::Infer(ty::FreshTy(_)) |
+            ty::Infer(ty::FreshIntTy(_)) |
+            ty::Infer(ty::FreshFloatTy(_)) =>
                 bug!("is_trivially_sized applied to unexpected type: {:?}", self),
         }
     }
@@ -1973,17 +1973,12 @@ pub fn to_bits(
         }
         let ty = tcx.lift_to_global(&ty).unwrap();
         let size = tcx.layout_of(ty).ok()?.size;
-        self.val.to_bits(size)
+        self.val.try_to_bits(size)
     }
 
     #[inline]
     pub fn to_ptr(&self) -> Option<Pointer> {
-        self.val.to_ptr()
-    }
-
-    #[inline]
-    pub fn to_byval_value(&self) -> Option<Value> {
-        self.val.to_byval_value()
+        self.val.try_to_ptr()
     }
 
     #[inline]
@@ -1995,7 +1990,7 @@ pub fn assert_bits(
         assert_eq!(self.ty, ty.value);
         let ty = tcx.lift_to_global(&ty).unwrap();
         let size = tcx.layout_of(ty).ok()?.size;
-        self.val.to_bits(size)
+        self.val.try_to_bits(size)
     }
 
     #[inline]
index a6ff979f472af46bd7b4ee1c677e7237510237a0..b6ffcd55d9150c1ed824b5ccbc1c47f20707b8ee 100644 (file)
 // Type substitutions.
 
 use hir::def_id::DefId;
-use ty::{self, Lift, Slice, Ty, TyCtxt};
+use infer::canonical::Canonical;
+use ty::{self, CanonicalVar, Lift, List, Ty, TyCtxt};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 
 use serialize::{self, Encodable, Encoder, Decodable, Decoder};
 use syntax_pos::{Span, DUMMY_SP};
-use rustc_data_structures::accumulate_vec::AccumulateVec;
-use rustc_data_structures::array_vec::ArrayVec;
+use rustc_data_structures::indexed_vec::Idx;
+use smallvec::SmallVec;
 
 use core::intrinsics;
 use std::cmp::Ordering;
@@ -177,7 +178,7 @@ fn decode<D: Decoder>(d: &mut D) -> Result<Kind<'tcx>, D::Error> {
 }
 
 /// A substitution mapping generic parameters to new values.
-pub type Substs<'tcx> = Slice<Kind<'tcx>>;
+pub type Substs<'tcx> = List<Kind<'tcx>>;
 
 impl<'a, 'gcx, 'tcx> Substs<'tcx> {
     /// Creates a Substs that maps each generic parameter to itself.
@@ -201,11 +202,7 @@ pub fn for_item<F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
     {
         let defs = tcx.generics_of(def_id);
         let count = defs.count();
-        let mut substs = if count <= 8 {
-            AccumulateVec::Array(ArrayVec::new())
-        } else {
-            AccumulateVec::Heap(Vec::with_capacity(count))
-        };
+        let mut substs = SmallVec::with_capacity(count);
         Substs::fill_item(&mut substs, tcx, defs, &mut mk_kind);
         tcx.intern_substs(&substs)
     }
@@ -225,7 +222,7 @@ pub fn extend_to<F>(&self,
         })
     }
 
-    fn fill_item<F>(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>,
+    fn fill_item<F>(substs: &mut SmallVec<[Kind<'tcx>; 8]>,
                     tcx: TyCtxt<'a, 'gcx, 'tcx>,
                     defs: &ty::Generics,
                     mk_kind: &mut F)
@@ -238,7 +235,7 @@ pub fn extend_to<F>(&self,
         Substs::fill_single(substs, defs, mk_kind)
     }
 
-    fn fill_single<F>(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>,
+    fn fill_single<F>(substs: &mut SmallVec<[Kind<'tcx>; 8]>,
                       defs: &ty::Generics,
                       mk_kind: &mut F)
     where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
@@ -246,10 +243,7 @@ pub fn extend_to<F>(&self,
         for param in &defs.params {
             let kind = mk_kind(param, substs);
             assert_eq!(param.index as usize, substs.len());
-            match *substs {
-                AccumulateVec::Array(ref mut arr) => arr.push(kind),
-                AccumulateVec::Heap(ref mut vec) => vec.push(kind),
-            }
+            substs.push(kind);
         }
     }
 
@@ -323,7 +317,7 @@ pub fn truncate_to(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, generics: &ty::Generics)
 
 impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        let params: AccumulateVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect();
+        let params: SmallVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect();
 
         // If folding doesn't change the substs, it's faster to avoid
         // calling `mk_substs` and instead reuse the existing substs.
@@ -339,6 +333,33 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
+pub type CanonicalSubsts<'gcx> = Canonical<'gcx, &'gcx Substs<'gcx>>;
+
+impl<'gcx> CanonicalSubsts<'gcx> {
+    /// True if this represents a substitution like
+    ///
+    /// ```text
+    /// [?0, ?1, ?2]
+    /// ```
+    ///
+    /// i.e., each thing is mapped to a canonical variable with the same index.
+    pub fn is_identity(&self) -> bool {
+        self.value.iter().zip(CanonicalVar::new(0)..).all(|(kind, cvar)| {
+            match kind.unpack() {
+                UnpackedKind::Type(ty) => match ty.sty {
+                    ty::Infer(ty::CanonicalTy(cvar1)) => cvar == cvar1,
+                    _ => false,
+                },
+
+                UnpackedKind::Lifetime(r) => match r {
+                    ty::ReCanonical(cvar1) => cvar == *cvar1,
+                    _ => false,
+                },
+            }
+        })
+    }
+}
+
 impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Substs<'tcx> {}
 
 ///////////////////////////////////////////////////////////////////////////
@@ -449,7 +470,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         self.ty_stack_depth += 1;
 
         let t1 = match t.sty {
-            ty::TyParam(p) => {
+            ty::Param(p) => {
                 self.ty_for_param(p, t)
             }
             _ => {
index 95caa0c185be1d74890309611b60773b3d3e9f18..f7679dc8ce0f02470a71112fbecc92572b38038e 100644 (file)
 
 use hir::def::Def;
 use hir::def_id::DefId;
-use hir::map::{DefPathData, Node};
-use hir;
+use hir::map::DefPathData;
+use hir::{self, Node};
 use ich::NodeIdHashingMode;
 use traits::{self, ObligationCause};
 use ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable};
 use ty::subst::{Substs, UnpackedKind};
 use ty::query::TyCtxtAt;
-use ty::TypeVariants::*;
+use ty::TyKind::*;
 use ty::layout::{Integer, IntegerExt};
 use util::common::ErrorReported;
 use middle::lang_items;
@@ -41,7 +41,7 @@ pub struct Discr<'tcx> {
 impl<'tcx> fmt::Display for Discr<'tcx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         match self.ty.sty {
-            ty::TyInt(ity) => {
+            ty::Int(ity) => {
                 let bits = ty::tls::with(|tcx| {
                     Integer::from_attr(tcx, SignedInt(ity)).size().bits()
                 });
@@ -62,8 +62,8 @@ pub fn wrap_incr<'a, 'gcx>(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self {
     }
     pub fn checked_add<'a, 'gcx>(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, n: u128) -> (Self, bool) {
         let (int, signed) = match self.ty.sty {
-            TyInt(ity) => (Integer::from_attr(tcx, SignedInt(ity)), true),
-            TyUint(uty) => (Integer::from_attr(tcx, UnsignedInt(uty)), false),
+            Int(ity) => (Integer::from_attr(tcx, SignedInt(ity)), true),
+            Uint(uty) => (Integer::from_attr(tcx, UnsignedInt(uty)), false),
             _ => bug!("non integer discriminant"),
         };
 
@@ -193,11 +193,11 @@ pub fn can_type_implement_copy<'a>(self,
             let (adt, substs) = match self_type.sty {
                 // These types used to have a builtin impl.
                 // Now libcore provides that impl.
-                ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
-                ty::TyChar | ty::TyRawPtr(..) | ty::TyNever |
-                ty::TyRef(_, _, hir::MutImmutable) => return Ok(()),
+                ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) |
+                ty::Char | ty::RawPtr(..) | ty::Never |
+                ty::Ref(_, _, hir::MutImmutable) => return Ok(()),
 
-                ty::TyAdt(adt, substs) => (adt, substs),
+                ty::Adt(adt, substs) => (adt, substs),
 
                 _ => return Err(CopyImplementationError::NotAnAdt),
             };
@@ -258,10 +258,10 @@ pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 {
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn has_error_field(self, ty: Ty<'tcx>) -> bool {
         match ty.sty {
-            ty::TyAdt(def, substs) => {
+            ty::Adt(def, substs) => {
                 for field in def.all_fields() {
                     let field_ty = field.ty(self, substs);
-                    if let TyError = field_ty.sty {
+                    if let Error = field_ty.sty {
                         return true;
                     }
                 }
@@ -277,7 +277,7 @@ pub fn has_error_field(self, ty: Ty<'tcx>) -> bool {
     pub fn struct_tail(self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
         loop {
             match ty.sty {
-                ty::TyAdt(def, substs) => {
+                ty::Adt(def, substs) => {
                     if !def.is_struct() {
                         break;
                     }
@@ -287,7 +287,7 @@ pub fn struct_tail(self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
                     }
                 }
 
-                ty::TyTuple(tys) => {
+                ty::Tuple(tys) => {
                     if let Some((&last_ty, _)) = tys.split_last() {
                         ty = last_ty;
                     } else {
@@ -315,7 +315,7 @@ pub fn struct_lockstep_tails(self,
         let (mut a, mut b) = (source, target);
         loop {
             match (&a.sty, &b.sty) {
-                (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs))
+                (&Adt(a_def, a_substs), &Adt(b_def, b_substs))
                         if a_def == b_def && a_def.is_struct() => {
                     if let Some(f) = a_def.non_enum_variant().fields.last() {
                         a = f.ty(self, a_substs);
@@ -324,7 +324,7 @@ pub fn struct_lockstep_tails(self,
                         break;
                     }
                 },
-                (&TyTuple(a_tys), &TyTuple(b_tys))
+                (&Tuple(a_tys), &Tuple(b_tys))
                         if a_tys.len() == b_tys.len() => {
                     if let Some(a_last) = a_tys.last() {
                         a = a_last;
@@ -487,12 +487,12 @@ pub fn destructor_constraints(self, def: &'tcx ty::AdtDef)
         // parameters marked as pure.
 
         let impl_substs = match self.type_of(impl_def_id).sty {
-            ty::TyAdt(def_, substs) if def_ == def => substs,
+            ty::Adt(def_, substs) if def_ == def => substs,
             _ => bug!()
         };
 
         let item_substs = match self.type_of(def.did).sty {
-            ty::TyAdt(def_, substs) if def_ == def => substs,
+            ty::Adt(def_, substs) if def_ == def => substs,
             _ => bug!()
         };
 
@@ -503,7 +503,7 @@ pub fn destructor_constraints(self, def: &'tcx ty::AdtDef)
                         !impl_generics.region_param(ebr, self).pure_wrt_drop
                     }
                     UnpackedKind::Type(&ty::TyS {
-                        sty: ty::TypeVariants::TyParam(ref pt), ..
+                        sty: ty::Param(ref pt), ..
                     }) => {
                         !impl_generics.type_param(pt, self).pure_wrt_drop
                     }
@@ -604,10 +604,10 @@ pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
     pub fn is_static(&self, def_id: DefId) -> Option<hir::Mutability> {
         if let Some(node) = self.hir.get_if_local(def_id) {
             match node {
-                Node::NodeItem(&hir::Item {
+                Node::Item(&hir::Item {
                     node: hir::ItemKind::Static(_, mutbl, _), ..
                 }) => Some(mutbl),
-                Node::NodeForeignItem(&hir::ForeignItem {
+                Node::ForeignItem(&hir::ForeignItem {
                     node: hir::ForeignItemKind::Static(_, is_mutbl), ..
                 }) =>
                     Some(if is_mutbl {
@@ -697,7 +697,7 @@ fn are_inner_types_recursive<'a, 'tcx>(
             -> Representability
         {
             match ty.sty {
-                TyTuple(ref ts) => {
+                Tuple(ref ts) => {
                     // Find non representable
                     fold_repr(ts.iter().map(|ty| {
                         is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty)
@@ -705,10 +705,10 @@ fn are_inner_types_recursive<'a, 'tcx>(
                 }
                 // Fixed-length vectors.
                 // FIXME(#11924) Behavior undecided for zero-length vectors.
-                TyArray(ty, _) => {
+                Array(ty, _) => {
                     is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty)
                 }
-                TyAdt(def, substs) => {
+                Adt(def, substs) => {
                     // Find non representable fields with their spans
                     fold_repr(def.all_fields().map(|field| {
                         let ty = field.ty(tcx, substs);
@@ -723,7 +723,7 @@ fn are_inner_types_recursive<'a, 'tcx>(
                         }
                     }))
                 }
-                TyClosure(..) => {
+                Closure(..) => {
                     // this check is run on type definitions, so we don't expect
                     // to see closure types
                     bug!("requires check invoked on inapplicable type: {:?}", ty)
@@ -734,7 +734,7 @@ fn are_inner_types_recursive<'a, 'tcx>(
 
         fn same_struct_or_enum<'tcx>(ty: Ty<'tcx>, def: &'tcx ty::AdtDef) -> bool {
             match ty.sty {
-                TyAdt(ty_def, _) => {
+                Adt(ty_def, _) => {
                      ty_def == def
                 }
                 _ => false
@@ -743,7 +743,7 @@ fn same_struct_or_enum<'tcx>(ty: Ty<'tcx>, def: &'tcx ty::AdtDef) -> bool {
 
         fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
             match (&a.sty, &b.sty) {
-                (&TyAdt(did_a, substs_a), &TyAdt(did_b, substs_b)) => {
+                (&Adt(did_a, substs_a), &Adt(did_b, substs_b)) => {
                     if did_a != did_b {
                         return false;
                     }
@@ -785,7 +785,7 @@ fn is_type_structurally_recursive_inner<'a, 'tcx>(
             ty: Ty<'tcx>) -> Representability
         {
             match ty.sty {
-                TyAdt(def, _) => {
+                Adt(def, _) => {
                     {
                         // Iterate through stack of previously seen types.
                         let mut iter = seen.iter();
@@ -924,16 +924,16 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     match ty.sty {
         // Fast-path for primitive types
-        ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
-        ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever |
-        ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar | ty::TyGeneratorWitness(..) |
-        ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyStr => false,
+        ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) |
+        ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Never |
+        ty::FnDef(..) | ty::FnPtr(_) | ty::Char | ty::GeneratorWitness(..) |
+        ty::RawPtr(_) | ty::Ref(..) | ty::Str => false,
 
         // Foreign types can never have destructors
-        ty::TyForeign(..) => false,
+        ty::Foreign(..) => false,
 
         // `ManuallyDrop` doesn't have a destructor regardless of field types.
-        ty::TyAdt(def, _) if Some(def.did) == tcx.lang_items().manually_drop() => false,
+        ty::Adt(def, _) if Some(def.did) == tcx.lang_items().manually_drop() => false,
 
         // Issue #22536: We first query type_moves_by_default.  It sees a
         // normalized version of the type, and therefore will definitely
@@ -951,30 +951,30 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // (see above), it is sound to treat it as having a destructor.
 
         // User destructors are the only way to have concrete drop types.
-        ty::TyAdt(def, _) if def.has_dtor(tcx) => true,
+        ty::Adt(def, _) if def.has_dtor(tcx) => true,
 
         // Can refer to a type which may drop.
         // FIXME(eddyb) check this against a ParamEnv.
-        ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyParam(_) |
-        ty::TyAnon(..) | ty::TyInfer(_) | ty::TyError => true,
+        ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) |
+        ty::Anon(..) | ty::Infer(_) | ty::Error => true,
 
         // Structural recursion.
-        ty::TyArray(ty, _) | ty::TySlice(ty) => needs_drop(ty),
+        ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty),
 
-        ty::TyClosure(def_id, ref substs) => substs.upvar_tys(def_id, tcx).any(needs_drop),
+        ty::Closure(def_id, ref substs) => substs.upvar_tys(def_id, tcx).any(needs_drop),
 
         // Pessimistically assume that all generators will require destructors
         // as we don't know if a destructor is a noop or not until after the MIR
         // state transformation pass
-        ty::TyGenerator(..) => true,
+        ty::Generator(..) => true,
 
-        ty::TyTuple(ref tys) => tys.iter().cloned().any(needs_drop),
+        ty::Tuple(ref tys) => tys.iter().cloned().any(needs_drop),
 
         // unions don't have destructors because of the child types,
         // only if they manually implement `Drop` (handled above).
-        ty::TyAdt(def, _) if def.is_union() => false,
+        ty::Adt(def, _) if def.is_union() => false,
 
-        ty::TyAdt(def, substs) =>
+        ty::Adt(def, substs) =>
             def.variants.iter().any(
                 |variant| variant.fields.iter().any(
                     |field| needs_drop(field.ty(tcx, substs)))),
@@ -1025,13 +1025,13 @@ pub fn determine<P>(
 
         match self_arg_ty.sty {
             _ if is_self_ty(self_arg_ty) => ByValue,
-            ty::TyRef(region, ty, mutbl) if is_self_ty(ty) => {
+            ty::Ref(region, ty, mutbl) if is_self_ty(ty) => {
                 ByReference(region, mutbl)
             }
-            ty::TyRawPtr(ty::TypeAndMut { ty, mutbl }) if is_self_ty(ty) => {
+            ty::RawPtr(ty::TypeAndMut { ty, mutbl }) if is_self_ty(ty) => {
                 ByRawPointer(mutbl)
             }
-            ty::TyAdt(def, _) if def.is_box() && is_self_ty(self_arg_ty.boxed_ty()) => {
+            ty::Adt(def, _) if def.is_box() && is_self_ty(self_arg_ty.boxed_ty()) => {
                 ByBox
             }
             _ => Other
index d12f73144269bf7e87676fb038526149b34d2008..6d3ba22c57f27f346c10d9316253a268c8ed8806 100644 (file)
@@ -13,8 +13,7 @@
 
 use mir::interpret::ConstValue;
 use ty::{self, Ty};
-use rustc_data_structures::small_vec::SmallVec;
-use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
+use smallvec::{self, SmallVec};
 
 // The TypeWalker's stack is hot enough that it's worth going to some effort to
 // avoid heap allocations.
@@ -28,7 +27,7 @@ pub struct TypeWalker<'tcx> {
 
 impl<'tcx> TypeWalker<'tcx> {
     pub fn new(ty: Ty<'tcx>) -> TypeWalker<'tcx> {
-        TypeWalker { stack: SmallVec::one(ty), last_subtree: 1, }
+        TypeWalker { stack: smallvec![ty], last_subtree: 1, }
     }
 
     /// Skips the subtree of types corresponding to the last type
@@ -67,7 +66,7 @@ fn next(&mut self) -> Option<Ty<'tcx>> {
     }
 }
 
-pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> AccIntoIter<TypeWalkerArray<'tcx>> {
+pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> smallvec::IntoIter<TypeWalkerArray<'tcx>> {
     let mut stack = SmallVec::new();
     push_subtypes(&mut stack, ty);
     stack.into_iter()
@@ -81,27 +80,27 @@ pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> AccIntoIter<TypeWalkerArray<'tcx>> {
 // types as they are written).
 fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
     match parent_ty.sty {
-        ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
-        ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyNever | ty::TyError |
-        ty::TyForeign(..) => {
+        ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) |
+        ty::Str | ty::Infer(_) | ty::Param(_) | ty::Never | ty::Error |
+        ty::Foreign(..) => {
         }
-        ty::TyArray(ty, len) => {
+        ty::Array(ty, len) => {
             push_const(stack, len);
             stack.push(ty);
         }
-        ty::TySlice(ty) => {
+        ty::Slice(ty) => {
             stack.push(ty);
         }
-        ty::TyRawPtr(ref mt) => {
+        ty::RawPtr(ref mt) => {
             stack.push(mt.ty);
         }
-        ty::TyRef(_, ty, _) => {
+        ty::Ref(_, ty, _) => {
             stack.push(ty);
         }
-        ty::TyProjection(ref data) => {
+        ty::Projection(ref data) => {
             stack.extend(data.substs.types().rev());
         }
-        ty::TyDynamic(ref obj, ..) => {
+        ty::Dynamic(ref obj, ..) => {
             stack.extend(obj.iter().rev().flat_map(|predicate| {
                 let (substs, opt_ty) = match *predicate.skip_binder() {
                     ty::ExistentialPredicate::Trait(tr) => (tr.substs, None),
@@ -115,25 +114,25 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
                 substs.types().rev().chain(opt_ty)
             }));
         }
-        ty::TyAdt(_, substs) | ty::TyAnon(_, substs) => {
+        ty::Adt(_, substs) | ty::Anon(_, substs) => {
             stack.extend(substs.types().rev());
         }
-        ty::TyClosure(_, ref substs) => {
+        ty::Closure(_, ref substs) => {
             stack.extend(substs.substs.types().rev());
         }
-        ty::TyGenerator(_, ref substs, _) => {
+        ty::Generator(_, ref substs, _) => {
             stack.extend(substs.substs.types().rev());
         }
-        ty::TyGeneratorWitness(ts) => {
+        ty::GeneratorWitness(ts) => {
             stack.extend(ts.skip_binder().iter().cloned().rev());
         }
-        ty::TyTuple(ts) => {
+        ty::Tuple(ts) => {
             stack.extend(ts.iter().cloned().rev());
         }
-        ty::TyFnDef(_, substs) => {
+        ty::FnDef(_, substs) => {
             stack.extend(substs.types().rev());
         }
-        ty::TyFnPtr(sig) => {
+        ty::FnPtr(sig) => {
             stack.push(sig.skip_binder().output());
             stack.extend(sig.skip_binder().inputs().iter().cloned().rev());
         }
index b99cdd59773aa71f18dfbf97332e4eed4c11a8a8..fc55d8f34a23fcff64a51de751dd0e2b53450892 100644 (file)
@@ -248,31 +248,31 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
         let param_env = self.param_env;
         while let Some(ty) = subtys.next() {
             match ty.sty {
-                ty::TyBool |
-                ty::TyChar |
-                ty::TyInt(..) |
-                ty::TyUint(..) |
-                ty::TyFloat(..) |
-                ty::TyError |
-                ty::TyStr |
-                ty::TyGeneratorWitness(..) |
-                ty::TyNever |
-                ty::TyParam(_) |
-                ty::TyForeign(..) => {
+                ty::Bool |
+                ty::Char |
+                ty::Int(..) |
+                ty::Uint(..) |
+                ty::Float(..) |
+                ty::Error |
+                ty::Str |
+                ty::GeneratorWitness(..) |
+                ty::Never |
+                ty::Param(_) |
+                ty::Foreign(..) => {
                     // WfScalar, WfParameter, etc
                 }
 
-                ty::TySlice(subty) => {
+                ty::Slice(subty) => {
                     self.require_sized(subty, traits::SliceOrArrayElem);
                 }
 
-                ty::TyArray(subty, len) => {
+                ty::Array(subty, len) => {
                     self.require_sized(subty, traits::SliceOrArrayElem);
                     assert_eq!(len.ty, self.infcx.tcx.types.usize);
                     self.compute_const(len);
                 }
 
-                ty::TyTuple(ref tys) => {
+                ty::Tuple(ref tys) => {
                     if let Some((_last, rest)) = tys.split_last() {
                         for elem in rest {
                             self.require_sized(elem, traits::TupleElem);
@@ -280,22 +280,22 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                     }
                 }
 
-                ty::TyRawPtr(_) => {
+                ty::RawPtr(_) => {
                     // simple cases that are WF if their type args are WF
                 }
 
-                ty::TyProjection(data) => {
+                ty::Projection(data) => {
                     subtys.skip_current_subtree(); // subtree handled by compute_projection
                     self.compute_projection(data);
                 }
 
-                ty::TyAdt(def, substs) => {
+                ty::Adt(def, substs) => {
                     // WfNominalType
                     let obligations = self.nominal_obligations(def.did, substs);
                     self.out.extend(obligations);
                 }
 
-                ty::TyRef(r, rty, _) => {
+                ty::Ref(r, rty, _) => {
                     // WfReference
                     if !r.has_escaping_regions() && !rty.has_escaping_regions() {
                         let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
@@ -309,7 +309,7 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                     }
                 }
 
-                ty::TyGenerator(..) => {
+                ty::Generator(..) => {
                     // Walk ALL the types in the generator: this will
                     // include the upvar types as well as the yield
                     // type. Note that this is mildly distinct from
@@ -319,7 +319,7 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                     // generators don't take arguments.
                 }
 
-                ty::TyClosure(def_id, substs) => {
+                ty::Closure(def_id, substs) => {
                     // Only check the upvar types for WF, not the rest
                     // of the types within. This is needed because we
                     // capture the signature and it may not be WF
@@ -355,12 +355,12 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                     }
                 }
 
-                ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+                ty::FnDef(..) | ty::FnPtr(_) => {
                     // let the loop iterate into the argument/return
                     // types appearing in the fn signature
                 }
 
-                ty::TyAnon(did, substs) => {
+                ty::Anon(did, substs) => {
                     // all of the requirements on type parameters
                     // should've been checked by the instantiation
                     // of whatever returned this exact `impl Trait`.
@@ -372,7 +372,7 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                     }
                 }
 
-                ty::TyDynamic(data, r) => {
+                ty::Dynamic(data, r) => {
                     // WfObject
                     //
                     // Here, we defer WF checking due to higher-ranked
@@ -408,9 +408,9 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                 //    register a pending obligation and keep
                 //    moving. (Goal is that an "inductive hypothesis"
                 //    is satisfied to ensure termination.)
-                ty::TyInfer(_) => {
+                ty::Infer(_) => {
                     let ty = self.infcx.shallow_resolve(ty);
-                    if let ty::TyInfer(_) = ty.sty { // not yet resolved...
+                    if let ty::Infer(_) = ty.sty { // not yet resolved...
                         if ty == ty0 { // ...this is the type we started from! no progress.
                             return false;
                         }
@@ -423,7 +423,7 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                     } else {
                         // Yes, resolved, proceed with the
                         // result. Should never return false because
-                        // `ty` is not a TyInfer.
+                        // `ty` is not a Infer.
                         assert!(self.compute(ty));
                     }
                 }
@@ -453,7 +453,7 @@ fn nominal_obligations(&mut self,
     }
 
     fn from_object_ty(&mut self, ty: Ty<'tcx>,
-                      data: ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>,
+                      data: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
                       region: ty::Region<'tcx>) {
         // Imagine a type like this:
         //
@@ -513,7 +513,7 @@ fn from_object_ty(&mut self, ty: Ty<'tcx>,
 /// `ty::required_region_bounds`, see that for more information.
 pub fn object_region_bounds<'a, 'gcx, 'tcx>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    existential_predicates: ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>)
+    existential_predicates: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>)
     -> Vec<ty::Region<'tcx>>
 {
     // Since we don't actually *know* the self type for an object,
index 1ec025f78c9aca3cdab2dbe0b63bb3bf3ce8345b..02bdc5f41b35428e04287114043e94ce6ad0b5f5 100644 (file)
@@ -84,7 +84,7 @@ pub struct ProfQDumpParams {
     pub dump_profq_msg_log:bool,
 }
 
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct QueryMsg {
     pub query: &'static str,
@@ -213,7 +213,7 @@ fn print_time_passes_entry_internal(what: &str, dur: Duration) {
             let mb = n as f64 / 1_000_000.0;
             format!("; rss: {}MB", mb.round() as usize)
         }
-        None => "".to_owned(),
+        None => String::new(),
     };
     println!("{}time: {}{}\t{}",
              "  ".repeat(indentation),
index 9513086667b28abf082a8a7c2f531baaff057fa0..0f15c75c2fb36115bdc221e7033ed82b4ab43843 100644 (file)
 use middle::region::{self, BlockRemainder};
 use ty::subst::{self, Subst};
 use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
-use ty::{TyBool, TyChar, TyAdt};
-use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
-use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
-use ty::{TyClosure, TyGenerator, TyGeneratorWitness, TyForeign, TyProjection, TyAnon};
-use ty::{TyDynamic, TyInt, TyUint, TyInfer};
+use ty::{Bool, Char, Adt};
+use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
+use ty::{Param, RawPtr, Ref, Never, Tuple};
+use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Anon};
+use ty::{Dynamic, Int, Uint, Infer};
 use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind};
 use util::nodemap::FxHashSet;
 
@@ -371,7 +371,7 @@ fn parameterized<F: fmt::Write>(&mut self,
 
         if !verbose && fn_trait_kind.is_some() && projections.len() == 1 {
             let projection_ty = projections[0].ty;
-            if let TyTuple(ref args) = substs.type_at(1).sty {
+            if let Tuple(ref args) = substs.type_at(1).sty {
                 return self.fn_sig(f, args, false, projection_ty);
             }
         }
@@ -586,7 +586,7 @@ fn print<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result
 }
 
 define_print! {
-    ('tcx) &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, (self, f, cx) {
+    ('tcx) &'tcx ty::List<ty::ExistentialPredicate<'tcx>>, (self, f, cx) {
         display {
             // Generate the main trait ref, including associated types.
             ty::tls::with(|tcx| {
@@ -672,7 +672,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 define_print! {
-    ('tcx) &'tcx ty::Slice<Ty<'tcx>>, (self, f, cx) {
+    ('tcx) &'tcx ty::List<Ty<'tcx>>, (self, f, cx) {
         display {
             write!(f, "{{")?;
             let mut tys = self.iter();
@@ -993,7 +993,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 define_print_multi! {
     [
-    ('tcx) ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>,
+    ('tcx) ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
     ('tcx) ty::Binder<ty::TraitRef<'tcx>>,
     ('tcx) ty::Binder<ty::FnSig<'tcx>>,
     ('tcx) ty::Binder<ty::TraitPredicate<'tcx>>,
@@ -1029,22 +1029,22 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 define_print! {
-    ('tcx) ty::TypeVariants<'tcx>, (self, f, cx) {
+    ('tcx) ty::TyKind<'tcx>, (self, f, cx) {
         display {
             match *self {
-                TyBool => write!(f, "bool"),
-                TyChar => write!(f, "char"),
-                TyInt(t) => write!(f, "{}", t.ty_to_string()),
-                TyUint(t) => write!(f, "{}", t.ty_to_string()),
-                TyFloat(t) => write!(f, "{}", t.ty_to_string()),
-                TyRawPtr(ref tm) => {
+                Bool => write!(f, "bool"),
+                Char => write!(f, "char"),
+                Int(t) => write!(f, "{}", t.ty_to_string()),
+                Uint(t) => write!(f, "{}", t.ty_to_string()),
+                Float(t) => write!(f, "{}", t.ty_to_string()),
+                RawPtr(ref tm) => {
                     write!(f, "*{} ", match tm.mutbl {
                         hir::MutMutable => "mut",
                         hir::MutImmutable => "const",
                     })?;
                     tm.ty.print(f, cx)
                 }
-                TyRef(r, ty, mutbl) => {
+                Ref(r, ty, mutbl) => {
                     write!(f, "&")?;
                     let s = r.print_to_string(cx);
                     if s != "'_" {
@@ -1055,8 +1055,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     }
                     ty::TypeAndMut { ty, mutbl }.print(f, cx)
                 }
-                TyNever => write!(f, "!"),
-                TyTuple(ref tys) => {
+                Never => write!(f, "!"),
+                Tuple(ref tys) => {
                     write!(f, "(")?;
                     let mut tys = tys.iter();
                     if let Some(&ty) = tys.next() {
@@ -1070,7 +1070,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     }
                     write!(f, ")")
                 }
-                TyFnDef(def_id, substs) => {
+                FnDef(def_id, substs) => {
                     ty::tls::with(|tcx| {
                         let mut sig = tcx.fn_sig(def_id);
                         if let Some(substs) = tcx.lift(&substs) {
@@ -1081,14 +1081,14 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     cx.parameterized(f, substs, def_id, &[])?;
                     write!(f, "}}")
                 }
-                TyFnPtr(ref bare_fn) => {
+                FnPtr(ref bare_fn) => {
                     bare_fn.print(f, cx)
                 }
-                TyInfer(infer_ty) => write!(f, "{}", infer_ty),
-                TyError => write!(f, "[type error]"),
-                TyParam(ref param_ty) => write!(f, "{}", param_ty),
-                TyAdt(def, substs) => cx.parameterized(f, substs, def.did, &[]),
-                TyDynamic(data, r) => {
+                Infer(infer_ty) => write!(f, "{}", infer_ty),
+                Error => write!(f, "[type error]"),
+                Param(ref param_ty) => write!(f, "{}", param_ty),
+                Adt(def, substs) => cx.parameterized(f, substs, def.did, &[]),
+                Dynamic(data, r) => {
                     let r = r.print_to_string(cx);
                     if !r.is_empty() {
                         write!(f, "(")?;
@@ -1101,11 +1101,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                         Ok(())
                     }
                 }
-                TyForeign(def_id) => parameterized(f, subst::Substs::empty(), def_id, &[]),
-                TyProjection(ref data) => data.print(f, cx),
-                TyAnon(def_id, substs) => {
+                Foreign(def_id) => parameterized(f, subst::Substs::empty(), def_id, &[]),
+                Projection(ref data) => data.print(f, cx),
+                Anon(def_id, substs) => {
                     if cx.is_verbose {
-                        return write!(f, "TyAnon({:?}, {:?})", def_id, substs);
+                        return write!(f, "Anon({:?}, {:?})", def_id, substs);
                     }
 
                     ty::tls::with(|tcx| {
@@ -1154,8 +1154,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                         Ok(())
                     })
                 }
-                TyStr => write!(f, "str"),
-                TyGenerator(did, substs, movability) => ty::tls::with(|tcx| {
+                Str => write!(f, "str"),
+                Generator(did, substs, movability) => ty::tls::with(|tcx| {
                     let upvar_tys = substs.upvar_tys(did, tcx);
                     let witness = substs.witness(did, tcx);
                     if movability == hir::GeneratorMovability::Movable {
@@ -1193,10 +1193,10 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
                     print!(f, cx, write(" "), print(witness), write("]"))
                 }),
-                TyGeneratorWitness(types) => {
+                GeneratorWitness(types) => {
                     ty::tls::with(|tcx| cx.in_binder(f, tcx, &types, tcx.lift(&types)))
                 }
-                TyClosure(did, substs) => ty::tls::with(|tcx| {
+                Closure(did, substs) => ty::tls::with(|tcx| {
                     let upvar_tys = substs.upvar_tys(did, tcx);
                     write!(f, "[closure")?;
 
@@ -1233,7 +1233,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
                     write!(f, "]")
                 }),
-                TyArray(ty, sz) => {
+                Array(ty, sz) => {
                     print!(f, cx, write("["), print(ty), write("; "))?;
                     match sz.val {
                         ConstValue::Unevaluated(_def_id, _substs) => {
@@ -1245,7 +1245,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     }
                     write!(f, "]")
                 }
-                TySlice(ty) => {
+                Slice(ty) => {
                     print!(f, cx, write("["), print(ty), write("]"))
                 }
             }
index 447b75e547f01d903c6fec73fe38aac2933fbb49..70760d35f7865c1f3e78d8b208f6990d37cb59d7 100644 (file)
@@ -21,7 +21,7 @@ pub enum ProfileCategory {
             $($name),*
         }
 
-        #[allow(bad_style)]
+        #[allow(nonstandard_style)]
         struct Categories<T> {
             $($name: T),*
         }
@@ -73,7 +73,7 @@ fn print(&self, lock: &mut StdoutLock) {
                         (format!("{:.2}",
                         (((hits as f32) / (total as f32)) * 100.0)), total.to_string())
                     } else {
-                        ("".into(), "".into())
+                        (String::new(), String::new())
                     };
 
                     writeln!(
index a8502682a806b718f93c6e5b7c9943d86cba759a..3ba4e4ddbb13bb7e883f26b7096ba4324aac5be1 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::HashMap;
+use rustc_data_structures::fx::FxHashMap;
 use std::fs::File;
 use std::io::prelude::*;
 use std::marker::PhantomData;
@@ -40,7 +40,7 @@ struct PerThread {
 
 #[derive(Clone)]
 pub struct TimeGraph {
-    data: Arc<Mutex<HashMap<TimelineId, PerThread>>>,
+    data: Arc<Mutex<FxHashMap<TimelineId, PerThread>>>,
 }
 
 #[derive(Clone, Copy)]
@@ -68,7 +68,7 @@ fn drop(&mut self) {
 impl TimeGraph {
     pub fn new() -> TimeGraph {
         TimeGraph {
-            data: Arc::new(Mutex::new(HashMap::new()))
+            data: Arc::new(Mutex::new(FxHashMap::default()))
         }
     }
 
index 83a918f2af83706ea4d4baf7a31fba915378a779..cd3ef6a1f043ce85c1935e7c3cb3289ea2e93db5 100644 (file)
@@ -16,3 +16,4 @@ rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 log = "0.4"
+smallvec = { version = "0.6.5", features = ["union"] }
index da60f41ee680ecbfc628dbd6f2b9180d789a05ba..11e8c30760b8a4f08ed22d0089b50ae89c665ba0 100644 (file)
@@ -78,20 +78,20 @@ fn fold_item(&mut self, item: P<Item>) -> OneVector<P<Item>> {
             _ => {
                 self.handler
                     .span_err(item.span, "allocators must be statics");
-                return OneVector::one(item);
+                return smallvec![item];
             }
         }
 
         if self.in_submod > 0 {
             self.handler
                 .span_err(item.span, "`global_allocator` cannot be used in submodules");
-            return OneVector::one(item);
+            return smallvec![item];
         }
 
         if self.found {
             self.handler
                 .span_err(item.span, "cannot define more than one #[global_allocator]");
-            return OneVector::one(item);
+            return smallvec![item];
         }
         self.found = true;
 
@@ -236,15 +236,9 @@ fn call_allocator(&self, method: &str, mut args: Vec<P<Expr>>) -> P<Expr> {
     }
 
     fn attrs(&self) -> Vec<Attribute> {
-        let no_mangle = Symbol::intern("no_mangle");
-        let no_mangle = self.cx.meta_word(self.span, no_mangle);
-
         let special = Symbol::intern("rustc_std_internal_symbol");
         let special = self.cx.meta_word(self.span, special);
-        vec![
-            self.cx.attribute(self.span, no_mangle),
-            self.cx.attribute(self.span, special),
-        ]
+        vec![self.cx.attribute(self.span, special)]
     }
 
     fn arg_ty(
index d020fe96335e91345fa20e09a3a111cfe5dac199..44fbcade6bc066eabf9754034f0dc7a1434ffc69 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(rustc_private)]
 
 #[macro_use] extern crate log;
@@ -18,6 +19,8 @@
 extern crate rustc_target;
 extern crate syntax;
 extern crate syntax_pos;
+#[macro_use]
+extern crate smallvec;
 
 pub mod expand;
 
index d6e821d427d0580f45266e98cce22d40be793747..c3c32ba7d5b6c05623ac577be65321111f81b171 100644 (file)
@@ -46,6 +46,7 @@
 #![forbid(unsafe_code)]
 
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(try_from)]
 // See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
 #[allow(unused_extern_crates)]
index b3ba86ad8a4b32af8f7f6629cca53f8891221b8f..ed8fd305977e5e9b7a71359411211774d4d81420 100644 (file)
@@ -11,6 +11,7 @@
 #![sanitizer_runtime]
 #![feature(alloc_system)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(sanitizer_runtime)]
 #![feature(staged_api)]
 #![no_std]
index dab60ef16613d77971791544a852685671cfb20f..1af117c97f569abbe829c82945a849bb40e262ed 100644 (file)
@@ -16,6 +16,7 @@
 // 2. loans made in overlapping scopes do not conflict
 // 3. assignments do not affect things loaned out as immutable
 // 4. moves do not affect things loaned out in any way
+
 use self::UseError::*;
 
 use borrowck::*;
@@ -29,6 +30,7 @@
 use syntax::ast;
 use syntax_pos::Span;
 use rustc::hir;
+use rustc::hir::Node;
 use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin};
 
 use std::rc::Rc;
@@ -201,7 +203,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
 
     let node_id = bccx.tcx.hir.as_local_node_id(def_id).unwrap();
     let movable_generator = !match bccx.tcx.hir.get(node_id) {
-        hir::map::Node::NodeExpr(&hir::Expr {
+        Node::Expr(&hir::Expr {
             node: hir::ExprKind::Closure(.., Some(hir::GeneratorMovability::Static)),
             ..
         }) => true,
@@ -843,7 +845,7 @@ fn check_if_assigned_path_is_moved(&self,
             }
             LpExtend(ref lp_base, _, LpInterior(_, InteriorField(_))) => {
                 match lp_base.to_type().sty {
-                    ty::TyAdt(def, _) if def.has_dtor(self.tcx()) => {
+                    ty::Adt(def, _) if def.has_dtor(self.tcx()) => {
                         // In the case where the owner implements drop, then
                         // the path must be initialized to prevent a case of
                         // partial reinitialization
index b76931c301748c44cc995473755bb1547833c017..ffc4fbfb4c9cb12839824eef37f04373f1dda358 100644 (file)
@@ -24,7 +24,7 @@
 use syntax::ast;
 use syntax_pos::Span;
 use rustc::hir::*;
-use rustc::hir::map::Node::*;
+use rustc::hir::Node;
 
 struct GatherMoveInfo<'c, 'tcx: 'c> {
     id: hir::ItemLocalId,
@@ -60,7 +60,7 @@ fn get_pattern_source<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &Pat) -> Patte
     let parent = tcx.hir.get_parent_node(pat.id);
 
     match tcx.hir.get(parent) {
-        NodeExpr(ref e) => {
+        Node::Expr(ref e) => {
             // the enclosing expression must be a `match` or something else
             assert!(match e.node {
                         ExprKind::Match(..) => true,
@@ -68,7 +68,7 @@ fn get_pattern_source<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &Pat) -> Patte
                     });
             PatternSource::MatchExpr(e)
         }
-        NodeLocal(local) => PatternSource::LetDecl(local),
+        Node::Local(local) => PatternSource::LetDecl(local),
         _ => return PatternSource::Other,
 
     }
@@ -191,14 +191,14 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         Categorization::Interior(ref b, mc::InteriorField(_)) |
         Categorization::Interior(ref b, mc::InteriorElement(Kind::Pattern)) => {
             match b.ty.sty {
-                ty::TyAdt(def, _) => {
+                ty::Adt(def, _) => {
                     if def.has_dtor(bccx.tcx) {
                         Some(cmt.clone())
                     } else {
                         check_and_get_illegal_move_origin(bccx, b)
                     }
                 }
-                ty::TySlice(..) => Some(cmt.clone()),
+                ty::Slice(..) => Some(cmt.clone()),
                 _ => {
                     check_and_get_illegal_move_origin(bccx, b)
                 }
index e1c3ac839902f0f52faee714205483488815dd21..b29ab55f9ba78a950197cb2c208ef7b8be43187c 100644 (file)
@@ -17,7 +17,7 @@
 use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin};
 use syntax::ast;
 use syntax_pos;
-use errors::DiagnosticBuilder;
+use errors::{DiagnosticBuilder, Applicability};
 use borrowck::gather_loans::gather_moves::PatternSource;
 
 pub struct MoveErrorCollector<'tcx> {
@@ -80,9 +80,12 @@ fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, errors: &[MoveErr
                 let initializer =
                     e.init.as_ref().expect("should have an initializer to get an error");
                 if let Ok(snippet) = bccx.tcx.sess.source_map().span_to_snippet(initializer.span) {
-                    err.span_suggestion(initializer.span,
-                                        "consider using a reference instead",
-                                        format!("&{}", snippet));
+                    err.span_suggestion_with_applicability(
+                        initializer.span,
+                        "consider using a reference instead",
+                        format!("&{}", snippet),
+                        Applicability::MaybeIncorrect // using a reference may not be the right fix
+                    );
                 }
             }
             _ => {
@@ -154,7 +157,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>,
         Categorization::Downcast(ref b, _) |
         Categorization::Interior(ref b, mc::InteriorField(_)) => {
             match b.ty.sty {
-                ty::TyAdt(def, _) if def.has_dtor(bccx.tcx) => {
+                ty::Adt(def, _) if def.has_dtor(bccx.tcx) => {
                     bccx.cannot_move_out_of_interior_of_drop(
                         move_from.span, b.ty, Origin::Ast)
                 }
index e332f68327546ac1b8684cd1039a4a37ec8c5355..d9784cc2177fde18003c252b9760e512d341b224 100644 (file)
@@ -104,7 +104,7 @@ fn restrict(&self,
                 let result = self.restrict(&cmt_base);
                 // Borrowing one union field automatically borrows all its fields.
                 match base_ty.sty {
-                    ty::TyAdt(adt_def, _) if adt_def.is_union() => match result {
+                    ty::Adt(adt_def, _) if adt_def.is_union() => match result {
                         RestrictionResult::Safe => RestrictionResult::Safe,
                         RestrictionResult::SafeIf(base_lp, mut base_vec) => {
                             for (i, field) in adt_def.non_enum_variant().fields.iter().enumerate() {
index 7208e1ca36299f7e20d9aed5625239ad3a5ab163..ad45c5429a512b3214a1a6544673f471f2150a88 100644 (file)
@@ -21,7 +21,7 @@
 use self::InteriorKind::*;
 
 use rustc::hir::HirId;
-use rustc::hir::map as hir_map;
+use rustc::hir::Node;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::cfg;
 use rustc::middle::borrowck::{BorrowCheckResult, SignalledError};
@@ -95,8 +95,8 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId)
     let owner_id = tcx.hir.as_local_node_id(owner_def_id).unwrap();
 
     match tcx.hir.get(owner_id) {
-        hir_map::NodeStructCtor(_) |
-        hir_map::NodeVariant(_) => {
+        Node::StructCtor(_) |
+        Node::Variant(_) => {
             // We get invoked with anything that has MIR, but some of
             // those things (notably the synthesized constructors from
             // tuple structs/variants) do not have an associated body
@@ -419,7 +419,7 @@ fn closure_to_block(closure_id: LocalDefId,
                     tcx: TyCtxt) -> ast::NodeId {
     let closure_id = tcx.hir.local_def_id_to_node_id(closure_id);
     match tcx.hir.get(closure_id) {
-        hir_map::NodeExpr(expr) => match expr.node {
+        Node::Expr(expr) => match expr.node {
             hir::ExprKind::Closure(.., body_id, _, _) => {
                 body_id.node_id
             }
@@ -697,7 +697,7 @@ pub fn report_use_of_moved_value(&self,
                                                              Some(nl.to_string()),
                                                              Origin::Ast);
                 let need_note = match lp.ty.sty {
-                    ty::TypeVariants::TyClosure(id, _) => {
+                    ty::Closure(id, _) => {
                         let node_id = self.tcx.hir.as_local_node_id(id).unwrap();
                         let hir_id = self.tcx.hir.node_to_hir_id(node_id);
                         if let Some((span, name)) = self.tables.closure_kind_origins().get(hir_id) {
@@ -908,7 +908,7 @@ fn report_bckerr(&self, err: &BckError<'a, 'tcx>) {
                     let node =  self.tcx.hir.get(node_id);
 
                     // This pattern probably always matches.
-                    if let hir_map::NodeExpr(
+                    if let Node::Expr(
                         hir::Expr { node: hir::ExprKind::Index(lhs, _), ..}
                     ) = node {
                         let ty = self.tables.expr_ty(lhs);
@@ -1032,7 +1032,7 @@ fn report_bckerr(&self, err: &BckError<'a, 'tcx>) {
                 if let ty::ReScope(scope) = *super_scope {
                     let node_id = scope.node_id(self.tcx, &self.region_scope_tree);
                     match self.tcx.hir.find(node_id) {
-                        Some(hir_map::NodeStmt(_)) => {
+                        Some(Node::Stmt(_)) => {
                             if *sub_scope != ty::ReStatic {
                                 db.note("consider using a `let` binding to increase its lifetime");
                             }
@@ -1183,7 +1183,7 @@ fn suggest_mut_for_immutable(&self, pty: &hir::Ty, is_implicit_self: bool) -> Op
 
     fn local_binding_mode(&self, node_id: ast::NodeId) -> ty::BindingMode {
         let pat = match self.tcx.hir.get(node_id) {
-            hir_map::Node::NodeBinding(pat) => pat,
+            Node::Binding(pat) => pat,
             node => bug!("bad node for local: {:?}", node)
         };
 
@@ -1259,7 +1259,7 @@ fn note_immutability_blame(&self,
                     None => return
                 };
 
-                if let hir_map::Node::NodeField(ref field) = self.tcx.hir.get(node_id) {
+                if let Node::Field(ref field) = self.tcx.hir.get(node_id) {
                     if let Some(msg) = self.suggest_mut_for_immutable(&field.ty, false) {
                         db.span_label(field.ty.span, msg);
                     }
index 979d71a0923c40ea4f468f04e80b07716bf13cb4..d9f223daf609179059a4ece46abc09e885162564 100644 (file)
@@ -329,7 +329,7 @@ pub fn add_move(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // all parent union fields, moves do not propagate upwards automatically.
         let mut lp = orig_lp.clone();
         while let LpExtend(ref base_lp, mutbl, lp_elem) = lp.clone().kind {
-            if let (&ty::TyAdt(adt_def, _), LpInterior(opt_variant_id, interior))
+            if let (&ty::Adt(adt_def, _), LpInterior(opt_variant_id, interior))
                     = (&base_lp.ty.sty, lp_elem) {
                 if adt_def.is_union() {
                     for (i, field) in adt_def.non_enum_variant().fields.iter().enumerate() {
@@ -381,7 +381,7 @@ pub fn add_assignment(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           span: Span) {
         // Assigning to one union field automatically assigns to all its fields.
         if let LpExtend(ref base_lp, mutbl, LpInterior(opt_variant_id, interior)) = lp.kind {
-            if let ty::TyAdt(adt_def, _) = base_lp.ty.sty {
+            if let ty::Adt(adt_def, _) = base_lp.ty.sty {
                 if adt_def.is_union() {
                     for (i, field) in adt_def.non_enum_variant().fields.iter().enumerate() {
                         let field =
index c5571ecb97cd9f92bf41d9351061bddc71a2bd22..f10361cb076bd2fd1e02bc4cac45ebc6856e46bb 100644 (file)
@@ -13,6 +13,7 @@
 use rustc::lint::builtin::UNUSED_MUT;
 use rustc::ty;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
+use errors::Applicability;
 use std::slice;
 use syntax::ptr::P;
 
@@ -83,7 +84,11 @@ fn check_unused_mut_pat(&self, pats: &[P<hir::Pat>]) {
                                      hir_id,
                                      span,
                                      "variable does not need to be mutable")
-                .span_suggestion_short(mut_span, "remove this `mut`", "".to_owned())
+                .span_suggestion_short_with_applicability(
+                    mut_span,
+                    "remove this `mut`",
+                    String::new(),
+                    Applicability::MachineApplicable)
                 .emit();
         }
     }
index 75dee2b78fddb1c24ce1070f080e044616f208f1..832b69cb2acc4d53860505a9d9e11028ba1bdb40 100644 (file)
@@ -117,12 +117,12 @@ fn pre(&self,
            ps: &mut pprust::State,
            node: pprust::AnnNode) -> io::Result<()> {
         let id = match node {
-            pprust::NodeName(_) => return Ok(()),
-            pprust::NodeExpr(expr) => expr.hir_id.local_id,
-            pprust::NodeBlock(blk) => blk.hir_id.local_id,
-            pprust::NodeItem(_) |
-            pprust::NodeSubItem(_) => return Ok(()),
-            pprust::NodePat(pat) => pat.hir_id.local_id
+            pprust::AnnNode::Name(_) => return Ok(()),
+            pprust::AnnNode::Expr(expr) => expr.hir_id.local_id,
+            pprust::AnnNode::Block(blk) => blk.hir_id.local_id,
+            pprust::AnnNode::Item(_) |
+            pprust::AnnNode::SubItem(_) => return Ok(()),
+            pprust::AnnNode::Pat(pat) => pat.hir_id.local_id
         };
 
         if !self.has_bitset_for_local_id(id) {
@@ -140,21 +140,21 @@ fn pre(&self,
             let gens_str = if gens.iter().any(|&u| u != 0) {
                 format!(" gen: {}", bits_to_string(gens))
             } else {
-                "".to_string()
+                String::new()
             };
 
             let action_kills = &self.action_kills[start .. end];
             let action_kills_str = if action_kills.iter().any(|&u| u != 0) {
                 format!(" action_kill: {}", bits_to_string(action_kills))
             } else {
-                "".to_string()
+                String::new()
             };
 
             let scope_kills = &self.scope_kills[start .. end];
             let scope_kills_str = if scope_kills.iter().any(|&u| u != 0) {
                 format!(" scope_kill: {}", bits_to_string(scope_kills))
             } else {
-                "".to_string()
+                String::new()
             };
 
             ps.synth_comment(
index dddd6a354c115bd6f95c24c62f68a8720cfc8294..c177ed85c3482ce49f419ecc7ac8a5961990a723 100644 (file)
@@ -53,7 +53,7 @@ impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> {
     fn dataflow_for(&self, e: EntryOrExit, n: &Node<'a>) -> String {
         let id = n.1.data.id();
         debug!("dataflow_for({:?}, id={:?}) {:?}", e, id, self.variants);
-        let mut sets = "".to_string();
+        let mut sets = String::new();
         let mut seen_one = false;
         for &variant in &self.variants {
             if seen_one { sets.push_str(" "); } else { seen_one = true; }
index 16da8c8a3b8bf6651dc41d8b70ef0f9b7cc8341d..edd837e9401a7da2097c39409ed73431dd6da0f3 100644 (file)
@@ -15,6 +15,7 @@
 #![allow(non_camel_case_types)]
 
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(quote)]
 
 #![recursion_limit="256"]
index 79343505c78a5b41705667d8ddf35c5994635df9..684f2b358858f935387d082d6b0b26607a796cb1 100644 (file)
@@ -364,7 +364,7 @@ fn new_internal(
             assert!(!sig.variadic && extra_args.is_empty());
 
             match sig.inputs().last().unwrap().sty {
-                ty::TyTuple(ref tupled_arguments) => {
+                ty::Tuple(ref tupled_arguments) => {
                     inputs = &sig.inputs()[0..sig.inputs().len() - 1];
                     tupled_arguments
                 }
index 2b64642b766ab9d8a5d85580e0844081d8b089c8..c8a2b47e98d77e9472b73d4abc4d1e0c886ea807 100644 (file)
@@ -124,7 +124,8 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
 }
 
 pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
-    let target_cpu = CString::new(cx.tcx.sess.target_cpu().to_string()).unwrap();
+    let cpu = llvm_util::target_cpu(cx.tcx.sess);
+    let target_cpu = CString::new(cpu).unwrap();
     llvm::AddFunctionAttrStringValue(
             llfn,
             llvm::AttributePlace::Function,
index 34ddfa9455229a8b996fda97b3050369eb271b1e..d50a56ad84ab2792d5c2b16cb71c9037258a29ea 100644 (file)
@@ -47,8 +47,7 @@
 use syntax::attr;
 
 pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default_output_for_target,
-                                  invalid_output_for_target, build_link_meta, out_filename,
-                                  check_file_is_writeable};
+                                  invalid_output_for_target, out_filename, check_file_is_writeable};
 
 // The third parameter is for env vars, used on windows to set up the
 // path for MSVC to find its DLLs, and gcc to find its bundled
index a429e8f2d815df76932262765047c6c57d0e4691..ebb229b7b6bfaca67f304b84c4f245e53fc5e3f1 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::HashMap;
+use rustc_data_structures::fx::FxHashMap;
 use std::ffi::{OsStr, OsString};
 use std::fs::{self, File};
 use std::io::prelude::*;
 use rustc::ty::TyCtxt;
 use rustc_target::spec::{LinkerFlavor, LldFlavor};
 use serialize::{json, Encoder};
+use llvm_util;
 
 /// For all the linkers we support, and information they might
 /// need out of the shared crate context before we get rid of it.
 pub struct LinkerInfo {
-    exports: HashMap<CrateType, Vec<String>>,
+    exports: FxHashMap<CrateType, Vec<String>>,
 }
 
 impl LinkerInfo {
@@ -202,7 +203,7 @@ fn push_cross_lang_lto_args(&mut self, plugin_path: Option<&OsStr>) {
         };
 
         self.linker_arg(&format!("-plugin-opt={}", opt_level));
-        self.linker_arg(&format!("-plugin-opt=mcpu={}", self.sess.target_cpu()));
+        self.linker_arg(&format!("-plugin-opt=mcpu={}", llvm_util::target_cpu(self.sess)));
 
         match self.sess.opts.cg.lto {
             config::Lto::Thin |
index 2c3a143646c24c57dabe9336f262bcee4aef8be4..aa4f7688b0f42fb7be454b93e8017609a3c88d93 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::HashSet;
+use rustc_data_structures::fx::FxHashSet;
 use std::env;
 use std::path::{Path, PathBuf};
 use std::fs;
@@ -172,7 +172,7 @@ fn get_install_prefix_rpath(config: &mut RPathConfig) -> String {
 }
 
 fn minimize_rpaths(rpaths: &[String]) -> Vec<String> {
-    let mut set = HashSet::new();
+    let mut set = FxHashSet::default();
     let mut minimized = Vec::new();
     for rpath in rpaths {
         if set.insert(rpath) {
index edb1da0b5582ee9306fbf394072f01c0f0703872..6b1b0b94fd9d7f747eb5d701add7e67064f28aba 100644 (file)
@@ -13,6 +13,7 @@
 
 use monomorphize::Instance;
 use rustc::hir;
+use rustc::hir::Node;
 use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -94,7 +95,7 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             // As a result, if this id is an FFI item (foreign item) then we only
             // let it through if it's included statically.
             match tcx.hir.get(node_id) {
-                hir::map::NodeForeignItem(..) => {
+                Node::ForeignItem(..) => {
                     let def_id = tcx.hir.local_def_id(node_id);
                     if tcx.is_statically_included_foreign_item(def_id) {
                         Some(def_id)
@@ -104,14 +105,14 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 }
 
                 // Only consider nodes that actually have exported symbols.
-                hir::map::NodeItem(&hir::Item {
+                Node::Item(&hir::Item {
                     node: hir::ItemKind::Static(..),
                     ..
                 }) |
-                hir::map::NodeItem(&hir::Item {
+                Node::Item(&hir::Item {
                     node: hir::ItemKind::Fn(..), ..
                 }) |
-                hir::map::NodeImplItem(&hir::ImplItem {
+                Node::ImplItem(&hir::ImplItem {
                     node: hir::ImplItemKind::Method(..),
                     ..
                 }) => {
index 462a2c9f0286335fd14cb0b3be265df25b765cd2..2373428d68c0d64be518e5cccd91c154770c46f6 100644 (file)
 use consts;
 use rustc_incremental::{copy_cgu_workproducts_to_incr_comp_cache_dir, in_incr_comp_dir};
 use rustc::dep_graph::{WorkProduct, WorkProductId, WorkProductFileKind};
-use rustc::middle::cstore::{LinkMeta, EncodedMetadata};
+use rustc::middle::cstore::EncodedMetadata;
 use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Sanitizer, Lto};
 use rustc::session::Session;
 use rustc::util::nodemap::FxHashMap;
 use time_graph::{self, TimeGraph, Timeline};
 use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic};
+use llvm_util;
 use {CodegenResults, ModuleSource, ModuleCodegen, CompiledModule, ModuleKind};
 use CrateInfo;
 use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
@@ -32,6 +33,7 @@
 use rustc::util::common::{time_ext, time_depth, set_time_depth, print_time_passes_entry};
 use rustc_fs_util::{path2cstr, link_or_copy};
 use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_data_structures::svh::Svh;
 use errors::{self, Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId};
 use errors::emitter::{Emitter};
 use syntax::attr;
@@ -172,7 +174,7 @@ pub fn target_machine_factory(sess: &Session, find_features: bool)
     let singlethread = sess.target.target.options.singlethread;
 
     let triple = SmallCStr::new(&sess.target.target.llvm_target);
-    let cpu = SmallCStr::new(sess.target_cpu());
+    let cpu = SmallCStr::new(llvm_util::target_cpu(sess));
     let features = attributes::llvm_target_features(sess)
         .collect::<Vec<_>>()
         .join(",");
@@ -327,7 +329,7 @@ struct AssemblerCommand {
 /// Additional resources used by optimize_and_codegen (not module specific)
 #[derive(Clone)]
 pub struct CodegenContext {
-    // Resouces needed when running LTO
+    // Resources needed when running LTO
     pub time_passes: bool,
     pub lto: Lto,
     pub no_landing_pads: bool,
@@ -595,7 +597,7 @@ unsafe fn optimize(cgcx: &CodegenContext,
                                      -C passes=name-anon-globals to the compiler command line.");
                 } else {
                     bug!("We are using thin LTO buffers without running the NameAnonGlobals pass. \
-                         This will likely cause errors in LLVM and shoud never happen.");
+                         This will likely cause errors in LLVM and should never happen.");
                 }
             }
         }
@@ -912,13 +914,13 @@ fn need_crate_bitcode_for_rlib(sess: &Session) -> bool {
 
 pub fn start_async_codegen(tcx: TyCtxt,
                                time_graph: Option<TimeGraph>,
-                               link: LinkMeta,
                                metadata: EncodedMetadata,
                                coordinator_receive: Receiver<Box<dyn Any + Send>>,
                                total_cgus: usize)
                                -> OngoingCodegen {
     let sess = tcx.sess;
     let crate_name = tcx.crate_name(LOCAL_CRATE);
+    let crate_hash = tcx.crate_hash(LOCAL_CRATE);
     let no_builtins = attr::contains_name(&tcx.hir.krate().attrs, "no_builtins");
     let subsystem = attr::first_attr_value_str_by_name(&tcx.hir.krate().attrs,
                                                        "windows_subsystem");
@@ -1037,7 +1039,7 @@ pub fn start_async_codegen(tcx: TyCtxt,
 
     OngoingCodegen {
         crate_name,
-        link,
+        crate_hash,
         metadata,
         windows_subsystem,
         linker_info,
@@ -2270,7 +2272,7 @@ pub fn check(&self, sess: &Session, blocking: bool) {
 
 pub struct OngoingCodegen {
     crate_name: Symbol,
-    link: LinkMeta,
+    crate_hash: Svh,
     metadata: EncodedMetadata,
     windows_subsystem: Option<String>,
     linker_info: LinkerInfo,
@@ -2321,7 +2323,7 @@ pub(crate) fn join(
 
         (CodegenResults {
             crate_name: self.crate_name,
-            link: self.link,
+            crate_hash: self.crate_hash,
             metadata: self.metadata,
             windows_subsystem: self.windows_subsystem,
             linker_info: self.linker_info,
index 0330a0598268ce842c4076c5b92fa83e6c8a3c8d..009c6da9d8d15a35f0bf60cbf96cb09834940e52 100644 (file)
@@ -29,7 +29,6 @@
 use super::ModuleKind;
 
 use abi;
-use back::link;
 use back::write::{self, OngoingCodegen};
 use llvm::{self, TypeKind, get_param};
 use metadata;
@@ -42,7 +41,7 @@
 use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
 use rustc::ty::query::Providers;
 use rustc::dep_graph::{DepNode, DepConstructor};
-use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
+use rustc::middle::cstore::{self, LinkagePreference};
 use rustc::middle::exported_symbols;
 use rustc::util::common::{time, print_time_passes_entry};
 use rustc::util::profiling::ProfileCategory;
@@ -167,12 +166,12 @@ pub fn compare_simd_types(
     op: hir::BinOpKind
 ) -> &'ll Value {
     let signed = match t.sty {
-        ty::TyFloat(_) => {
+        ty::Float(_) => {
             let cmp = bin_op_to_fcmp_predicate(op);
             return bx.sext(bx.fcmp(cmp, lhs, rhs), ret_ty);
         },
-        ty::TyUint(_) => false,
-        ty::TyInt(_) => true,
+        ty::Uint(_) => false,
+        ty::Int(_) => true,
         _ => bug!("compare_simd_types: invalid SIMD type"),
     };
 
@@ -198,16 +197,16 @@ pub fn unsized_info(
 ) -> &'ll Value {
     let (source, target) = cx.tcx.struct_lockstep_tails(source, target);
     match (&source.sty, &target.sty) {
-        (&ty::TyArray(_, len), &ty::TySlice(_)) => {
+        (&ty::Array(_, len), &ty::Slice(_)) => {
             C_usize(cx, len.unwrap_usize(cx.tcx))
         }
-        (&ty::TyDynamic(..), &ty::TyDynamic(..)) => {
+        (&ty::Dynamic(..), &ty::Dynamic(..)) => {
             // For now, upcasts are limited to changes in marker
             // traits, and hence never actually require an actual
             // change to the vtable.
             old_info.expect("unsized_info: missing old info for trait upcast")
         }
-        (_, &ty::TyDynamic(ref data, ..)) => {
+        (_, &ty::Dynamic(ref data, ..)) => {
             let vtable_ptr = cx.layout_of(cx.tcx.mk_mut_ptr(target))
                 .field(cx, abi::FAT_PTR_EXTRA);
             consts::ptrcast(meth::get_vtable(cx, source, data.principal()),
@@ -228,23 +227,23 @@ pub fn unsize_thin_ptr(
 ) -> (&'ll Value, &'ll Value) {
     debug!("unsize_thin_ptr: {:?} => {:?}", src_ty, dst_ty);
     match (&src_ty.sty, &dst_ty.sty) {
-        (&ty::TyRef(_, a, _),
-         &ty::TyRef(_, b, _)) |
-        (&ty::TyRef(_, a, _),
-         &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) |
-        (&ty::TyRawPtr(ty::TypeAndMut { ty: a, .. }),
-         &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) => {
+        (&ty::Ref(_, a, _),
+         &ty::Ref(_, b, _)) |
+        (&ty::Ref(_, a, _),
+         &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) |
+        (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }),
+         &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
             assert!(bx.cx.type_is_sized(a));
             let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to();
             (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None))
         }
-        (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
+        (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
             let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty());
             assert!(bx.cx.type_is_sized(a));
             let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to();
             (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None))
         }
-        (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => {
+        (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
             assert_eq!(def_a, def_b);
 
             let src_layout = bx.cx.layout_of(src_ty);
@@ -300,16 +299,16 @@ pub fn coerce_unsized_into(
         OperandValue::Pair(base, info).store(bx, dst);
     };
     match (&src_ty.sty, &dst_ty.sty) {
-        (&ty::TyRef(..), &ty::TyRef(..)) |
-        (&ty::TyRef(..), &ty::TyRawPtr(..)) |
-        (&ty::TyRawPtr(..), &ty::TyRawPtr(..)) => {
+        (&ty::Ref(..), &ty::Ref(..)) |
+        (&ty::Ref(..), &ty::RawPtr(..)) |
+        (&ty::RawPtr(..), &ty::RawPtr(..)) => {
             coerce_ptr()
         }
-        (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
+        (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
             coerce_ptr()
         }
 
-        (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => {
+        (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
             assert_eq!(def_a, def_b);
 
             for i in 0..def_a.variants[0].fields.len() {
@@ -608,8 +607,7 @@ fn create_entry_fn(
 }
 
 fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
-                            llvm_module: &ModuleLlvm,
-                            link_meta: &LinkMeta)
+                            llvm_module: &ModuleLlvm)
                             -> EncodedMetadata {
     use std::io::Write;
     use flate2::Compression;
@@ -641,7 +639,7 @@ enum MetadataKind {
         return EncodedMetadata::new();
     }
 
-    let metadata = tcx.encode_metadata(link_meta);
+    let metadata = tcx.encode_metadata();
     if kind == MetadataKind::Uncompressed {
         return metadata;
     }
@@ -719,8 +717,6 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         tcx.sess.fatal("this compiler's LLVM does not support PGO");
     }
 
-    let crate_hash = tcx.crate_hash(LOCAL_CRATE);
-    let link_meta = link::build_link_meta(crate_hash);
     let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
 
     // Codegen the metadata.
@@ -732,7 +728,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                                              .to_string();
     let metadata_llvm_module = ModuleLlvm::new(tcx.sess, &metadata_cgu_name);
     let metadata = time(tcx.sess, "write metadata", || {
-        write_metadata(tcx, &metadata_llvm_module, &link_meta)
+        write_metadata(tcx, &metadata_llvm_module)
     });
     tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen));
 
@@ -754,7 +750,6 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let ongoing_codegen = write::start_async_codegen(
             tcx,
             time_graph.clone(),
-            link_meta,
             metadata,
             rx,
             1);
@@ -789,7 +784,6 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let ongoing_codegen = write::start_async_codegen(
         tcx,
         time_graph.clone(),
-        link_meta,
         metadata,
         rx,
         codegen_units.len());
index 51fc610408b5213538dc7f2ce8c6fa5aa6df8ff5..53bb02ddd99d947887ad4a555fb4330114df511e 100644 (file)
@@ -413,10 +413,10 @@ pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                            -> ty::PolyFnSig<'tcx>
 {
     match ty.sty {
-        ty::TyFnDef(..) |
-        // Shims currently have type TyFnPtr. Not sure this should remain.
-        ty::TyFnPtr(_) => ty.fn_sig(cx.tcx),
-        ty::TyClosure(def_id, substs) => {
+        ty::FnDef(..) |
+        // Shims currently have type FnPtr. Not sure this should remain.
+        ty::FnPtr(_) => ty.fn_sig(cx.tcx),
+        ty::Closure(def_id, substs) => {
             let tcx = cx.tcx;
             let sig = substs.closure_sig(def_id, tcx);
 
@@ -429,7 +429,7 @@ pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 sig.abi
             ))
         }
-        ty::TyGenerator(def_id, substs, _) => {
+        ty::Generator(def_id, substs, _) => {
             let tcx = cx.tcx;
             let sig = substs.poly_sig(def_id, cx.tcx);
 
index 770a22ad65842e0916ec185709828ea86d9efaa5..522de2f15e0a95806b15fc2f3023b54a9ae3ed4b 100644 (file)
@@ -11,7 +11,7 @@
 use libc::c_uint;
 use llvm::{self, SetUnnamedAddr, True};
 use rustc::hir::def_id::DefId;
-use rustc::hir::map as hir_map;
+use rustc::hir::Node;
 use debuginfo;
 use base;
 use monomorphize::MonoItem;
@@ -135,7 +135,7 @@ pub fn get_static(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll Value {
 
         let llty = cx.layout_of(ty).llvm_type(cx);
         let (g, attrs) = match cx.tcx.hir.get(id) {
-            hir_map::NodeItem(&hir::Item {
+            Node::Item(&hir::Item {
                 ref attrs, span, node: hir::ItemKind::Static(..), ..
             }) => {
                 if declare::get_declared_value(cx, &sym[..]).is_some() {
@@ -153,7 +153,7 @@ pub fn get_static(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll Value {
                 (g, attrs)
             }
 
-            hir_map::NodeForeignItem(&hir::ForeignItem {
+            Node::ForeignItem(&hir::ForeignItem {
                 ref attrs, span, node: hir::ForeignItemKind::Static(..), ..
             }) => {
                 let fn_attrs = cx.tcx.codegen_fn_attrs(def_id);
@@ -250,7 +250,7 @@ fn check_and_apply_linkage(
         // static and call it a day. Some linkages (like weak) will make it such
         // that the static actually has a null value.
         let llty2 = match ty.sty {
-            ty::TyRawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx),
+            ty::RawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx),
             _ => {
                 if span.is_some() {
                     cx.sess().span_fatal(span.unwrap(), "must have type `*const T` or `*mut T`")
index 32ea2c5eb8f354484150233a01af17b36ce900ba..9547f4a190e7896d721cda285efb8217b05fc674 100644 (file)
@@ -434,8 +434,8 @@ pub fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
 
         let tail = self.tcx.struct_tail(ty);
         match tail.sty {
-            ty::TyForeign(..) => false,
-            ty::TyStr | ty::TySlice(..) | ty::TyDynamic(..) => true,
+            ty::Foreign(..) => false,
+            ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
             _ => bug!("unexpected unsized tail: {:?}", tail.sty),
         }
     }
index cac2ae0302e3ed72116de1030ef8d9d7409fa103..0221cfd9b2c28c3601eea39627cf22260f52b3e3 100644 (file)
@@ -309,7 +309,7 @@ fn fixed_vec_metadata(
     let (size, align) = cx.size_and_align_of(array_or_slice_type);
 
     let upper_bound = match array_or_slice_type.sty {
-        ty::TyArray(_, len) => {
+        ty::Array(_, len) => {
             len.unwrap_usize(cx.tcx) as c_longlong
         }
         _ => -1
@@ -396,7 +396,7 @@ fn subroutine_type_metadata(
     let signature_metadata: Vec<_> = iter::once(
         // return type
         match signature.output().sty {
-            ty::TyTuple(ref tys) if tys.is_empty() => None,
+            ty::Tuple(ref tys) if tys.is_empty() => None,
             _ => Some(type_metadata(cx, signature.output(), span))
         }
     ).chain(
@@ -435,7 +435,7 @@ fn trait_pointer_metadata(
     // But it does not describe the trait's methods.
 
     let containing_scope = match trait_type.sty {
-        ty::TyDynamic(ref data, ..) => if let Some(principal) = data.principal() {
+        ty::Dynamic(ref data, ..) => if let Some(principal) = data.principal() {
             let def_id = principal.def_id();
             Some(get_namespace_for_item(cx, def_id))
         } else {
@@ -534,13 +534,13 @@ pub fn type_metadata(
 
     let ptr_metadata = |ty: Ty<'tcx>| {
         match ty.sty {
-            ty::TySlice(typ) => {
+            ty::Slice(typ) => {
                 Ok(vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span))
             }
-            ty::TyStr => {
+            ty::Str => {
                 Ok(vec_slice_metadata(cx, t, cx.tcx.types.u8, unique_type_id, usage_site_span))
             }
-            ty::TyDynamic(..) => {
+            ty::Dynamic(..) => {
                 Ok(MetadataCreationResult::new(
                     trait_pointer_metadata(cx, ty, Some(t), unique_type_id),
                     false))
@@ -562,48 +562,48 @@ pub fn type_metadata(
     };
 
     let MetadataCreationResult { metadata, already_stored_in_typemap } = match t.sty {
-        ty::TyNever    |
-        ty::TyBool     |
-        ty::TyChar     |
-        ty::TyInt(_)   |
-        ty::TyUint(_)  |
-        ty::TyFloat(_) => {
+        ty::Never    |
+        ty::Bool     |
+        ty::Char     |
+        ty::Int(_)   |
+        ty::Uint(_)  |
+        ty::Float(_) => {
             MetadataCreationResult::new(basic_type_metadata(cx, t), false)
         }
-        ty::TyTuple(ref elements) if elements.is_empty() => {
+        ty::Tuple(ref elements) if elements.is_empty() => {
             MetadataCreationResult::new(basic_type_metadata(cx, t), false)
         }
-        ty::TyArray(typ, _) |
-        ty::TySlice(typ) => {
+        ty::Array(typ, _) |
+        ty::Slice(typ) => {
             fixed_vec_metadata(cx, unique_type_id, t, typ, usage_site_span)
         }
-        ty::TyStr => {
+        ty::Str => {
             fixed_vec_metadata(cx, unique_type_id, t, cx.tcx.types.i8, usage_site_span)
         }
-        ty::TyDynamic(..) => {
+        ty::Dynamic(..) => {
             MetadataCreationResult::new(
                         trait_pointer_metadata(cx, t, None, unique_type_id),
             false)
         }
-        ty::TyForeign(..) => {
+        ty::Foreign(..) => {
             MetadataCreationResult::new(
                         foreign_type_metadata(cx, t, unique_type_id),
             false)
         }
-        ty::TyRawPtr(ty::TypeAndMut{ty, ..}) |
-        ty::TyRef(_, ty, _) => {
+        ty::RawPtr(ty::TypeAndMut{ty, ..}) |
+        ty::Ref(_, ty, _) => {
             match ptr_metadata(ty) {
                 Ok(res) => res,
                 Err(metadata) => return metadata,
             }
         }
-        ty::TyAdt(def, _) if def.is_box() => {
+        ty::Adt(def, _) if def.is_box() => {
             match ptr_metadata(t.boxed_ty()) {
                 Ok(res) => res,
                 Err(metadata) => return metadata,
             }
         }
-        ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+        ty::FnDef(..) | ty::FnPtr(_) => {
             let fn_metadata = subroutine_type_metadata(cx,
                                                        unique_type_id,
                                                        t.fn_sig(cx.tcx),
@@ -619,7 +619,7 @@ pub fn type_metadata(
             MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false)
 
         }
-        ty::TyClosure(def_id, substs) => {
+        ty::Closure(def_id, substs) => {
             let upvar_tys : Vec<_> = substs.upvar_tys(def_id, cx.tcx).collect();
             prepare_tuple_metadata(cx,
                                    t,
@@ -627,7 +627,7 @@ pub fn type_metadata(
                                    unique_type_id,
                                    usage_site_span).finalize(cx)
         }
-        ty::TyGenerator(def_id, substs,  _) => {
+        ty::Generator(def_id, substs,  _) => {
             let upvar_tys : Vec<_> = substs.field_tys(def_id, cx.tcx).map(|t| {
                 cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)
             }).collect();
@@ -637,7 +637,7 @@ pub fn type_metadata(
                                    unique_type_id,
                                    usage_site_span).finalize(cx)
         }
-        ty::TyAdt(def, ..) => match def.adt_kind() {
+        ty::Adt(def, ..) => match def.adt_kind() {
             AdtKind::Struct => {
                 prepare_struct_metadata(cx,
                                         t,
@@ -658,7 +658,7 @@ pub fn type_metadata(
                                     usage_site_span).finalize(cx)
             }
         },
-        ty::TyTuple(ref elements) => {
+        ty::Tuple(ref elements) => {
             prepare_tuple_metadata(cx,
                                    t,
                                    &elements[..],
@@ -765,18 +765,18 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
     debug!("basic_type_metadata: {:?}", t);
 
     let (name, encoding) = match t.sty {
-        ty::TyNever => ("!", DW_ATE_unsigned),
-        ty::TyTuple(ref elements) if elements.is_empty() =>
+        ty::Never => ("!", DW_ATE_unsigned),
+        ty::Tuple(ref elements) if elements.is_empty() =>
             ("()", DW_ATE_unsigned),
-        ty::TyBool => ("bool", DW_ATE_boolean),
-        ty::TyChar => ("char", DW_ATE_unsigned_char),
-        ty::TyInt(int_ty) => {
+        ty::Bool => ("bool", DW_ATE_boolean),
+        ty::Char => ("char", DW_ATE_unsigned_char),
+        ty::Int(int_ty) => {
             (int_ty.ty_to_string(), DW_ATE_signed)
         },
-        ty::TyUint(uint_ty) => {
+        ty::Uint(uint_ty) => {
             (uint_ty.ty_to_string(), DW_ATE_unsigned)
         },
-        ty::TyFloat(float_ty) => {
+        ty::Float(float_ty) => {
             (float_ty.ty_to_string(), DW_ATE_float)
         },
         _ => bug!("debuginfo::basic_type_metadata - t is invalid type")
@@ -1009,7 +1009,7 @@ fn prepare_struct_metadata(
     let struct_name = compute_debuginfo_type_name(cx, struct_type, false);
 
     let (struct_def_id, variant) = match struct_type.sty {
-        ty::TyAdt(def, _) => (def.did, def.non_enum_variant()),
+        ty::Adt(def, _) => (def.did, def.non_enum_variant()),
         _ => bug!("prepare_struct_metadata on a non-ADT")
     };
 
@@ -1126,7 +1126,7 @@ fn prepare_union_metadata(
     let union_name = compute_debuginfo_type_name(cx, union_type, false);
 
     let (union_def_id, variant) = match union_type.sty {
-        ty::TyAdt(def, _) => (def.did, def.non_enum_variant()),
+        ty::Adt(def, _) => (def.did, def.non_enum_variant()),
         _ => bug!("prepare_union_metadata on a non-ADT")
     };
 
@@ -1191,7 +1191,7 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
                                               member_descriptions);
                 vec![
                     MemberDescription {
-                        name: "".to_string(),
+                        name: String::new(),
                         type_metadata: variant_type_metadata,
                         offset: Size::ZERO,
                         size: self.layout.size,
@@ -1220,7 +1220,7 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
                                                   variant_type_metadata,
                                                   member_descriptions);
                     MemberDescription {
-                        name: "".to_string(),
+                        name: String::new(),
                         type_metadata: variant_type_metadata,
                         offset: Size::ZERO,
                         size: variant.size,
@@ -1359,6 +1359,7 @@ fn describe_enum_variant(
     // If this is not a univariant enum, there is also the discriminant field.
     let (discr_offset, discr_arg) = match discriminant_info {
         RegularDiscriminant(_) => {
+            // We have the layout of an enum variant, we need the layout of the outer enum
             let enum_layout = cx.layout_of(layout.ty);
             (Some(enum_layout.fields.offset(0)),
              Some(("RUST$ENUM$DISR".to_string(), enum_layout.field(cx, 0).ty)))
index fcb8bc3fe2b21dc8e2f93625f7c06f4947db4b63..99919a940b40511dcd605cea460440d5a1a9e05a 100644 (file)
@@ -323,7 +323,7 @@ fn get_function_signature(
 
         // Return type -- llvm::DIBuilder wants this at index 0
         signature.push(match sig.output().sty {
-            ty::TyTuple(ref tys) if tys.is_empty() => None,
+            ty::Tuple(ref tys) if tys.is_empty() => None,
             _ => Some(type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP))
         });
 
@@ -347,7 +347,7 @@ fn get_function_signature(
             // already inaccurate due to ABI adjustments (see #42800).
             signature.extend(inputs.iter().map(|&t| {
                 let t = match t.sty {
-                    ty::TyArray(ct, _)
+                    ty::Array(ct, _)
                         if (ct == cx.tcx.types.u8) || cx.layout_of(ct).is_zst() => {
                         cx.tcx.mk_imm_ptr(ct)
                     }
@@ -362,7 +362,7 @@ fn get_function_signature(
         }
 
         if sig.abi == Abi::RustCall && !sig.inputs().is_empty() {
-            if let ty::TyTuple(args) = sig.inputs()[sig.inputs().len() - 1].sty {
+            if let ty::Tuple(args) = sig.inputs()[sig.inputs().len() - 1].sty {
                 signature.extend(
                     args.iter().map(|argument_type| {
                         Some(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP))
@@ -460,7 +460,7 @@ fn get_containing_scope(
                 // Only "class" methods are generally understood by LLVM,
                 // so avoid methods on other types (e.g. `<*mut T>::null`).
                 match impl_self_ty.sty {
-                    ty::TyAdt(def, ..) if !def.is_box() => {
+                    ty::Adt(def, ..) if !def.is_box() => {
                         Some(type_metadata(cx, impl_self_ty, syntax_pos::DUMMY_SP))
                     }
                     _ => None
index 05a74db3a6ca9842470d51991fc589dc5998c88a..a08b964cd721d6b1d3a6ec7fe95f7850e0416fd3 100644 (file)
@@ -41,19 +41,19 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     let cpp_like_names = cx.sess().target.target.options.is_like_msvc;
 
     match t.sty {
-        ty::TyBool => output.push_str("bool"),
-        ty::TyChar => output.push_str("char"),
-        ty::TyStr => output.push_str("str"),
-        ty::TyNever => output.push_str("!"),
-        ty::TyInt(int_ty) => output.push_str(int_ty.ty_to_string()),
-        ty::TyUint(uint_ty) => output.push_str(uint_ty.ty_to_string()),
-        ty::TyFloat(float_ty) => output.push_str(float_ty.ty_to_string()),
-        ty::TyForeign(def_id) => push_item_name(cx, def_id, qualified, output),
-        ty::TyAdt(def, substs) => {
+        ty::Bool => output.push_str("bool"),
+        ty::Char => output.push_str("char"),
+        ty::Str => output.push_str("str"),
+        ty::Never => output.push_str("!"),
+        ty::Int(int_ty) => output.push_str(int_ty.ty_to_string()),
+        ty::Uint(uint_ty) => output.push_str(uint_ty.ty_to_string()),
+        ty::Float(float_ty) => output.push_str(float_ty.ty_to_string()),
+        ty::Foreign(def_id) => push_item_name(cx, def_id, qualified, output),
+        ty::Adt(def, substs) => {
             push_item_name(cx, def.did, qualified, output);
             push_type_params(cx, substs, output);
         },
-        ty::TyTuple(component_types) => {
+        ty::Tuple(component_types) => {
             output.push('(');
             for &component_type in component_types {
                 push_debuginfo_type_name(cx, component_type, true, output);
@@ -65,7 +65,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             }
             output.push(')');
         },
-        ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
+        ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
             if !cpp_like_names {
                 output.push('*');
             }
@@ -80,7 +80,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 output.push('*');
             }
         },
-        ty::TyRef(_, inner_type, mutbl) => {
+        ty::Ref(_, inner_type, mutbl) => {
             if !cpp_like_names {
                 output.push('&');
             }
@@ -94,13 +94,13 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 output.push('*');
             }
         },
-        ty::TyArray(inner_type, len) => {
+        ty::Array(inner_type, len) => {
             output.push('[');
             push_debuginfo_type_name(cx, inner_type, true, output);
             output.push_str(&format!("; {}", len.unwrap_usize(cx.tcx)));
             output.push(']');
         },
-        ty::TySlice(inner_type) => {
+        ty::Slice(inner_type) => {
             if cpp_like_names {
                 output.push_str("slice<");
             } else {
@@ -115,7 +115,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 output.push(']');
             }
         },
-        ty::TyDynamic(ref trait_data, ..) => {
+        ty::Dynamic(ref trait_data, ..) => {
             if let Some(principal) = trait_data.principal() {
                 let principal = cx.tcx.normalize_erasing_late_bound_regions(
                     ty::ParamEnv::reveal_all(),
@@ -125,7 +125,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 push_type_params(cx, principal.substs, output);
             }
         },
-        ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+        ty::FnDef(..) | ty::FnPtr(_) => {
             let sig = t.fn_sig(cx.tcx);
             if sig.unsafety() == hir::Unsafety::Unsafe {
                 output.push_str("unsafe ");
@@ -165,18 +165,18 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 push_debuginfo_type_name(cx, sig.output(), true, output);
             }
         },
-        ty::TyClosure(..) => {
+        ty::Closure(..) => {
             output.push_str("closure");
         }
-        ty::TyGenerator(..) => {
+        ty::Generator(..) => {
             output.push_str("generator");
         }
-        ty::TyError |
-        ty::TyInfer(_) |
-        ty::TyProjection(..) |
-        ty::TyAnon(..) |
-        ty::TyGeneratorWitness(..) |
-        ty::TyParam(_) => {
+        ty::Error |
+        ty::Infer(_) |
+        ty::Projection(..) |
+        ty::Anon(..) |
+        ty::GeneratorWitness(..) |
+        ty::Param(_) => {
             bug!("debuginfo: Trying to create type name for \
                 unexpected type: {:?}", t);
         }
index 37ce51da778235f7e58a4a83ef7dcf52c0477126..ff33cec043729eaacffd4a1dddce437e147da263 100644 (file)
@@ -35,12 +35,12 @@ pub fn size_and_align_of_dst(bx: &Builder<'_, 'll, 'tcx>, t: Ty<'tcx>, info: Opt
         return (size, align);
     }
     match t.sty {
-        ty::TyDynamic(..) => {
+        ty::Dynamic(..) => {
             // load size/align from vtable
             let vtable = info.unwrap();
             (meth::SIZE.get_usize(bx, vtable), meth::ALIGN.get_usize(bx, vtable))
         }
-        ty::TySlice(_) | ty::TyStr => {
+        ty::Slice(_) | ty::Str => {
             let unit = t.sequence_element_type(bx.tcx());
             // The info in this case is the length of the str, so the size is that
             // times the unit size.
@@ -81,7 +81,7 @@ pub fn size_and_align_of_dst(bx: &Builder<'_, 'll, 'tcx>, t: Ty<'tcx>, info: Opt
             let size = bx.add(sized_size, unsized_size);
 
             // Packed types ignore the alignment of their fields.
-            if let ty::TyAdt(def, _) = t.sty {
+            if let ty::Adt(def, _) = t.sty {
                 if def.repr.packed() {
                     unsized_align = sized_align;
                 }
index be3e0d9d4b1ed3a6a92d33f7eb7aae27b656397f..5d00e0807991e1d6607571237c0a8e7be911cb70 100644 (file)
@@ -98,7 +98,7 @@ pub fn codegen_intrinsic_call(
     let tcx = cx.tcx;
 
     let (def_id, substs) = match callee_ty.sty {
-        ty::TyFnDef(def_id, substs) => (def_id, substs),
+        ty::FnDef(def_id, substs) => (def_id, substs),
         _ => bug!("expected fn item type, found {}", callee_ty)
     };
 
@@ -1149,7 +1149,7 @@ macro_rules! require_simd {
                  m_len, v_len
         );
         match m_elem_ty.sty {
-            ty::TyInt(_) => {},
+            ty::Int(_) => {},
             _ => {
                 return_error!("mask element type is `{}`, expected `i_`", m_elem_ty);
             }
@@ -1191,7 +1191,7 @@ macro_rules! return_error {
             }
         }
         let ety = match in_elem.sty {
-            ty::TyFloat(f) if f.bit_width() == 32 => {
+            ty::Float(f) if f.bit_width() == 32 => {
                 if in_len < 2 || in_len > 16 {
                     return_error!(
                         "unsupported floating-point vector `{}` with length `{}` \
@@ -1200,7 +1200,7 @@ macro_rules! return_error {
                 }
                 "f32"
             },
-            ty::TyFloat(f) if f.bit_width() == 64 => {
+            ty::Float(f) if f.bit_width() == 64 => {
                 if in_len < 2 || in_len > 8 {
                     return_error!("unsupported floating-point vector `{}` with length `{}` \
                                    out-of-range [2, 8]",
@@ -1208,7 +1208,7 @@ macro_rules! return_error {
                 }
                 "f64"
             },
-            ty::TyFloat(f) => {
+            ty::Float(f) => {
                 return_error!("unsupported element type `{}` of floating-point vector `{}`",
                               f, in_ty);
             },
@@ -1288,9 +1288,9 @@ macro_rules! return_error {
     fn llvm_vector_str(elem_ty: ty::Ty, vec_len: usize, no_pointers: usize) -> String {
         let p0s: String = "p0".repeat(no_pointers);
         match elem_ty.sty {
-            ty::TyInt(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()),
-            ty::TyUint(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()),
-            ty::TyFloat(v) => format!("v{}{}f{}", vec_len, p0s, v.bit_width()),
+            ty::Int(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()),
+            ty::Uint(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()),
+            ty::Float(v) => format!("v{}{}f{}", vec_len, p0s, v.bit_width()),
             _ => unreachable!(),
         }
     }
@@ -1299,9 +1299,9 @@ fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: ty::Ty, vec_len: usize,
                       mut no_pointers: usize) -> &'ll Type {
         // FIXME: use cx.layout_of(ty).llvm_type() ?
         let mut elem_ty = match elem_ty.sty {
-            ty::TyInt(v) => Type::int_from_ty(cx, v),
-            ty::TyUint(v) => Type::uint_from_ty(cx, v),
-            ty::TyFloat(v) => Type::float_from_ty(cx, v),
+            ty::Int(v) => Type::int_from_ty(cx, v),
+            ty::Uint(v) => Type::uint_from_ty(cx, v),
+            ty::Float(v) => Type::float_from_ty(cx, v),
             _ => unreachable!(),
         };
         while no_pointers > 0 {
@@ -1343,7 +1343,7 @@ fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: ty::Ty, vec_len: usize,
         // This counts how many pointers
         fn ptr_count(t: ty::Ty) -> usize {
             match t.sty {
-                ty::TyRawPtr(p) => 1 + ptr_count(p.ty),
+                ty::RawPtr(p) => 1 + ptr_count(p.ty),
                 _ => 0,
             }
         }
@@ -1351,7 +1351,7 @@ fn ptr_count(t: ty::Ty) -> usize {
         // Non-ptr type
         fn non_ptr(t: ty::Ty) -> ty::Ty {
             match t.sty {
-                ty::TyRawPtr(p) => non_ptr(p.ty),
+                ty::RawPtr(p) => non_ptr(p.ty),
                 _ => t,
             }
         }
@@ -1359,7 +1359,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
         // The second argument must be a simd vector with an element type that's a pointer
         // to the element type of the first argument
         let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).sty {
-            ty::TyRawPtr(p) if p.ty == in_elem => (ptr_count(arg_tys[1].simd_type(tcx)),
+            ty::RawPtr(p) if p.ty == in_elem => (ptr_count(arg_tys[1].simd_type(tcx)),
                                                    non_ptr(arg_tys[1].simd_type(tcx))),
             _ => {
                 require!(false, "expected element type `{}` of second argument `{}` \
@@ -1376,7 +1376,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
 
         // The element type of the third argument must be a signed integer type of any width:
         match arg_tys[2].simd_type(tcx).sty {
-            ty::TyInt(_) => (),
+            ty::Int(_) => (),
             _ => {
                 require!(false, "expected element type `{}` of third argument `{}` \
                                  to be a signed integer type",
@@ -1439,7 +1439,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
         // This counts how many pointers
         fn ptr_count(t: ty::Ty) -> usize {
             match t.sty {
-                ty::TyRawPtr(p) => 1 + ptr_count(p.ty),
+                ty::RawPtr(p) => 1 + ptr_count(p.ty),
                 _ => 0,
             }
         }
@@ -1447,7 +1447,7 @@ fn ptr_count(t: ty::Ty) -> usize {
         // Non-ptr type
         fn non_ptr(t: ty::Ty) -> ty::Ty {
             match t.sty {
-                ty::TyRawPtr(p) => non_ptr(p.ty),
+                ty::RawPtr(p) => non_ptr(p.ty),
                 _ => t,
             }
         }
@@ -1455,7 +1455,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
         // The second argument must be a simd vector with an element type that's a pointer
         // to the element type of the first argument
         let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).sty {
-            ty::TyRawPtr(p) if p.ty == in_elem && p.mutbl == hir::MutMutable
+            ty::RawPtr(p) if p.ty == in_elem && p.mutbl == hir::MutMutable
                 => (ptr_count(arg_tys[1].simd_type(tcx)),
                     non_ptr(arg_tys[1].simd_type(tcx))),
             _ => {
@@ -1473,7 +1473,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
 
         // The element type of the third argument must be a signed integer type of any width:
         match arg_tys[2].simd_type(tcx).sty {
-            ty::TyInt(_) => (),
+            ty::Int(_) => (),
             _ => {
                 require!(false, "expected element type `{}` of third argument `{}` \
                                  to be a signed integer type",
@@ -1522,7 +1522,7 @@ macro_rules! arith_red {
                          "expected return type `{}` (element of input `{}`), found `{}`",
                          in_elem, in_ty, ret_ty);
                 return match in_elem.sty {
-                    ty::TyInt(_) | ty::TyUint(_) => {
+                    ty::Int(_) | ty::Uint(_) => {
                         let r = bx.$integer_reduce(args[0].immediate());
                         if $ordered {
                             // if overflow occurs, the result is the
@@ -1536,7 +1536,7 @@ macro_rules! arith_red {
                             Ok(bx.$integer_reduce(args[0].immediate()))
                         }
                     },
-                    ty::TyFloat(f) => {
+                    ty::Float(f) => {
                         // ordered arithmetic reductions take an accumulator
                         let acc = if $ordered {
                             let acc = args[1].immediate();
@@ -1597,13 +1597,13 @@ macro_rules! minmax_red {
                          "expected return type `{}` (element of input `{}`), found `{}`",
                          in_elem, in_ty, ret_ty);
                 return match in_elem.sty {
-                    ty::TyInt(_i) => {
+                    ty::Int(_i) => {
                         Ok(bx.$int_red(args[0].immediate(), true))
                     },
-                    ty::TyUint(_u) => {
+                    ty::Uint(_u) => {
                         Ok(bx.$int_red(args[0].immediate(), false))
                     },
-                    ty::TyFloat(_f) => {
+                    ty::Float(_f) => {
                         Ok(bx.$float_red(args[0].immediate()))
                     }
                     _ => {
@@ -1632,7 +1632,7 @@ macro_rules! bitwise_red {
                     args[0].immediate()
                 } else {
                     match in_elem.sty {
-                        ty::TyInt(_) | ty::TyUint(_) => {},
+                        ty::Int(_) | ty::Uint(_) => {},
                         _ => {
                             return_error!("unsupported {} from `{}` with element `{}` to `{}`",
                                           $name, in_ty, in_elem, ret_ty)
@@ -1645,7 +1645,7 @@ macro_rules! bitwise_red {
                     bx.trunc(args[0].immediate(), i1xn)
                 };
                 return match in_elem.sty {
-                    ty::TyInt(_) | ty::TyUint(_) => {
+                    ty::Int(_) | ty::Uint(_) => {
                         let r = bx.$red(input);
                         Ok(
                             if !$boolean {
@@ -1688,15 +1688,15 @@ enum Style { Float, Int(/* is signed? */ bool), Unsupported }
         let (in_style, in_width) = match in_elem.sty {
             // vectors of pointer-sized integers should've been
             // disallowed before here, so this unwrap is safe.
-            ty::TyInt(i) => (Style::Int(true), i.bit_width().unwrap()),
-            ty::TyUint(u) => (Style::Int(false), u.bit_width().unwrap()),
-            ty::TyFloat(f) => (Style::Float, f.bit_width()),
+            ty::Int(i) => (Style::Int(true), i.bit_width().unwrap()),
+            ty::Uint(u) => (Style::Int(false), u.bit_width().unwrap()),
+            ty::Float(f) => (Style::Float, f.bit_width()),
             _ => (Style::Unsupported, 0)
         };
         let (out_style, out_width) = match out_elem.sty {
-            ty::TyInt(i) => (Style::Int(true), i.bit_width().unwrap()),
-            ty::TyUint(u) => (Style::Int(false), u.bit_width().unwrap()),
-            ty::TyFloat(f) => (Style::Float, f.bit_width()),
+            ty::Int(i) => (Style::Int(true), i.bit_width().unwrap()),
+            ty::Uint(u) => (Style::Int(false), u.bit_width().unwrap()),
+            ty::Float(f) => (Style::Float, f.bit_width()),
             _ => (Style::Unsupported, 0)
         };
 
@@ -1757,18 +1757,18 @@ macro_rules! arith {
         }
     }
     arith! {
-        simd_add: TyUint, TyInt => add, TyFloat => fadd;
-        simd_sub: TyUint, TyInt => sub, TyFloat => fsub;
-        simd_mul: TyUint, TyInt => mul, TyFloat => fmul;
-        simd_div: TyUint => udiv, TyInt => sdiv, TyFloat => fdiv;
-        simd_rem: TyUint => urem, TyInt => srem, TyFloat => frem;
-        simd_shl: TyUint, TyInt => shl;
-        simd_shr: TyUint => lshr, TyInt => ashr;
-        simd_and: TyUint, TyInt => and;
-        simd_or: TyUint, TyInt => or;
-        simd_xor: TyUint, TyInt => xor;
-        simd_fmax: TyFloat => maxnum;
-        simd_fmin: TyFloat => minnum;
+        simd_add: Uint, Int => add, Float => fadd;
+        simd_sub: Uint, Int => sub, Float => fsub;
+        simd_mul: Uint, Int => mul, Float => fmul;
+        simd_div: Uint => udiv, Int => sdiv, Float => fdiv;
+        simd_rem: Uint => urem, Int => srem, Float => frem;
+        simd_shl: Uint, Int => shl;
+        simd_shr: Uint => lshr, Int => ashr;
+        simd_and: Uint, Int => and;
+        simd_or: Uint, Int => or;
+        simd_xor: Uint, Int => xor;
+        simd_fmax: Float => maxnum;
+        simd_fmin: Float => minnum;
     }
     span_bug!(span, "unknown SIMD intrinsic");
 }
@@ -1779,7 +1779,7 @@ macro_rules! arith {
 // stuffs.
 fn int_type_width_signed(ty: Ty, cx: &CodegenCx) -> Option<(u64, bool)> {
     match ty.sty {
-        ty::TyInt(t) => Some((match t {
+        ty::Int(t) => Some((match t {
             ast::IntTy::Isize => cx.tcx.sess.target.isize_ty.bit_width().unwrap() as u64,
             ast::IntTy::I8 => 8,
             ast::IntTy::I16 => 16,
@@ -1787,7 +1787,7 @@ fn int_type_width_signed(ty: Ty, cx: &CodegenCx) -> Option<(u64, bool)> {
             ast::IntTy::I64 => 64,
             ast::IntTy::I128 => 128,
         }, true)),
-        ty::TyUint(t) => Some((match t {
+        ty::Uint(t) => Some((match t {
             ast::UintTy::Usize => cx.tcx.sess.target.usize_ty.bit_width().unwrap() as u64,
             ast::UintTy::U8 => 8,
             ast::UintTy::U16 => 16,
@@ -1801,9 +1801,9 @@ fn int_type_width_signed(ty: Ty, cx: &CodegenCx) -> Option<(u64, bool)> {
 
 // Returns the width of a float TypeVariant
 // Returns None if the type is not a float
-fn float_type_width<'tcx>(sty: &ty::TypeVariants<'tcx>) -> Option<u64> {
+fn float_type_width<'tcx>(sty: &ty::TyKind<'tcx>) -> Option<u64> {
     match *sty {
-        ty::TyFloat(t) => Some(t.bit_width() as u64),
+        ty::Float(t) => Some(t.bit_width() as u64),
         _ => None,
     }
 }
index a65511a24af727413a9b7a26835513da7c2be97d..31eeb5633fba9c020c4b49860ec900606f11caa0 100644 (file)
@@ -27,6 +27,7 @@
 #![allow(unused_attributes)]
 #![feature(libc)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(quote)]
 #![feature(range_contains)]
 #![feature(rustc_diagnostic_macros)]
@@ -88,6 +89,7 @@
 use rustc::util::profiling::ProfileCategory;
 use rustc_mir::monomorphize;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
+use rustc_data_structures::svh::Svh;
 
 mod diagnostics;
 
@@ -251,7 +253,7 @@ fn join_codegen_and_link(
 
         // Now that we won't touch anything in the incremental compilation directory
         // any more, we can finalize it (which involves renaming it)
-        rustc_incremental::finalize_session_directory(sess, ongoing_codegen.link.crate_hash);
+        rustc_incremental::finalize_session_directory(sess, ongoing_codegen.crate_hash);
 
         Ok(())
     }
@@ -389,7 +391,7 @@ struct CodegenResults {
     modules: Vec<CompiledModule>,
     allocator_module: Option<CompiledModule>,
     metadata_module: CompiledModule,
-    link: rustc::middle::cstore::LinkMeta,
+    crate_hash: Svh,
     metadata: rustc::middle::cstore::EncodedMetadata,
     windows_subsystem: Option<String>,
     linker_info: back::linker::LinkerInfo,
index d3039a05b6db84d070e8eed5f7ce4ba2a6c608f8..51b0299e63f46c57eff8199809d3595ccb963716 100644 (file)
@@ -1449,6 +1449,7 @@ pub fn LLVMRustDIBuilderCreateDebugLocation(Context: &'a Context,
     pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine);
     pub fn LLVMRustPrintTargetFeatures(T: &TargetMachine);
 
+    pub fn LLVMRustGetHostCPUName(len: *mut usize) -> *const c_char;
     pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
                                        CPU: *const c_char,
                                        Features: *const c_char,
index ff26e0f35f00f085bdc595522e3169fef4c55ff4..9fcc33d82cfa4d1ea751db891308dc3680eda081 100644 (file)
@@ -17,6 +17,8 @@
 use std::ffi::CString;
 use syntax::feature_gate::UnstableFeatures;
 
+use std::str;
+use std::slice;
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::Once;
 
@@ -262,3 +264,19 @@ pub(crate) fn print(req: PrintRequest, sess: &Session) {
         }
     }
 }
+
+pub fn target_cpu(sess: &Session) -> &str {
+    let name = match sess.opts.cg.target_cpu {
+        Some(ref s) => &**s,
+        None => &*sess.target.target.options.cpu
+    };
+    if name != "native" {
+        return name
+    }
+
+    unsafe {
+        let mut len = 0;
+        let ptr = llvm::LLVMRustGetHostCPUName(&mut len);
+        str::from_utf8(slice::from_raw_parts(ptr as *const u8, len)).unwrap()
+    }
+}
index 993138aee1cec90e9560c9a5859baec62c96f3bf..0206744eb2b6b2daabc4f60f67cdb95a99d4f51f 100644 (file)
@@ -131,7 +131,7 @@ fn visit_terminator_kind(&mut self,
                 func: mir::Operand::Constant(ref c),
                 ref args, ..
             } => match c.ty.sty {
-                ty::TyFnDef(did, _) => Some((did, args)),
+                ty::FnDef(did, _) => Some((did, args)),
                 _ => None,
             },
             _ => None,
index 1104408c1c8d76f0a4041685f3623d8050a23bb6..a534b4e478fb793e4f96496e4621287c25eb0a24 100644 (file)
@@ -296,7 +296,7 @@ fn codegen_terminator(&mut self,
                     &args1[..]
                 };
                 let (drop_fn, fn_ty) = match ty.sty {
-                    ty::TyDynamic(..) => {
+                    ty::Dynamic(..) => {
                         let fn_ty = drop_fn.ty(bx.cx.tcx);
                         let sig = common::ty_fn_sig(bx.cx, fn_ty);
                         let sig = bx.tcx().normalize_erasing_late_bound_regions(
@@ -417,14 +417,14 @@ fn codegen_terminator(&mut self,
                 let callee = self.codegen_operand(&bx, func);
 
                 let (instance, mut llfn) = match callee.layout.ty.sty {
-                    ty::TyFnDef(def_id, substs) => {
+                    ty::FnDef(def_id, substs) => {
                         (Some(ty::Instance::resolve(bx.cx.tcx,
                                                     ty::ParamEnv::reveal_all(),
                                                     def_id,
                                                     substs).unwrap()),
                          None)
                     }
-                    ty::TyFnPtr(_) => {
+                    ty::FnPtr(_) => {
                         (None, Some(callee.immediate()))
                     }
                     _ => bug!("{} is not callable", callee.layout.ty)
@@ -656,7 +656,7 @@ fn codegen_argument(&mut self,
                     llargs.push(b);
                     return;
                 }
-                _ => bug!("codegen_argument: {:?} invalid for pair arugment", op)
+                _ => bug!("codegen_argument: {:?} invalid for pair argument", op)
             }
         } else if arg.is_unsized_indirect() {
             match op.val {
index 47fd92682fdc4b8787f13621815cb0c26d8bff30..b6c9658dd6fc36f67fe5c0cef76e43d7464c4a62 100644 (file)
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 use llvm;
-use rustc::mir::interpret::ConstEvalErr;
-use rustc_mir::interpret::{read_target_uint, const_val_field};
+use rustc::mir::interpret::{ConstEvalErr, read_target_uint};
+use rustc_mir::interpret::{const_field};
 use rustc::hir::def_id::DefId;
 use rustc::mir;
 use rustc_data_structures::indexed_vec::Idx;
@@ -57,7 +57,7 @@ pub fn scalar_to_llvm(
             let base_addr = match alloc_type {
                 Some(AllocType::Memory(alloc)) => {
                     let init = const_alloc_to_llvm(cx, alloc);
-                    if alloc.runtime_mutability == Mutability::Mutable {
+                    if alloc.mutability == Mutability::Mutable {
                         consts::addr_of_mut(cx, init, alloc.align, None)
                     } else {
                         consts::addr_of(cx, init, alloc.align, None)
@@ -134,7 +134,7 @@ pub fn codegen_static_initializer(
     let static_ = cx.tcx.const_eval(param_env.and(cid))?;
 
     let alloc = match static_.val {
-        ConstValue::ByRef(alloc, n) if n.bytes() == 0 => alloc,
+        ConstValue::ByRef(_, alloc, n) if n.bytes() == 0 => alloc,
         _ => bug!("static const eval returned {:#?}", static_),
     };
     Ok((const_alloc_to_llvm(cx, alloc), alloc))
@@ -182,11 +182,11 @@ pub fn simd_shuffle_indices(
             .and_then(|c| {
                 let field_ty = c.ty.builtin_index().unwrap();
                 let fields = match c.ty.sty {
-                    ty::TyArray(_, n) => n.unwrap_usize(bx.tcx()),
+                    ty::Array(_, n) => n.unwrap_usize(bx.tcx()),
                     ref other => bug!("invalid simd shuffle type: {}", other),
                 };
                 let values: Result<Vec<_>, Lrc<_>> = (0..fields).map(|field| {
-                    let field = const_val_field(
+                    let field = const_field(
                         bx.tcx(),
                         ty::ParamEnv::reveal_all(),
                         self.instance,
index d3cb97f65ce264c132abcace628b0d13650e9839..9e65144bd60a1fd87fd6ff425fd76a676fe34a42 100644 (file)
@@ -467,7 +467,7 @@ fn arg_local_refs(
 
             let arg_ty = fx.monomorphize(&arg_decl.ty);
             let tupled_arg_tys = match arg_ty.sty {
-                ty::TyTuple(ref tys) => tys,
+                ty::Tuple(ref tys) => tys,
                 _ => bug!("spread argument isn't a tuple?!")
             };
 
@@ -592,14 +592,14 @@ fn arg_local_refs(
 
             // Or is it the closure environment?
             let (closure_layout, env_ref) = match arg.layout.ty.sty {
-                ty::TyRawPtr(ty::TypeAndMut { ty, .. }) |
-                ty::TyRef(_, ty, _)  => (bx.cx.layout_of(ty), true),
+                ty::RawPtr(ty::TypeAndMut { ty, .. }) |
+                ty::Ref(_, ty, _)  => (bx.cx.layout_of(ty), true),
                 _ => (arg.layout, false)
             };
 
             let (def_id, upvar_substs) = match closure_layout.ty.sty {
-                ty::TyClosure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
-                ty::TyGenerator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
+                ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
+                ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
                 _ => bug!("upvar_decls with non-closure arg0 type `{}`", closure_layout.ty)
             };
             let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
@@ -639,7 +639,7 @@ fn arg_local_refs(
                 // a pointer in an alloca for debuginfo atm.
                 let mut ops = if env_ref || env_alloca { &ops[..] } else { &ops[1..] };
 
-                let ty = if let (true, &ty::TyRef(_, ty, _)) = (decl.by_ref, &ty.sty) {
+                let ty = if let (true, &ty::Ref(_, ty, _)) = (decl.by_ref, &ty.sty) {
                     ty
                 } else {
                     ops = &ops[..ops.len() - 1];
index 9537379813d522eaf08cc18f9b535c8557d8a0f3..419e7298588c595f95aad5a2d2e70fa2da1b65b8 100644 (file)
@@ -126,7 +126,7 @@ pub fn from_const(bx: &Builder<'a, 'll, 'tcx>,
                 };
                 OperandValue::Pair(a_llval, b_llval)
             },
-            ConstValue::ByRef(alloc, offset) => {
+            ConstValue::ByRef(_, alloc, offset) => {
                 return Ok(PlaceRef::from_const_alloc(bx, layout, alloc, offset).load(bx));
             },
         };
index 89d41dcc8e9946029ab19d81c80cacf7aa584832..833dca8c75fd52ed4dc753f83e346e163a36b801 100644 (file)
@@ -211,8 +211,8 @@ pub fn project_field(self, bx: &Builder<'a, 'll, 'tcx>, ix: usize) -> PlaceRef<'
                 return simple();
             }
             _ if !field.is_unsized() => return simple(),
-            ty::TySlice(..) | ty::TyStr | ty::TyForeign(..) => return simple(),
-            ty::TyAdt(def, _) => {
+            ty::Slice(..) | ty::Str | ty::Foreign(..) => return simple(),
+            ty::Adt(def, _) => {
                 if def.repr.packed() {
                     // FIXME(eddyb) generalize the adjustment when we
                     // start supporting packing to larger alignments.
@@ -458,7 +458,7 @@ pub fn codegen_place(&mut self,
                 let layout = cx.layout_of(self.monomorphize(&ty));
                 match bx.tcx().const_eval(param_env.and(cid)) {
                     Ok(val) => match val.val {
-                        mir::interpret::ConstValue::ByRef(alloc, offset) => {
+                        mir::interpret::ConstValue::ByRef(_, alloc, offset) => {
                             PlaceRef::from_const_alloc(bx, layout, alloc, offset)
                         }
                         _ => bug!("promoteds should have an allocation: {:?}", val),
index 84427d8b40f79f70aff82a69eb5777f437dc6374..e301e5ae70be8a9723634bf56220f1d88badc838 100644 (file)
@@ -148,7 +148,7 @@ pub fn codegen_rvalue(&mut self,
 
             mir::Rvalue::Aggregate(ref kind, ref operands) => {
                 let (dest, active_field_index) = match **kind {
-                    mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
+                    mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
                         dest.codegen_set_discr(&bx, variant_index);
                         if adt_def.is_enum() {
                             (dest.project_downcast(&bx, variant_index), active_field_index)
@@ -214,7 +214,7 @@ pub fn codegen_rvalue_operand(&mut self,
                 let val = match *kind {
                     mir::CastKind::ReifyFnPointer => {
                         match operand.layout.ty.sty {
-                            ty::TyFnDef(def_id, substs) => {
+                            ty::FnDef(def_id, substs) => {
                                 if bx.cx.tcx.has_attr(def_id, "rustc_args_required_const") {
                                     bug!("reifying a fn ptr that requires \
                                           const arguments");
@@ -229,7 +229,7 @@ pub fn codegen_rvalue_operand(&mut self,
                     }
                     mir::CastKind::ClosureFnPointer => {
                         match operand.layout.ty.sty {
-                            ty::TyClosure(def_id, substs) => {
+                            ty::Closure(def_id, substs) => {
                                 let instance = monomorphize::resolve_closure(
                                     bx.cx.tcx, def_id, substs, ty::ClosureKind::FnOnce);
                                 OperandValue::Immediate(callee::get_fn(bx.cx, instance))
@@ -545,7 +545,7 @@ fn evaluate_array_len(
         // because codegen_place() panics if Local is operand.
         if let mir::Place::Local(index) = *place {
             if let LocalRef::Operand(Some(op)) = self.locals[index] {
-                if let ty::TyArray(_, n) = op.layout.ty.sty {
+                if let ty::Array(_, n) = op.layout.ty.sty {
                     let n = n.unwrap_usize(bx.cx.tcx);
                     return common::C_usize(bx.cx, n);
                 }
@@ -753,60 +753,60 @@ enum OverflowOp {
 fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder<'_, 'll, '_>, ty: Ty) -> &'ll Value {
     use syntax::ast::IntTy::*;
     use syntax::ast::UintTy::*;
-    use rustc::ty::{TyInt, TyUint};
+    use rustc::ty::{Int, Uint};
 
     let tcx = bx.tcx();
 
     let new_sty = match ty.sty {
-        TyInt(Isize) => TyInt(tcx.sess.target.isize_ty),
-        TyUint(Usize) => TyUint(tcx.sess.target.usize_ty),
-        ref t @ TyUint(_) | ref t @ TyInt(_) => t.clone(),
+        Int(Isize) => Int(tcx.sess.target.isize_ty),
+        Uint(Usize) => Uint(tcx.sess.target.usize_ty),
+        ref t @ Uint(_) | ref t @ Int(_) => t.clone(),
         _ => panic!("tried to get overflow intrinsic for op applied to non-int type")
     };
 
     let name = match oop {
         OverflowOp::Add => match new_sty {
-            TyInt(I8) => "llvm.sadd.with.overflow.i8",
-            TyInt(I16) => "llvm.sadd.with.overflow.i16",
-            TyInt(I32) => "llvm.sadd.with.overflow.i32",
-            TyInt(I64) => "llvm.sadd.with.overflow.i64",
-            TyInt(I128) => "llvm.sadd.with.overflow.i128",
-
-            TyUint(U8) => "llvm.uadd.with.overflow.i8",
-            TyUint(U16) => "llvm.uadd.with.overflow.i16",
-            TyUint(U32) => "llvm.uadd.with.overflow.i32",
-            TyUint(U64) => "llvm.uadd.with.overflow.i64",
-            TyUint(U128) => "llvm.uadd.with.overflow.i128",
+            Int(I8) => "llvm.sadd.with.overflow.i8",
+            Int(I16) => "llvm.sadd.with.overflow.i16",
+            Int(I32) => "llvm.sadd.with.overflow.i32",
+            Int(I64) => "llvm.sadd.with.overflow.i64",
+            Int(I128) => "llvm.sadd.with.overflow.i128",
+
+            Uint(U8) => "llvm.uadd.with.overflow.i8",
+            Uint(U16) => "llvm.uadd.with.overflow.i16",
+            Uint(U32) => "llvm.uadd.with.overflow.i32",
+            Uint(U64) => "llvm.uadd.with.overflow.i64",
+            Uint(U128) => "llvm.uadd.with.overflow.i128",
 
             _ => unreachable!(),
         },
         OverflowOp::Sub => match new_sty {
-            TyInt(I8) => "llvm.ssub.with.overflow.i8",
-            TyInt(I16) => "llvm.ssub.with.overflow.i16",
-            TyInt(I32) => "llvm.ssub.with.overflow.i32",
-            TyInt(I64) => "llvm.ssub.with.overflow.i64",
-            TyInt(I128) => "llvm.ssub.with.overflow.i128",
-
-            TyUint(U8) => "llvm.usub.with.overflow.i8",
-            TyUint(U16) => "llvm.usub.with.overflow.i16",
-            TyUint(U32) => "llvm.usub.with.overflow.i32",
-            TyUint(U64) => "llvm.usub.with.overflow.i64",
-            TyUint(U128) => "llvm.usub.with.overflow.i128",
+            Int(I8) => "llvm.ssub.with.overflow.i8",
+            Int(I16) => "llvm.ssub.with.overflow.i16",
+            Int(I32) => "llvm.ssub.with.overflow.i32",
+            Int(I64) => "llvm.ssub.with.overflow.i64",
+            Int(I128) => "llvm.ssub.with.overflow.i128",
+
+            Uint(U8) => "llvm.usub.with.overflow.i8",
+            Uint(U16) => "llvm.usub.with.overflow.i16",
+            Uint(U32) => "llvm.usub.with.overflow.i32",
+            Uint(U64) => "llvm.usub.with.overflow.i64",
+            Uint(U128) => "llvm.usub.with.overflow.i128",
 
             _ => unreachable!(),
         },
         OverflowOp::Mul => match new_sty {
-            TyInt(I8) => "llvm.smul.with.overflow.i8",
-            TyInt(I16) => "llvm.smul.with.overflow.i16",
-            TyInt(I32) => "llvm.smul.with.overflow.i32",
-            TyInt(I64) => "llvm.smul.with.overflow.i64",
-            TyInt(I128) => "llvm.smul.with.overflow.i128",
-
-            TyUint(U8) => "llvm.umul.with.overflow.i8",
-            TyUint(U16) => "llvm.umul.with.overflow.i16",
-            TyUint(U32) => "llvm.umul.with.overflow.i32",
-            TyUint(U64) => "llvm.umul.with.overflow.i64",
-            TyUint(U128) => "llvm.umul.with.overflow.i128",
+            Int(I8) => "llvm.smul.with.overflow.i8",
+            Int(I16) => "llvm.smul.with.overflow.i16",
+            Int(I32) => "llvm.smul.with.overflow.i32",
+            Int(I64) => "llvm.smul.with.overflow.i64",
+            Int(I128) => "llvm.smul.with.overflow.i128",
+
+            Uint(U8) => "llvm.umul.with.overflow.i8",
+            Uint(U16) => "llvm.umul.with.overflow.i16",
+            Uint(U32) => "llvm.umul.with.overflow.i32",
+            Uint(U64) => "llvm.umul.with.overflow.i64",
+            Uint(U128) => "llvm.umul.with.overflow.i128",
 
             _ => unreachable!(),
         },
index 69d91b327283d87050616d6b3494423c367cadb9..e6907030ae6352e59ac6c48df0926838bbab49fc 100644 (file)
@@ -56,19 +56,19 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     }
 
     let name = match layout.ty.sty {
-        ty::TyClosure(..) |
-        ty::TyGenerator(..) |
-        ty::TyAdt(..) |
+        ty::Closure(..) |
+        ty::Generator(..) |
+        ty::Adt(..) |
         // FIXME(eddyb) producing readable type names for trait objects can result
         // in problematically distinct types due to HRTB and subtyping (see #47638).
-        // ty::TyDynamic(..) |
-        ty::TyForeign(..) |
-        ty::TyStr => {
+        // ty::Dynamic(..) |
+        ty::Foreign(..) |
+        ty::Str => {
             let mut name = String::with_capacity(32);
             let printer = DefPathBasedNames::new(cx.tcx, true, true);
             printer.push_type_name(layout.ty, &mut name);
             match (&layout.ty.sty, &layout.variants) {
-                (&ty::TyAdt(def, _), &layout::Variants::Single { index }) => {
+                (&ty::Adt(def, _), &layout::Variants::Single { index }) => {
                     if def.is_enum() && !def.variants.is_empty() {
                         write!(&mut name, "::{}", def.variants[index].name).unwrap();
                     }
@@ -252,14 +252,14 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
                 return llty;
             }
             let llty = match self.ty.sty {
-                ty::TyRef(_, ty, _) |
-                ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => {
+                ty::Ref(_, ty, _) |
+                ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
                     cx.layout_of(ty).llvm_type(cx).ptr_to()
                 }
-                ty::TyAdt(def, _) if def.is_box() => {
+                ty::Adt(def, _) if def.is_box() => {
                     cx.layout_of(self.ty.boxed_ty()).llvm_type(cx).ptr_to()
                 }
-                ty::TyFnPtr(sig) => {
+                ty::FnPtr(sig) => {
                     let sig = cx.tcx.normalize_erasing_late_bound_regions(
                         ty::ParamEnv::reveal_all(),
                         &sig,
@@ -344,11 +344,11 @@ fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
         // HACK(eddyb) special-case fat pointers until LLVM removes
         // pointee types, to avoid bitcasting every `OperandRef::deref`.
         match self.ty.sty {
-            ty::TyRef(..) |
-            ty::TyRawPtr(_) => {
+            ty::Ref(..) |
+            ty::RawPtr(_) => {
                 return self.field(cx, index).llvm_type(cx);
             }
-            ty::TyAdt(def, _) if def.is_box() => {
+            ty::Adt(def, _) if def.is_box() => {
                 let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty());
                 return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index, immediate);
             }
@@ -410,7 +410,7 @@ fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size)
 
         let mut result = None;
         match self.ty.sty {
-            ty::TyRawPtr(mt) if offset.bytes() == 0 => {
+            ty::RawPtr(mt) if offset.bytes() == 0 => {
                 let (size, align) = cx.size_and_align_of(mt.ty);
                 result = Some(PointeeInfo {
                     size,
@@ -419,7 +419,7 @@ fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size)
                 });
             }
 
-            ty::TyRef(_, ty, mt) if offset.bytes() == 0 => {
+            ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
                 let (size, align) = cx.size_and_align_of(ty);
 
                 let kind = match mt {
@@ -497,7 +497,7 @@ fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size)
 
                 // FIXME(eddyb) This should be for `ptr::Unique<T>`, not `Box<T>`.
                 if let Some(ref mut pointee) = result {
-                    if let ty::TyAdt(def, _) = self.ty.sty {
+                    if let ty::Adt(def, _) = self.ty.sty {
                         if def.is_box() && offset.bytes() == 0 {
                             pointee.safe = Some(PointerKind::UniqueOwned);
                         }
index ae8f65303a7fec7b95cc4b869ea67e1c8d7b53b6..d693e088360d45e4f87e229ac2c4291be7d7ceb7 100644 (file)
@@ -44,7 +44,7 @@
 use rustc_target::spec::Target;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_mir::monomorphize::collector;
-use link::{build_link_meta, out_filename};
+use link::out_filename;
 
 pub use rustc_data_structures::sync::MetadataRef;
 
@@ -180,8 +180,7 @@ fn codegen_crate<'a, 'tcx>(
         }
         tcx.sess.abort_if_errors();
 
-        let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE));
-        let metadata = tcx.encode_metadata(&link_meta);
+        let metadata = tcx.encode_metadata();
 
         box OngoingCodegen {
             metadata: metadata,
index 635819e94e8679bfed6b729350c25cb400ce79c9..45db22ec6dabc59945ee62c28fd1deea617348c9 100644 (file)
@@ -20,6 +20,7 @@
 #![feature(box_syntax)]
 #![feature(custom_attribute)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![allow(unused_attributes)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
index a0d88ccae0f135d1ec0263b62b534bbbb2fa7031..75f1d614ae72ffa6a034e96e250f92a2ad37fb97 100644 (file)
@@ -10,8 +10,6 @@
 
 use rustc::session::config::{self, OutputFilenames, Input, OutputType};
 use rustc::session::Session;
-use rustc::middle::cstore::LinkMeta;
-use rustc_data_structures::svh::Svh;
 use std::path::{Path, PathBuf};
 use syntax::{ast, attr};
 use syntax_pos::Span;
@@ -50,14 +48,6 @@ fn is_writeable(p: &Path) -> bool {
     }
 }
 
-pub fn build_link_meta(crate_hash: Svh) -> LinkMeta {
-    let r = LinkMeta {
-        crate_hash,
-    };
-    info!("{:?}", r);
-    return r;
-}
-
 pub fn find_crate_name(sess: Option<&Session>,
                        attrs: &[ast::Attribute],
                        input: &Input) -> String {
index d834a6502b280fa8f9f4b391df546ccbf532f35a..39b88b225edc75c22da63a492b74d51fcf157f55 100644 (file)
 //! DefPaths which are much more robust in the face of changes to the code base.
 
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::hir::map as hir_map;
+use rustc::hir::Node;
+use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::map::definitions::DefPathData;
 use rustc::ich::NodeIdHashingMode;
-use rustc::middle::weak_lang_items;
 use rustc::ty::item_path::{self, ItemPathBuffer, RootMode};
 use rustc::ty::query::Providers;
 use rustc::ty::subst::Substs;
 use rustc_mir::monomorphize::item::{InstantiationMode, MonoItem, MonoItemExt};
 use rustc_mir::monomorphize::Instance;
 
-use syntax::attr;
 use syntax_pos::symbol::Symbol;
 
 use std::fmt::Write;
@@ -171,7 +170,7 @@ fn get_symbol_hash<'a, 'tcx>(
         // If this is a function, we hash the signature as well.
         // This is not *strictly* needed, but it may help in some
         // situations, see the `run-make/a-b-a-linker-guard` test.
-        if let ty::TyFnDef(..) = item_type.sty {
+        if let ty::FnDef(..) = item_type.sty {
             item_type.fn_sig(tcx).hash_stable(&mut hcx, &mut hasher);
         }
 
@@ -260,34 +259,30 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance
     }
 
     // FIXME(eddyb) Precompute a custom symbol name based on attributes.
-    let attrs = tcx.get_attrs(def_id);
     let is_foreign = if let Some(id) = node_id {
         match tcx.hir.get(id) {
-            hir_map::NodeForeignItem(_) => true,
+            Node::ForeignItem(_) => true,
             _ => false,
         }
     } else {
         tcx.is_foreign_item(def_id)
     };
 
-    if let Some(name) = weak_lang_items::link_name(&attrs) {
-        return name.to_string();
-    }
-
+    let attrs = tcx.codegen_fn_attrs(def_id);
     if is_foreign {
-        if let Some(name) = attr::first_attr_value_str_by_name(&attrs, "link_name") {
+        if let Some(name) = attrs.link_name {
             return name.to_string();
         }
         // Don't mangle foreign items.
         return tcx.item_name(def_id).to_string();
     }
 
-    if let Some(name) = tcx.codegen_fn_attrs(def_id).export_name {
+    if let Some(name) = &attrs.export_name {
         // Use provided name
         return name.to_string();
     }
 
-    if attr::contains_name(&attrs, "no_mangle") {
+    if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) {
         // Don't mangle
         return tcx.item_name(def_id).to_string();
     }
index 39087c5f74616bfb3cadafbc8339f99aa49f8af2..481f2f54c5e44abbc9aa322bb6a3854189a1b32a 100644 (file)
@@ -12,6 +12,7 @@
 #![allow(unused_extern_crates)]
 
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 
 extern crate bitflags;
 extern crate log;
index fc5fe91c977d410057d189a3bd9ab425e9ed5b47..0376cf8115756bf43e89d0d2c31d61df566ae25f 100644 (file)
@@ -19,6 +19,7 @@ parking_lot_core = "0.2.8"
 rustc-rayon = "0.1.1"
 rustc-rayon-core = "0.1.1"
 rustc-hash = "1.0.1"
+smallvec = { version = "0.6.5", features = ["union"] }
 
 [dependencies.parking_lot]
 version = "0.5"
diff --git a/src/librustc_data_structures/accumulate_vec.rs b/src/librustc_data_structures/accumulate_vec.rs
deleted file mode 100644 (file)
index 9423e6b..0000000
+++ /dev/null
@@ -1,242 +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.
-
-//! A vector type intended to be used for collecting from iterators onto the stack.
-//!
-//! Space for up to N elements is provided on the stack.  If more elements are collected, Vec is
-//! used to store the values on the heap.
-//!
-//! The N above is determined by Array's implementor, by way of an associated constant.
-
-use std::ops::{Deref, DerefMut, RangeBounds};
-use std::iter::{self, IntoIterator, FromIterator};
-use std::slice;
-use std::vec;
-
-use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
-
-use array_vec::{self, Array, ArrayVec};
-
-#[derive(Hash, Debug)]
-pub enum AccumulateVec<A: Array> {
-    Array(ArrayVec<A>),
-    Heap(Vec<A::Element>)
-}
-
-impl<A> Clone for AccumulateVec<A>
-    where A: Array,
-          A::Element: Clone {
-    fn clone(&self) -> Self {
-        match *self {
-            AccumulateVec::Array(ref arr) => AccumulateVec::Array(arr.clone()),
-            AccumulateVec::Heap(ref vec) => AccumulateVec::Heap(vec.clone()),
-        }
-    }
-}
-
-impl<A: Array> AccumulateVec<A> {
-    pub fn new() -> AccumulateVec<A> {
-        AccumulateVec::Array(ArrayVec::new())
-    }
-
-    pub fn is_array(&self) -> bool {
-        match self {
-            AccumulateVec::Array(..) => true,
-            AccumulateVec::Heap(..) => false,
-        }
-    }
-
-    pub fn one(el: A::Element) -> Self {
-        iter::once(el).collect()
-    }
-
-    pub fn many<I: IntoIterator<Item=A::Element>>(iter: I) -> Self {
-        iter.into_iter().collect()
-    }
-
-    pub fn len(&self) -> usize {
-        match *self {
-            AccumulateVec::Array(ref arr) => arr.len(),
-            AccumulateVec::Heap(ref vec) => vec.len(),
-        }
-    }
-
-    pub fn is_empty(&self) -> bool {
-        self.len() == 0
-    }
-
-    pub fn pop(&mut self) -> Option<A::Element> {
-        match *self {
-            AccumulateVec::Array(ref mut arr) => arr.pop(),
-            AccumulateVec::Heap(ref mut vec) => vec.pop(),
-        }
-    }
-
-    pub fn drain<R>(&mut self, range: R) -> Drain<A>
-        where R: RangeBounds<usize>
-    {
-        match *self {
-            AccumulateVec::Array(ref mut v) => {
-                Drain::Array(v.drain(range))
-            },
-            AccumulateVec::Heap(ref mut v) => {
-                Drain::Heap(v.drain(range))
-            },
-        }
-    }
-}
-
-impl<A: Array> Deref for AccumulateVec<A> {
-    type Target = [A::Element];
-    fn deref(&self) -> &Self::Target {
-        match *self {
-            AccumulateVec::Array(ref v) => v,
-            AccumulateVec::Heap(ref v) => v,
-        }
-    }
-}
-
-impl<A: Array> DerefMut for AccumulateVec<A> {
-    fn deref_mut(&mut self) -> &mut [A::Element] {
-        match *self {
-            AccumulateVec::Array(ref mut v) => v,
-            AccumulateVec::Heap(ref mut v) => v,
-        }
-    }
-}
-
-impl<A: Array> FromIterator<A::Element> for AccumulateVec<A> {
-    fn from_iter<I>(iter: I) -> AccumulateVec<A> where I: IntoIterator<Item=A::Element> {
-        let iter = iter.into_iter();
-        if iter.size_hint().1.map_or(false, |n| n <= A::LEN) {
-            let mut v = ArrayVec::new();
-            v.extend(iter);
-            AccumulateVec::Array(v)
-        } else {
-            AccumulateVec::Heap(iter.collect())
-        }
-    }
-}
-
-pub struct IntoIter<A: Array> {
-    repr: IntoIterRepr<A>,
-}
-
-enum IntoIterRepr<A: Array> {
-    Array(array_vec::Iter<A>),
-    Heap(vec::IntoIter<A::Element>),
-}
-
-impl<A: Array> Iterator for IntoIter<A> {
-    type Item = A::Element;
-
-    fn next(&mut self) -> Option<A::Element> {
-        match self.repr {
-            IntoIterRepr::Array(ref mut arr) => arr.next(),
-            IntoIterRepr::Heap(ref mut iter) => iter.next(),
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        match self.repr {
-            IntoIterRepr::Array(ref iter) => iter.size_hint(),
-            IntoIterRepr::Heap(ref iter) => iter.size_hint(),
-        }
-    }
-}
-
-pub enum Drain<'a, A: Array>
-        where A::Element: 'a
-{
-    Array(array_vec::Drain<'a, A>),
-    Heap(vec::Drain<'a, A::Element>),
-}
-
-impl<'a, A: Array> Iterator for Drain<'a, A> {
-    type Item = A::Element;
-
-    fn next(&mut self) -> Option<A::Element> {
-        match *self {
-            Drain::Array(ref mut drain) => drain.next(),
-            Drain::Heap(ref mut drain) => drain.next(),
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        match *self {
-            Drain::Array(ref drain) => drain.size_hint(),
-            Drain::Heap(ref drain) => drain.size_hint(),
-        }
-    }
-}
-
-impl<A: Array> IntoIterator for AccumulateVec<A> {
-    type Item = A::Element;
-    type IntoIter = IntoIter<A>;
-    fn into_iter(self) -> Self::IntoIter {
-        IntoIter {
-            repr: match self {
-                AccumulateVec::Array(arr) => IntoIterRepr::Array(arr.into_iter()),
-                AccumulateVec::Heap(vec) => IntoIterRepr::Heap(vec.into_iter()),
-            }
-        }
-    }
-}
-
-impl<'a, A: Array> IntoIterator for &'a AccumulateVec<A> {
-    type Item = &'a A::Element;
-    type IntoIter = slice::Iter<'a, A::Element>;
-    fn into_iter(self) -> Self::IntoIter {
-        self.iter()
-    }
-}
-
-impl<'a, A: Array> IntoIterator for &'a mut AccumulateVec<A> {
-    type Item = &'a mut A::Element;
-    type IntoIter = slice::IterMut<'a, A::Element>;
-    fn into_iter(self) -> Self::IntoIter {
-        self.iter_mut()
-    }
-}
-
-impl<A: Array> From<Vec<A::Element>> for AccumulateVec<A> {
-    fn from(v: Vec<A::Element>) -> AccumulateVec<A> {
-        AccumulateVec::many(v)
-    }
-}
-
-impl<A: Array> Default for AccumulateVec<A> {
-    fn default() -> AccumulateVec<A> {
-        AccumulateVec::new()
-    }
-}
-
-impl<A> Encodable for AccumulateVec<A>
-    where A: Array,
-          A::Element: Encodable {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_seq(self.len(), |s| {
-            for (i, e) in self.iter().enumerate() {
-                s.emit_seq_elt(i, |s| e.encode(s))?;
-            }
-            Ok(())
-        })
-    }
-}
-
-impl<A> Decodable for AccumulateVec<A>
-    where A: Array,
-          A::Element: Decodable {
-    fn decode<D: Decoder>(d: &mut D) -> Result<AccumulateVec<A>, D::Error> {
-        d.read_seq(|d, len| {
-            (0..len).map(|i| d.read_seq_elt(i, |d| Decodable::decode(d))).collect()
-        })
-    }
-}
index 56bb961324210620f35a50afd74f51a34cd14d15..45fb56570618093f556f85134daa61a450e0da69 100644 (file)
@@ -139,7 +139,7 @@ pub fn drain<R>(&mut self, range: R) -> Drain<A>
             // whole Drain iterator (like &mut T).
             let range_slice = {
                 let arr = &mut self.values as &mut [ManuallyDrop<<A as Array>::Element>];
-                slice::from_raw_parts_mut(arr.as_mut_ptr().offset(start as isize),
+                slice::from_raw_parts_mut(arr.as_mut_ptr().add(start),
                                           end - start)
             };
             Drain {
@@ -262,8 +262,8 @@ fn drop(&mut self) {
                 {
                     let arr =
                         &mut source_array_vec.values as &mut [ManuallyDrop<<A as Array>::Element>];
-                    let src = arr.as_ptr().offset(tail as isize);
-                    let dst = arr.as_mut_ptr().offset(start as isize);
+                    let src = arr.as_ptr().add(tail);
+                    let dst = arr.as_mut_ptr().add(start);
                     ptr::copy(src, dst, self.tail_len);
                 };
                 source_array_vec.set_len(start + self.tail_len);
index 49ab3e58812dcfb703ea926798cc610a7ed57024..642d24f48313a26cb76f4880863c115f713f8829 100644 (file)
@@ -318,31 +318,41 @@ pub fn iter<'a>(&'a self, row: R) -> BitIter<'a, C> {
     }
 }
 
-/// A moderately sparse bit matrix: rows are appended lazily, but columns
-/// within appended rows are instantiated fully upon creation.
+/// A moderately sparse bit matrix, in which rows are instantiated lazily.
+///
+/// Initially, every row has no explicit representation. If any bit within a
+/// row is set, the entire row is instantiated as
+/// `Some(<full-column-width-BitArray>)`. Furthermore, any previously
+/// uninstantiated rows prior to it will be instantiated as `None`. Those prior
+/// rows may themselves become fully instantiated later on if any of their bits
+/// are set.
 #[derive(Clone, Debug)]
 pub struct SparseBitMatrix<R, C>
 where
     R: Idx,
     C: Idx,
 {
-    columns: usize,
-    vector: IndexVec<R, BitArray<C>>,
+    num_columns: usize,
+    rows: IndexVec<R, Option<BitArray<C>>>,
 }
 
 impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
     /// Create a new empty sparse bit matrix with no rows or columns.
-    pub fn new(columns: usize) -> Self {
+    pub fn new(num_columns: usize) -> Self {
         Self {
-            columns,
-            vector: IndexVec::new(),
+            num_columns,
+            rows: IndexVec::new(),
         }
     }
 
-    fn ensure_row(&mut self, row: R) {
-        let columns = self.columns;
-        self.vector
-            .ensure_contains_elem(row, || BitArray::new(columns));
+    fn ensure_row(&mut self, row: R) -> &mut BitArray<C> {
+        // Instantiate any missing rows up to and including row `row` with an
+        // empty BitArray.
+        self.rows.ensure_contains_elem(row, || None);
+
+        // Then replace row `row` with a full BitArray if necessary.
+        let num_columns = self.num_columns;
+        self.rows[row].get_or_insert_with(|| BitArray::new(num_columns))
     }
 
     /// Sets the cell at `(row, column)` to true. Put another way, insert
@@ -350,8 +360,7 @@ fn ensure_row(&mut self, row: R) {
     ///
     /// Returns true if this changed the matrix, and false otherwise.
     pub fn add(&mut self, row: R, column: C) -> bool {
-        self.ensure_row(row);
-        self.vector[row].insert(column)
+        self.ensure_row(row).insert(column)
     }
 
     /// Do the bits from `row` contain `column`? Put another way, is
@@ -359,7 +368,7 @@ pub fn add(&mut self, row: R, column: C) -> bool {
     /// if the matrix represents (transitive) reachability, can
     /// `row` reach `column`?
     pub fn contains(&self, row: R, column: C) -> bool {
-        self.vector.get(row).map_or(false, |r| r.contains(column))
+        self.row(row).map_or(false, |r| r.contains(column))
     }
 
     /// Add the bits from row `read` to the bits from row `write`,
@@ -370,49 +379,44 @@ pub fn contains(&self, row: R, column: C) -> bool {
     /// `write` can reach everything that `read` can (and
     /// potentially more).
     pub fn merge(&mut self, read: R, write: R) -> bool {
-        if read == write || self.vector.get(read).is_none() {
+        if read == write || self.row(read).is_none() {
             return false;
         }
 
         self.ensure_row(write);
-        let (bitvec_read, bitvec_write) = self.vector.pick2_mut(read, write);
-        bitvec_write.merge(bitvec_read)
+        if let (Some(bitvec_read), Some(bitvec_write)) = self.rows.pick2_mut(read, write) {
+            bitvec_write.merge(bitvec_read)
+        } else {
+            unreachable!()
+        }
     }
 
     /// Merge a row, `from`, into the `into` row.
     pub fn merge_into(&mut self, into: R, from: &BitArray<C>) -> bool {
-        self.ensure_row(into);
-        self.vector[into].merge(from)
+        self.ensure_row(into).merge(from)
     }
 
     /// Add all bits to the given row.
     pub fn add_all(&mut self, row: R) {
-        self.ensure_row(row);
-        self.vector[row].insert_all();
-    }
-
-    /// Number of elements in the matrix.
-    pub fn len(&self) -> usize {
-        self.vector.len()
+        self.ensure_row(row).insert_all();
     }
 
     pub fn rows(&self) -> impl Iterator<Item = R> {
-        self.vector.indices()
+        self.rows.indices()
     }
 
     /// Iterates through all the columns set to true in a given row of
     /// the matrix.
     pub fn iter<'a>(&'a self, row: R) -> impl Iterator<Item = C> + 'a {
-        self.vector.get(row).into_iter().flat_map(|r| r.iter())
-    }
-
-    /// Iterates through each row and the accompanying bit set.
-    pub fn iter_enumerated<'a>(&'a self) -> impl Iterator<Item = (R, &'a BitArray<C>)> + 'a {
-        self.vector.iter_enumerated()
+        self.row(row).into_iter().flat_map(|r| r.iter())
     }
 
     pub fn row(&self, row: R) -> Option<&BitArray<C>> {
-        self.vector.get(row)
+        if let Some(Some(row)) = self.rows.get(row) {
+            Some(row)
+        } else {
+            None
+        }
     }
 }
 
index 3f248dadb66c14b02a556996ffacc77abb4a29bd..f10a9a68bed5b3a73d2354b2e6a2e61b34572fd5 100644 (file)
@@ -239,7 +239,7 @@ fn drop(&mut self) {
 }
 
 #[cfg(windows)]
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 mod imp {
     use std::io;
     use std::mem;
index e54147cbe7c8793a9e4d36925f14c5d5c296d4e7..9b7f4cec47b8e70fb90ef8c0e731c2bef5285002 100644 (file)
@@ -38,13 +38,13 @@ pub fn dominators_given_rpo<G: ControlFlowGraph>(
 
     // compute the post order index (rank) for each node
     let mut post_order_rank: IndexVec<G::Node, usize> =
-        IndexVec::from_elem_n(usize::default(), graph.num_nodes());
+        (0..graph.num_nodes()).map(|_| 0).collect();
     for (index, node) in rpo.iter().rev().cloned().enumerate() {
         post_order_rank[node] = index;
     }
 
     let mut immediate_dominators: IndexVec<G::Node, Option<G::Node>> =
-        IndexVec::from_elem_n(Option::default(), graph.num_nodes());
+        (0..graph.num_nodes()).map(|_| None).collect();
     immediate_dominators[start_node] = Some(start_node);
 
     let mut changed = true;
index b72d011c99bad9ea84a98c35e9f368c29d888799..26cc2c9f17cfbd57dba41abe1cdc796fb6022e4b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::HashMap;
+use fx::FxHashMap;
 use std::cmp::max;
 use std::slice;
 use std::iter;
@@ -18,8 +18,8 @@
 pub struct TestGraph {
     num_nodes: usize,
     start_node: usize,
-    successors: HashMap<usize, Vec<usize>>,
-    predecessors: HashMap<usize, Vec<usize>>,
+    successors: FxHashMap<usize, Vec<usize>>,
+    predecessors: FxHashMap<usize, Vec<usize>>,
 }
 
 impl TestGraph {
@@ -27,8 +27,8 @@ pub fn new(start_node: usize, edges: &[(usize, usize)]) -> Self {
         let mut graph = TestGraph {
             num_nodes: start_node + 1,
             start_node,
-            successors: HashMap::new(),
-            predecessors: HashMap::new(),
+            successors: FxHashMap::default(),
+            predecessors: FxHashMap::default(),
         };
         for &(source, target) in edges {
             graph.num_nodes = max(graph.num_nodes, source + 1);
index a7672d1ffe8911595c9bc19f94fc4abed22c2bbd..65fdf10a86d13f7d6fa1897a7bbe9a40f9adea62 100644 (file)
@@ -9,38 +9,50 @@
 // except according to those terms.
 
 use array_vec::ArrayVec;
-use std::borrow::{Borrow, BorrowMut, ToOwned};
 use std::fmt;
 use std::iter;
 use std::marker::PhantomData;
 use std::mem;
-use std::ops::{Deref, DerefMut, Range};
 use std::slice;
 use bitslice::{BitSlice, Word};
 use bitslice::{bitwise, Union, Subtract, Intersect};
 use indexed_vec::Idx;
 use rustc_serialize;
 
-/// Represents a set (or packed family of sets), of some element type
-/// E, where each E is identified by some unique index type `T`.
+/// This is implemented by all the index sets so that IdxSet::union() can be
+/// passed any type of index set.
+pub trait UnionIntoIdxSet<T: Idx> {
+    // Performs `other = other | self`.
+    fn union_into(&self, other: &mut IdxSet<T>) -> bool;
+}
+
+/// This is implemented by all the index sets so that IdxSet::subtract() can be
+/// passed any type of index set.
+pub trait SubtractFromIdxSet<T: Idx> {
+    // Performs `other = other - self`.
+    fn subtract_from(&self, other: &mut IdxSet<T>) -> bool;
+}
+
+/// Represents a set of some element type E, where each E is identified by some
+/// unique index type `T`.
 ///
 /// In other words, `T` is the type used to index into the bitvector
 /// this type uses to represent the set of object it holds.
 ///
 /// The representation is dense, using one bit per possible element.
 #[derive(Eq, PartialEq)]
-pub struct IdxSetBuf<T: Idx> {
+pub struct IdxSet<T: Idx> {
     _pd: PhantomData<fn(&T)>,
     bits: Vec<Word>,
 }
 
-impl<T: Idx> Clone for IdxSetBuf<T> {
+impl<T: Idx> Clone for IdxSet<T> {
     fn clone(&self) -> Self {
-        IdxSetBuf { _pd: PhantomData, bits: self.bits.clone() }
+        IdxSet { _pd: PhantomData, bits: self.bits.clone() }
     }
 }
 
-impl<T: Idx> rustc_serialize::Encodable for IdxSetBuf<T> {
+impl<T: Idx> rustc_serialize::Encodable for IdxSet<T> {
     fn encode<E: rustc_serialize::Encoder>(&self,
                                      encoder: &mut E)
                                      -> Result<(), E::Error> {
@@ -48,61 +60,19 @@ fn encode<E: rustc_serialize::Encoder>(&self,
     }
 }
 
-impl<T: Idx> rustc_serialize::Decodable for IdxSetBuf<T> {
-    fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<IdxSetBuf<T>, D::Error> {
+impl<T: Idx> rustc_serialize::Decodable for IdxSet<T> {
+    fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<IdxSet<T>, D::Error> {
         let words: Vec<Word> = rustc_serialize::Decodable::decode(d)?;
 
-        Ok(IdxSetBuf {
+        Ok(IdxSet {
             _pd: PhantomData,
             bits: words,
         })
     }
 }
 
-
-// pnkfelix wants to have this be `IdxSet<T>([Word]) and then pass
-// around `&mut IdxSet<T>` or `&IdxSet<T>`.
-
-/// Represents a set (or packed family of sets), of some element type
-/// E, where each E is identified by some unique index type `T`.
-///
-/// In other words, `T` is the type used to index into the bitslice
-/// this type uses to represent the set of object it holds.
-#[repr(transparent)]
-pub struct IdxSet<T: Idx> {
-    _pd: PhantomData<fn(&T)>,
-    bits: [Word],
-}
-
-impl<T: Idx> Borrow<IdxSet<T>> for IdxSetBuf<T> {
-    fn borrow(&self) -> &IdxSet<T> {
-        &*self
-    }
-}
-
-impl<T: Idx> BorrowMut<IdxSet<T>> for IdxSetBuf<T> {
-    fn borrow_mut(&mut self) -> &mut IdxSet<T> {
-        &mut *self
-    }
-}
-
-impl<T: Idx> ToOwned for IdxSet<T> {
-    type Owned = IdxSetBuf<T>;
-    fn to_owned(&self) -> Self::Owned {
-        IdxSet::to_owned(self)
-    }
-}
-
 const BITS_PER_WORD: usize = mem::size_of::<Word>() * 8;
 
-impl<T: Idx> fmt::Debug for IdxSetBuf<T> {
-    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
-        w.debug_list()
-         .entries(self.iter())
-         .finish()
-    }
-}
-
 impl<T: Idx> fmt::Debug for IdxSet<T> {
     fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
         w.debug_list()
@@ -111,67 +81,35 @@ fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-impl<T: Idx> IdxSetBuf<T> {
-    fn new(init: Word, universe_size: usize) -> Self {
-        let num_words = (universe_size + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
-        IdxSetBuf {
+impl<T: Idx> IdxSet<T> {
+    fn new(init: Word, domain_size: usize) -> Self {
+        let num_words = (domain_size + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
+        IdxSet {
             _pd: Default::default(),
             bits: vec![init; num_words],
         }
     }
 
-    /// Creates set holding every element whose index falls in range 0..universe_size.
-    pub fn new_filled(universe_size: usize) -> Self {
-        let mut result = Self::new(!0, universe_size);
-        result.trim_to(universe_size);
+    /// Creates set holding every element whose index falls in range 0..domain_size.
+    pub fn new_filled(domain_size: usize) -> Self {
+        let mut result = Self::new(!0, domain_size);
+        result.trim_to(domain_size);
         result
     }
 
     /// Creates set holding no elements.
-    pub fn new_empty(universe_size: usize) -> Self {
-        Self::new(0, universe_size)
-    }
-}
-
-impl<T: Idx> IdxSet<T> {
-    unsafe fn from_slice(s: &[Word]) -> &Self {
-        &*(s as *const [Word] as *const Self)
-    }
-
-    unsafe fn from_slice_mut(s: &mut [Word]) -> &mut Self {
-        &mut *(s as *mut [Word] as *mut Self)
-    }
-}
-
-impl<T: Idx> Deref for IdxSetBuf<T> {
-    type Target = IdxSet<T>;
-    fn deref(&self) -> &IdxSet<T> {
-        unsafe { IdxSet::from_slice(&self.bits) }
-    }
-}
-
-impl<T: Idx> DerefMut for IdxSetBuf<T> {
-    fn deref_mut(&mut self) -> &mut IdxSet<T> {
-        unsafe { IdxSet::from_slice_mut(&mut self.bits) }
-    }
-}
-
-impl<T: Idx> IdxSet<T> {
-    pub fn to_owned(&self) -> IdxSetBuf<T> {
-        IdxSetBuf {
-            _pd: Default::default(),
-            bits: self.bits.to_owned(),
-        }
+    pub fn new_empty(domain_size: usize) -> Self {
+        Self::new(0, domain_size)
     }
 
     /// Duplicates as a hybrid set.
-    pub fn to_hybrid(&self) -> HybridIdxSetBuf<T> {
-        // This universe_size may be slightly larger than the one specified
+    pub fn to_hybrid(&self) -> HybridIdxSet<T> {
+        // This domain_size may be slightly larger than the one specified
         // upon creation, due to rounding up to a whole word. That's ok.
-        let universe_size = self.bits.len() * BITS_PER_WORD;
+        let domain_size = self.bits.len() * BITS_PER_WORD;
 
         // Note: we currently don't bother trying to make a Sparse set.
-        HybridIdxSetBuf::Dense(self.to_owned(), universe_size)
+        HybridIdxSet::Dense(self.to_owned(), domain_size)
     }
 
     /// Removes all elements
@@ -181,19 +119,19 @@ pub fn clear(&mut self) {
         }
     }
 
-    /// Sets all elements up to `universe_size`
-    pub fn set_up_to(&mut self, universe_size: usize) {
+    /// Sets all elements up to `domain_size`
+    pub fn set_up_to(&mut self, domain_size: usize) {
         for b in &mut self.bits {
             *b = !0;
         }
-        self.trim_to(universe_size);
+        self.trim_to(domain_size);
     }
 
-    /// Clear all elements above `universe_size`.
-    fn trim_to(&mut self, universe_size: usize) {
+    /// Clear all elements above `domain_size`.
+    fn trim_to(&mut self, domain_size: usize) {
         // `trim_block` is the first block where some bits have
         // to be cleared.
-        let trim_block = universe_size / BITS_PER_WORD;
+        let trim_block = domain_size / BITS_PER_WORD;
 
         // all the blocks above it have to be completely cleared.
         if trim_block < self.bits.len() {
@@ -201,9 +139,9 @@ fn trim_to(&mut self, universe_size: usize) {
                 *b = 0;
             }
 
-            // at that block, the `universe_size % BITS_PER_WORD` lsbs
+            // at that block, the `domain_size % BITS_PER_WORD` LSBs
             // should remain.
-            let remaining_bits = universe_size % BITS_PER_WORD;
+            let remaining_bits = domain_size % BITS_PER_WORD;
             let mask = (1<<remaining_bits)-1;
             self.bits[trim_block] &= mask;
         }
@@ -219,16 +157,6 @@ pub fn add(&mut self, elem: &T) -> bool {
         self.bits.set_bit(elem.index())
     }
 
-    pub fn range(&self, elems: &Range<T>) -> &Self {
-        let elems = elems.start.index()..elems.end.index();
-        unsafe { Self::from_slice(&self.bits[elems]) }
-    }
-
-    pub fn range_mut(&mut self, elems: &Range<T>) -> &mut Self {
-        let elems = elems.start.index()..elems.end.index();
-        unsafe { Self::from_slice_mut(&mut self.bits[elems]) }
-    }
-
     /// Returns true iff set `self` contains `elem`.
     pub fn contains(&self, elem: &T) -> bool {
         self.bits.get_bit(elem.index())
@@ -250,48 +178,14 @@ pub fn overwrite(&mut self, other: &IdxSet<T>) {
 
     /// Set `self = self | other` and return true if `self` changed
     /// (i.e., if new bits were added).
-    pub fn union(&mut self, other: &IdxSet<T>) -> bool {
-        bitwise(self.words_mut(), other.words(), &Union)
-    }
-
-    /// Like `union()`, but takes a `SparseIdxSetBuf` argument.
-    fn union_sparse(&mut self, other: &SparseIdxSetBuf<T>) -> bool {
-        let mut changed = false;
-        for elem in other.iter() {
-            changed |= self.add(&elem);
-        }
-        changed
-    }
-
-    /// Like `union()`, but takes a `HybridIdxSetBuf` argument.
-    pub fn union_hybrid(&mut self, other: &HybridIdxSetBuf<T>) -> bool {
-        match other {
-            HybridIdxSetBuf::Sparse(sparse, _) => self.union_sparse(sparse),
-            HybridIdxSetBuf::Dense(dense, _) => self.union(dense),
-        }
+    pub fn union(&mut self, other: &impl UnionIntoIdxSet<T>) -> bool {
+        other.union_into(self)
     }
 
     /// Set `self = self - other` and return true if `self` changed.
     /// (i.e., if any bits were removed).
-    pub fn subtract(&mut self, other: &IdxSet<T>) -> bool {
-        bitwise(self.words_mut(), other.words(), &Subtract)
-    }
-
-    /// Like `subtract()`, but takes a `SparseIdxSetBuf` argument.
-    fn subtract_sparse(&mut self, other: &SparseIdxSetBuf<T>) -> bool {
-        let mut changed = false;
-        for elem in other.iter() {
-            changed |= self.remove(&elem);
-        }
-        changed
-    }
-
-    /// Like `subtract()`, but takes a `HybridIdxSetBuf` argument.
-    pub fn subtract_hybrid(&mut self, other: &HybridIdxSetBuf<T>) -> bool {
-        match other {
-            HybridIdxSetBuf::Sparse(sparse, _) => self.subtract_sparse(sparse),
-            HybridIdxSetBuf::Dense(dense, _) => self.subtract(dense),
-        }
+    pub fn subtract(&mut self, other: &impl SubtractFromIdxSet<T>) -> bool {
+        other.subtract_from(self)
     }
 
     /// Set `self = self & other` and return true if `self` changed.
@@ -309,6 +203,18 @@ pub fn iter(&self) -> Iter<T> {
     }
 }
 
+impl<T: Idx> UnionIntoIdxSet<T> for IdxSet<T> {
+    fn union_into(&self, other: &mut IdxSet<T>) -> bool {
+        bitwise(other.words_mut(), self.words(), &Union)
+    }
+}
+
+impl<T: Idx> SubtractFromIdxSet<T> for IdxSet<T> {
+    fn subtract_from(&self, other: &mut IdxSet<T>) -> bool {
+        bitwise(other.words_mut(), self.words(), &Subtract)
+    }
+}
+
 pub struct Iter<'a, T: Idx> {
     cur: Option<(Word, usize)>,
     iter: iter::Enumerate<slice::Iter<'a, Word>>,
@@ -338,15 +244,15 @@ fn next(&mut self) -> Option<T> {
 const SPARSE_MAX: usize = 8;
 
 /// A sparse index set with a maximum of SPARSE_MAX elements. Used by
-/// HybridIdxSetBuf; do not use directly.
+/// HybridIdxSet; do not use directly.
 ///
 /// The elements are stored as an unsorted vector with no duplicates.
 #[derive(Clone, Debug)]
-pub struct SparseIdxSetBuf<T: Idx>(ArrayVec<[T; SPARSE_MAX]>);
+pub struct SparseIdxSet<T: Idx>(ArrayVec<[T; SPARSE_MAX]>);
 
-impl<T: Idx> SparseIdxSetBuf<T> {
+impl<T: Idx> SparseIdxSet<T> {
     fn new() -> Self {
-        SparseIdxSetBuf(ArrayVec::new())
+        SparseIdxSet(ArrayVec::new())
     }
 
     fn len(&self) -> usize {
@@ -379,8 +285,8 @@ fn remove(&mut self, elem: &T) -> bool {
         }
     }
 
-    fn to_dense(&self, universe_size: usize) -> IdxSetBuf<T> {
-        let mut dense = IdxSetBuf::new_empty(universe_size);
+    fn to_dense(&self, domain_size: usize) -> IdxSet<T> {
+        let mut dense = IdxSet::new_empty(domain_size);
         for elem in self.0.iter() {
             dense.add(elem);
         }
@@ -394,6 +300,26 @@ fn iter(&self) -> SparseIter<T> {
     }
 }
 
+impl<T: Idx> UnionIntoIdxSet<T> for SparseIdxSet<T> {
+    fn union_into(&self, other: &mut IdxSet<T>) -> bool {
+        let mut changed = false;
+        for elem in self.iter() {
+            changed |= other.add(&elem);
+        }
+        changed
+    }
+}
+
+impl<T: Idx> SubtractFromIdxSet<T> for SparseIdxSet<T> {
+    fn subtract_from(&self, other: &mut IdxSet<T>) -> bool {
+        let mut changed = false;
+        for elem in self.iter() {
+            changed |= other.remove(&elem);
+        }
+        changed
+    }
+}
+
 pub struct SparseIter<'a, T: Idx> {
     iter: slice::Iter<'a, T>,
 }
@@ -406,72 +332,68 @@ fn next(&mut self) -> Option<T> {
     }
 }
 
-/// Like IdxSetBuf, but with a hybrid representation: sparse when there are few
+/// Like IdxSet, but with a hybrid representation: sparse when there are few
 /// elements in the set, but dense when there are many. It's especially
 /// efficient for sets that typically have a small number of elements, but a
-/// large `universe_size`, and are cleared frequently.
+/// large `domain_size`, and are cleared frequently.
 #[derive(Clone, Debug)]
-pub enum HybridIdxSetBuf<T: Idx> {
-    Sparse(SparseIdxSetBuf<T>, usize),
-    Dense(IdxSetBuf<T>, usize),
+pub enum HybridIdxSet<T: Idx> {
+    Sparse(SparseIdxSet<T>, usize),
+    Dense(IdxSet<T>, usize),
 }
 
-impl<T: Idx> HybridIdxSetBuf<T> {
-    pub fn new_empty(universe_size: usize) -> Self {
-        HybridIdxSetBuf::Sparse(SparseIdxSetBuf::new(), universe_size)
-    }
-
-    fn universe_size(&mut self) -> usize {
-        match *self {
-            HybridIdxSetBuf::Sparse(_, size) => size,
-            HybridIdxSetBuf::Dense(_, size) => size,
-        }
+impl<T: Idx> HybridIdxSet<T> {
+    pub fn new_empty(domain_size: usize) -> Self {
+        HybridIdxSet::Sparse(SparseIdxSet::new(), domain_size)
     }
 
     pub fn clear(&mut self) {
-        let universe_size = self.universe_size();
-        *self = HybridIdxSetBuf::new_empty(universe_size);
+        let domain_size = match *self {
+            HybridIdxSet::Sparse(_, size) => size,
+            HybridIdxSet::Dense(_, size) => size,
+        };
+        *self = HybridIdxSet::new_empty(domain_size);
     }
 
     /// Returns true iff set `self` contains `elem`.
     pub fn contains(&self, elem: &T) -> bool {
         match self {
-            HybridIdxSetBuf::Sparse(sparse, _) => sparse.contains(elem),
-            HybridIdxSetBuf::Dense(dense, _) => dense.contains(elem),
+            HybridIdxSet::Sparse(sparse, _) => sparse.contains(elem),
+            HybridIdxSet::Dense(dense, _) => dense.contains(elem),
         }
     }
 
     /// Adds `elem` to the set `self`.
     pub fn add(&mut self, elem: &T) -> bool {
         match self {
-            HybridIdxSetBuf::Sparse(sparse, _) if sparse.len() < SPARSE_MAX => {
+            HybridIdxSet::Sparse(sparse, _) if sparse.len() < SPARSE_MAX => {
                 // The set is sparse and has space for `elem`.
                 sparse.add(elem)
             }
-            HybridIdxSetBuf::Sparse(sparse, _) if sparse.contains(elem) => {
+            HybridIdxSet::Sparse(sparse, _) if sparse.contains(elem) => {
                 // The set is sparse and does not have space for `elem`, but
                 // that doesn't matter because `elem` is already present.
                 false
             }
-            HybridIdxSetBuf::Sparse(_, _) => {
+            HybridIdxSet::Sparse(_, _) => {
                 // The set is sparse and full. Convert to a dense set.
                 //
                 // FIXME: This code is awful, but I can't work out how else to
                 //        appease the borrow checker.
-                let dummy = HybridIdxSetBuf::Sparse(SparseIdxSetBuf::new(), 0);
+                let dummy = HybridIdxSet::Sparse(SparseIdxSet::new(), 0);
                 match mem::replace(self, dummy) {
-                    HybridIdxSetBuf::Sparse(sparse, universe_size) => {
-                        let mut dense = sparse.to_dense(universe_size);
+                    HybridIdxSet::Sparse(sparse, domain_size) => {
+                        let mut dense = sparse.to_dense(domain_size);
                         let changed = dense.add(elem);
                         assert!(changed);
-                        mem::replace(self, HybridIdxSetBuf::Dense(dense, universe_size));
+                        mem::replace(self, HybridIdxSet::Dense(dense, domain_size));
                         changed
                     }
                     _ => panic!("impossible"),
                 }
             }
 
-            HybridIdxSetBuf::Dense(dense, _) => dense.add(elem),
+            HybridIdxSet::Dense(dense, _) => dense.add(elem),
         }
     }
 
@@ -479,24 +401,42 @@ pub fn add(&mut self, elem: &T) -> bool {
     pub fn remove(&mut self, elem: &T) -> bool {
         // Note: we currently don't bother going from Dense back to Sparse.
         match self {
-            HybridIdxSetBuf::Sparse(sparse, _) => sparse.remove(elem),
-            HybridIdxSetBuf::Dense(dense, _) => dense.remove(elem),
+            HybridIdxSet::Sparse(sparse, _) => sparse.remove(elem),
+            HybridIdxSet::Dense(dense, _) => dense.remove(elem),
         }
     }
 
     /// Converts to a dense set, consuming itself in the process.
-    pub fn to_dense(self) -> IdxSetBuf<T> {
+    pub fn to_dense(self) -> IdxSet<T> {
         match self {
-            HybridIdxSetBuf::Sparse(sparse, universe_size) => sparse.to_dense(universe_size),
-            HybridIdxSetBuf::Dense(dense, _) => dense,
+            HybridIdxSet::Sparse(sparse, domain_size) => sparse.to_dense(domain_size),
+            HybridIdxSet::Dense(dense, _) => dense,
         }
     }
 
     /// Iteration order is unspecified.
     pub fn iter(&self) -> HybridIter<T> {
         match self {
-            HybridIdxSetBuf::Sparse(sparse, _) => HybridIter::Sparse(sparse.iter()),
-            HybridIdxSetBuf::Dense(dense, _) => HybridIter::Dense(dense.iter()),
+            HybridIdxSet::Sparse(sparse, _) => HybridIter::Sparse(sparse.iter()),
+            HybridIdxSet::Dense(dense, _) => HybridIter::Dense(dense.iter()),
+        }
+    }
+}
+
+impl<T: Idx> UnionIntoIdxSet<T> for HybridIdxSet<T> {
+    fn union_into(&self, other: &mut IdxSet<T>) -> bool {
+        match self {
+            HybridIdxSet::Sparse(sparse, _) => sparse.union_into(other),
+            HybridIdxSet::Dense(dense, _) => dense.union_into(other),
+        }
+    }
+}
+
+impl<T: Idx> SubtractFromIdxSet<T> for HybridIdxSet<T> {
+    fn subtract_from(&self, other: &mut IdxSet<T>) -> bool {
+        match self {
+            HybridIdxSet::Sparse(sparse, _) => sparse.subtract_from(other),
+            HybridIdxSet::Dense(dense, _) => dense.subtract_from(other),
         }
     }
 }
@@ -522,7 +462,7 @@ fn test_trim_to() {
     use std::cmp;
 
     for i in 0..256 {
-        let mut idx_buf: IdxSetBuf<usize> = IdxSetBuf::new_filled(128);
+        let mut idx_buf: IdxSet<usize> = IdxSet::new_filled(128);
         idx_buf.trim_to(i);
 
         let elems: Vec<usize> = idx_buf.iter().collect();
@@ -535,7 +475,7 @@ fn test_trim_to() {
 fn test_set_up_to() {
     for i in 0..128 {
         for mut idx_buf in
-            vec![IdxSetBuf::new_empty(128), IdxSetBuf::new_filled(128)]
+            vec![IdxSet::new_empty(128), IdxSet::new_filled(128)]
             .into_iter()
         {
             idx_buf.set_up_to(i);
@@ -550,7 +490,7 @@ fn test_set_up_to() {
 #[test]
 fn test_new_filled() {
     for i in 0..128 {
-        let idx_buf = IdxSetBuf::new_filled(i);
+        let idx_buf = IdxSet::new_filled(i);
         let elems: Vec<usize> = idx_buf.iter().collect();
         let expected: Vec<usize> = (0..i).collect();
         assert_eq!(elems, expected);
index 5699512326a37d128936c371344808174a7b3109..7915650fd89f70401d79422f01aa15105168394a 100644 (file)
       html_favicon_url = "https://www.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 
+#![feature(in_band_lifetimes)]
+#![feature(impl_header_lifetime_elision)]
 #![feature(unboxed_closures)]
 #![feature(fn_traits)]
 #![feature(unsize)]
 #![feature(specialization)]
 #![feature(optin_builtin_traits)]
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(allow_internal_unstable)]
 #![feature(vec_resize_with)]
 
@@ -48,6 +51,8 @@
 extern crate rustc_rayon_core as rayon_core;
 extern crate rustc_hash;
 extern crate serialize;
+#[cfg_attr(test, macro_use)]
+extern crate smallvec;
 
 // See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
 #[allow(unused_extern_crates)]
@@ -56,7 +61,6 @@
 pub use rustc_serialize::hex::ToHex;
 
 pub mod svh;
-pub mod accumulate_vec;
 pub mod array_vec;
 pub mod base_n;
 pub mod bitslice;
@@ -83,6 +87,7 @@
 pub mod transitive_relation;
 pub mod tuple_slice;
 pub use ena::unify;
+pub mod vec_linked_list;
 pub mod work_queue;
 pub mod fingerprint;
 
index b0ad83e4979380cd48395fe7156d4480de13771a..08794fbec8dc5df7adb7ae66083e137e94b85b64 100644 (file)
 use std::ffi;
 use std::ops::Deref;
 
-const SIZE: usize = 38;
+use smallvec::SmallVec;
+
+const SIZE: usize = 36;
 
 /// Like SmallVec but for C strings.
 #[derive(Clone)]
-pub enum SmallCStr {
-    OnStack {
-        data: [u8; SIZE],
-        len_with_nul: u8,
-    },
-    OnHeap {
-        data: ffi::CString,
-    }
+pub struct SmallCStr {
+    data: SmallVec<[u8; SIZE]>,
 }
 
 impl SmallCStr {
     #[inline]
     pub fn new(s: &str) -> SmallCStr {
-        if s.len() < SIZE {
-            let mut data = [0; SIZE];
-            data[.. s.len()].copy_from_slice(s.as_bytes());
-            let len_with_nul = s.len() + 1;
-
-            // Make sure once that this is a valid CStr
-            if let Err(e) = ffi::CStr::from_bytes_with_nul(&data[.. len_with_nul]) {
-                panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e);
-            }
-
-            SmallCStr::OnStack {
-                data,
-                len_with_nul: len_with_nul as u8,
-            }
+        let len = s.len();
+        let len1 = len + 1;
+        let data = if len < SIZE {
+            let mut buf = [0; SIZE];
+            buf[..len].copy_from_slice(s.as_bytes());
+            SmallVec::from_buf_and_len(buf, len1)
         } else {
-            SmallCStr::OnHeap {
-                data: ffi::CString::new(s).unwrap()
-            }
+            let mut data = Vec::with_capacity(len1);
+            data.extend_from_slice(s.as_bytes());
+            data.push(0);
+            SmallVec::from_vec(data)
+        };
+        if let Err(e) = ffi::CStr::from_bytes_with_nul(&data) {
+            panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e);
         }
+        SmallCStr { data }
     }
 
+    #[inline]
+    pub fn new_with_nul(s: &str) -> SmallCStr {
+        let b = s.as_bytes();
+        if let Err(e) = ffi::CStr::from_bytes_with_nul(b) {
+            panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e);
+        }
+        SmallCStr { data: SmallVec::from_slice(s.as_bytes()) }
+    }
+
+
     #[inline]
     pub fn as_c_str(&self) -> &ffi::CStr {
-        match *self {
-            SmallCStr::OnStack { ref data, len_with_nul } => {
-                unsafe {
-                    let slice = &data[.. len_with_nul as usize];
-                    ffi::CStr::from_bytes_with_nul_unchecked(slice)
-                }
-            }
-            SmallCStr::OnHeap { ref data } => {
-                data.as_c_str()
-            }
+        unsafe {
+            ffi::CStr::from_bytes_with_nul_unchecked(&self.data[..])
         }
     }
 
     #[inline]
     pub fn len_with_nul(&self) -> usize {
-        match *self {
-            SmallCStr::OnStack { len_with_nul, .. } => {
-                len_with_nul as usize
-            }
-            SmallCStr::OnHeap { ref data } => {
-                data.as_bytes_with_nul().len()
-            }
-        }
+        self.data.len()
+    }
+
+    pub fn spilled(&self) -> bool {
+        self.data.spilled()
     }
 }
 
@@ -85,7 +77,6 @@ fn deref(&self) -> &ffi::CStr {
     }
 }
 
-
 #[test]
 fn short() {
     const TEXT: &str = "abcd";
@@ -95,7 +86,7 @@ fn short() {
 
     assert_eq!(scs.len_with_nul(), TEXT.len() + 1);
     assert_eq!(scs.as_c_str(), reference.as_c_str());
-    assert!(if let SmallCStr::OnStack { .. } = scs { true } else { false });
+    assert!(!scs.spilled());
 }
 
 #[test]
@@ -107,7 +98,7 @@ fn empty() {
 
     assert_eq!(scs.len_with_nul(), TEXT.len() + 1);
     assert_eq!(scs.as_c_str(), reference.as_c_str());
-    assert!(if let SmallCStr::OnStack { .. } = scs { true } else { false });
+    assert!(!scs.spilled());
 }
 
 #[test]
@@ -121,7 +112,7 @@ fn long() {
 
     assert_eq!(scs.len_with_nul(), TEXT.len() + 1);
     assert_eq!(scs.as_c_str(), reference.as_c_str());
-    assert!(if let SmallCStr::OnHeap { .. } = scs { true } else { false });
+    assert!(scs.spilled());
 }
 
 #[test]
index 6f101b20d880659cd19ba20a35dedc652cc48435..075b70c6426fb8407d4e00a3fd5835bf1a8bada7 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! A vector type intended to be used for collecting from iterators onto the stack.
+//! A vector type intended to be used for small vectors.
 //!
-//! Space for up to N elements is provided on the stack.  If more elements are collected, Vec is
-//! used to store the values on the heap. SmallVec is similar to AccumulateVec, but adds
-//! the ability to push elements.
+//! Space for up to N elements is provided on the stack. If more elements are collected, Vec is
+//! used to store the values on the heap.
 //!
 //! The N above is determined by Array's implementor, by way of an associated constant.
 
-use std::ops::{Deref, DerefMut};
-use std::iter::{IntoIterator, FromIterator};
-use std::fmt::{self, Debug};
-use std::mem;
-use std::ptr;
-
-use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
-
-use accumulate_vec::{IntoIter, AccumulateVec};
-use array_vec::Array;
-
-pub struct SmallVec<A: Array>(AccumulateVec<A>);
+use smallvec::{Array, SmallVec};
 
 pub type OneVector<T> = SmallVec<[T; 1]>;
 
-impl<A> Clone for SmallVec<A>
-    where A: Array,
-          A::Element: Clone {
-    fn clone(&self) -> Self {
-        SmallVec(self.0.clone())
-    }
-}
-
-impl<A> Debug for SmallVec<A>
-    where A: Array + Debug,
-          A::Element: Debug {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_tuple("SmallVec").field(&self.0).finish()
-    }
+pub trait ExpectOne<A: Array> {
+    fn expect_one(self, err: &'static str) -> A::Item;
 }
 
-impl<A: Array> SmallVec<A> {
-    pub fn new() -> Self {
-        SmallVec(AccumulateVec::new())
-    }
-
-    pub fn is_array(&self) -> bool {
-        self.0.is_array()
-    }
-
-    pub fn with_capacity(cap: usize) -> Self {
-        let mut vec = SmallVec::new();
-        vec.reserve(cap);
-        vec
-    }
-
-    pub fn one(el: A::Element) -> Self {
-        SmallVec(AccumulateVec::one(el))
-    }
-
-    pub fn many<I: IntoIterator<Item=A::Element>>(els: I) -> Self {
-        SmallVec(AccumulateVec::many(els))
-    }
-
-    pub fn expect_one(self, err: &'static str) -> A::Element {
+impl<A: Array> ExpectOne<A> for SmallVec<A> {
+    fn expect_one(self, err: &'static str) -> A::Item {
         assert!(self.len() == 1, err);
-        match self.0 {
-            AccumulateVec::Array(arr) => arr.into_iter().next().unwrap(),
-            AccumulateVec::Heap(vec) => vec.into_iter().next().unwrap(),
-        }
-    }
-
-    /// Will reallocate onto the heap if needed.
-    pub fn push(&mut self, el: A::Element) {
-        self.reserve(1);
-        match self.0 {
-            AccumulateVec::Array(ref mut array) => array.push(el),
-            AccumulateVec::Heap(ref mut vec) => vec.push(el),
-        }
-    }
-
-    pub fn reserve(&mut self, n: usize) {
-        match self.0 {
-            AccumulateVec::Array(_) => {
-                if self.len() + n > A::LEN {
-                    let len = self.len();
-                    let array = mem::replace(&mut self.0,
-                            AccumulateVec::Heap(Vec::with_capacity(len + n)));
-                    if let AccumulateVec::Array(array) = array {
-                        match self.0 {
-                            AccumulateVec::Heap(ref mut vec) => vec.extend(array),
-                            _ => unreachable!()
-                        }
-                    }
-                }
-            }
-            AccumulateVec::Heap(ref mut vec) => vec.reserve(n)
-        }
-    }
-
-    pub unsafe fn set_len(&mut self, len: usize) {
-        match self.0 {
-            AccumulateVec::Array(ref mut arr) => arr.set_len(len),
-            AccumulateVec::Heap(ref mut vec) => vec.set_len(len),
-        }
-    }
-
-    pub fn insert(&mut self, index: usize, element: A::Element) {
-        let len = self.len();
-
-        // Reserve space for shifting elements to the right
-        self.reserve(1);
-
-        assert!(index <= len);
-
-        unsafe {
-            // infallible
-            // The spot to put the new value
-            {
-                let p = self.as_mut_ptr().offset(index as isize);
-                // Shift everything over to make space. (Duplicating the
-                // `index`th element into two consecutive places.)
-                ptr::copy(p, p.offset(1), len - index);
-                // Write it in, overwriting the first copy of the `index`th
-                // element.
-                ptr::write(p, element);
-            }
-            self.set_len(len + 1);
-        }
-    }
-
-    pub fn truncate(&mut self, len: usize) {
-        unsafe {
-            while len < self.len() {
-                // Decrement len before the drop_in_place(), so a panic on Drop
-                // doesn't re-drop the just-failed value.
-                let newlen = self.len() - 1;
-                self.set_len(newlen);
-                ::std::ptr::drop_in_place(self.get_unchecked_mut(newlen));
-            }
-        }
-    }
-}
-
-impl<A: Array> Deref for SmallVec<A> {
-    type Target = AccumulateVec<A>;
-    fn deref(&self) -> &Self::Target {
-        &self.0
-    }
-}
-
-impl<A: Array> DerefMut for SmallVec<A> {
-    fn deref_mut(&mut self) -> &mut AccumulateVec<A> {
-        &mut self.0
-    }
-}
-
-impl<A: Array> FromIterator<A::Element> for SmallVec<A> {
-    fn from_iter<I>(iter: I) -> Self where I: IntoIterator<Item=A::Element> {
-        SmallVec(iter.into_iter().collect())
-    }
-}
-
-impl<A: Array> Extend<A::Element> for SmallVec<A> {
-    fn extend<I: IntoIterator<Item=A::Element>>(&mut self, iter: I) {
-        let iter = iter.into_iter();
-        self.reserve(iter.size_hint().0);
-        match self.0 {
-            AccumulateVec::Heap(ref mut vec) => vec.extend(iter),
-            _ => iter.for_each(|el| self.push(el))
-        }
-    }
-}
-
-impl<A: Array> IntoIterator for SmallVec<A> {
-    type Item = A::Element;
-    type IntoIter = IntoIter<A>;
-    fn into_iter(self) -> Self::IntoIter {
-        self.0.into_iter()
-    }
-}
-
-impl<A: Array> Default for SmallVec<A> {
-    fn default() -> SmallVec<A> {
-        SmallVec::new()
-    }
-}
-
-impl<A> Encodable for SmallVec<A>
-    where A: Array,
-          A::Element: Encodable {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_seq(self.len(), |s| {
-            for (i, e) in self.iter().enumerate() {
-                s.emit_seq_elt(i, |s| e.encode(s))?;
-            }
-            Ok(())
-        })
-    }
-}
-
-impl<A> Decodable for SmallVec<A>
-    where A: Array,
-          A::Element: Decodable {
-    fn decode<D: Decoder>(d: &mut D) -> Result<SmallVec<A>, D::Error> {
-        d.read_seq(|d, len| {
-            let mut vec = SmallVec::with_capacity(len);
-            // FIXME(#48994) - could just be collected into a Result<SmallVec, D::Error>
-            for i in 0..len {
-                vec.push(d.read_seq_elt(i, |d| Decodable::decode(d))?);
-            }
-            Ok(vec)
-        })
+        self.into_iter().next().unwrap()
     }
 }
 
 #[cfg(test)]
 mod tests {
     extern crate test;
-    use self::test::Bencher;
-
     use super::*;
 
-    #[test]
-    fn test_len() {
-        let v: OneVector<isize> = OneVector::new();
-        assert_eq!(0, v.len());
-
-        assert_eq!(1, OneVector::one(1).len());
-        assert_eq!(5, OneVector::many(vec![1, 2, 3, 4, 5]).len());
-    }
-
-    #[test]
-    fn test_push_get() {
-        let mut v = OneVector::new();
-        v.push(1);
-        assert_eq!(1, v.len());
-        assert_eq!(1, v[0]);
-        v.push(2);
-        assert_eq!(2, v.len());
-        assert_eq!(2, v[1]);
-        v.push(3);
-        assert_eq!(3, v.len());
-        assert_eq!(3, v[2]);
-    }
-
-    #[test]
-    fn test_from_iter() {
-        let v: OneVector<isize> = (vec![1, 2, 3]).into_iter().collect();
-        assert_eq!(3, v.len());
-        assert_eq!(1, v[0]);
-        assert_eq!(2, v[1]);
-        assert_eq!(3, v[2]);
-    }
-
-    #[test]
-    fn test_move_iter() {
-        let v = OneVector::new();
-        let v: Vec<isize> = v.into_iter().collect();
-        assert_eq!(v, Vec::new());
-
-        let v = OneVector::one(1);
-        assert_eq!(v.into_iter().collect::<Vec<_>>(), [1]);
-
-        let v = OneVector::many(vec![1, 2, 3]);
-        assert_eq!(v.into_iter().collect::<Vec<_>>(), [1, 2, 3]);
-    }
-
     #[test]
     #[should_panic]
     fn test_expect_one_zero() {
@@ -283,120 +44,12 @@ fn test_expect_one_zero() {
     #[test]
     #[should_panic]
     fn test_expect_one_many() {
-        OneVector::many(vec![1, 2]).expect_one("");
+        OneVector::from_vec(vec![1, 2]).expect_one("");
     }
 
     #[test]
     fn test_expect_one_one() {
-        assert_eq!(1, OneVector::one(1).expect_one(""));
-        assert_eq!(1, OneVector::many(vec![1]).expect_one(""));
-    }
-
-    #[bench]
-    fn fill_small_vec_1_10_with_cap(b: &mut Bencher) {
-        b.iter(|| {
-            let mut sv: SmallVec<[usize; 1]> = SmallVec::with_capacity(10);
-
-            sv.extend(0..10);
-        })
-    }
-
-    #[bench]
-    fn fill_small_vec_1_10_wo_cap(b: &mut Bencher) {
-        b.iter(|| {
-            let mut sv: SmallVec<[usize; 1]> = SmallVec::new();
-
-            sv.extend(0..10);
-        })
-    }
-
-    #[bench]
-    fn fill_small_vec_8_10_with_cap(b: &mut Bencher) {
-        b.iter(|| {
-            let mut sv: SmallVec<[usize; 8]> = SmallVec::with_capacity(10);
-
-            sv.extend(0..10);
-        })
-    }
-
-    #[bench]
-    fn fill_small_vec_8_10_wo_cap(b: &mut Bencher) {
-        b.iter(|| {
-            let mut sv: SmallVec<[usize; 8]> = SmallVec::new();
-
-            sv.extend(0..10);
-        })
-    }
-
-    #[bench]
-    fn fill_small_vec_32_10_with_cap(b: &mut Bencher) {
-        b.iter(|| {
-            let mut sv: SmallVec<[usize; 32]> = SmallVec::with_capacity(10);
-
-            sv.extend(0..10);
-        })
-    }
-
-    #[bench]
-    fn fill_small_vec_32_10_wo_cap(b: &mut Bencher) {
-        b.iter(|| {
-            let mut sv: SmallVec<[usize; 32]> = SmallVec::new();
-
-            sv.extend(0..10);
-        })
-    }
-
-    #[bench]
-    fn fill_small_vec_1_50_with_cap(b: &mut Bencher) {
-        b.iter(|| {
-            let mut sv: SmallVec<[usize; 1]> = SmallVec::with_capacity(50);
-
-            sv.extend(0..50);
-        })
-    }
-
-    #[bench]
-    fn fill_small_vec_1_50_wo_cap(b: &mut Bencher) {
-        b.iter(|| {
-            let mut sv: SmallVec<[usize; 1]> = SmallVec::new();
-
-            sv.extend(0..50);
-        })
-    }
-
-    #[bench]
-    fn fill_small_vec_8_50_with_cap(b: &mut Bencher) {
-        b.iter(|| {
-            let mut sv: SmallVec<[usize; 8]> = SmallVec::with_capacity(50);
-
-            sv.extend(0..50);
-        })
-    }
-
-    #[bench]
-    fn fill_small_vec_8_50_wo_cap(b: &mut Bencher) {
-        b.iter(|| {
-            let mut sv: SmallVec<[usize; 8]> = SmallVec::new();
-
-            sv.extend(0..50);
-        })
-    }
-
-    #[bench]
-    fn fill_small_vec_32_50_with_cap(b: &mut Bencher) {
-        b.iter(|| {
-            let mut sv: SmallVec<[usize; 32]> = SmallVec::with_capacity(50);
-
-            sv.extend(0..50);
-        })
-    }
-
-    #[bench]
-    fn fill_small_vec_32_50_wo_cap(b: &mut Bencher) {
-        b.iter(|| {
-            let mut sv: SmallVec<[usize; 32]> = SmallVec::new();
-
-            sv.extend(0..50);
-        })
+        assert_eq!(1, (smallvec![1] as OneVector<_>).expect_one(""));
+        assert_eq!(1, OneVector::from_vec(vec![1]).expect_one(""));
     }
 }
index 9f1c7dac1194ef3c48f20b46a11e092232204642..1024e69cc2b0e889b67d74b35ad75fbfba58240e 100644 (file)
@@ -432,7 +432,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 
-impl<I: ::indexed_vec::Idx, CTX> HashStable<CTX> for ::indexed_set::IdxSetBuf<I>
+impl<I: ::indexed_vec::Idx, CTX> HashStable<CTX> for ::indexed_set::IdxSet<I>
 {
     fn hash_stable<W: StableHasherResult>(&self,
                                           ctx: &mut CTX,
index d4c6b1c2ced812fc4ddce1fedc8988180ec8665d..6989cdc0a9a15afaf1e545cb3a10068f918d40b5 100644 (file)
@@ -26,7 +26,7 @@
 //!
 //! `MTLock` is a mutex which disappears if cfg!(parallel_queries) is false.
 //!
-//! `MTRef` is a immutable refernce if cfg!(parallel_queries), and an mutable reference otherwise.
+//! `MTRef` is a immutable reference if cfg!(parallel_queries), and an mutable reference otherwise.
 //!
 //! `rustc_erase_owner!` erases a OwningRef owner into Erased or Erased + Send + Sync
 //! depending on the value of cfg!(parallel_queries).
@@ -432,7 +432,7 @@ pub fn init_nonlocking<F: FnOnce() -> T>(&self, f: F) -> Option<T> {
     /// closures may concurrently be computing a value which the inner value should take.
     /// Only one of these closures are used to actually initialize the value.
     /// If some other closure already set the value, we assert that it our closure computed
-    /// a value equal to the value aready set and then
+    /// a value equal to the value already set and then
     /// we return the value our closure computed wrapped in a `Option`.
     /// If our closure set the value, `None` is returned.
     /// If the value is already initialized, the closure is not called and `None` is returned.
diff --git a/src/librustc_data_structures/vec_linked_list.rs b/src/librustc_data_structures/vec_linked_list.rs
new file mode 100644 (file)
index 0000000..390dca6
--- /dev/null
@@ -0,0 +1,83 @@
+// 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 indexed_vec::{Idx, IndexVec};
+
+pub fn iter<Ls>(
+    first: Option<Ls::LinkIndex>,
+    links: &'a Ls,
+) -> impl Iterator<Item = Ls::LinkIndex> + 'a
+where
+    Ls: Links,
+{
+    VecLinkedListIterator {
+        links: links,
+        current: first,
+    }
+}
+
+pub struct VecLinkedListIterator<Ls>
+where
+    Ls: Links,
+{
+    links: Ls,
+    current: Option<Ls::LinkIndex>,
+}
+
+impl<Ls> Iterator for VecLinkedListIterator<Ls>
+where
+    Ls: Links,
+{
+    type Item = Ls::LinkIndex;
+
+    fn next(&mut self) -> Option<Ls::LinkIndex> {
+        if let Some(c) = self.current {
+            self.current = <Ls as Links>::next(&self.links, c);
+            Some(c)
+        } else {
+            None
+        }
+    }
+}
+
+pub trait Links {
+    type LinkIndex: Copy;
+
+    fn next(links: &Self, index: Self::LinkIndex) -> Option<Self::LinkIndex>;
+}
+
+impl<Ls> Links for &Ls
+where
+    Ls: Links,
+{
+    type LinkIndex = Ls::LinkIndex;
+
+    fn next(links: &Self, index: Ls::LinkIndex) -> Option<Ls::LinkIndex> {
+        <Ls as Links>::next(links, index)
+    }
+}
+
+pub trait LinkElem {
+    type LinkIndex: Copy;
+
+    fn next(elem: &Self) -> Option<Self::LinkIndex>;
+}
+
+impl<L, E> Links for IndexVec<L, E>
+where
+    E: LinkElem<LinkIndex = L>,
+    L: Idx,
+{
+    type LinkIndex = L;
+
+    fn next(links: &Self, index: L) -> Option<L> {
+        <E as LinkElem>::next(&links[index])
+    }
+}
index b8e8b249bb504018d2f5037ee0072a6eabdeff27..0c8ec753a18f6e6e126e7d263d4fce910c7c5506 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use indexed_set::IdxSetBuf;
+use indexed_set::IdxSet;
 use indexed_vec::Idx;
 use std::collections::VecDeque;
 
@@ -20,7 +20,7 @@
 /// and also use a bit set to track occupancy.
 pub struct WorkQueue<T: Idx> {
     deque: VecDeque<T>,
-    set: IdxSetBuf<T>,
+    set: IdxSet<T>,
 }
 
 impl<T: Idx> WorkQueue<T> {
@@ -29,7 +29,7 @@ impl<T: Idx> WorkQueue<T> {
     pub fn with_all(len: usize) -> Self {
         WorkQueue {
             deque: (0..len).map(T::new).collect(),
-            set: IdxSetBuf::new_filled(len),
+            set: IdxSet::new_filled(len),
         }
     }
 
@@ -38,7 +38,7 @@ pub fn with_all(len: usize) -> Self {
     pub fn with_none(len: usize) -> Self {
         WorkQueue {
             deque: VecDeque::with_capacity(len),
-            set: IdxSetBuf::new_empty(len),
+            set: IdxSet::new_empty(len),
         }
     }
 
index 1c2c0ad73a89751a587904d666bdeead2e19a3df..c6344cb921044fa9d7e8e76687130fb6fda4fa61 100644 (file)
@@ -924,8 +924,8 @@ pub fn phase_2_configure_and_expand_inner<'a, 'b: 'a, F>(
             ls.register_late_pass(Some(sess), true, pass);
         }
 
-        for (name, to) in lint_groups {
-            ls.register_group(Some(sess), true, name, to);
+        for (name, (to, deprecated_name)) in lint_groups {
+            ls.register_group(Some(sess), true, name, deprecated_name, to);
         }
 
         *sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
index f88c619bf77918454f11db0771c4dc2f7c73de65..13e1df6e538887c4735a413a4da600351b55d40c 100644 (file)
@@ -21,6 +21,7 @@
 #![feature(box_syntax)]
 #![cfg_attr(unix, feature(libc))]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(option_replace)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
@@ -185,27 +186,29 @@ pub fn run<F>(run_compiler: F) -> isize
     where F: FnOnce() -> (CompileResult, Option<Session>) + Send + 'static
 {
     let result = monitor(move || {
-        let (result, session) = run_compiler();
-        if let Err(CompileIncomplete::Errored(_)) = result {
-            match session {
-                Some(sess) => {
-                    sess.abort_if_errors();
-                    panic!("error reported but abort_if_errors didn't abort???");
-                }
-                None => {
-                    let emitter =
-                        errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
-                                                               None,
-                                                               true,
-                                                               false);
-                    let handler = errors::Handler::with_emitter(true, false, Box::new(emitter));
-                    handler.emit(&MultiSpan::new(),
-                                 "aborting due to previous error(s)",
-                                 errors::Level::Fatal);
-                    panic::resume_unwind(Box::new(errors::FatalErrorMarker));
+        syntax::with_globals(|| {
+            let (result, session) = run_compiler();
+            if let Err(CompileIncomplete::Errored(_)) = result {
+                match session {
+                    Some(sess) => {
+                        sess.abort_if_errors();
+                        panic!("error reported but abort_if_errors didn't abort???");
+                    }
+                    None => {
+                        let emitter =
+                            errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
+                                                                None,
+                                                                true,
+                                                                false);
+                        let handler = errors::Handler::with_emitter(true, false, Box::new(emitter));
+                        handler.emit(&MultiSpan::new(),
+                                    "aborting due to previous error(s)",
+                                    errors::Level::Fatal);
+                        panic::resume_unwind(Box::new(errors::FatalErrorMarker));
+                    }
                 }
             }
-        }
+        });
     });
 
     match result {
@@ -471,17 +474,15 @@ pub fn run_compiler<'a>(args: &[String],
                         emitter_dest: Option<Box<dyn Write + Send>>)
                         -> (CompileResult, Option<Session>)
 {
-    syntax::with_globals(|| {
-        let matches = match handle_options(args) {
-            Some(matches) => matches,
-            None => return (Ok(()), None),
-        };
+    let matches = match handle_options(args) {
+        Some(matches) => matches,
+        None => return (Ok(()), None),
+    };
 
-        let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
+    let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
 
-        driver::spawn_thread_pool(sopts, |sopts| {
-            run_compiler_with_pool(matches, sopts, cfg, callbacks, file_loader, emitter_dest)
-        })
+    driver::spawn_thread_pool(sopts, |sopts| {
+        run_compiler_with_pool(matches, sopts, cfg, callbacks, file_loader, emitter_dest)
     })
 }
 
index 65cbee821e86443cd31e27e9737b96e99f9061a0..c49631515eab9eb6cd63346d53e8e58a7361359f 100644 (file)
@@ -355,33 +355,33 @@ fn pp_ann<'a>(&'a self) -> &'a dyn pprust::PpAnn {
 impl<'hir> pprust::PpAnn for IdentifiedAnnotation<'hir> {
     fn pre(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> {
         match node {
-            pprust::NodeExpr(_) => s.popen(),
+            pprust::AnnNode::Expr(_) => s.popen(),
             _ => Ok(()),
         }
     }
     fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> {
         match node {
-            pprust::NodeIdent(_) |
-            pprust::NodeName(_) => Ok(()),
+            pprust::AnnNode::Ident(_) |
+            pprust::AnnNode::Name(_) => Ok(()),
 
-            pprust::NodeItem(item) => {
+            pprust::AnnNode::Item(item) => {
                 s.s.space()?;
                 s.synth_comment(item.id.to_string())
             }
-            pprust::NodeSubItem(id) => {
+            pprust::AnnNode::SubItem(id) => {
                 s.s.space()?;
                 s.synth_comment(id.to_string())
             }
-            pprust::NodeBlock(blk) => {
+            pprust::AnnNode::Block(blk) => {
                 s.s.space()?;
                 s.synth_comment(format!("block {}", blk.id))
             }
-            pprust::NodeExpr(expr) => {
+            pprust::AnnNode::Expr(expr) => {
                 s.s.space()?;
                 s.synth_comment(expr.id.to_string())?;
                 s.pclose()
             }
-            pprust::NodePat(pat) => {
+            pprust::AnnNode::Pat(pat) => {
                 s.s.space()?;
                 s.synth_comment(format!("pat {}", pat.id))
             }
@@ -414,34 +414,34 @@ fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested)
     }
     fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
         match node {
-            pprust_hir::NodeExpr(_) => s.popen(),
+            pprust_hir::AnnNode::Expr(_) => s.popen(),
             _ => Ok(()),
         }
     }
     fn post(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
         match node {
-            pprust_hir::NodeName(_) => Ok(()),
-            pprust_hir::NodeItem(item) => {
+            pprust_hir::AnnNode::Name(_) => Ok(()),
+            pprust_hir::AnnNode::Item(item) => {
                 s.s.space()?;
                 s.synth_comment(format!("node_id: {} hir local_id: {}",
                                         item.id, item.hir_id.local_id.0))
             }
-            pprust_hir::NodeSubItem(id) => {
+            pprust_hir::AnnNode::SubItem(id) => {
                 s.s.space()?;
                 s.synth_comment(id.to_string())
             }
-            pprust_hir::NodeBlock(blk) => {
+            pprust_hir::AnnNode::Block(blk) => {
                 s.s.space()?;
                 s.synth_comment(format!("block node_id: {} hir local_id: {}",
                                         blk.id, blk.hir_id.local_id.0))
             }
-            pprust_hir::NodeExpr(expr) => {
+            pprust_hir::AnnNode::Expr(expr) => {
                 s.s.space()?;
                 s.synth_comment(format!("node_id: {} hir local_id: {}",
                                         expr.id, expr.hir_id.local_id.0))?;
                 s.pclose()
             }
-            pprust_hir::NodePat(pat) => {
+            pprust_hir::AnnNode::Pat(pat) => {
                 s.s.space()?;
                 s.synth_comment(format!("pat node_id: {} hir local_id: {}",
                                         pat.id, pat.hir_id.local_id.0))
@@ -467,13 +467,13 @@ fn pp_ann(&self) -> &dyn pprust::PpAnn {
 impl<'a> pprust::PpAnn for HygieneAnnotation<'a> {
     fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> {
         match node {
-            pprust::NodeIdent(&ast::Ident { name, span }) => {
+            pprust::AnnNode::Ident(&ast::Ident { name, span }) => {
                 s.s.space()?;
                 // FIXME #16420: this doesn't display the connections
                 // between syntax contexts
                 s.synth_comment(format!("{}{:?}", name.as_u32(), span.ctxt()))
             }
-            pprust::NodeName(&name) => {
+            pprust::AnnNode::Name(&name) => {
                 s.s.space()?;
                 s.synth_comment(name.as_u32().to_string())
             }
@@ -519,13 +519,13 @@ fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested)
     }
     fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
         match node {
-            pprust_hir::NodeExpr(_) => s.popen(),
+            pprust_hir::AnnNode::Expr(_) => s.popen(),
             _ => Ok(()),
         }
     }
     fn post(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
         match node {
-            pprust_hir::NodeExpr(expr) => {
+            pprust_hir::AnnNode::Expr(expr) => {
                 s.s.space()?;
                 s.s.word("as")?;
                 s.s.space()?;
index f31111e37ba08d40569e0d73fd19e09d098f5b2e..e329b037d22aafce284a8e8337467d9fb7fe863e 100644 (file)
 
 use super::*;
 use syntax_pos::SpanData;
+use rustc_data_structures::fx::FxHashMap;
 use rustc::util::common::QueryMsg;
 use std::fs::File;
 use std::time::{Duration, Instant};
-use std::collections::hash_map::HashMap;
 use rustc::dep_graph::{DepNode};
 
 #[derive(Debug, Clone, Eq, PartialEq)]
@@ -85,7 +85,7 @@ pub fn html_of_effect(eff: &Effect) -> (String, String) {
 fn html_of_duration(_start: &Instant, dur: &Duration) -> (String, String) {
     use rustc::util::common::duration_to_secs_str;
     (duration_to_secs_str(dur.clone()),
-     "".to_string()
+     String::new()
     )
 }
 
@@ -149,7 +149,7 @@ fn write_traces_rec(file: &mut File, traces: &[Rec], total: Duration, depth: usi
     }
 }
 
-fn compute_counts_rec(counts: &mut HashMap<String,QueryMetric>, traces: &[Rec]) {
+fn compute_counts_rec(counts: &mut FxHashMap<String,QueryMetric>, traces: &[Rec]) {
     for t in traces.iter() {
         match t.effect {
             Effect::TimeBegin(ref msg) => {
@@ -200,7 +200,7 @@ fn compute_counts_rec(counts: &mut HashMap<String,QueryMetric>, traces: &[Rec])
     }
 }
 
-pub fn write_counts(count_file: &mut File, counts: &mut HashMap<String,QueryMetric>) {
+pub fn write_counts(count_file: &mut File, counts: &mut FxHashMap<String,QueryMetric>) {
     use rustc::util::common::duration_to_secs_str;
     use std::cmp::Reverse;
 
@@ -219,7 +219,7 @@ pub fn write_counts(count_file: &mut File, counts: &mut HashMap<String,QueryMetr
 
 pub fn write_traces(html_file: &mut File, counts_file: &mut File, traces: &[Rec]) {
     let capacity = traces.iter().fold(0, |acc, t| acc + 1 + t.extent.len());
-    let mut counts : HashMap<String, QueryMetric> = HashMap::with_capacity(capacity);
+    let mut counts = FxHashMap::with_capacity_and_hasher(capacity, Default::default());
     compute_counts_rec(&mut counts, traces);
     write_counts(counts_file, &mut counts);
 
index b4034a6a529bd65313240732ae5f1e93124103f5..5f275b700387360eaec802315d1fffc30a726853 100644 (file)
 use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style};
 use styled_buffer::StyledBuffer;
 
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use atty;
 use std::borrow::Cow;
 use std::io::prelude::*;
 use std::io;
-use std::collections::HashMap;
 use std::cmp::{min, Reverse};
 use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter};
 use termcolor::{WriteColor, Color, Buffer};
@@ -798,7 +798,7 @@ fn fix_multispan_in_std_macros(&mut self,
                                                          // at by "in this macro invocation"
                                                          format!(" (#{})", i + 1)
                                                      } else {
-                                                         "".to_string()
+                                                         String::new()
                                                      })));
                         }
                         // Check to make sure we're not in any <*macros>
@@ -813,7 +813,7 @@ fn fix_multispan_in_std_macros(&mut self,
                                                          // backtrace is multiple levels deep
                                                          format!(" (#{})", i + 1)
                                                      } else {
-                                                         "".to_string()
+                                                         String::new()
                                                      })));
                             if !always_backtrace {
                                 break;
@@ -1065,7 +1065,7 @@ fn emit_message_default(&mut self,
                     let col = if let Some(first_annotation) = first_line.annotations.first() {
                         format!(":{}", first_annotation.start_col + 1)
                     } else {
-                        "".to_string()
+                        String::new()
                     };
                     format!("{}:{}{}",
                             annotated_file.file.name,
@@ -1090,7 +1090,7 @@ fn emit_message_default(&mut self,
                                             max_line_num_len + 1);
 
                 // Contains the vertical lines' positions for active multiline annotations
-                let mut multilines = HashMap::new();
+                let mut multilines = FxHashMap::default();
 
                 // Next, output the annotate source for this file
                 for line_idx in 0..annotated_file.lines.len() {
@@ -1109,7 +1109,7 @@ fn emit_message_default(&mut self,
                                                          width_offset,
                                                          code_offset);
 
-                    let mut to_add = HashMap::new();
+                    let mut to_add = FxHashMap::default();
 
                     for (depth, style) in depths {
                         if multilines.get(&depth).is_some() {
index 3582c2359c8b9f653f5ed5d27148f2845e18e801..d31db4b2d00acc8b9e706fbf46cef352ba871ee4 100644 (file)
@@ -17,6 +17,7 @@
 #![feature(range_contains)]
 #![cfg_attr(unix, feature(libc))]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(optin_builtin_traits)]
 
 extern crate atty;
index dff8d53986db598a204fba5e6c32b355e8bc71cb..e5baf93b00064abf32a50b65f3cd1ea70a0de1af 100644 (file)
@@ -22,7 +22,7 @@
 use std::any::Any;
 
 #[cfg(windows)]
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 pub fn acquire_global_lock(name: &str) -> Box<dyn Any> {
     use std::ffi::CString;
     use std::io;
index 83737681471e2f6fd9e1db306940e9aee0f9ce60..9a2302171bab3fe8fb222e22f875b15c6f9526f7 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::HashMap;
+use rustc_data_structures::fx::FxHashMap;
 
 #[derive(Clone)]
 pub struct Registry {
-    descriptions: HashMap<&'static str, &'static str>,
+    descriptions: FxHashMap<&'static str, &'static str>,
 }
 
 impl Registry {
index ad8714fa4d52dc2a6e806e0f878853acac510860..e100b49c7f244242141a2070cc83c812e7dd9efa 100644 (file)
@@ -15,6 +15,7 @@
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(specialization)]
 
 #![recursion_limit="256"]
index 7f2da5a326aceca1e3be76bc2e4ee6fa44ef00e0..1b3819474c22e6b8e4a3f8ce6ffc49c89ce9d705 100644 (file)
 //! the required condition is not met.
 //!
 
-use std::collections::HashSet;
 use std::iter::FromIterator;
 use std::vec::Vec;
 use rustc::dep_graph::{DepNode, label_strs};
 use rustc::hir;
 use rustc::hir::{ItemKind as HirItem, ImplItemKind, TraitItemKind};
-use rustc::hir::map::Node as HirNode;
+use rustc::hir::Node as HirNode;
 use rustc::hir::def_id::DefId;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir::intravisit;
 //
 //     TypeOfItem for these.
 
-type Labels = HashSet<String>;
+type Labels = FxHashSet<String>;
 
 /// Represents the requested configuration by rustc_clean/dirty
 struct Assertion {
@@ -205,13 +204,13 @@ impl Assertion {
     fn from_clean_labels(labels: Labels) -> Assertion {
         Assertion {
             clean: labels,
-            dirty: Labels::new(),
+            dirty: Labels::default(),
         }
     }
 
     fn from_dirty_labels(labels: Labels) -> Assertion {
         Assertion {
-            clean: Labels::new(),
+            clean: Labels::default(),
             dirty: labels,
         }
     }
@@ -328,7 +327,7 @@ fn except(&self, attr: &Attribute) -> Labels {
             }
         }
         // if no `label` or `except` is given, only the node's group are asserted
-        Labels::new()
+        Labels::default()
     }
 
     /// Return all DepNode labels that should be asserted for this item.
@@ -336,7 +335,7 @@ fn except(&self, attr: &Attribute) -> Labels {
     fn auto_labels(&mut self, item_id: ast::NodeId, attr: &Attribute) -> (&'static str, Labels) {
         let node = self.tcx.hir.get(item_id);
         let (name, labels) = match node {
-            HirNode::NodeItem(item) => {
+            HirNode::Item(item) => {
                 match item.node {
                     // note: these are in the same order as hir::Item_;
                     // FIXME(michaelwoerister): do commented out ones
@@ -399,22 +398,23 @@ fn auto_labels(&mut self, item_id: ast::NodeId, attr: &Attribute) -> (&'static s
                     _ => self.tcx.sess.span_fatal(
                         attr.span,
                         &format!(
-                            "clean/dirty auto-assertions not yet defined for NodeItem.node={:?}",
+                            "clean/dirty auto-assertions not yet defined \
+                             for Node::Item.node={:?}",
                             item.node
                         )
                     ),
                 }
             },
-            HirNode::NodeTraitItem(item) => {
+            HirNode::TraitItem(item) => {
                 match item.node {
-                    TraitItemKind::Method(..) => ("NodeTraitItem", LABELS_FN_IN_TRAIT),
+                    TraitItemKind::Method(..) => ("Node::TraitItem", LABELS_FN_IN_TRAIT),
                     TraitItemKind::Const(..) => ("NodeTraitConst", LABELS_CONST_IN_TRAIT),
                     TraitItemKind::Type(..) => ("NodeTraitType", LABELS_CONST_IN_TRAIT),
                 }
             },
-            HirNode::NodeImplItem(item) => {
+            HirNode::ImplItem(item) => {
                 match item.node {
-                    ImplItemKind::Method(..) => ("NodeImplItem", LABELS_FN_IN_IMPL),
+                    ImplItemKind::Method(..) => ("Node::ImplItem", LABELS_FN_IN_IMPL),
                     ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL),
                     ImplItemKind::Type(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
                     ImplItemKind::Existential(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
@@ -435,7 +435,7 @@ fn auto_labels(&mut self, item_id: ast::NodeId, attr: &Attribute) -> (&'static s
     }
 
     fn resolve_labels(&self, item: &NestedMetaItem, value: &str) -> Labels {
-        let mut out: Labels = HashSet::new();
+        let mut out = Labels::default();
         for label in value.split(',') {
             let label = label.trim();
             if DepNode::has_label_string(label) {
diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs
deleted file mode 100644 (file)
index 09871c0..0000000
+++ /dev/null
@@ -1,416 +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.
-
-use rustc::hir::def::Def;
-use rustc::ty;
-use lint::{LateContext, LintContext, LintArray};
-use lint::{LintPass, LateLintPass};
-
-use rustc_target::spec::abi::Abi;
-use syntax::ast;
-use syntax::attr;
-use syntax_pos::Span;
-
-use rustc::hir::{self, GenericParamKind, PatKind};
-use rustc::hir::intravisit::FnKind;
-
-#[derive(PartialEq)]
-pub enum MethodLateContext {
-    TraitAutoImpl,
-    TraitImpl,
-    PlainImpl,
-}
-
-pub fn method_context(cx: &LateContext, id: ast::NodeId) -> MethodLateContext {
-    let def_id = cx.tcx.hir.local_def_id(id);
-    let item = cx.tcx.associated_item(def_id);
-    match item.container {
-        ty::TraitContainer(..) => MethodLateContext::TraitAutoImpl,
-        ty::ImplContainer(cid) => {
-            match cx.tcx.impl_trait_ref(cid) {
-                Some(_) => MethodLateContext::TraitImpl,
-                None => MethodLateContext::PlainImpl,
-            }
-        }
-    }
-}
-
-declare_lint! {
-    pub NON_CAMEL_CASE_TYPES,
-    Warn,
-    "types, variants, traits and type parameters should have camel case names"
-}
-
-#[derive(Copy, Clone)]
-pub struct NonCamelCaseTypes;
-
-impl NonCamelCaseTypes {
-    fn check_case(&self, cx: &LateContext, sort: &str, name: ast::Name, span: Span) {
-        fn char_has_case(c: char) -> bool {
-            c.is_lowercase() || c.is_uppercase()
-        }
-
-        fn is_camel_case(name: ast::Name) -> bool {
-            let name = name.as_str();
-            if name.is_empty() {
-                return true;
-            }
-            let name = name.trim_matches('_');
-
-            // start with a non-lowercase letter rather than non-uppercase
-            // ones (some scripts don't have a concept of upper/lowercase)
-            !name.is_empty() && !name.chars().next().unwrap().is_lowercase() &&
-                !name.contains("__") && !name.chars().collect::<Vec<_>>().windows(2).any(|pair| {
-                    // contains a capitalisable character followed by, or preceded by, an underscore
-                    char_has_case(pair[0]) && pair[1] == '_' ||
-                    char_has_case(pair[1]) && pair[0] == '_'
-                })
-        }
-
-        fn to_camel_case(s: &str) -> String {
-            s.trim_matches('_')
-                .split('_')
-                .map(|word| {
-                    word.chars().enumerate().map(|(i, c)| if i == 0 {
-                        c.to_uppercase().collect::<String>()
-                    } else {
-                        c.to_lowercase().collect()
-                    })
-                    .collect::<String>()
-                })
-                .filter(|x| !x.is_empty())
-                .fold((String::new(), None), |(acc, prev): (String, Option<String>), next| {
-                    // separate two components with an underscore if their boundary cannot
-                    // be distinguished using a uppercase/lowercase case distinction
-                    let join = if let Some(prev) = prev {
-                                    let l = prev.chars().last().unwrap();
-                                    let f = next.chars().next().unwrap();
-                                    !char_has_case(l) && !char_has_case(f)
-                                } else { false };
-                    (acc + if join { "_" } else { "" } + &next, Some(next))
-                }).0
-        }
-
-        if !is_camel_case(name) {
-            let c = to_camel_case(&name.as_str());
-            let m = if c.is_empty() {
-                format!("{} `{}` should have a camel case name such as `CamelCase`", sort, name)
-            } else {
-                format!("{} `{}` should have a camel case name such as `{}`", sort, name, c)
-            };
-            cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m);
-        }
-    }
-}
-
-impl LintPass for NonCamelCaseTypes {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_CAMEL_CASE_TYPES)
-    }
-}
-
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCamelCaseTypes {
-    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
-        let has_repr_c = it.attrs
-            .iter()
-            .any(|attr| {
-                attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr)
-                    .iter()
-                    .any(|r| r == &attr::ReprC)
-            });
-
-        if has_repr_c {
-            return;
-        }
-
-        match it.node {
-            hir::ItemKind::Ty(..) |
-            hir::ItemKind::Enum(..) |
-            hir::ItemKind::Struct(..) |
-            hir::ItemKind::Union(..) => self.check_case(cx, "type", it.name, it.span),
-            hir::ItemKind::Trait(..) => self.check_case(cx, "trait", it.name, it.span),
-            _ => (),
-        }
-    }
-
-    fn check_variant(&mut self, cx: &LateContext, v: &hir::Variant, _: &hir::Generics) {
-        self.check_case(cx, "variant", v.node.name, v.span);
-    }
-
-    fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
-        match param.kind {
-            GenericParamKind::Lifetime { .. } => {}
-            GenericParamKind::Type { synthetic, .. } => {
-                if synthetic.is_none() {
-                    self.check_case(cx, "type parameter", param.name.ident().name, param.span);
-                }
-            }
-        }
-    }
-}
-
-declare_lint! {
-    pub NON_SNAKE_CASE,
-    Warn,
-    "variables, methods, functions, lifetime parameters and modules should have snake case names"
-}
-
-#[derive(Copy, Clone)]
-pub struct NonSnakeCase;
-
-impl NonSnakeCase {
-    fn to_snake_case(mut str: &str) -> String {
-        let mut words = vec![];
-        // Preserve leading underscores
-        str = str.trim_left_matches(|c: char| {
-            if c == '_' {
-                words.push(String::new());
-                true
-            } else {
-                false
-            }
-        });
-        for s in str.split('_') {
-            let mut last_upper = false;
-            let mut buf = String::new();
-            if s.is_empty() {
-                continue;
-            }
-            for ch in s.chars() {
-                if !buf.is_empty() && buf != "'" && ch.is_uppercase() && !last_upper {
-                    words.push(buf);
-                    buf = String::new();
-                }
-                last_upper = ch.is_uppercase();
-                buf.extend(ch.to_lowercase());
-            }
-            words.push(buf);
-        }
-        words.join("_")
-    }
-
-    fn check_snake_case(&self, cx: &LateContext, sort: &str, name: &str, span: Option<Span>) {
-        fn is_snake_case(ident: &str) -> bool {
-            if ident.is_empty() {
-                return true;
-            }
-            let ident = ident.trim_left_matches('\'');
-            let ident = ident.trim_matches('_');
-
-            let mut allow_underscore = true;
-            ident.chars().all(|c| {
-                allow_underscore = match c {
-                    '_' if !allow_underscore => return false,
-                    '_' => false,
-                    // It would be more obvious to use `c.is_lowercase()`,
-                    // but some characters do not have a lowercase form
-                    c if !c.is_uppercase() => true,
-                    _ => return false,
-                };
-                true
-            })
-        }
-
-        if !is_snake_case(name) {
-            let sc = NonSnakeCase::to_snake_case(name);
-            let msg = if sc != name {
-                format!("{} `{}` should have a snake case name such as `{}`",
-                        sort,
-                        name,
-                        sc)
-            } else {
-                format!("{} `{}` should have a snake case name", sort, name)
-            };
-            match span {
-                Some(span) => cx.span_lint(NON_SNAKE_CASE, span, &msg),
-                None => cx.lint(NON_SNAKE_CASE, &msg),
-            }
-        }
-    }
-}
-
-impl LintPass for NonSnakeCase {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_SNAKE_CASE)
-    }
-}
-
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
-    fn check_crate(&mut self, cx: &LateContext, cr: &hir::Crate) {
-        let attr_crate_name = attr::find_by_name(&cr.attrs, "crate_name")
-            .and_then(|at| at.value_str().map(|s| (at, s)));
-        if let Some(ref name) = cx.tcx.sess.opts.crate_name {
-            self.check_snake_case(cx, "crate", name, None);
-        } else if let Some((attr, name)) = attr_crate_name {
-            self.check_snake_case(cx, "crate", &name.as_str(), Some(attr.span));
-        }
-    }
-
-    fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
-        match param.kind {
-            GenericParamKind::Lifetime { .. } => {
-                let name = param.name.ident().as_str();
-                self.check_snake_case(cx, "lifetime", &name, Some(param.span));
-            }
-            GenericParamKind::Type { .. } => {}
-        }
-    }
-
-    fn check_fn(&mut self,
-                cx: &LateContext,
-                fk: FnKind,
-                _: &hir::FnDecl,
-                _: &hir::Body,
-                span: Span,
-                id: ast::NodeId) {
-        match fk {
-            FnKind::Method(name, ..) => {
-                match method_context(cx, id) {
-                    MethodLateContext::PlainImpl => {
-                        self.check_snake_case(cx, "method", &name.as_str(), Some(span))
-                    }
-                    MethodLateContext::TraitAutoImpl => {
-                        self.check_snake_case(cx, "trait method", &name.as_str(), Some(span))
-                    }
-                    _ => (),
-                }
-            }
-            FnKind::ItemFn(name, _, header, _, attrs) => {
-                // Skip foreign-ABI #[no_mangle] functions (Issue #31924)
-                if header.abi != Abi::Rust && attr::find_by_name(attrs, "no_mangle").is_some() {
-                    return;
-                }
-                self.check_snake_case(cx, "function", &name.as_str(), Some(span))
-            }
-            FnKind::Closure(_) => (),
-        }
-    }
-
-    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
-        if let hir::ItemKind::Mod(_) = it.node {
-            self.check_snake_case(cx, "module", &it.name.as_str(), Some(it.span));
-        }
-    }
-
-    fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
-        if let hir::TraitItemKind::Method(_, hir::TraitMethod::Required(ref pnames)) = item.node {
-            self.check_snake_case(cx,
-                                  "trait method",
-                                  &item.ident.as_str(),
-                                  Some(item.span));
-            for param_name in pnames {
-                self.check_snake_case(cx, "variable", &param_name.as_str(), Some(param_name.span));
-            }
-        }
-    }
-
-    fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
-        if let &PatKind::Binding(_, _, ref ident, _) = &p.node {
-            self.check_snake_case(cx, "variable", &ident.as_str(), Some(p.span));
-        }
-    }
-
-    fn check_struct_def(&mut self,
-                        cx: &LateContext,
-                        s: &hir::VariantData,
-                        _: ast::Name,
-                        _: &hir::Generics,
-                        _: ast::NodeId) {
-        for sf in s.fields() {
-            self.check_snake_case(cx, "structure field", &sf.ident.as_str(), Some(sf.span));
-        }
-    }
-}
-
-declare_lint! {
-    pub NON_UPPER_CASE_GLOBALS,
-    Warn,
-    "static constants should have uppercase identifiers"
-}
-
-#[derive(Copy, Clone)]
-pub struct NonUpperCaseGlobals;
-
-impl NonUpperCaseGlobals {
-    fn check_upper_case(cx: &LateContext, sort: &str, name: ast::Name, span: Span) {
-        if name.as_str().chars().any(|c| c.is_lowercase()) {
-            let uc = NonSnakeCase::to_snake_case(&name.as_str()).to_uppercase();
-            if name != &*uc {
-                cx.span_lint(NON_UPPER_CASE_GLOBALS,
-                             span,
-                             &format!("{} `{}` should have an upper case name such as `{}`",
-                                      sort,
-                                      name,
-                                      uc));
-            } else {
-                cx.span_lint(NON_UPPER_CASE_GLOBALS,
-                             span,
-                             &format!("{} `{}` should have an upper case name", sort, name));
-            }
-        }
-    }
-}
-
-impl LintPass for NonUpperCaseGlobals {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_UPPER_CASE_GLOBALS)
-    }
-}
-
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals {
-    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
-        match it.node {
-            hir::ItemKind::Static(..) => {
-                if attr::find_by_name(&it.attrs, "no_mangle").is_some() {
-                    return;
-                }
-                NonUpperCaseGlobals::check_upper_case(cx, "static variable", it.name, it.span);
-            }
-            hir::ItemKind::Const(..) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "constant", it.name, it.span);
-            }
-            _ => {}
-        }
-    }
-
-    fn check_trait_item(&mut self, cx: &LateContext, ti: &hir::TraitItem) {
-        match ti.node {
-            hir::TraitItemKind::Const(..) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
-                                                      ti.ident.name, ti.span);
-            }
-            _ => {}
-        }
-    }
-
-    fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) {
-        match ii.node {
-            hir::ImplItemKind::Const(..) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
-                                                      ii.ident.name, ii.span);
-            }
-            _ => {}
-        }
-    }
-
-    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 let Def::Const(..) = path.def {
-                if path.segments.len() == 1 {
-                    NonUpperCaseGlobals::check_upper_case(cx,
-                                                          "constant in pattern",
-                                                          path.segments[0].ident.name,
-                                                          path.span);
-                }
-            }
-        }
-    }
-}
index 0936f28a8fb1e991f4496dfb94d797adfd0df213..822590450e278cbb3daeb142f0547353435d103c 100644 (file)
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty};
 use rustc::traits;
-use rustc::hir::map as hir_map;
+use hir::Node;
 use util::nodemap::NodeSet;
 use lint::{LateContext, LintContext, LintArray};
 use lint::{LintPass, LateLintPass, EarlyLintPass, EarlyContext};
 
-use std::collections::HashSet;
 use rustc::util::nodemap::FxHashSet;
 
 use syntax::tokenstream::{TokenTree, TokenStream};
@@ -55,7 +54,7 @@
 use rustc::hir::{self, GenericParamKind, PatKind};
 use rustc::hir::intravisit::FnKind;
 
-use bad_style::{MethodLateContext, method_context};
+use nonstandard_style::{MethodLateContext, method_context};
 
 // hardwired lints from librustc
 pub use lint::builtin::*;
@@ -295,7 +294,8 @@ fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
 declare_lint! {
     pub MISSING_DOCS,
     Allow,
-    "detects missing documentation for public members"
+    "detects missing documentation for public members",
+    report_in_external_macro: true
 }
 
 pub struct MissingDoc {
@@ -304,14 +304,14 @@ pub struct MissingDoc {
     doc_hidden_stack: Vec<bool>,
 
     /// Private traits or trait items that leaked through. Don't check their methods.
-    private_traits: HashSet<ast::NodeId>,
+    private_traits: FxHashSet<ast::NodeId>,
 }
 
 impl MissingDoc {
     pub fn new() -> MissingDoc {
         MissingDoc {
             doc_hidden_stack: vec![false],
-            private_traits: HashSet::new(),
+            private_traits: FxHashSet::default(),
         }
     }
 
@@ -426,7 +426,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                 let real_trait = trait_ref.path.def.def_id();
                 if let Some(node_id) = cx.tcx.hir.as_local_node_id(real_trait) {
                     match cx.tcx.hir.find(node_id) {
-                        Some(hir_map::NodeItem(item)) => {
+                        Some(Node::Item(item)) => {
                             if let hir::VisibilityKind::Inherited = item.vis.node {
                                 for impl_item_ref in impl_item_refs {
                                     self.private_traits.insert(impl_item_ref.id.node_id);
@@ -628,8 +628,7 @@ fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
 declare_lint! {
     pub ANONYMOUS_PARAMETERS,
     Allow,
-    "detects anonymous parameters",
-    Edition::Edition2018 => Warn
+    "detects anonymous parameters"
 }
 
 /// Checks for use of anonymous parameters (RFC 1685)
@@ -794,7 +793,7 @@ fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
                     err.span_suggestion_short_with_applicability(
                         attr.span,
                         "remove this attribute",
-                        "".to_owned(),
+                        String::new(),
                         Applicability::MachineApplicable
                     );
                     err.emit();
@@ -889,7 +888,7 @@ fn check_fn(&mut self,
         // NB. this has an edge case with non-returning statements,
         // like `loop {}` or `panic!()`: control flow never reaches
         // the exit node through these, so one can have a function
-        // that never actually calls itselfs but is still picked up by
+        // that never actually calls itself but is still picked up by
         // this lint:
         //
         //     fn f(cond: bool) {
@@ -909,7 +908,7 @@ fn check_fn(&mut self,
         let mut work_queue = vec![cfg.entry];
         let mut reached_exit_without_self_call = false;
         let mut self_call_spans = vec![];
-        let mut visited = HashSet::new();
+        let mut visited = FxHashSet::default();
 
         while let Some(idx) = work_queue.pop() {
             if idx == cfg.exit {
@@ -980,7 +979,7 @@ fn check_fn(&mut self,
 
         fn expr_refers_to_this_fn(cx: &LateContext, fn_id: ast::NodeId, id: ast::NodeId) -> bool {
             match cx.tcx.hir.get(id) {
-                hir_map::NodeExpr(&hir::Expr { node: hir::ExprKind::Call(ref callee, _), .. }) => {
+                Node::Expr(&hir::Expr { node: hir::ExprKind::Call(ref callee, _), .. }) => {
                     let def = if let hir::ExprKind::Path(ref qpath) = callee.node {
                         cx.tables.qpath_def(qpath, callee.hir_id)
                     } else {
@@ -1003,7 +1002,7 @@ fn expr_refers_to_this_method(cx: &LateContext,
             use rustc::ty::adjustment::*;
 
             // Ignore non-expressions.
-            let expr = if let hir_map::NodeExpr(e) = cx.tcx.hir.get(id) {
+            let expr = if let Node::Expr(e) = cx.tcx.hir.get(id) {
                 e
             } else {
                 return false;
@@ -1250,7 +1249,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                                 err.span_suggestion_short_with_applicability(
                                     no_mangle_attr.span,
                                     "remove this attribute",
-                                    "".to_owned(),
+                                    String::new(),
                                     // Use of `#[no_mangle]` suggests FFI intent; correct
                                     // fix may be to monomorphize source by hand
                                     Applicability::MaybeIncorrect
@@ -1320,7 +1319,7 @@ fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
         let msg = "mutating transmuted &mut T from &T may cause undefined behavior, \
                    consider instead using an UnsafeCell";
         match get_transmute_from_to(cx, expr) {
-            Some((&ty::TyRef(_, _, from_mt), &ty::TyRef(_, _, to_mt))) => {
+            Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) => {
                 if to_mt == hir::Mutability::MutMutable &&
                    from_mt == hir::Mutability::MutImmutable {
                     cx.span_lint(MUTABLE_TRANSMUTES, expr.span, msg);
@@ -1332,7 +1331,7 @@ fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
         fn get_transmute_from_to<'a, 'tcx>
             (cx: &LateContext<'a, 'tcx>,
              expr: &hir::Expr)
-             -> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> {
+             -> Option<(&'tcx ty::TyKind<'tcx>, &'tcx ty::TyKind<'tcx>)> {
             let def = if let hir::ExprKind::Path(ref qpath) = expr.node {
                 cx.tables.qpath_def(qpath, expr.hir_id)
             } else {
@@ -1613,23 +1612,16 @@ fn validate_const<'a, 'tcx>(
     gid: ::rustc::mir::interpret::GlobalId<'tcx>,
     what: &str,
 ) {
-    let mut ecx = ::rustc_mir::interpret::mk_eval_cx(tcx, gid.instance, param_env).unwrap();
+    let ecx = ::rustc_mir::interpret::mk_eval_cx(tcx, gid.instance, param_env).unwrap();
     let result = (|| {
-        let val = ecx.const_to_value(constant.val)?;
-        use rustc_target::abi::LayoutOf;
-        let layout = ecx.layout_of(constant.ty)?;
-        let place = ecx.allocate_place_for_value(val, layout, None)?;
-        let ptr = place.to_ptr()?;
-        let mut todo = vec![(ptr, layout.ty, String::new())];
+        let op = ecx.const_to_op(constant)?;
+        let mut todo = vec![(op, Vec::new())];
         let mut seen = FxHashSet();
-        seen.insert((ptr, layout.ty));
-        while let Some((ptr, ty, path)) = todo.pop() {
-            let layout = ecx.layout_of(ty)?;
-            ecx.validate_ptr_target(
-                ptr,
-                layout.align,
-                layout,
-                path,
+        seen.insert(op);
+        while let Some((op, mut path)) = todo.pop() {
+            ecx.validate_operand(
+                op,
+                &mut path,
                 &mut seen,
                 &mut todo,
             )?;
@@ -1864,7 +1856,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                     if attr.name() == "test" {
                         let parent = cx.tcx.hir.get_parent(it.id);
                         match cx.tcx.hir.find(parent) {
-                            Some(hir_map::NodeItem(hir::Item {node: hir::ItemKind::Mod(_), ..})) |
+                            Some(Node::Item(hir::Item {node: hir::ItemKind::Mod(_), ..})) |
                             None => {}
                             _ => {
                                 cx.struct_span_lint(
@@ -1884,30 +1876,33 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
 }
 
 declare_lint! {
-    pub ASYNC_IDENTS,
+    pub KEYWORD_IDENTS,
     Allow,
-    "detects `async` being used as an identifier"
+    "detects edition keywords being used as an identifier"
 }
 
-/// Checks for uses of `async` as an identifier
+/// Checks for uses of edtion keywords used as an identifier
 #[derive(Clone)]
-pub struct Async2018;
+pub struct KeywordIdents;
 
-impl LintPass for Async2018 {
+impl LintPass for KeywordIdents {
     fn get_lints(&self) -> LintArray {
-        lint_array!(ASYNC_IDENTS)
+        lint_array!(KEYWORD_IDENTS)
     }
 }
 
-impl Async2018 {
+impl KeywordIdents {
     fn check_tokens(&mut self, cx: &EarlyContext, tokens: TokenStream) {
         for tt in tokens.into_trees() {
             match tt {
                 TokenTree::Token(span, tok) => match tok.ident() {
                     // only report non-raw idents
-                    Some((ident, false)) if ident.as_str() == "async" => {
-                        self.report(cx, span.substitute_dummy(ident.span))
-                    },
+                    Some((ident, false)) => {
+                        self.check_ident(cx, ast::Ident {
+                            span: span.substitute_dummy(ident.span),
+                            ..ident
+                        });
+                    }
                     _ => {},
                 }
                 TokenTree::Delimited(_, ref delim) => {
@@ -1916,31 +1911,9 @@ fn check_tokens(&mut self, cx: &EarlyContext, tokens: TokenStream) {
             }
         }
     }
-    fn report(&mut self, cx: &EarlyContext, span: Span) {
-        // don't lint `r#async`
-        if cx.sess.parse_sess.raw_identifier_spans.borrow().contains(&span) {
-            return;
-        }
-        let mut lint = cx.struct_span_lint(
-            ASYNC_IDENTS,
-            span,
-            "`async` is a keyword in the 2018 edition",
-        );
-
-        // Don't suggest about raw identifiers if the feature isn't active
-        if cx.sess.features_untracked().raw_identifiers {
-            lint.span_suggestion_with_applicability(
-                span,
-                "you can use a raw identifier to stay compatible",
-                "r#async".to_string(),
-                Applicability::MachineApplicable,
-            );
-        }
-        lint.emit()
-    }
 }
 
-impl EarlyLintPass for Async2018 {
+impl EarlyLintPass for KeywordIdents {
     fn check_mac_def(&mut self, cx: &EarlyContext, mac_def: &ast::MacroDef, _id: ast::NodeId) {
         self.check_tokens(cx, mac_def.stream());
     }
@@ -1948,8 +1921,37 @@ fn check_mac(&mut self, cx: &EarlyContext, mac: &ast::Mac) {
         self.check_tokens(cx, mac.node.tts.clone().into());
     }
     fn check_ident(&mut self, cx: &EarlyContext, ident: ast::Ident) {
-        if ident.as_str() == "async" {
-            self.report(cx, ident.span);
+        let next_edition = match cx.sess.edition() {
+            Edition::Edition2015 => {
+                match &ident.as_str()[..] {
+                    "async" |
+                    "try" => Edition::Edition2018,
+                    _ => return,
+                }
+            }
+
+            // no new keywords yet for 2018 edition and beyond
+            _ => return,
+        };
+
+        // don't lint `r#foo`
+        if cx.sess.parse_sess.raw_identifier_spans.borrow().contains(&ident.span) {
+            return;
         }
+
+        let mut lint = cx.struct_span_lint(
+            KEYWORD_IDENTS,
+            ident.span,
+            &format!("`{}` is a keyword in the {} edition",
+                     ident.as_str(),
+                     next_edition),
+        );
+        lint.span_suggestion_with_applicability(
+            ident.span,
+            "you can use a raw identifier to stay compatible",
+            format!("r#{}", ident.as_str()),
+            Applicability::MachineApplicable,
+        );
+        lint.emit()
     }
 }
index 801604d1379e33f4244b34b5dce8daca9b8e3f8e..46c5b0092a271e8d0caba276bc8ed45a4767c36a 100644 (file)
@@ -26,8 +26,9 @@
 #![cfg_attr(test, feature(test))]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(macro_at_most_once_rep)]
 use lint::LintId;
 use lint::FutureIncompatibleInfo;
 
-mod bad_style;
+mod nonstandard_style;
 pub mod builtin;
 mod types;
 mod unused;
 
-use bad_style::*;
+use nonstandard_style::*;
 use builtin::*;
 use types::*;
 use unused::*;
@@ -104,12 +105,12 @@ macro_rules! add_early_builtin_with_new {
 
     macro_rules! add_lint_group {
         ($sess:ident, $name:expr, $($lint:ident),*) => (
-            store.register_group($sess, false, $name, vec![$(LintId::of($lint)),*]);
+            store.register_group($sess, false, $name, None, vec![$(LintId::of($lint)),*]);
             )
     }
 
     add_pre_expansion_builtin!(sess,
-        Async2018,
+        KeywordIdents,
     );
 
     add_early_builtin!(sess,
@@ -239,7 +240,7 @@ macro_rules! add_lint_group {
             edition: Some(Edition::Edition2018),
         },
         FutureIncompatibleInfo {
-            id: LintId::of(ASYNC_IDENTS),
+            id: LintId::of(KEYWORD_IDENTS),
             reference: "issue #49716 <https://github.com/rust-lang/rust/issues/49716>",
             edition: Some(Edition::Edition2018),
         },
@@ -276,7 +277,7 @@ macro_rules! add_lint_group {
         FutureIncompatibleInfo {
             id: LintId::of(ANONYMOUS_PARAMETERS),
             reference: "issue #41686 <https://github.com/rust-lang/rust/issues/41686>",
-            edition: None,
+            edition: Some(Edition::Edition2018),
         },
         FutureIncompatibleInfo {
             id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES),
@@ -334,7 +335,12 @@ macro_rules! add_lint_group {
             id: LintId::of(QUESTION_MARK_MACRO_SEP),
             reference: "issue #48075 <https://github.com/rust-lang/rust/issues/48075>",
             edition: Some(Edition::Edition2018),
-        }
+        },
+        FutureIncompatibleInfo {
+            id: LintId::of(MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS),
+            reference: "issue #52234 <https://github.com/rust-lang/rust/issues/52234>",
+            edition: None,
+        },
         ]);
 
     // Register renamed and removed lints
@@ -343,6 +349,7 @@ macro_rules! add_lint_group {
     store.register_renamed("bare_trait_object", "bare_trait_objects");
     store.register_renamed("unstable_name_collision", "unstable_name_collisions");
     store.register_renamed("unused_doc_comment", "unused_doc_comments");
+    store.register_renamed("async_idents", "keyword_idents");
     store.register_removed("unknown_features", "replaced by an error");
     store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate");
     store.register_removed("negate_unsigned", "cast a signed value instead");
diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs
new file mode 100644 (file)
index 0000000..09871c0
--- /dev/null
@@ -0,0 +1,416 @@
+// 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.
+
+use rustc::hir::def::Def;
+use rustc::ty;
+use lint::{LateContext, LintContext, LintArray};
+use lint::{LintPass, LateLintPass};
+
+use rustc_target::spec::abi::Abi;
+use syntax::ast;
+use syntax::attr;
+use syntax_pos::Span;
+
+use rustc::hir::{self, GenericParamKind, PatKind};
+use rustc::hir::intravisit::FnKind;
+
+#[derive(PartialEq)]
+pub enum MethodLateContext {
+    TraitAutoImpl,
+    TraitImpl,
+    PlainImpl,
+}
+
+pub fn method_context(cx: &LateContext, id: ast::NodeId) -> MethodLateContext {
+    let def_id = cx.tcx.hir.local_def_id(id);
+    let item = cx.tcx.associated_item(def_id);
+    match item.container {
+        ty::TraitContainer(..) => MethodLateContext::TraitAutoImpl,
+        ty::ImplContainer(cid) => {
+            match cx.tcx.impl_trait_ref(cid) {
+                Some(_) => MethodLateContext::TraitImpl,
+                None => MethodLateContext::PlainImpl,
+            }
+        }
+    }
+}
+
+declare_lint! {
+    pub NON_CAMEL_CASE_TYPES,
+    Warn,
+    "types, variants, traits and type parameters should have camel case names"
+}
+
+#[derive(Copy, Clone)]
+pub struct NonCamelCaseTypes;
+
+impl NonCamelCaseTypes {
+    fn check_case(&self, cx: &LateContext, sort: &str, name: ast::Name, span: Span) {
+        fn char_has_case(c: char) -> bool {
+            c.is_lowercase() || c.is_uppercase()
+        }
+
+        fn is_camel_case(name: ast::Name) -> bool {
+            let name = name.as_str();
+            if name.is_empty() {
+                return true;
+            }
+            let name = name.trim_matches('_');
+
+            // start with a non-lowercase letter rather than non-uppercase
+            // ones (some scripts don't have a concept of upper/lowercase)
+            !name.is_empty() && !name.chars().next().unwrap().is_lowercase() &&
+                !name.contains("__") && !name.chars().collect::<Vec<_>>().windows(2).any(|pair| {
+                    // contains a capitalisable character followed by, or preceded by, an underscore
+                    char_has_case(pair[0]) && pair[1] == '_' ||
+                    char_has_case(pair[1]) && pair[0] == '_'
+                })
+        }
+
+        fn to_camel_case(s: &str) -> String {
+            s.trim_matches('_')
+                .split('_')
+                .map(|word| {
+                    word.chars().enumerate().map(|(i, c)| if i == 0 {
+                        c.to_uppercase().collect::<String>()
+                    } else {
+                        c.to_lowercase().collect()
+                    })
+                    .collect::<String>()
+                })
+                .filter(|x| !x.is_empty())
+                .fold((String::new(), None), |(acc, prev): (String, Option<String>), next| {
+                    // separate two components with an underscore if their boundary cannot
+                    // be distinguished using a uppercase/lowercase case distinction
+                    let join = if let Some(prev) = prev {
+                                    let l = prev.chars().last().unwrap();
+                                    let f = next.chars().next().unwrap();
+                                    !char_has_case(l) && !char_has_case(f)
+                                } else { false };
+                    (acc + if join { "_" } else { "" } + &next, Some(next))
+                }).0
+        }
+
+        if !is_camel_case(name) {
+            let c = to_camel_case(&name.as_str());
+            let m = if c.is_empty() {
+                format!("{} `{}` should have a camel case name such as `CamelCase`", sort, name)
+            } else {
+                format!("{} `{}` should have a camel case name such as `{}`", sort, name, c)
+            };
+            cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m);
+        }
+    }
+}
+
+impl LintPass for NonCamelCaseTypes {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(NON_CAMEL_CASE_TYPES)
+    }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCamelCaseTypes {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        let has_repr_c = it.attrs
+            .iter()
+            .any(|attr| {
+                attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr)
+                    .iter()
+                    .any(|r| r == &attr::ReprC)
+            });
+
+        if has_repr_c {
+            return;
+        }
+
+        match it.node {
+            hir::ItemKind::Ty(..) |
+            hir::ItemKind::Enum(..) |
+            hir::ItemKind::Struct(..) |
+            hir::ItemKind::Union(..) => self.check_case(cx, "type", it.name, it.span),
+            hir::ItemKind::Trait(..) => self.check_case(cx, "trait", it.name, it.span),
+            _ => (),
+        }
+    }
+
+    fn check_variant(&mut self, cx: &LateContext, v: &hir::Variant, _: &hir::Generics) {
+        self.check_case(cx, "variant", v.node.name, v.span);
+    }
+
+    fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
+        match param.kind {
+            GenericParamKind::Lifetime { .. } => {}
+            GenericParamKind::Type { synthetic, .. } => {
+                if synthetic.is_none() {
+                    self.check_case(cx, "type parameter", param.name.ident().name, param.span);
+                }
+            }
+        }
+    }
+}
+
+declare_lint! {
+    pub NON_SNAKE_CASE,
+    Warn,
+    "variables, methods, functions, lifetime parameters and modules should have snake case names"
+}
+
+#[derive(Copy, Clone)]
+pub struct NonSnakeCase;
+
+impl NonSnakeCase {
+    fn to_snake_case(mut str: &str) -> String {
+        let mut words = vec![];
+        // Preserve leading underscores
+        str = str.trim_left_matches(|c: char| {
+            if c == '_' {
+                words.push(String::new());
+                true
+            } else {
+                false
+            }
+        });
+        for s in str.split('_') {
+            let mut last_upper = false;
+            let mut buf = String::new();
+            if s.is_empty() {
+                continue;
+            }
+            for ch in s.chars() {
+                if !buf.is_empty() && buf != "'" && ch.is_uppercase() && !last_upper {
+                    words.push(buf);
+                    buf = String::new();
+                }
+                last_upper = ch.is_uppercase();
+                buf.extend(ch.to_lowercase());
+            }
+            words.push(buf);
+        }
+        words.join("_")
+    }
+
+    fn check_snake_case(&self, cx: &LateContext, sort: &str, name: &str, span: Option<Span>) {
+        fn is_snake_case(ident: &str) -> bool {
+            if ident.is_empty() {
+                return true;
+            }
+            let ident = ident.trim_left_matches('\'');
+            let ident = ident.trim_matches('_');
+
+            let mut allow_underscore = true;
+            ident.chars().all(|c| {
+                allow_underscore = match c {
+                    '_' if !allow_underscore => return false,
+                    '_' => false,
+                    // It would be more obvious to use `c.is_lowercase()`,
+                    // but some characters do not have a lowercase form
+                    c if !c.is_uppercase() => true,
+                    _ => return false,
+                };
+                true
+            })
+        }
+
+        if !is_snake_case(name) {
+            let sc = NonSnakeCase::to_snake_case(name);
+            let msg = if sc != name {
+                format!("{} `{}` should have a snake case name such as `{}`",
+                        sort,
+                        name,
+                        sc)
+            } else {
+                format!("{} `{}` should have a snake case name", sort, name)
+            };
+            match span {
+                Some(span) => cx.span_lint(NON_SNAKE_CASE, span, &msg),
+                None => cx.lint(NON_SNAKE_CASE, &msg),
+            }
+        }
+    }
+}
+
+impl LintPass for NonSnakeCase {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(NON_SNAKE_CASE)
+    }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
+    fn check_crate(&mut self, cx: &LateContext, cr: &hir::Crate) {
+        let attr_crate_name = attr::find_by_name(&cr.attrs, "crate_name")
+            .and_then(|at| at.value_str().map(|s| (at, s)));
+        if let Some(ref name) = cx.tcx.sess.opts.crate_name {
+            self.check_snake_case(cx, "crate", name, None);
+        } else if let Some((attr, name)) = attr_crate_name {
+            self.check_snake_case(cx, "crate", &name.as_str(), Some(attr.span));
+        }
+    }
+
+    fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
+        match param.kind {
+            GenericParamKind::Lifetime { .. } => {
+                let name = param.name.ident().as_str();
+                self.check_snake_case(cx, "lifetime", &name, Some(param.span));
+            }
+            GenericParamKind::Type { .. } => {}
+        }
+    }
+
+    fn check_fn(&mut self,
+                cx: &LateContext,
+                fk: FnKind,
+                _: &hir::FnDecl,
+                _: &hir::Body,
+                span: Span,
+                id: ast::NodeId) {
+        match fk {
+            FnKind::Method(name, ..) => {
+                match method_context(cx, id) {
+                    MethodLateContext::PlainImpl => {
+                        self.check_snake_case(cx, "method", &name.as_str(), Some(span))
+                    }
+                    MethodLateContext::TraitAutoImpl => {
+                        self.check_snake_case(cx, "trait method", &name.as_str(), Some(span))
+                    }
+                    _ => (),
+                }
+            }
+            FnKind::ItemFn(name, _, header, _, attrs) => {
+                // Skip foreign-ABI #[no_mangle] functions (Issue #31924)
+                if header.abi != Abi::Rust && attr::find_by_name(attrs, "no_mangle").is_some() {
+                    return;
+                }
+                self.check_snake_case(cx, "function", &name.as_str(), Some(span))
+            }
+            FnKind::Closure(_) => (),
+        }
+    }
+
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        if let hir::ItemKind::Mod(_) = it.node {
+            self.check_snake_case(cx, "module", &it.name.as_str(), Some(it.span));
+        }
+    }
+
+    fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
+        if let hir::TraitItemKind::Method(_, hir::TraitMethod::Required(ref pnames)) = item.node {
+            self.check_snake_case(cx,
+                                  "trait method",
+                                  &item.ident.as_str(),
+                                  Some(item.span));
+            for param_name in pnames {
+                self.check_snake_case(cx, "variable", &param_name.as_str(), Some(param_name.span));
+            }
+        }
+    }
+
+    fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
+        if let &PatKind::Binding(_, _, ref ident, _) = &p.node {
+            self.check_snake_case(cx, "variable", &ident.as_str(), Some(p.span));
+        }
+    }
+
+    fn check_struct_def(&mut self,
+                        cx: &LateContext,
+                        s: &hir::VariantData,
+                        _: ast::Name,
+                        _: &hir::Generics,
+                        _: ast::NodeId) {
+        for sf in s.fields() {
+            self.check_snake_case(cx, "structure field", &sf.ident.as_str(), Some(sf.span));
+        }
+    }
+}
+
+declare_lint! {
+    pub NON_UPPER_CASE_GLOBALS,
+    Warn,
+    "static constants should have uppercase identifiers"
+}
+
+#[derive(Copy, Clone)]
+pub struct NonUpperCaseGlobals;
+
+impl NonUpperCaseGlobals {
+    fn check_upper_case(cx: &LateContext, sort: &str, name: ast::Name, span: Span) {
+        if name.as_str().chars().any(|c| c.is_lowercase()) {
+            let uc = NonSnakeCase::to_snake_case(&name.as_str()).to_uppercase();
+            if name != &*uc {
+                cx.span_lint(NON_UPPER_CASE_GLOBALS,
+                             span,
+                             &format!("{} `{}` should have an upper case name such as `{}`",
+                                      sort,
+                                      name,
+                                      uc));
+            } else {
+                cx.span_lint(NON_UPPER_CASE_GLOBALS,
+                             span,
+                             &format!("{} `{}` should have an upper case name", sort, name));
+            }
+        }
+    }
+}
+
+impl LintPass for NonUpperCaseGlobals {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(NON_UPPER_CASE_GLOBALS)
+    }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        match it.node {
+            hir::ItemKind::Static(..) => {
+                if attr::find_by_name(&it.attrs, "no_mangle").is_some() {
+                    return;
+                }
+                NonUpperCaseGlobals::check_upper_case(cx, "static variable", it.name, it.span);
+            }
+            hir::ItemKind::Const(..) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "constant", it.name, it.span);
+            }
+            _ => {}
+        }
+    }
+
+    fn check_trait_item(&mut self, cx: &LateContext, ti: &hir::TraitItem) {
+        match ti.node {
+            hir::TraitItemKind::Const(..) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
+                                                      ti.ident.name, ti.span);
+            }
+            _ => {}
+        }
+    }
+
+    fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) {
+        match ii.node {
+            hir::ImplItemKind::Const(..) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
+                                                      ii.ident.name, ii.span);
+            }
+            _ => {}
+        }
+    }
+
+    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 let Def::Const(..) = path.def {
+                if path.segments.len() == 1 {
+                    NonUpperCaseGlobals::check_upper_case(cx,
+                                                          "constant in pattern",
+                                                          path.segments[0].ident.name,
+                                                          path.span);
+                }
+            }
+        }
+    }
+}
index 32a68738fb28dda37051e5e7813d3b0a931b6c6b..2c410e8efb10a65fb0e852b92a83eed75954a6b7 100644 (file)
@@ -10,7 +10,7 @@
 
 #![allow(non_snake_case)]
 
-use rustc::hir::map as hir_map;
+use rustc::hir::Node;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
 use rustc::ty::layout::{self, IntegerExt, LayoutOf};
@@ -84,7 +84,7 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
             }
             hir::ExprKind::Lit(ref lit) => {
                 match cx.tables.node_id_to_type(e.hir_id).sty {
-                    ty::TyInt(t) => {
+                    ty::Int(t) => {
                         match lit.node {
                             ast::LitKind::Int(v, ast::LitIntType::Signed(_)) |
                             ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => {
@@ -104,7 +104,7 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
                                         report_bin_hex_error(
                                             cx,
                                             e,
-                                            ty::TyInt(t),
+                                            ty::Int(t),
                                             repr_str,
                                             v,
                                             negative,
@@ -122,7 +122,7 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
                             _ => bug!(),
                         };
                     }
-                    ty::TyUint(t) => {
+                    ty::Uint(t) => {
                         let uint_type = if let ast::UintTy::Usize = t {
                             cx.sess().target.usize_ty
                         } else {
@@ -137,9 +137,9 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
                         };
                         if lit_val < min || lit_val > max {
                             let parent_id = cx.tcx.hir.get_parent_node(e.id);
-                            if let hir_map::NodeExpr(parent_expr) = cx.tcx.hir.get(parent_id) {
+                            if let Node::Expr(parent_expr) = cx.tcx.hir.get(parent_id) {
                                 if let hir::ExprKind::Cast(..) = parent_expr.node {
-                                    if let ty::TyChar = cx.tables.expr_ty(parent_expr).sty {
+                                    if let ty::Char = cx.tables.expr_ty(parent_expr).sty {
                                         let mut err = cx.struct_span_lint(
                                                              OVERFLOWING_LITERALS,
                                                              parent_expr.span,
@@ -159,7 +159,7 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
                                 report_bin_hex_error(
                                     cx,
                                     e,
-                                    ty::TyUint(t),
+                                    ty::Uint(t),
                                     repr_str,
                                     lit_val,
                                     false,
@@ -173,7 +173,7 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
                             );
                         }
                     }
-                    ty::TyFloat(t) => {
+                    ty::Float(t) => {
                         let is_infinite = match lit.node {
                             ast::LitKind::Float(v, _) |
                             ast::LitKind::FloatUnsuffixed(v) => {
@@ -256,7 +256,7 @@ fn check_limits(cx: &LateContext,
             // the comparison
             let norm_binop = if swap { rev_binop(binop) } else { binop };
             match cx.tables.node_id_to_type(expr.hir_id).sty {
-                ty::TyInt(int_ty) => {
+                ty::Int(int_ty) => {
                     let (min, max) = int_ty_range(int_ty);
                     let lit_val: i128 = match lit.node {
                         hir::ExprKind::Lit(ref li) => {
@@ -270,7 +270,7 @@ fn check_limits(cx: &LateContext,
                     };
                     is_valid(norm_binop, lit_val, min, max)
                 }
-                ty::TyUint(uint_ty) => {
+                ty::Uint(uint_ty) => {
                     let (min, max) :(u128, u128) = uint_ty_range(uint_ty);
                     let lit_val: u128 = match lit.node {
                         hir::ExprKind::Lit(ref li) => {
@@ -321,7 +321,7 @@ fn get_bin_hex_repr(cx: &LateContext, lit: &ast::Lit) -> Option<String> {
         //
         // No suggestion for: `isize`, `usize`.
         fn get_type_suggestion<'a>(
-            t: &ty::TypeVariants,
+            t: &ty::TyKind,
             val: u128,
             negative: bool,
         ) -> Option<String> {
@@ -348,13 +348,13 @@ macro_rules! find_fit {
                 }
             }
             match t {
-                &ty::TyInt(i) => find_fit!(i, val, negative,
+                &ty::Int(i) => find_fit!(i, val, negative,
                               I8 => [U8] => [I16, I32, I64, I128],
                               I16 => [U16] => [I32, I64, I128],
                               I32 => [U32] => [I64, I128],
                               I64 => [U64] => [I128],
                               I128 => [U128] => []),
-                &ty::TyUint(u) => find_fit!(u, val, negative,
+                &ty::Uint(u) => find_fit!(u, val, negative,
                               U8 => [U8, U16, U32, U64, U128] => [],
                               U16 => [U16, U32, U64, U128] => [],
                               U32 => [U32, U64, U128] => [],
@@ -367,19 +367,19 @@ macro_rules! find_fit {
         fn report_bin_hex_error(
             cx: &LateContext,
             expr: &hir::Expr,
-            ty: ty::TypeVariants,
+            ty: ty::TyKind,
             repr_str: String,
             val: u128,
             negative: bool,
         ) {
             let (t, actually) = match ty {
-                ty::TyInt(t) => {
+                ty::Int(t) => {
                     let ity = attr::IntType::SignedInt(t);
                     let bits = layout::Integer::from_attr(cx.tcx, ity).size().bits();
                     let actually = (val << (128 - bits)) as i128 >> (128 - bits);
                     (format!("{:?}", t), actually.to_string())
                 }
-                ty::TyUint(t) => {
+                ty::Uint(t) => {
                     let ity = attr::IntType::UnsignedInt(t);
                     let bits = layout::Integer::from_attr(cx.tcx, ity).size().bits();
                     let actually = (val << (128 - bits)) >> (128 - bits);
@@ -460,10 +460,10 @@ fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         if def.variants[data_idx].fields.len() == 1 {
             match def.variants[data_idx].fields[0].ty(tcx, substs).sty {
-                ty::TyFnPtr(_) => {
+                ty::FnPtr(_) => {
                     return true;
                 }
-                ty::TyRef(..) => {
+                ty::Ref(..) => {
                     return true;
                 }
                 _ => {}
@@ -486,13 +486,13 @@ fn check_type_for_ffi(&self,
         // Protect against infinite recursion, for example
         // `struct S(*mut S);`.
         // FIXME: A recursion limit is necessary as well, for irregular
-        // recusive types.
+        // recursive types.
         if !cache.insert(ty) {
             return FfiSafe;
         }
 
         match ty.sty {
-            ty::TyAdt(def, substs) => {
+            ty::Adt(def, substs) => {
                 if def.is_phantom_data() {
                     return FfiPhantom(ty);
                 }
@@ -633,51 +633,51 @@ fn check_type_for_ffi(&self,
                 }
             }
 
-            ty::TyChar => FfiUnsafe {
+            ty::Char => FfiUnsafe {
                 ty: ty,
                 reason: "the `char` type has no C equivalent",
                 help: Some("consider using `u32` or `libc::wchar_t` instead"),
             },
 
-            ty::TyInt(ast::IntTy::I128) | ty::TyUint(ast::UintTy::U128) => FfiUnsafe {
+            ty::Int(ast::IntTy::I128) | ty::Uint(ast::UintTy::U128) => FfiUnsafe {
                 ty: ty,
                 reason: "128-bit integers don't currently have a known stable ABI",
                 help: None,
             },
 
             // Primitive types with a stable representation.
-            ty::TyBool | ty::TyInt(..) | ty::TyUint(..) | ty::TyFloat(..) | ty::TyNever => FfiSafe,
+            ty::Bool | ty::Int(..) | ty::Uint(..) | ty::Float(..) | ty::Never => FfiSafe,
 
-            ty::TySlice(_) => FfiUnsafe {
+            ty::Slice(_) => FfiUnsafe {
                 ty: ty,
                 reason: "slices have no C equivalent",
                 help: Some("consider using a raw pointer instead"),
             },
 
-            ty::TyDynamic(..) => FfiUnsafe {
+            ty::Dynamic(..) => FfiUnsafe {
                 ty: ty,
                 reason: "trait objects have no C equivalent",
                 help: None,
             },
 
-            ty::TyStr => FfiUnsafe {
+            ty::Str => FfiUnsafe {
                 ty: ty,
                 reason: "string slices have no C equivalent",
                 help: Some("consider using `*const u8` and a length instead"),
             },
 
-            ty::TyTuple(..) => FfiUnsafe {
+            ty::Tuple(..) => FfiUnsafe {
                 ty: ty,
                 reason: "tuples have unspecified layout",
                 help: Some("consider using a struct instead"),
             },
 
-            ty::TyRawPtr(ty::TypeAndMut { ty, .. }) |
-            ty::TyRef(_, ty, _) => self.check_type_for_ffi(cache, ty),
+            ty::RawPtr(ty::TypeAndMut { ty, .. }) |
+            ty::Ref(_, ty, _) => self.check_type_for_ffi(cache, ty),
 
-            ty::TyArray(ty, _) => self.check_type_for_ffi(cache, ty),
+            ty::Array(ty, _) => self.check_type_for_ffi(cache, ty),
 
-            ty::TyFnPtr(sig) => {
+            ty::FnPtr(sig) => {
                 match sig.abi() {
                     Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic | Abi::RustCall => {
                         return FfiUnsafe {
@@ -712,17 +712,17 @@ fn check_type_for_ffi(&self,
                 FfiSafe
             }
 
-            ty::TyForeign(..) => FfiSafe,
-
-            ty::TyParam(..) |
-            ty::TyInfer(..) |
-            ty::TyError |
-            ty::TyClosure(..) |
-            ty::TyGenerator(..) |
-            ty::TyGeneratorWitness(..) |
-            ty::TyProjection(..) |
-            ty::TyAnon(..) |
-            ty::TyFnDef(..) => bug!("Unexpected type in foreign function"),
+            ty::Foreign(..) => FfiSafe,
+
+            ty::Param(..) |
+            ty::Infer(..) |
+            ty::Error |
+            ty::Closure(..) |
+            ty::Generator(..) |
+            ty::GeneratorWitness(..) |
+            ty::Projection(..) |
+            ty::Anon(..) |
+            ty::FnDef(..) => bug!("Unexpected type in foreign function"),
         }
     }
 
@@ -746,7 +746,7 @@ fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) {
                 if let Some(s) = help {
                     diag.help(s);
                 }
-                if let ty::TyAdt(def, _) = unsafe_ty.sty {
+                if let ty::Adt(def, _) = unsafe_ty.sty {
                     if let Some(sp) = self.cx.tcx.hir.span_if_local(def.did) {
                         diag.span_note(sp, "type defined here");
                     }
index 2b8540ea3861a25761de61597d1cae79f8ebefc6..7a9d18676cf6c9d2e405a819d4de8aeaea599fd6 100644 (file)
@@ -60,9 +60,9 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
 
         let t = cx.tables.expr_ty(&expr);
         let ty_warned = match t.sty {
-            ty::TyTuple(ref tys) if tys.is_empty() => return,
-            ty::TyNever => return,
-            ty::TyAdt(def, _) => {
+            ty::Tuple(ref tys) if tys.is_empty() => return,
+            ty::Never => return,
+            ty::Adt(def, _) => {
                 if def.variants.is_empty() {
                     return;
                 } else {
index 387660473a887dea0a2524a4bdceefbd0b78b515..13605e993a59cc5140811691c94590fc9964a15f 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(static_nobundle)]
 
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
index b3ba86ad8a4b32af8f7f6629cca53f8891221b8f..ed8fd305977e5e9b7a71359411211774d4d81420 100644 (file)
@@ -11,6 +11,7 @@
 #![sanitizer_runtime]
 #![feature(alloc_system)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(sanitizer_runtime)]
 #![feature(staged_api)]
 #![no_std]
index c242f8d476a71c2bbbf314984b3f08475c244792..5eb541952150f06cb3955f5089ea1f18a905657e 100644 (file)
@@ -12,6 +12,7 @@
 
 use cstore::{self, CStore, CrateSource, MetadataBlob};
 use locator::{self, CratePaths};
+use decoder::proc_macro_def_path_table;
 use schema::CrateRoot;
 use rustc_data_structures::sync::{Lrc, RwLock, Lock};
 
@@ -219,8 +220,16 @@ fn register_crate(&mut self,
 
         let dependencies: Vec<CrateNum> = cnum_map.iter().cloned().collect();
 
+        let proc_macros = crate_root.macro_derive_registrar.map(|_| {
+            self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
+        });
+
         let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || {
-            crate_root.def_path_table.decode((&metadata, self.sess))
+            if let Some(proc_macros) = &proc_macros {
+                proc_macro_def_path_table(&crate_root, proc_macros)
+            } else {
+                crate_root.def_path_table.decode((&metadata, self.sess))
+            }
         });
 
         let interpret_alloc_index: Vec<u32> = crate_root.interpret_alloc_index
@@ -237,9 +246,7 @@ fn register_crate(&mut self,
             extern_crate: Lock::new(None),
             def_path_table: Lrc::new(def_path_table),
             trait_impls,
-            proc_macros: crate_root.macro_derive_registrar.map(|_| {
-                self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
-            }),
+            proc_macros,
             root: crate_root,
             blob: metadata,
             cnum_map,
index c51bebd2e3b6373e7f07dd69cab27bee24cf8509..5aa05270a2a0ba8d674c7d22571881d780809643 100644 (file)
@@ -17,7 +17,6 @@
 
 use rustc::ty::query::QueryConfig;
 use rustc::middle::cstore::{CrateStore, DepKind,
-                            LinkMeta,
                             EncodedMetadata, NativeLibraryKind};
 use rustc::middle::exported_symbols::ExportedSymbol;
 use rustc::middle::stability::DeprecationEntry;
@@ -43,7 +42,7 @@
 use syntax::parse::source_file_to_stream;
 use syntax::symbol::Symbol;
 use syntax_pos::{Span, NO_EXPANSION, FileName};
-use rustc_data_structures::indexed_set::IdxSetBuf;
+use rustc_data_structures::indexed_set::IdxSet;
 use rustc::hir;
 
 macro_rules! provide {
@@ -142,7 +141,7 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
         mir
     }
     mir_const_qualif => {
-        (cdata.mir_const_qualif(def_id.index), Lrc::new(IdxSetBuf::new_empty(0)))
+        (cdata.mir_const_qualif(def_id.index), Lrc::new(IdxSet::new_empty(0)))
     }
     fn_sig => { cdata.fn_sig(def_id.index, tcx) }
     inherent_impls => { Lrc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
@@ -567,11 +566,10 @@ fn postorder_cnums_untracked(&self) -> Vec<CrateNum> {
     }
 
     fn encode_metadata<'a, 'tcx>(&self,
-                                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                 link_meta: &LinkMeta)
+                                 tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                  -> EncodedMetadata
     {
-        encoder::encode_metadata(tcx, link_meta)
+        encoder::encode_metadata(tcx)
     }
 
     fn metadata_encoding_version(&self) -> &[u8]
index f4dd8861e2a2ce2c81eb8cc2536443f3c98bd2b4..f4456b96027aeba2c9e3685c5b241250fdccf46a 100644 (file)
 use schema::*;
 
 use rustc_data_structures::sync::{Lrc, ReadGuard};
-use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash,
-                      DisambiguatedDefPathData};
+use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, Definitions};
 use rustc::hir;
 use rustc::middle::cstore::LinkagePreference;
 use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc::hir::def::{self, Def, CtorKind};
-use rustc::hir::def_id::{CrateNum, DefId, DefIndex,
+use rustc::hir::def_id::{CrateNum, DefId, DefIndex, DefIndexAddressSpace,
                          CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId};
+use rustc::hir::map::definitions::DefPathTable;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc::middle::lang_items;
 use rustc::mir::{self, interpret};
@@ -41,7 +41,8 @@
 use syntax::ast::{self, Ident};
 use syntax::source_map;
 use syntax::symbol::InternedString;
-use syntax::ext::base::MacroKind;
+use syntax::ext::base::{MacroKind, SyntaxExtension};
+use syntax::ext::hygiene::Mark;
 use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION};
 
 pub struct DecodeContext<'a, 'tcx: 'a> {
@@ -429,7 +430,7 @@ fn to_def(&self, did: DefId) -> Option<Def> {
             EntryKind::Trait(_) => Def::Trait(did),
             EntryKind::Enum(..) => Def::Enum(did),
             EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
-            EntryKind::ForeignType => Def::TyForeign(did),
+            EntryKind::ForeignType => Def::ForeignTy(did),
 
             EntryKind::ForeignMod |
             EntryKind::GlobalAsm |
@@ -441,6 +442,40 @@ fn to_def(&self, did: DefId) -> Option<Def> {
     }
 }
 
+/// Create the "fake" DefPathTable for a given proc macro crate.
+///
+/// The DefPathTable is as follows:
+///
+/// CRATE_ROOT (DefIndex 0:0)
+///  |- GlobalMetaDataKind data (DefIndex 1:0 .. DefIndex 1:N)
+///  |- proc macro #0 (DefIndex 1:N)
+///  |- proc macro #1 (DefIndex 1:N+1)
+///  \- ...
+crate fn proc_macro_def_path_table(crate_root: &CrateRoot,
+                                   proc_macros: &[(ast::Name, Lrc<SyntaxExtension>)])
+                                   -> DefPathTable
+{
+    let mut definitions = Definitions::new();
+
+    let name = crate_root.name.as_str();
+    let disambiguator = crate_root.disambiguator;
+    debug!("creating proc macro def path table for {:?}/{:?}", name, disambiguator);
+    let crate_root = definitions.create_root_def(&name, disambiguator);
+    for (index, (name, _)) in proc_macros.iter().enumerate() {
+        let def_index = definitions.create_def_with_parent(
+            crate_root,
+            ast::DUMMY_NODE_ID,
+            DefPathData::MacroDef(name.as_interned_str()),
+            DefIndexAddressSpace::High,
+            Mark::root(),
+            DUMMY_SP);
+        debug!("definition for {:?} is {:?}", name, def_index);
+        assert_eq!(def_index, DefIndex::from_proc_macro_index(index));
+    }
+
+    definitions.def_path_table().clone()
+}
+
 impl<'a, 'tcx> CrateMetadata {
     fn is_proc_macro(&self, id: DefIndex) -> bool {
         self.proc_macros.is_some() && id != CRATE_DEF_INDEX
@@ -669,6 +704,10 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Sessio
         where F: FnMut(def::Export)
     {
         if let Some(ref proc_macros) = self.proc_macros {
+            /* If we are loading as a proc macro, we want to return the view of this crate
+             * as a proc macro crate, not as a Rust crate. See `proc_macro_def_path_table`
+             * for the DefPathTable we are corresponding to.
+             */
             if id == CRATE_DEF_INDEX {
                 for (id, &(name, ref ext)) in proc_macros.iter().enumerate() {
                     let def = Def::Macro(
@@ -1066,28 +1105,12 @@ pub fn fn_sig(&self,
 
     #[inline]
     pub fn def_key(&self, index: DefIndex) -> DefKey {
-        if !self.is_proc_macro(index) {
-            self.def_path_table.def_key(index)
-        } else {
-            // FIXME(#49271) - It would be better if the DefIds were consistent
-            //                 with the DefPathTable, but for proc-macro crates
-            //                 they aren't.
-            let name = self.proc_macros
-                           .as_ref()
-                           .unwrap()[index.to_proc_macro_index()].0;
-            DefKey {
-                parent: Some(CRATE_DEF_INDEX),
-                disambiguated_data: DisambiguatedDefPathData {
-                    data: DefPathData::MacroDef(name.as_interned_str()),
-                    disambiguator: 0,
-                }
-            }
-        }
+        self.def_path_table.def_key(index)
     }
 
     // Returns the path leading to the thing with this `id`.
     pub fn def_path(&self, id: DefIndex) -> DefPath {
-        debug!("def_path(id={:?})", id);
+        debug!("def_path(cnum={:?}, id={:?})", self.cnum, id);
         DefPath::make(self.cnum, id, |parent| self.def_path_table.def_key(parent))
     }
 
index 1b13c240a87e309556be7c2c1538f07c4f08db38..8219ec3df248aaebdbb096987fe6fae2cb5339d7 100644 (file)
@@ -13,7 +13,7 @@
 use isolated_encoder::IsolatedEncoder;
 use schema::*;
 
-use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary,
+use rustc::middle::cstore::{LinkagePreference, NativeLibrary,
                             EncodedMetadata, ForeignModule};
 use rustc::hir::def::CtorKind;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LocalDefId, LOCAL_CRATE};
@@ -52,7 +52,6 @@
 pub struct EncodeContext<'a, 'tcx: 'a> {
     opaque: opaque::Encoder,
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    link_meta: &'a LinkMeta,
 
     lazy_state: LazyState,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
@@ -482,7 +481,6 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
         let index_bytes = self.position() - i;
 
         let attrs = tcx.hir.krate_attrs();
-        let link_meta = self.link_meta;
         let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
         let has_default_lib_allocator = attr::contains_name(&attrs, "default_lib_allocator");
         let has_global_allocator = *tcx.sess.has_global_allocator.get();
@@ -491,7 +489,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
             name: tcx.crate_name(LOCAL_CRATE),
             extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
             triple: tcx.sess.opts.target_triple.clone(),
-            hash: link_meta.crate_hash,
+            hash: tcx.crate_hash(LOCAL_CRATE),
             disambiguator: tcx.sess.local_crate_disambiguator(),
             panic_strategy: tcx.sess.panic_strategy(),
             edition: hygiene::default_edition(),
@@ -1113,7 +1111,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 let trait_ref = tcx.impl_trait_ref(def_id);
                 let parent = if let Some(trait_ref) = trait_ref {
                     let trait_def = tcx.trait_def(trait_ref.def_id);
-                    trait_def.ancestors(tcx, def_id).skip(1).next().and_then(|node| {
+                    trait_def.ancestors(tcx, def_id).nth(1).and_then(|node| {
                         match node {
                             specialization_graph::Node::Impl(parent) => Some(parent),
                             _ => None,
@@ -1344,7 +1342,7 @@ fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
         let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
         let hir_id = self.tcx.hir.node_to_hir_id(node_id);
         let kind = match tables.node_id_to_type(hir_id).sty {
-            ty::TyGenerator(def_id, ..) => {
+            ty::Generator(def_id, ..) => {
                 let layout = self.tcx.generator_layout(def_id);
                 let data = GeneratorData {
                     layout: layout.clone(),
@@ -1352,7 +1350,7 @@ fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
                 EntryKind::Generator(self.lazy(&data))
             }
 
-            ty::TyClosure(def_id, substs) => {
+            ty::Closure(def_id, substs) => {
                 let sig = substs.closure_sig(def_id, self.tcx);
                 let data = ClosureData { sig: self.lazy(&sig) };
                 EntryKind::Closure(self.lazy(&data))
@@ -1823,8 +1821,7 @@ fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) {
 // will allow us to slice the metadata to the precise length that we just
 // generated regardless of trailing bytes that end up in it.
 
-pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                 link_meta: &LinkMeta)
+pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                  -> EncodedMetadata
 {
     let mut encoder = opaque::Encoder::new(vec![]);
@@ -1837,7 +1834,6 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let mut ecx = EncodeContext {
             opaque: encoder,
             tcx,
-            link_meta,
             lazy_state: LazyState::NoNode,
             type_shorthands: Default::default(),
             predicate_shorthands: Default::default(),
@@ -1869,7 +1865,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 pub fn get_repr_options<'a, 'tcx, 'gcx>(tcx: &TyCtxt<'a, 'tcx, 'gcx>, did: DefId) -> ReprOptions {
     let ty = tcx.type_of(did);
     match ty.sty {
-        ty::TyAdt(ref def, _) => return def.repr,
+        ty::Adt(ref def, _) => return def.repr,
         _ => bug!("{} is not an ADT", ty),
     }
 }
index a3591b2415a8959df8867845bdffb4ba16d4ae98..107245488acf322c30c58eb911cf2bafaa46315b 100644 (file)
 #![feature(libc)]
 #![feature(macro_at_most_once_rep)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_quote)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
+#![feature(crate_visibility_modifier)]
 #![feature(specialization)]
 #![feature(rustc_private)]
 
index f78a19403acf8b06cf2ae638cf63c12d1bcc152b..9492385957eabe79f7571b120bbfde0a5f868f72 100644 (file)
 use creader::Library;
 use schema::{METADATA_HEADER, rustc_version};
 
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::svh::Svh;
 use rustc::middle::cstore::MetadataLoader;
 use rustc::session::{config, Session};
 use rustc_target::spec::{Target, TargetTriple};
 
 use std::cmp;
-use std::collections::HashSet;
 use std::fmt;
 use std::fs;
 use std::io::{self, Read};
@@ -308,7 +308,7 @@ fn paths(&self) -> Vec<PathBuf> {
 
 impl<'a> Context<'a> {
     pub fn maybe_load_library_crate(&mut self) -> Option<Library> {
-        let mut seen_paths = HashSet::new();
+        let mut seen_paths = FxHashSet::default();
         match self.extra_filename {
             Some(s) => self.find_library_crate(s, &mut seen_paths)
                 .or_else(|| self.find_library_crate("", &mut seen_paths)),
@@ -431,7 +431,7 @@ pub fn report_errs(&mut self) -> ! {
 
     fn find_library_crate(&mut self,
                           extra_prefix: &str,
-                          seen_paths: &mut HashSet<PathBuf>)
+                          seen_paths: &mut FxHashSet<PathBuf>)
                           -> Option<Library> {
         // If an SVH is specified, then this is a transitive dependency that
         // must be loaded via -L plus some filtering.
index 70eda895bd0a24029d9439d52fb14ac7978392b5..446ea6c32444184d4a2a06032650187107965e6f 100644 (file)
@@ -207,7 +207,7 @@ fn process_command_line(&mut self) {
             }
         }
 
-        // Update kind and, optionally, the name of all native libaries
+        // Update kind and, optionally, the name of all native libraries
         // (there may be more than one) with the specified name.
         for &(ref name, ref new_name, kind) in &self.tcx.sess.opts.libs {
             let mut found = false;
index 0fd1f92a516278e06669a63bc9d3e02f8cba4a84..2da0ede9d15ce45f702a6468f1c9514608175456 100644 (file)
@@ -25,3 +25,4 @@ syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 byteorder = { version = "1.1", features = ["i128"] }
 rustc_apfloat = { path = "../librustc_apfloat" }
+smallvec = { version = "0.6.5", features = ["union"] }
index 2ae06375af13c311f8005158148798c9d4d947ad..a0b0aabf73e02b40a6beefdb36305933ceca53b6 100644 (file)
@@ -15,6 +15,7 @@
 use rustc::mir::{LocalDecl, LocalKind, Location, Operand, Place};
 use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind};
 use rustc::ty;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::DiagnosticBuilder;
@@ -24,8 +25,9 @@
 use super::{Context, MirBorrowckCtxt};
 use super::{InitializationRequiringAction, PrefixSet};
 
+use dataflow::drop_flag_effects;
+use dataflow::move_paths::indexes::MoveOutIndex;
 use dataflow::move_paths::MovePathIndex;
-use dataflow::{FlowAtLocation, MovingOutStatements};
 use util::borrowck_errors::{BorrowckErrors, Origin};
 
 impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
@@ -35,17 +37,14 @@ pub(super) fn report_use_of_moved_or_uninitialized(
         desired_action: InitializationRequiringAction,
         (place, span): (&Place<'tcx>, Span),
         mpi: MovePathIndex,
-        curr_move_out: &FlowAtLocation<MovingOutStatements<'_, 'gcx, 'tcx>>,
     ) {
         let use_spans = self
             .move_spans(place, context.loc)
             .or_else(|| self.borrow_spans(span, context.loc));
         let span = use_spans.args_or_use();
 
-        let mois = self.move_data.path_map[mpi]
-            .iter()
-            .filter(|moi| curr_move_out.contains(moi))
-            .collect::<Vec<_>>();
+        let mois = self.get_moved_indexes(context, mpi);
+        debug!("report_use_of_moved_or_uninitialized: mois={:?}", mois);
 
         if mois.is_empty() {
             let root_place = self.prefixes(&place, PrefixSet::All).last().unwrap();
@@ -93,7 +92,7 @@ pub(super) fn report_use_of_moved_or_uninitialized(
 
             let mut is_loop_move = false;
             for moi in &mois {
-                let move_out = self.move_data.moves[**moi];
+                let move_out = self.move_data.moves[*moi];
                 let moved_place = &self.move_data.move_paths[move_out.path].place;
 
                 let move_spans = self.move_spans(moved_place, move_out.source);
@@ -134,7 +133,7 @@ pub(super) fn report_use_of_moved_or_uninitialized(
 
             if let Some(ty) = self.retrieve_type_for_place(place) {
                 let needs_note = match ty.sty {
-                    ty::TypeVariants::TyClosure(id, _) => {
+                    ty::Closure(id, _) => {
                         let tables = self.tcx.typeck_tables_of(id);
                         let node_id = self.tcx.hir.as_local_node_id(id).unwrap();
                         let hir_id = self.tcx.hir.node_to_hir_id(node_id);
@@ -148,7 +147,7 @@ pub(super) fn report_use_of_moved_or_uninitialized(
                 };
 
                 if needs_note {
-                    let mpi = self.move_data.moves[*mois[0]].path;
+                    let mpi = self.move_data.moves[mois[0]].path;
                     let place = &self.move_data.move_paths[mpi].place;
 
                     if let Some(ty) = self.retrieve_type_for_place(place) {
@@ -348,10 +347,7 @@ pub(super) fn report_conflicting_borrow(
         if issued_spans == borrow_spans {
             borrow_spans.var_span_label(
                 &mut err,
-                format!(
-                    "borrows occur due to use of `{}` in closure",
-                    desc_place
-                ),
+                format!("borrows occur due to use of `{}` in closure", desc_place),
             );
         } else {
             let borrow_place = &issued_borrow.borrowed_place;
@@ -366,7 +362,10 @@ pub(super) fn report_conflicting_borrow(
 
             borrow_spans.var_span_label(
                 &mut err,
-                format!("second borrow occurs due to use of `{}` in closure", desc_place),
+                format!(
+                    "second borrow occurs due to use of `{}` in closure",
+                    desc_place
+                ),
             );
         }
 
@@ -413,10 +412,7 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
 
         let mut err = match &self.describe_place(&borrow.borrowed_place) {
             Some(_) if self.is_place_thread_local(root_place) => {
-                self.report_thread_local_value_does_not_live_long_enough(
-                    drop_span,
-                    borrow_span,
-                )
+                self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span)
             }
             Some(name) => self.report_local_value_does_not_live_long_enough(
                 context,
@@ -462,7 +458,10 @@ fn report_local_value_does_not_live_long_enough(
         );
 
         let mut err = self.tcx.path_does_not_live_long_enough(
-            borrow_span, &format!("`{}`", name), Origin::Mir);
+            borrow_span,
+            &format!("`{}`", name),
+            Origin::Mir,
+        );
 
         err.span_label(borrow_span, "borrowed value does not live long enough");
         err.span_label(
@@ -486,11 +485,14 @@ fn report_thread_local_value_does_not_live_long_enough(
             drop_span, borrow_span
         );
 
-        let mut err = self.tcx.thread_local_value_does_not_live_long_enough(
-            borrow_span, Origin::Mir);
+        let mut err = self
+            .tcx
+            .thread_local_value_does_not_live_long_enough(borrow_span, Origin::Mir);
 
-        err.span_label(borrow_span,
-                       "thread-local variables cannot be borrowed beyond the end of the function");
+        err.span_label(
+            borrow_span,
+            "thread-local variables cannot be borrowed beyond the end of the function",
+        );
         err.span_label(drop_span, "end of enclosing function is here");
         err
     }
@@ -521,6 +523,80 @@ fn report_temporary_value_does_not_live_long_enough(
         err
     }
 
+    fn get_moved_indexes(&mut self, context: Context, mpi: MovePathIndex) -> Vec<MoveOutIndex> {
+        let mir = self.mir;
+
+        let mut stack = Vec::new();
+        stack.extend(mir.predecessor_locations(context.loc));
+
+        let mut visited = FxHashSet();
+        let mut result = vec![];
+
+        'dfs: while let Some(l) = stack.pop() {
+            debug!(
+                "report_use_of_moved_or_uninitialized: current_location={:?}",
+                l
+            );
+
+            if !visited.insert(l) {
+                continue;
+            }
+
+            // check for moves
+            let stmt_kind = mir[l.block]
+                .statements
+                .get(l.statement_index)
+                .map(|s| &s.kind);
+            if let Some(StatementKind::StorageDead(..)) = stmt_kind {
+                // this analysis only tries to find moves explicitly
+                // written by the user, so we ignore the move-outs
+                // created by `StorageDead` and at the beginning
+                // of a function.
+            } else {
+                for moi in &self.move_data.loc_map[l] {
+                    debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi);
+                    if self.move_data.moves[*moi].path == mpi {
+                        debug!("report_use_of_moved_or_uninitialized: found");
+                        result.push(*moi);
+
+                        // Strictly speaking, we could continue our DFS here. There may be
+                        // other moves that can reach the point of error. But it is kind of
+                        // confusing to highlight them.
+                        //
+                        // Example:
+                        //
+                        // ```
+                        // let a = vec![];
+                        // let b = a;
+                        // let c = a;
+                        // drop(a); // <-- current point of error
+                        // ```
+                        //
+                        // Because we stop the DFS here, we only highlight `let c = a`,
+                        // and not `let b = a`. We will of course also report an error at
+                        // `let c = a` which highlights `let b = a` as the move.
+                        continue 'dfs;
+                    }
+                }
+            }
+
+            // check for inits
+            let mut any_match = false;
+            drop_flag_effects::for_location_inits(self.tcx, self.mir, self.move_data, l, |m| {
+                if m == mpi {
+                    any_match = true;
+                }
+            });
+            if any_match {
+                continue 'dfs;
+            }
+
+            stack.extend(mir.predecessor_locations(l));
+        }
+
+        result
+    }
+
     pub(super) fn report_illegal_mutation_of_borrowed(
         &mut self,
         context: Context,
@@ -834,19 +910,19 @@ fn describe_field_from_ty(&self, ty: &ty::Ty, field: Field) -> String {
             self.describe_field_from_ty(&ty.boxed_ty(), field)
         } else {
             match ty.sty {
-                ty::TyAdt(def, _) => if def.is_enum() {
+                ty::Adt(def, _) => if def.is_enum() {
                     field.index().to_string()
                 } else {
                     def.non_enum_variant().fields[field.index()]
                         .ident
                         .to_string()
                 },
-                ty::TyTuple(_) => field.index().to_string(),
-                ty::TyRef(_, ty, _) | ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => {
+                ty::Tuple(_) => field.index().to_string(),
+                ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
                     self.describe_field_from_ty(&ty, field)
                 }
-                ty::TyArray(ty, _) | ty::TySlice(ty) => self.describe_field_from_ty(&ty, field),
-                ty::TyClosure(def_id, _) | ty::TyGenerator(def_id, _, _) => {
+                ty::Array(ty, _) | ty::Slice(ty) => self.describe_field_from_ty(&ty, field),
+                ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
                     // Convert the def-id into a node-id. node-ids are only valid for
                     // the local code in the current crate, so this returns an `Option` in case
                     // the closure comes from another crate. But in that case we wouldn't
@@ -890,8 +966,10 @@ pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
             let attrs = self.tcx.get_attrs(statik.def_id);
             let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local"));
 
-            debug!("is_place_thread_local: attrs={:?} is_thread_local={:?}",
-                   attrs, is_thread_local);
+            debug!(
+                "is_place_thread_local: attrs={:?} is_thread_local={:?}",
+                attrs, is_thread_local
+            );
             is_thread_local
         } else {
             debug!("is_place_thread_local: no");
@@ -909,7 +987,7 @@ pub(super) enum UseSpans {
         // it's present.
         args_span: Span,
         // The span of the first use of the captured variable inside the closure.
-        var_span: Span
+        var_span: Span,
     },
     // This access has a single span associated to it: common case.
     OtherUse(Span),
index 90dc96cbd3cf32e0d7f27c1d0c20a35b972cb3aa..6b964fec74fdd1417b1145de05f44ed2df3b696e 100644 (file)
@@ -24,7 +24,7 @@
 use dataflow::move_paths::indexes::BorrowIndex;
 use dataflow::move_paths::HasMoveData;
 use dataflow::Borrows;
-use dataflow::{EverInitializedPlaces, MovingOutStatements};
+use dataflow::EverInitializedPlaces;
 use dataflow::{FlowAtLocation, FlowsAtLocation};
 use dataflow::MaybeUninitializedPlaces;
 use either::Either;
@@ -35,7 +35,6 @@
 crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
     borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
     pub uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
-    pub move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
     pub ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
 
     /// Polonius Output
@@ -46,14 +45,12 @@ impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
     crate fn new(
         borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
         uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
-        move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
         ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
         polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
     ) -> Self {
         Flows {
             borrows,
             uninits,
-            move_outs,
             ever_inits,
             polonius_output,
         }
@@ -79,7 +76,6 @@ macro_rules! each_flow {
     ($this:ident, $meth:ident($arg:ident)) => {
         FlowAtLocation::$meth(&mut $this.borrows, $arg);
         FlowAtLocation::$meth(&mut $this.uninits, $arg);
-        FlowAtLocation::$meth(&mut $this.move_outs, $arg);
         FlowAtLocation::$meth(&mut $this.ever_inits, $arg);
     };
 }
@@ -89,6 +85,10 @@ fn reset_to_entry_of(&mut self, bb: BasicBlock) {
         each_flow!(self, reset_to_entry_of(bb));
     }
 
+    fn reset_to_exit_of(&mut self, bb: BasicBlock) {
+        each_flow!(self, reset_to_exit_of(bb));
+    }
+
     fn reconstruct_statement_effect(&mut self, location: Location) {
         each_flow!(self, reconstruct_statement_effect(location));
     }
@@ -142,18 +142,6 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         });
         s.push_str("] ");
 
-        s.push_str("move_out: [");
-        let mut saw_one = false;
-        self.move_outs.each_state_bit(|mpi_move_out| {
-            if saw_one {
-                s.push_str(", ");
-            };
-            saw_one = true;
-            let move_out = &self.move_outs.operator().move_data().moves[mpi_move_out];
-            s.push_str(&format!("{:?}", move_out));
-        });
-        s.push_str("] ");
-
         s.push_str("ever_init: [");
         let mut saw_one = false;
         self.ever_inits.each_state_bit(|mpi_ever_init| {
index 82d3d31a52eb3b33e82a986e62e865f3469dabca..3536947b25ebfbdba7e75f2049751a82deced06d 100644 (file)
@@ -12,6 +12,7 @@
 
 use borrow_check::nll::region_infer::RegionInferenceContext;
 use rustc::hir;
+use rustc::hir::Node;
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::definitions::DefPathData;
 use rustc::infer::InferCtxt;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, ParamEnv, TyCtxt, Ty};
 
-use rustc_errors::{Diagnostic, DiagnosticBuilder, Level};
+use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, Level};
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::indexed_set::IdxSetBuf;
+use rustc_data_structures::indexed_set::IdxSet;
 use rustc_data_structures::indexed_vec::Idx;
-use rustc_data_structures::small_vec::SmallVec;
+use smallvec::SmallVec;
 
 use std::rc::Rc;
 
@@ -42,7 +43,7 @@
 use dataflow::FlowAtLocation;
 use dataflow::MoveDataParamEnv;
 use dataflow::{do_dataflow, DebugFormatted};
-use dataflow::{EverInitializedPlaces, MovingOutStatements};
+use dataflow::EverInitializedPlaces;
 use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
 use util::borrowck_errors::{BorrowckErrors, Origin};
 
@@ -166,7 +167,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         _ => Some(tcx.hir.body_owned_by(id)),
     };
 
-    let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
+    let dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len());
     let mut flow_inits = FlowAtLocation::new(do_dataflow(
         tcx,
         mir,
@@ -185,15 +186,6 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         MaybeUninitializedPlaces::new(tcx, mir, &mdpe),
         |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
     ));
-    let flow_move_outs = FlowAtLocation::new(do_dataflow(
-        tcx,
-        mir,
-        id,
-        &attributes,
-        &dead_unwinds,
-        MovingOutStatements::new(tcx, mir, &mdpe),
-        |bd, i| DebugFormatted::new(&bd.move_data().moves[i]),
-    ));
     let flow_ever_inits = FlowAtLocation::new(do_dataflow(
         tcx,
         mir,
@@ -232,7 +224,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     ));
 
     let movable_generator = match tcx.hir.get(id) {
-        hir::map::Node::NodeExpr(&hir::Expr {
+        Node::Expr(&hir::Expr {
             node: hir::ExprKind::Closure(.., Some(hir::GeneratorMovability::Static)),
             ..
         }) => false,
@@ -267,7 +259,6 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     let mut state = Flows::new(
         flow_borrows,
         flow_uninits,
-        flow_move_outs,
         flow_ever_inits,
         polonius_output,
     );
@@ -324,7 +315,11 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
                 span,
                 "variable does not need to be mutable",
             );
-            err.span_suggestion_short(mut_span, "remove this `mut`", "".to_owned());
+            err.span_suggestion_short_with_applicability(
+                mut_span,
+                "remove this `mut`",
+                String::new(),
+                Applicability::MachineApplicable);
 
             err.buffer(&mut mbcx.errors_buffer);
         }
@@ -935,14 +930,14 @@ fn visit_terminator_drop(
             // individual fields instead. This way if `foo` has a
             // destructor but `bar` does not, we will only check for
             // borrows of `x.foo` and not `x.bar`. See #47703.
-            ty::TyAdt(def, substs) if def.is_struct() && !def.has_dtor(self.tcx) => {
+            ty::Adt(def, substs) if def.is_struct() && !def.has_dtor(self.tcx) => {
                 def.all_fields()
                     .map(|field| field.ty(gcx, substs))
                     .enumerate()
                     .for_each(|field| drop_field(self, field));
             }
             // Same as above, but for tuples.
-            ty::TyTuple(tys) => {
+            ty::Tuple(tys) => {
                 tys.iter()
                     .cloned()
                     .enumerate()
@@ -950,7 +945,7 @@ fn visit_terminator_drop(
             }
             // Closures also have disjoint fields, but they are only
             // directly accessed in the body of the closure.
-            ty::TyClosure(def, substs)
+            ty::Closure(def, substs)
                 if *drop_place == Place::Local(Local::new(1))
                     && !self.mir.upvar_decls.is_empty() =>
             {
@@ -961,7 +956,7 @@ fn visit_terminator_drop(
             }
             // Generators also have disjoint fields, but they are only
             // directly accessed in the body of the generator.
-            ty::TyGenerator(def, substs, _)
+            ty::Generator(def, substs, _)
                 if *drop_place == Place::Local(Local::new(1))
                     && !self.mir.upvar_decls.is_empty() =>
             {
@@ -978,7 +973,7 @@ fn visit_terminator_drop(
             // the base case below, we would have a Deep Write due to
             // the box being `needs_drop`, and that Deep Write would
             // touch `&mut` data in the box.
-            ty::TyAdt(def, _) if def.is_box() => {
+            ty::Adt(def, _) if def.is_box() => {
                 // When/if we add a `&own T` type, this action would
                 // be like running the destructor of the `&own T`.
                 // (And the owner of backing storage referenced by the
@@ -1080,7 +1075,10 @@ fn access_place(
             }
         }
 
-        if self
+        // Check is_empty() first because it's the common case, and doing that
+        // way we avoid the clone() call.
+        if !self.access_place_error_reported.is_empty() &&
+           self
             .access_place_error_reported
             .contains(&(place_span.0.clone(), place_span.1))
         {
@@ -1609,7 +1607,6 @@ fn check_if_full_path_is_moved(
         let place = self.base_path(place_span.0);
 
         let maybe_uninits = &flow_state.uninits;
-        let curr_move_outs = &flow_state.move_outs;
 
         // Bad scenarios:
         //
@@ -1655,7 +1652,6 @@ fn check_if_full_path_is_moved(
                         desired_action,
                         place_span,
                         mpi,
-                        curr_move_outs,
                     );
                     return; // don't bother finding other problems.
                 }
@@ -1683,7 +1679,6 @@ fn check_if_path_or_subpath_is_moved(
         let place = self.base_path(place_span.0);
 
         let maybe_uninits = &flow_state.uninits;
-        let curr_move_outs = &flow_state.move_outs;
 
         // Bad scenarios:
         //
@@ -1719,7 +1714,6 @@ fn check_if_path_or_subpath_is_moved(
                     desired_action,
                     place_span,
                     child_mpi,
-                    curr_move_outs,
                 );
                 return; // don't bother finding other problems.
             }
@@ -1815,7 +1809,7 @@ fn check_if_assigned_path_is_moved(
                             // be already initialized
                             let tcx = self.tcx;
                             match base.ty(self.mir, tcx).to_ty(tcx).sty {
-                                ty::TyAdt(def, _) if def.has_dtor(tcx) => {
+                                ty::Adt(def, _) if def.has_dtor(tcx) => {
 
                                     // FIXME: analogous code in
                                     // check_loans.rs first maps
@@ -2059,7 +2053,7 @@ fn is_mutable<'d>(
 
                         // Check the kind of deref to decide
                         match base_ty.sty {
-                            ty::TyRef(_, _, mutbl) => {
+                            ty::Ref(_, _, mutbl) => {
                                 match mutbl {
                                     // Shared borrowed data is never mutable
                                     hir::MutImmutable => Err(place),
@@ -2083,7 +2077,7 @@ fn is_mutable<'d>(
                                     }
                                 }
                             }
-                            ty::TyRawPtr(tnm) => {
+                            ty::RawPtr(tnm) => {
                                 match tnm.mutbl {
                                     // `*const` raw pointers are not mutable
                                     hir::MutImmutable => return Err(place),
index 5ef647585c38e8d00871e77403a48beb59a47f38..497e8e07853fbdb7e3992244b44d4f4b2e949115 100644 (file)
@@ -261,10 +261,10 @@ fn report(&mut self, error: GroupedMoveError<'tcx>) {
                             .any(|p| p.is_upvar_field_projection(self.mir, &self.tcx)
                                  .is_some());
                         match ty.sty {
-                            ty::TyArray(..) | ty::TySlice(..) => self
+                            ty::Array(..) | ty::Slice(..) => self
                                 .tcx
                                 .cannot_move_out_of_interior_noncopy(span, ty, None, origin),
-                            ty::TyClosure(def_id, closure_substs)
+                            ty::Closure(def_id, closure_substs)
                                 if !self.mir.upvar_decls.is_empty() && is_upvar_field_projection
                             => {
                                 let closure_kind_ty =
index 05d6f49d97c6cce3177d6545e4da9a4bee82cc10..f96ef909c0df8ace584c08ca153c59455446e851 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use rustc::hir;
+use rustc::hir::Node;
 use rustc::mir::{self, BindingForm, ClearCrossCrate, Local, Location, Mir};
 use rustc::mir::{Mutability, Place, Projection, ProjectionElem, Static};
 use rustc::ty::{self, TyCtxt};
@@ -128,7 +129,7 @@ pub(super) fn report_mutability_error(
                         }
                     } else {
                         item_msg = format!("data in a {}", pointer_type);
-                        reason = "".to_string();
+                        reason = String::new();
                     }
                 }
             }
@@ -138,7 +139,7 @@ pub(super) fn report_mutability_error(
             Place::Static(box Static { def_id, ty: _ }) => {
                 if let Place::Static(_) = access_place {
                     item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
-                    reason = "".to_string();
+                    reason = String::new();
                 } else {
                     item_msg = format!("`{}`", access_place_desc.unwrap());
                     let static_name = &self.tcx.item_name(*def_id);
@@ -246,7 +247,7 @@ pub(super) fn report_mutability_error(
                     .var_hir_id
                     .assert_crate_local();
                 let upvar_node_id = self.tcx.hir.hir_to_node_id(upvar_hir_id);
-                if let Some(hir::map::NodeBinding(pat)) = self.tcx.hir.find(upvar_node_id) {
+                if let Some(Node::Binding(pat)) = self.tcx.hir.find(upvar_node_id) {
                     if let hir::PatKind::Binding(
                         hir::BindingAnnotation::Unannotated,
                         _,
index aa88fa11174b1d078fae1e6ae4e5be48d1efafb0..a35117f2e35605ec82c83f7f9eed0c46de95162e 100644 (file)
@@ -17,7 +17,7 @@
 use rustc::mir::{Local, Location, Mir};
 use rustc::ty::{RegionVid, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
-use util::liveness::{self, DefUse, LivenessMode};
+use util::liveness::{self, DefUse};
 
 crate fn find<'tcx>(
     mir: &Mir<'tcx>,
         tcx,
         region_vid,
         start_point,
-        liveness_mode: LivenessMode {
-            include_regular_use: true,
-            include_drops: true,
-        },
     };
 
     uf.find()
@@ -47,7 +43,6 @@ struct UseFinder<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
     region_vid: RegionVid,
     start_point: Location,
-    liveness_mode: LivenessMode,
 }
 
 impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> {
@@ -108,7 +103,6 @@ fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> Option<
             mir: self.mir,
             tcx: self.tcx,
             region_vid: self.region_vid,
-            liveness_mode: self.liveness_mode,
             def_use_result: None,
         };
 
@@ -122,7 +116,6 @@ struct DefUseVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     mir: &'cx Mir<'tcx>,
     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
     region_vid: RegionVid,
-    liveness_mode: LivenessMode,
     def_use_result: Option<DefUseResult>,
 }
 
@@ -146,23 +139,12 @@ fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Locati
         });
 
         if found_it {
-            match liveness::categorize(context, self.liveness_mode) {
-                Some(DefUse::Def) => {
-                    self.def_use_result = Some(DefUseResult::Def);
-                }
-
-                Some(DefUse::Use) => {
-                    self.def_use_result = if context.is_drop() {
-                        Some(DefUseResult::UseDrop { local })
-                    } else {
-                        Some(DefUseResult::UseLive { local })
-                    };
-                }
-
-                None => {
-                    self.def_use_result = None;
-                }
-            }
+            self.def_use_result = match liveness::categorize(context) {
+                Some(DefUse::Def) => Some(DefUseResult::Def),
+                Some(DefUse::Use) => Some(DefUseResult::UseLive { local }),
+                Some(DefUse::Drop) => Some(DefUseResult::UseDrop { local }),
+                None => None,
+            };
         }
     }
 }
index 301999cc4a51e120755a6755cde8d6d6a1e07cae..f233a17597a5468f5a88d72c4266889640a2e2fe 100644 (file)
@@ -312,26 +312,26 @@ fn visit_terminator_drop(
             // individual fields instead. This way if `foo` has a
             // destructor but `bar` does not, we will only check for
             // borrows of `x.foo` and not `x.bar`. See #47703.
-            ty::TyAdt(def, substs) if def.is_struct() && !def.has_dtor(self.infcx.tcx) => {
+            ty::Adt(def, substs) if def.is_struct() && !def.has_dtor(self.infcx.tcx) => {
                 def.all_fields()
                     .map(|field| field.ty(gcx, substs))
                     .enumerate()
                     .for_each(|field| drop_field(self, field));
             }
             // Same as above, but for tuples.
-            ty::TyTuple(tys) => {
+            ty::Tuple(tys) => {
                 tys.iter().cloned().enumerate()
                     .for_each(|field| drop_field(self, field));
             }
             // Closures and generators also have disjoint fields, but they are only
             // directly accessed in the body of the closure/generator.
-            ty::TyGenerator(def, substs, ..)
+            ty::Generator(def, substs, ..)
                 if *drop_place == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty()
             => {
                 substs.upvar_tys(def, self.infcx.tcx).enumerate()
                     .for_each(|field| drop_field(self, field));
             }
-            ty::TyClosure(def, substs)
+            ty::Closure(def, substs)
                 if *drop_place == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty()
                 => {
                     substs.upvar_tys(def, self.infcx.tcx).enumerate()
@@ -541,7 +541,7 @@ fn check_access_for_conflict(
                             // unique or mutable borrows are invalidated by writes.
                             // Reservations count as writes since we need to check
                             // that activating the borrow will be OK
-                            // TOOD(bob_twinkles) is this actually the right thing to do?
+                            // FIXME(bob_twinkles) is this actually the right thing to do?
                             this.generate_invalidates(borrow_index, context.loc);
                         }
                 }
index f54d80d5f4f7e7e86701ca6fdbc53bc0f52dc389..b80f9784d6f8757879ecff6571036725c581fe8b 100644 (file)
@@ -12,7 +12,7 @@
 use borrow_check::location::{LocationIndex, LocationTable};
 use borrow_check::nll::facts::AllFactsExt;
 use borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints};
-use borrow_check::nll::type_check::liveness::liveness_map::{NllLivenessMap, LocalWithRegion};
+use borrow_check::nll::type_check::liveness::liveness_map::NllLivenessMap;
 use borrow_check::nll::region_infer::values::RegionValueElements;
 use dataflow::indexes::BorrowIndex;
 use dataflow::move_paths::MoveData;
@@ -22,9 +22,7 @@
 use rustc::infer::InferCtxt;
 use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir};
 use rustc::ty::{self, RegionKind, RegionVid};
-use rustc::util::nodemap::FxHashMap;
 use rustc_errors::Diagnostic;
-use std::collections::BTreeSet;
 use std::fmt::Debug;
 use std::env;
 use std::io;
 use std::rc::Rc;
 use std::str::FromStr;
 use transform::MirSource;
-use util::liveness::{LivenessResults, LiveVarSet};
 
 use self::mir_util::PassWhere;
 use polonius_engine::{Algorithm, Output};
 use util as mir_util;
-use util::pretty::{self, ALIGN};
+use util::pretty;
 
 mod constraint_generation;
 pub mod explain_borrow;
@@ -111,8 +108,6 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     let MirTypeckResults {
         constraints,
         universal_region_relations,
-        liveness,
-        liveness_map,
     } = type_check::type_check(
         infcx,
         param_env,
@@ -205,8 +200,6 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     // write unit-tests, as well as helping with debugging.
     dump_mir_results(
         infcx,
-        &liveness,
-        &liveness_map,
         MirSource::item(def_id),
         &mir,
         &regioncx,
@@ -222,8 +215,6 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
 
 fn dump_mir_results<'a, 'gcx, 'tcx>(
     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-    liveness: &LivenessResults<LocalWithRegion>,
-    liveness_map: &NllLivenessMap,
     source: MirSource,
     mir: &Mir<'tcx>,
     regioncx: &RegionInferenceContext,
@@ -233,34 +224,6 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
         return;
     }
 
-    let regular_liveness_per_location: FxHashMap<_, _> = mir
-        .basic_blocks()
-        .indices()
-        .flat_map(|bb| {
-            let mut results = vec![];
-            liveness
-                .regular
-                .simulate_block(&mir, bb, liveness_map, |location, local_set| {
-                    results.push((location, local_set.clone()));
-                });
-            results
-        })
-        .collect();
-
-    let drop_liveness_per_location: FxHashMap<_, _> = mir
-        .basic_blocks()
-        .indices()
-        .flat_map(|bb| {
-            let mut results = vec![];
-            liveness
-                .drop
-                .simulate_block(&mir, bb, liveness_map, |location, local_set| {
-                    results.push((location, local_set.clone()));
-                });
-            results
-        })
-        .collect();
-
     mir_util::dump_mir(
         infcx.tcx,
         None,
@@ -283,26 +246,10 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
                     }
                 }
 
-                PassWhere::BeforeLocation(location) => {
-                    let s = live_variable_set(
-                        &regular_liveness_per_location[&location],
-                        &drop_liveness_per_location[&location],
-                    );
-                    writeln!(
-                        out,
-                        "{:ALIGN$} | Live variables on entry to {:?}: {}",
-                        "",
-                        location,
-                        s,
-                        ALIGN = ALIGN
-                    )?;
+                PassWhere::BeforeLocation(_) => {
                 }
 
-                // After each basic block, dump out the values
-                // that are live on exit from the basic block.
-                PassWhere::AfterTerminator(bb) => {
-                    let s = live_variable_set(&liveness.regular.outs[bb], &liveness.drop.outs[bb]);
-                    writeln!(out, "    | Live variables on exit from {:?}: {}", bb, s)?;
+                PassWhere::AfterTerminator(_) => {
                 }
 
                 PassWhere::BeforeBlock(_) | PassWhere::AfterLocation(_) | PassWhere::AfterCFG => {}
@@ -312,14 +259,14 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
     );
 
     // Also dump the inference graph constraints as a graphviz file.
-    let _: io::Result<()> = do catch {
+    let _: io::Result<()> = try_block! {
         let mut file =
             pretty::create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, source)?;
         regioncx.dump_graphviz_raw_constraints(&mut file)?;
     };
 
     // Also dump the inference graph constraints as a graphviz file.
-    let _: io::Result<()> = do catch {
+    let _: io::Result<()> = try_block! {
         let mut file =
             pretty::create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, source)?;
         regioncx.dump_graphviz_scc_constraints(&mut file)?;
@@ -420,33 +367,3 @@ fn to_region_vid(self) -> RegionVid {
         self
     }
 }
-
-fn live_variable_set(
-    regular: &LiveVarSet<LocalWithRegion>,
-    drops: &LiveVarSet<LocalWithRegion>
-) -> String {
-    // sort and deduplicate:
-    let all_locals: BTreeSet<_> = regular.iter().chain(drops.iter()).collect();
-
-    // construct a string with each local, including `(drop)` if it is
-    // only dropped, versus a regular use.
-    let mut string = String::new();
-    for local in all_locals {
-        string.push_str(&format!("{:?}", local));
-
-        if !regular.contains(&local) {
-            assert!(drops.contains(&local));
-            string.push_str(" (drop)");
-        }
-
-        string.push_str(", ");
-    }
-
-    let len = if string.is_empty() {
-        0
-    } else {
-        string.len() - 2
-    };
-
-    format!("[{}]", &string[..len])
-}
index 532c36f427b5a1ad62c79607b4b2eadc4e44f75a..6177194ab914d5817d69e9ef1fa0f159b2bb0d6d 100644 (file)
@@ -376,7 +376,7 @@ fn give_name_if_we_can_match_hir_ty(
                 //     &
                 //     - let's call the lifetime of this reference `'1`
                 (
-                    ty::TyRef(region, referent_ty, _),
+                    ty::Ref(region, referent_ty, _),
                     hir::TyKind::Rptr(_lifetime, referent_hir_ty),
                 ) => {
                     if region.to_region_vid() == needle_fr {
@@ -403,7 +403,7 @@ fn give_name_if_we_can_match_hir_ty(
 
                 // Match up something like `Foo<'1>`
                 (
-                    ty::TyAdt(_adt_def, substs),
+                    ty::Adt(_adt_def, substs),
                     hir::TyKind::Path(hir::QPath::Resolved(None, path)),
                 ) => {
                     if let Some(last_segment) = path.segments.last() {
@@ -423,16 +423,16 @@ fn give_name_if_we_can_match_hir_ty(
                 // The following cases don't have lifetimes, so we
                 // just worry about trying to match up the rustc type
                 // with the HIR types:
-                (ty::TyTuple(elem_tys), hir::TyKind::Tup(elem_hir_tys)) => {
+                (ty::Tuple(elem_tys), hir::TyKind::Tup(elem_hir_tys)) => {
                     search_stack.extend(elem_tys.iter().cloned().zip(elem_hir_tys));
                 }
 
-                (ty::TySlice(elem_ty), hir::TyKind::Slice(elem_hir_ty))
-                | (ty::TyArray(elem_ty, _), hir::TyKind::Array(elem_hir_ty, _)) => {
+                (ty::Slice(elem_ty), hir::TyKind::Slice(elem_hir_ty))
+                | (ty::Array(elem_ty, _), hir::TyKind::Array(elem_hir_ty, _)) => {
                     search_stack.push((elem_ty, elem_hir_ty));
                 }
 
-                (ty::TyRawPtr(mut_ty), hir::TyKind::Ptr(mut_hir_ty)) => {
+                (ty::RawPtr(mut_ty), hir::TyKind::Ptr(mut_hir_ty)) => {
                     search_stack.push((mut_ty.ty, &mut_hir_ty.ty));
                 }
 
index ebcc044093a6589ae5344a61fd083dcdd4994977..ff68b5987e85a21d2ec9072e21c4dbb99f5a8b61 100644 (file)
@@ -27,7 +27,7 @@
 use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
 use rustc::util::common;
 use rustc_data_structures::graph::scc::Sccs;
-use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf};
+use rustc_data_structures::indexed_set::IdxSet;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_errors::Diagnostic;
 
@@ -468,7 +468,7 @@ fn propagate_constraints(&mut self, _mir: &Mir<'tcx>) {
         // SCC. For each SCC, we visit its successors and compute
         // their values, then we union all those values to get our
         // own.
-        let visited = &mut IdxSetBuf::new_empty(self.constraint_sccs.num_sccs());
+        let visited = &mut IdxSet::new_empty(self.constraint_sccs.num_sccs());
         for scc_index in self.constraint_sccs.all_sccs() {
             self.propagate_constraint_sccs_if_new(scc_index, visited);
         }
index 8db5809e53f5eea9f2376fe429f1989b7a7e6fae..ae5d57906739bd8b0be2f684ef993e247a56be40 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc::mir::{BasicBlock, Location, Mir};
 use rustc::ty::{self, RegionVid};
-use rustc_data_structures::bitvec::SparseBitMatrix;
+use rustc_data_structures::bitvec::{BitArray, SparseBitMatrix};
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::indexed_vec::IndexVec;
 use std::fmt::Debug;
 crate struct RegionValueElements {
     /// For each basic block, how many points are contained within?
     statements_before_block: IndexVec<BasicBlock, usize>,
+
+    /// Map backward from each point to the basic block that it
+    /// belongs to.
+    basic_blocks: IndexVec<PointIndex, BasicBlock>,
+
     num_points: usize,
 }
 
 impl RegionValueElements {
     crate fn new(mir: &Mir<'_>) -> Self {
         let mut num_points = 0;
-        let statements_before_block = mir
+        let statements_before_block: IndexVec<BasicBlock, usize> = mir
             .basic_blocks()
             .iter()
             .map(|block_data| {
@@ -41,14 +46,25 @@ impl RegionValueElements {
         );
         debug!("RegionValueElements: num_points={:#?}", num_points);
 
+        let mut basic_blocks = IndexVec::with_capacity(num_points);
+        for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {
+            basic_blocks.extend((0 .. bb_data.statements.len() + 1).map(|_| bb));
+        }
+
         Self {
             statements_before_block,
+            basic_blocks,
             num_points,
         }
     }
 
+    /// Total number of point indices
+    crate fn num_points(&self) -> usize {
+        self.num_points
+    }
+
     /// Converts a `Location` into a `PointIndex`. O(1).
-    fn point_from_location(&self, location: Location) -> PointIndex {
+    crate fn point_from_location(&self, location: Location) -> PointIndex {
         let Location {
             block,
             statement_index,
@@ -57,39 +73,50 @@ fn point_from_location(&self, location: Location) -> PointIndex {
         PointIndex::new(start_index + statement_index)
     }
 
-    /// Converts a `PointIndex` back to a location. O(N) where N is
-    /// the number of blocks; could be faster if we ever cared.
-    crate fn to_location(&self, i: PointIndex) -> Location {
-        let point_index = i.index();
-
-        // Find the basic block. We have a vector with the
-        // starting index of the statement in each block. Imagine
-        // we have statement #22, and we have a vector like:
-        //
-        // [0, 10, 20]
-        //
-        // In that case, this represents point_index 2 of
-        // basic block BB2. We know this because BB0 accounts for
-        // 0..10, BB1 accounts for 11..20, and BB2 accounts for
-        // 20...
-        //
-        // To compute this, we could do a binary search, but
-        // because I am lazy we instead iterate through to find
-        // the last point where the "first index" (0, 10, or 20)
-        // was less than the statement index (22). In our case, this will
-        // be (BB2, 20).
-        //
-        // Nit: we could do a binary search here but I'm too lazy.
-        let (block, &first_index) = self
-            .statements_before_block
-            .iter_enumerated()
-            .filter(|(_, first_index)| **first_index <= point_index)
-            .last()
-            .unwrap();
-
-        Location {
-            block,
-            statement_index: point_index - first_index,
+    /// Converts a `Location` into a `PointIndex`. O(1).
+    crate fn entry_point(&self, block: BasicBlock) -> PointIndex {
+        let start_index = self.statements_before_block[block];
+        PointIndex::new(start_index)
+    }
+
+    /// Converts a `PointIndex` back to a location. O(1).
+    crate fn to_location(&self, index: PointIndex) -> Location {
+        assert!(index.index() < self.num_points);
+        let block = self.basic_blocks[index];
+        let start_index = self.statements_before_block[block];
+        let statement_index = index.index() - start_index;
+        Location { block, statement_index }
+    }
+
+    /// Sometimes we get point-indices back from bitsets that may be
+    /// out of range (because they round up to the nearest 2^N number
+    /// of bits). Use this function to filter such points out if you
+    /// like.
+    crate fn point_in_range(&self, index: PointIndex) -> bool {
+        index.index() < self.num_points
+    }
+
+    /// Pushes all predecessors of `index` onto `stack`.
+    crate fn push_predecessors(
+        &self,
+        mir: &Mir<'_>,
+        index: PointIndex,
+        stack: &mut Vec<PointIndex>,
+    ) {
+        let Location { block, statement_index } = self.to_location(index);
+        if statement_index == 0 {
+            // If this is a basic block head, then the predecessors are
+            // the the terminators of other basic blocks
+            stack.extend(
+                mir
+                    .predecessors_for(block)
+                    .iter()
+                    .map(|&pred_bb| mir.terminator_loc(pred_bb))
+                    .map(|pred_loc| self.point_from_location(pred_loc)),
+            );
+        } else {
+            // Otherwise, the pred is just the previous statement
+            stack.push(PointIndex::new(index.index() - 1));
         }
     }
 }
@@ -151,6 +178,13 @@ impl<N: Idx> LivenessValues<N> {
         self.points.add(row, index)
     }
 
+    /// Adds all the elements in the given bit array into the given
+    /// region. Returns true if any of them are newly added.
+    crate fn add_elements(&mut self, row: N, locations: &BitArray<PointIndex>) -> bool {
+        debug!("LivenessValues::add_elements(row={:?}, locations={:?})", row, locations);
+        self.points.merge_into(row, locations)
+    }
+
     /// Adds all the control-flow points to the values for `r`.
     crate fn add_all_points(&mut self, row: N) {
         self.points.add_all(row);
@@ -169,6 +203,7 @@ impl<N: Idx> LivenessValues<N> {
                 .row(r)
                 .into_iter()
                 .flat_map(|set| set.iter())
+                .take_while(|&p| self.elements.point_in_range(p))
                 .map(|p| self.elements.to_location(p))
                 .map(RegionElement::Location),
         )
@@ -277,7 +312,11 @@ impl<N: Idx> RegionValues<N> {
         self.points
             .row(r)
             .into_iter()
-            .flat_map(move |set| set.iter().map(move |p| self.elements.to_location(p)))
+            .flat_map(move |set| {
+                set.iter()
+                    .take_while(move |&p| self.elements.point_in_range(p))
+                    .map(move |p| self.elements.to_location(p))
+            })
     }
 
     /// Returns just the universal regions that are contained in a given region's value.
@@ -366,6 +405,19 @@ fn contained_in_row<N: Idx>(self, values: &RegionValues<N>, row: N) -> bool {
     }
 }
 
+crate fn location_set_str(
+    elements: &RegionValueElements,
+    points: impl IntoIterator<Item = PointIndex>,
+) -> String {
+    region_value_str(
+        points
+            .into_iter()
+            .take_while(|&p| elements.point_in_range(p))
+            .map(|p| elements.to_location(p))
+            .map(RegionElement::Location),
+    )
+}
+
 fn region_value_str(elements: impl IntoIterator<Item = RegionElement>) -> String {
     let mut result = String::new();
     result.push_str("{");
index e4b1aacd34f71fad8306bf6e1efa98696d147a66..e21c490622c089638b71eab8e2d63abb14ce4744 100644 (file)
@@ -14,7 +14,7 @@
 use borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
 use borrow_check::nll::universal_regions::UniversalRegions;
 use borrow_check::nll::ToRegionVid;
-use rustc::hir::def_id::DefId;
+use rustc::infer::canonical::QueryRegionConstraint;
 use rustc::infer::outlives::free_region_map::FreeRegionRelations;
 use rustc::infer::region_constraints::GenericKind;
 use rustc::infer::InferCtxt;
@@ -23,7 +23,6 @@
 use rustc::ty::{self, RegionVid, Ty};
 use rustc_data_structures::transitive_relation::TransitiveRelation;
 use std::rc::Rc;
-use syntax::ast;
 
 #[derive(Debug)]
 crate struct UniversalRegionRelations<'tcx> {
@@ -67,7 +66,6 @@
 
 crate fn create(
     infcx: &InferCtxt<'_, '_, 'tcx>,
-    mir_def_id: DefId,
     param_env: ty::ParamEnv<'tcx>,
     location_table: &LocationTable,
     implicit_region_bound: Option<ty::Region<'tcx>>,
     constraints: &mut MirTypeckRegionConstraints<'tcx>,
     all_facts: &mut Option<AllFacts>,
 ) -> CreateResult<'tcx> {
-    let mir_node_id = infcx.tcx.hir.as_local_node_id(mir_def_id).unwrap();
     UniversalRegionRelationsBuilder {
         infcx,
-        mir_def_id,
-        mir_node_id,
         param_env,
         implicit_region_bound,
         constraints,
@@ -212,8 +207,6 @@ fn non_local_bound(
 
 struct UniversalRegionRelationsBuilder<'this, 'gcx: 'tcx, 'tcx: 'this> {
     infcx: &'this InferCtxt<'this, 'gcx, 'tcx>,
-    mir_def_id: DefId,
-    mir_node_id: ast::NodeId,
     param_env: ty::ParamEnv<'tcx>,
     location_table: &'this LocationTable,
     universal_regions: Rc<UniversalRegions<'tcx>>,
@@ -248,14 +241,16 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> {
         let constraint_sets: Vec<_> = unnormalized_input_output_tys
             .flat_map(|ty| {
                 debug!("build: input_or_output={:?}", ty);
-                let (ty, constraints) = self
+                let (ty, constraints1) = self
                     .param_env
                     .and(type_op::normalize::Normalize::new(ty))
                     .fully_perform(self.infcx)
                     .unwrap_or_else(|_| bug!("failed to normalize {:?}", ty));
-                self.add_implied_bounds(ty);
+                let constraints2 = self.add_implied_bounds(ty);
                 normalized_inputs_and_output.push(ty);
-                constraints
+                constraints1
+                    .into_iter()
+                    .chain(constraints2)
             })
             .collect();
 
@@ -306,13 +301,15 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> {
     /// either the return type of the MIR or one of its arguments. At
     /// the same time, compute and add any implied bounds that come
     /// from this local.
-    fn add_implied_bounds(&mut self, ty: Ty<'tcx>) {
+    fn add_implied_bounds(&mut self, ty: Ty<'tcx>) -> Option<Rc<Vec<QueryRegionConstraint<'tcx>>>> {
         debug!("add_implied_bounds(ty={:?})", ty);
-        let span = self.infcx.tcx.def_span(self.mir_def_id);
-        let bounds = self
-            .infcx
-            .implied_outlives_bounds(self.param_env, self.mir_node_id, ty, span);
+        let (bounds, constraints) =
+            self.param_env
+            .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
+            .fully_perform(self.infcx)
+            .unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty));
         self.add_outlives_bounds(bounds);
+        constraints
     }
 
     /// Registers the `OutlivesBound` items from `outlives_bounds` in
index 89e8c76b22fb456ed31ec645f7e6b253c9d254f7..15affbbc27a20b9468195ef68913de3dee843c1c 100644 (file)
@@ -10,9 +10,9 @@
 
 //! For the NLL computation, we need to compute liveness, but only for those
 //! local variables whose types contain regions. The others are not of interest
-//! to us. This file defines a new index type (LocalWithRegion) that indexes into
+//! to us. This file defines a new index type (LiveVar) that indexes into
 //! a list of "variables whose type contain regions". It also defines a map from
-//! Local to LocalWithRegion and vice versa -- this map can be given to the
+//! Local to LiveVar and vice versa -- this map can be given to the
 //! liveness code so that it only operates over variables with regions in their
 //! types, instead of all variables.
 
@@ -23,7 +23,7 @@
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use util::liveness::LiveVariableMap;
 
-/// Map between Local and LocalWithRegion indices: the purpose of this
+/// Map between Local and LiveVar indices: the purpose of this
 /// map is to define the subset of local variables for which we need
 /// to do a liveness computation. We only need to compute whether a
 /// variable `X` is live if that variable contains some region `R` in
 crate struct NllLivenessMap {
     /// For each local variable, contains `Some(i)` if liveness is
     /// needed for this variable.
-    pub from_local: IndexVec<Local, Option<LocalWithRegion>>,
+    pub from_local: IndexVec<Local, Option<LiveVar>>,
 
-    /// For each `LocalWithRegion`, maps back to the original `Local` index.
-    pub to_local: IndexVec<LocalWithRegion, Local>,
+    /// For each `LiveVar`, maps back to the original `Local` index.
+    pub to_local: IndexVec<LiveVar, Local>,
 }
 
 impl LiveVariableMap for NllLivenessMap {
@@ -43,7 +43,7 @@ fn from_local(&self, local: Local) -> Option<Self::LiveVar> {
         self.from_local[local]
     }
 
-    type LiveVar = LocalWithRegion;
+    type LiveVar = LiveVar;
 
     fn from_live_var(&self, local: Self::LiveVar) -> Local {
         self.to_local[local]
@@ -93,5 +93,10 @@ impl NllLivenessMap {
     }
 }
 
-/// Index given to each local variable whose type contains a region.
-newtype_index!(LocalWithRegion);
+/// Index given to each local variable for which we need to
+/// compute liveness information. For many locals, we are able to
+/// skip liveness information: for example, those variables whose
+/// types contain no regions.
+newtype_index!(
+    LiveVar
+);
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
new file mode 100644 (file)
index 0000000..73d285c
--- /dev/null
@@ -0,0 +1,159 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements};
+use borrow_check::nll::type_check::liveness::liveness_map::{LiveVar, NllLivenessMap};
+use rustc::mir::visit::{PlaceContext, Visitor};
+use rustc::mir::{Local, Location, Mir};
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use rustc_data_structures::vec_linked_list as vll;
+use util::liveness::{categorize, DefUse, LiveVariableMap};
+
+/// A map that cross references each local with the locations where it
+/// is defined (assigned), used, or dropped. Used during liveness
+/// computation.
+crate struct LocalUseMap<'me> {
+    liveness_map: &'me NllLivenessMap,
+
+    /// Head of a linked list of **definitions** of each variable --
+    /// definition in this context means assignment, e.g. `x` is
+    /// defined in `x = y` but not `y`; that first def is the head of
+    /// a linked list that lets you enumerate all places the variable
+    /// is assigned.
+    first_def_at: IndexVec<LiveVar, Option<AppearanceIndex>>,
+
+    /// Head of a linked list of **uses** of each variable -- use in
+    /// this context means that the existing value of the variable is
+    /// read or modified. e.g., `y` is used in `x = y` but not `x`.
+    /// Note that `DROP(x)` terminators are excluded from this list.
+    first_use_at: IndexVec<LiveVar, Option<AppearanceIndex>>,
+
+    /// Head of a linked list of **drops** of each variable -- these
+    /// are a special category of uses corresponding to the drop that
+    /// we add for each local variable.
+    first_drop_at: IndexVec<LiveVar, Option<AppearanceIndex>>,
+
+    appearances: IndexVec<AppearanceIndex, Appearance>,
+}
+
+struct Appearance {
+    point_index: PointIndex,
+    next: Option<AppearanceIndex>,
+}
+
+newtype_index!(AppearanceIndex);
+
+impl vll::LinkElem for Appearance {
+    type LinkIndex = AppearanceIndex;
+
+    fn next(elem: &Self) -> Option<AppearanceIndex> {
+        elem.next
+    }
+}
+
+impl LocalUseMap<'me> {
+    crate fn build(
+        liveness_map: &'me NllLivenessMap,
+        elements: &RegionValueElements,
+        mir: &Mir<'_>,
+    ) -> Self {
+        let nones = IndexVec::from_elem_n(None, liveness_map.num_variables());
+        let mut local_use_map = LocalUseMap {
+            liveness_map,
+            first_def_at: nones.clone(),
+            first_use_at: nones.clone(),
+            first_drop_at: nones,
+            appearances: IndexVec::new(),
+        };
+
+        LocalUseMapBuild {
+            local_use_map: &mut local_use_map,
+            elements,
+        }.visit_mir(mir);
+
+        local_use_map
+    }
+
+    crate fn defs(&self, local: LiveVar) -> impl Iterator<Item = PointIndex> + '_ {
+        vll::iter(self.first_def_at[local], &self.appearances)
+            .map(move |aa| self.appearances[aa].point_index)
+    }
+
+    crate fn uses(&self, local: LiveVar) -> impl Iterator<Item = PointIndex> + '_ {
+        vll::iter(self.first_use_at[local], &self.appearances)
+            .map(move |aa| self.appearances[aa].point_index)
+    }
+
+    crate fn drops(&self, local: LiveVar) -> impl Iterator<Item = PointIndex> + '_ {
+        vll::iter(self.first_drop_at[local], &self.appearances)
+            .map(move |aa| self.appearances[aa].point_index)
+    }
+}
+
+struct LocalUseMapBuild<'me, 'map: 'me> {
+    local_use_map: &'me mut LocalUseMap<'map>,
+    elements: &'me RegionValueElements,
+}
+
+impl LocalUseMapBuild<'_, '_> {
+    fn insert_def(&mut self, local: LiveVar, location: Location) {
+        Self::insert(
+            self.elements,
+            &mut self.local_use_map.first_def_at[local],
+            &mut self.local_use_map.appearances,
+            location,
+        );
+    }
+
+    fn insert_use(&mut self, local: LiveVar, location: Location) {
+        Self::insert(
+            self.elements,
+            &mut self.local_use_map.first_use_at[local],
+            &mut self.local_use_map.appearances,
+            location,
+        );
+    }
+
+    fn insert_drop(&mut self, local: LiveVar, location: Location) {
+        Self::insert(
+            self.elements,
+            &mut self.local_use_map.first_drop_at[local],
+            &mut self.local_use_map.appearances,
+            location,
+        );
+    }
+
+    fn insert(
+        elements: &RegionValueElements,
+        first_appearance: &mut Option<AppearanceIndex>,
+        appearances: &mut IndexVec<AppearanceIndex, Appearance>,
+        location: Location,
+    ) {
+        let point_index = elements.point_from_location(location);
+        let appearance_index = appearances.push(Appearance {
+            point_index,
+            next: *first_appearance,
+        });
+        *first_appearance = Some(appearance_index);
+    }
+}
+
+impl Visitor<'tcx> for LocalUseMapBuild<'_, '_> {
+    fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, location: Location) {
+        if let Some(local_with_region) = self.local_use_map.liveness_map.from_local(local) {
+            match categorize(context) {
+                Some(DefUse::Def) => self.insert_def(local_with_region, location),
+                Some(DefUse::Use) => self.insert_use(local_with_region, location),
+                Some(DefUse::Drop) => self.insert_drop(local_with_region, location),
+                _ => (),
+            }
+        }
+    }
+}
index a9b69cfe761abc4dded3ee3da2ab797dc9b55b72..b3fc73e9b7be342a11244c9e324fdeaf6a9ff544 100644 (file)
@@ -8,26 +8,23 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use borrow_check::nll::region_infer::values::RegionValueElements;
 use borrow_check::nll::constraints::ConstraintSet;
-use borrow_check::nll::type_check::AtLocation;
-use borrow_check::nll::{LocalWithRegion, NllLivenessMap};
+use borrow_check::nll::NllLivenessMap;
 use borrow_check::nll::universal_regions::UniversalRegions;
-use dataflow::move_paths::{HasMoveData, MoveData};
+use dataflow::move_paths::MoveData;
 use dataflow::MaybeInitializedPlaces;
-use dataflow::{FlowAtLocation, FlowsAtLocation};
-use rustc::infer::canonical::QueryRegionConstraint;
-use rustc::mir::{BasicBlock, Location, Mir};
-use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
-use rustc::traits::query::type_op::outlives::DropckOutlives;
-use rustc::traits::query::type_op::TypeOp;
-use rustc::ty::{RegionVid, Ty, TypeFoldable};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use dataflow::FlowAtLocation;
+use rustc::mir::Mir;
+use rustc::ty::RegionVid;
+use rustc_data_structures::fx::FxHashSet;
 use std::rc::Rc;
-use util::liveness::{LiveVariableMap, LivenessResults};
 
 use super::TypeChecker;
 
 crate mod liveness_map;
+mod local_use_map;
+mod trace;
 
 /// Combines liveness analysis with initialization analysis to
 /// determine which variables are live at which points, both due to
 /// NB. This computation requires normalization; therefore, it must be
 /// performed before
 pub(super) fn generate<'gcx, 'tcx>(
-    cx: &mut TypeChecker<'_, 'gcx, 'tcx>,
+    typeck: &mut TypeChecker<'_, 'gcx, 'tcx>,
     mir: &Mir<'tcx>,
+    elements: &Rc<RegionValueElements>,
     flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,
-) -> (LivenessResults<LocalWithRegion>, NllLivenessMap) {
+) {
+    debug!("liveness::generate");
     let free_regions = {
-        let borrowck_context = cx.borrowck_context.as_ref().unwrap();
+        let borrowck_context = typeck.borrowck_context.as_ref().unwrap();
         regions_that_outlive_free_regions(
-            cx.infcx.num_region_vars(),
+            typeck.infcx.num_region_vars(),
             &borrowck_context.universal_regions,
             &borrowck_context.constraints.outlives_constraints,
         )
     };
-    let liveness_map = NllLivenessMap::compute(cx.tcx(), &free_regions, mir);
-    let liveness = LivenessResults::compute(mir, &liveness_map);
-
-    // For everything else, it is only live where it is actually used.
-    if !liveness_map.is_empty() {
-        let mut generator = TypeLivenessGenerator {
-            cx,
-            mir,
-            liveness: &liveness,
-            flow_inits,
-            move_data,
-            drop_data: FxHashMap(),
-            map: &liveness_map,
-        };
-
-        for bb in mir.basic_blocks().indices() {
-            generator.add_liveness_constraints(bb);
-        }
-    }
-
-    (liveness, liveness_map)
+    let liveness_map = NllLivenessMap::compute(typeck.tcx(), &free_regions, mir);
+    trace::trace(typeck, mir, elements, flow_inits, move_data, &liveness_map);
 }
 
 /// Compute all regions that are (currently) known to outlive free
@@ -112,198 +92,3 @@ fn regions_that_outlive_free_regions(
     // Return the final set of things we visited.
     outlives_free_region
 }
-
-struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx>
-where
-    'typeck: 'gen,
-    'flow: 'gen,
-    'tcx: 'typeck + 'flow,
-    'gcx: 'tcx,
-{
-    cx: &'gen mut TypeChecker<'typeck, 'gcx, 'tcx>,
-    mir: &'gen Mir<'tcx>,
-    liveness: &'gen LivenessResults<LocalWithRegion>,
-    flow_inits: &'gen mut FlowAtLocation<MaybeInitializedPlaces<'flow, 'gcx, 'tcx>>,
-    move_data: &'gen MoveData<'tcx>,
-    drop_data: FxHashMap<Ty<'tcx>, DropData<'tcx>>,
-    map: &'gen NllLivenessMap,
-}
-
-struct DropData<'tcx> {
-    dropck_result: DropckOutlivesResult<'tcx>,
-    region_constraint_data: Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>,
-}
-
-impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> {
-    /// Liveness constraints:
-    ///
-    /// > If a variable V is live at point P, then all regions R in the type of V
-    /// > must include the point P.
-    fn add_liveness_constraints(&mut self, bb: BasicBlock) {
-        debug!("add_liveness_constraints(bb={:?})", bb);
-
-        self.liveness
-            .regular
-            .simulate_block(self.mir, bb, self.map, |location, live_locals| {
-                for live_local in live_locals.iter() {
-                    let local = self.map.from_live_var(live_local);
-                    let live_local_ty = self.mir.local_decls[local].ty;
-                    Self::push_type_live_constraint(&mut self.cx, live_local_ty, location);
-                }
-            });
-
-        let mut all_live_locals: Vec<(Location, Vec<LocalWithRegion>)> = vec![];
-        self.liveness
-            .drop
-            .simulate_block(self.mir, bb, self.map, |location, live_locals| {
-                all_live_locals.push((location, live_locals.iter().collect()));
-            });
-        debug!(
-            "add_liveness_constraints: all_live_locals={:#?}",
-            all_live_locals
-        );
-
-        let terminator_index = self.mir.basic_blocks()[bb].statements.len();
-        self.flow_inits.reset_to_entry_of(bb);
-        while let Some((location, live_locals)) = all_live_locals.pop() {
-            for live_local in live_locals {
-                debug!(
-                    "add_liveness_constraints: location={:?} live_local={:?}",
-                    location, live_local
-                );
-
-                if log_enabled!(::log::Level::Debug) {
-                    self.flow_inits.each_state_bit(|mpi_init| {
-                        debug!(
-                            "add_liveness_constraints: location={:?} initialized={:?}",
-                            location,
-                            &self.flow_inits.operator().move_data().move_paths[mpi_init]
-                        );
-                    });
-                }
-
-                let local = self.map.from_live_var(live_local);
-                let mpi = self.move_data.rev_lookup.find_local(local);
-                if let Some(initialized_child) = self.flow_inits.has_any_child_of(mpi) {
-                    debug!(
-                        "add_liveness_constraints: mpi={:?} has initialized child {:?}",
-                        self.move_data.move_paths[mpi],
-                        self.move_data.move_paths[initialized_child]
-                    );
-
-                    let local = self.map.from_live_var(live_local);
-                    let live_local_ty = self.mir.local_decls[local].ty;
-                    self.add_drop_live_constraint(live_local, live_local_ty, location);
-                }
-            }
-
-            if location.statement_index == terminator_index {
-                debug!(
-                    "add_liveness_constraints: reconstruct_terminator_effect from {:#?}",
-                    location
-                );
-                self.flow_inits.reconstruct_terminator_effect(location);
-            } else {
-                debug!(
-                    "add_liveness_constraints: reconstruct_statement_effect from {:#?}",
-                    location
-                );
-                self.flow_inits.reconstruct_statement_effect(location);
-            }
-            self.flow_inits.apply_local_effect(location);
-        }
-    }
-
-    /// Some variable with type `live_ty` is "regular live" at
-    /// `location` -- i.e., it may be used later. This means that all
-    /// regions appearing in the type `live_ty` must be live at
-    /// `location`.
-    fn push_type_live_constraint<T>(
-        cx: &mut TypeChecker<'_, 'gcx, 'tcx>,
-        value: T,
-        location: Location,
-    ) where
-        T: TypeFoldable<'tcx>,
-    {
-        debug!(
-            "push_type_live_constraint(live_ty={:?}, location={:?})",
-            value, location
-        );
-
-        cx.tcx().for_each_free_region(&value, |live_region| {
-            if let Some(ref mut borrowck_context) = cx.borrowck_context {
-                let region_vid = borrowck_context
-                    .universal_regions
-                    .to_region_vid(live_region);
-                borrowck_context
-                    .constraints
-                    .liveness_constraints
-                    .add_element(region_vid, location);
-
-                if let Some(all_facts) = borrowck_context.all_facts {
-                    let start_index = borrowck_context.location_table.start_index(location);
-                    all_facts.region_live_at.push((region_vid, start_index));
-
-                    let mid_index = borrowck_context.location_table.mid_index(location);
-                    all_facts.region_live_at.push((region_vid, mid_index));
-                }
-            }
-        });
-    }
-
-    /// Some variable with type `live_ty` is "drop live" at `location`
-    /// -- i.e., it may be dropped later. This means that *some* of
-    /// the regions in its type must be live at `location`. The
-    /// precise set will depend on the dropck constraints, and in
-    /// particular this takes `#[may_dangle]` into account.
-    fn add_drop_live_constraint(
-        &mut self,
-        dropped_local: LocalWithRegion,
-        dropped_ty: Ty<'tcx>,
-        location: Location,
-    ) {
-        debug!(
-            "add_drop_live_constraint(dropped_local={:?}, dropped_ty={:?}, location={:?})",
-            dropped_local, dropped_ty, location
-        );
-
-        let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({
-            let cx = &mut self.cx;
-            move || Self::compute_drop_data(cx, dropped_ty)
-        });
-
-        if let Some(data) = &drop_data.region_constraint_data {
-            self.cx.push_region_constraints(location.boring(), data);
-        }
-
-        drop_data.dropck_result.report_overflows(
-            self.cx.infcx.tcx,
-            self.mir.source_info(location).span,
-            dropped_ty,
-        );
-
-        // All things in the `outlives` array may be touched by
-        // the destructor and must be live at this point.
-        for &kind in &drop_data.dropck_result.kinds {
-            Self::push_type_live_constraint(&mut self.cx, kind, location);
-        }
-    }
-
-    fn compute_drop_data(
-        cx: &mut TypeChecker<'_, 'gcx, 'tcx>,
-        dropped_ty: Ty<'tcx>,
-    ) -> DropData<'tcx> {
-        debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
-
-        let param_env = cx.param_env;
-        let (dropck_result, region_constraint_data) = param_env
-            .and(DropckOutlives::new(dropped_ty))
-            .fully_perform(cx.infcx)
-            .unwrap();
-
-        DropData {
-            dropck_result,
-            region_constraint_data,
-        }
-    }
-}
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
new file mode 100644 (file)
index 0000000..79589ce
--- /dev/null
@@ -0,0 +1,553 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use borrow_check::nll::region_infer::values::{self, PointIndex, RegionValueElements};
+use borrow_check::nll::type_check::liveness::liveness_map::{LiveVar, NllLivenessMap};
+use borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap;
+use borrow_check::nll::type_check::AtLocation;
+use borrow_check::nll::type_check::TypeChecker;
+use dataflow::move_paths::indexes::MovePathIndex;
+use dataflow::move_paths::MoveData;
+use dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
+use rustc::infer::canonical::QueryRegionConstraint;
+use rustc::mir::{BasicBlock, Local, Location, Mir};
+use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
+use rustc::traits::query::type_op::outlives::DropckOutlives;
+use rustc::traits::query::type_op::TypeOp;
+use rustc::ty::{Ty, TypeFoldable};
+use rustc_data_structures::bitvec::BitArray;
+use rustc_data_structures::fx::FxHashMap;
+use std::rc::Rc;
+use util::liveness::LiveVariableMap;
+
+/// This is the heart of the liveness computation. For each variable X
+/// that requires a liveness computation, it walks over all the uses
+/// of X and does a reverse depth-first search ("trace") through the
+/// MIR. This search stops when we find a definition of that variable.
+/// The points visited in this search is the USE-LIVE set for the variable;
+/// of those points is added to all the regions that appear in the variable's
+/// type.
+///
+/// We then also walks through each *drop* of those variables and does
+/// another search, stopping when we reach a use or definition. This
+/// is the DROP-LIVE set of points. Each of the points in the
+/// DROP-LIVE set are to the liveness sets for regions found in the
+/// `dropck_outlives` result of the variable's type (in particular,
+/// this respects `#[may_dangle]` annotations).
+pub(super) fn trace(
+    typeck: &mut TypeChecker<'_, 'gcx, 'tcx>,
+    mir: &Mir<'tcx>,
+    elements: &Rc<RegionValueElements>,
+    flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
+    move_data: &MoveData<'tcx>,
+    liveness_map: &NllLivenessMap,
+) {
+    debug!("trace()");
+
+    if liveness_map.is_empty() {
+        return;
+    }
+
+    let local_use_map = &LocalUseMap::build(liveness_map, elements, mir);
+
+    let cx = LivenessContext {
+        typeck,
+        mir,
+        flow_inits,
+        elements,
+        local_use_map,
+        move_data,
+        liveness_map,
+        drop_data: FxHashMap::default(),
+    };
+
+    LivenessResults::new(cx).compute_for_all_locals();
+}
+
+/// Contextual state for the type-liveness generator.
+struct LivenessContext<'me, 'typeck, 'flow, 'gcx, 'tcx>
+where
+    'typeck: 'me,
+    'flow: 'me,
+    'tcx: 'typeck + 'flow,
+    'gcx: 'tcx,
+{
+    /// Current type-checker, giving us our inference context etc.
+    typeck: &'me mut TypeChecker<'typeck, 'gcx, 'tcx>,
+
+    /// Defines the `PointIndex` mapping
+    elements: &'me RegionValueElements,
+
+    /// MIR we are analyzing.
+    mir: &'me Mir<'tcx>,
+
+    /// Mapping to/from the various indices used for initialization tracking.
+    move_data: &'me MoveData<'tcx>,
+
+    /// Cache for the results of `dropck_outlives` query.
+    drop_data: FxHashMap<Ty<'tcx>, DropData<'tcx>>,
+
+    /// Results of dataflow tracking which variables (and paths) have been
+    /// initialized.
+    flow_inits: &'me mut FlowAtLocation<MaybeInitializedPlaces<'flow, 'gcx, 'tcx>>,
+
+    /// Index indicating where each variable is assigned, used, or
+    /// dropped.
+    local_use_map: &'me LocalUseMap<'me>,
+
+    /// Map tracking which variables need liveness computation.
+    liveness_map: &'me NllLivenessMap,
+}
+
+struct DropData<'tcx> {
+    dropck_result: DropckOutlivesResult<'tcx>,
+    region_constraint_data: Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>,
+}
+
+struct LivenessResults<'me, 'typeck, 'flow, 'gcx, 'tcx>
+where
+    'typeck: 'me,
+    'flow: 'me,
+    'tcx: 'typeck + 'flow,
+    'gcx: 'tcx,
+{
+    cx: LivenessContext<'me, 'typeck, 'flow, 'gcx, 'tcx>,
+
+    /// Set of points that define the current local.
+    defs: BitArray<PointIndex>,
+
+    /// Points where the current variable is "use live" -- meaning
+    /// that there is a future "full use" that may use its value.
+    use_live_at: BitArray<PointIndex>,
+
+    /// Points where the current variable is "drop live" -- meaning
+    /// that there is no future "full use" that may use its value, but
+    /// there is a future drop.
+    drop_live_at: BitArray<PointIndex>,
+
+    /// Locations where drops may occur.
+    drop_locations: Vec<Location>,
+
+    /// Stack used when doing (reverse) DFS.
+    stack: Vec<PointIndex>,
+}
+
+impl LivenessResults<'me, 'typeck, 'flow, 'gcx, 'tcx> {
+    fn new(cx: LivenessContext<'me, 'typeck, 'flow, 'gcx, 'tcx>) -> Self {
+        let num_points = cx.elements.num_points();
+        LivenessResults {
+            cx,
+            defs: BitArray::new(num_points),
+            use_live_at: BitArray::new(num_points),
+            drop_live_at: BitArray::new(num_points),
+            drop_locations: vec![],
+            stack: vec![],
+        }
+    }
+
+    fn compute_for_all_locals(&mut self) {
+        for live_local in self.cx.liveness_map.to_local.indices() {
+            let local = self.cx.liveness_map.from_live_var(live_local);
+            debug!("local={:?} live_local={:?}", local, live_local);
+
+            self.reset_local_state();
+            self.add_defs_for(live_local);
+            self.compute_use_live_points_for(live_local);
+            self.compute_drop_live_points_for(live_local);
+
+            let local_ty = self.cx.mir.local_decls[local].ty;
+
+            if !self.use_live_at.is_empty() {
+                self.cx.add_use_live_facts_for(local_ty, &self.use_live_at);
+            }
+
+            if !self.drop_live_at.is_empty() {
+                self.cx.add_drop_live_facts_for(
+                    local,
+                    local_ty,
+                    &self.drop_locations,
+                    &self.drop_live_at,
+                );
+            }
+        }
+    }
+
+    /// Clear the value of fields that are "per local variable".
+    fn reset_local_state(&mut self) {
+        self.defs.clear();
+        self.use_live_at.clear();
+        self.drop_live_at.clear();
+        self.drop_locations.clear();
+        assert!(self.stack.is_empty());
+    }
+
+    /// Adds the definitions of `local` into `self.defs`.
+    fn add_defs_for(&mut self, live_local: LiveVar) {
+        for def in self.cx.local_use_map.defs(live_local) {
+            debug!("- defined at {:?}", def);
+            self.defs.insert(def);
+        }
+    }
+
+    /// Compute all points where local is "use live" -- meaning its
+    /// current value may be used later (except by a drop). This is
+    /// done by walking backwards from each use of `live_local` until we
+    /// find a `def` of local.
+    ///
+    /// Requires `add_defs_for(live_local)` to have been executed.
+    fn compute_use_live_points_for(&mut self, live_local: LiveVar) {
+        debug!("compute_use_live_points_for(live_local={:?})", live_local);
+
+        self.stack.extend(self.cx.local_use_map.uses(live_local));
+        while let Some(p) = self.stack.pop() {
+            if self.defs.contains(p) {
+                continue;
+            }
+
+            if self.use_live_at.insert(p) {
+                self.cx
+                    .elements
+                    .push_predecessors(self.cx.mir, p, &mut self.stack)
+            }
+        }
+    }
+
+    /// Compute all points where local is "drop live" -- meaning its
+    /// current value may be dropped later (but not used). This is
+    /// done by iterating over the drops of `local` where `local` (or
+    /// some subpart of `local`) is initialized. For each such drop,
+    /// we walk backwards until we find a point where `local` is
+    /// either defined or use-live.
+    ///
+    /// Requires `compute_use_live_points_for` and `add_defs_for` to
+    /// have been executed.
+    fn compute_drop_live_points_for(&mut self, live_local: LiveVar) {
+        debug!("compute_drop_live_points_for(live_local={:?})", live_local);
+
+        let local = self.cx.liveness_map.from_live_var(live_local);
+        let mpi = self.cx.move_data.rev_lookup.find_local(local);
+        debug!("compute_drop_live_points_for: mpi = {:?}", mpi);
+
+        // Find the drops where `local` is initialized.
+        for drop_point in self.cx.local_use_map.drops(live_local) {
+            let location = self.cx.elements.to_location(drop_point);
+            debug_assert_eq!(self.cx.mir.terminator_loc(location.block), location,);
+
+            if self.cx.initialized_at_terminator(location.block, mpi) {
+                if self.drop_live_at.insert(drop_point) {
+                    self.drop_locations.push(location);
+                    self.stack.push(drop_point);
+                }
+            }
+        }
+
+        debug!(
+            "compute_drop_live_points_for: drop_locations={:?}",
+            self.drop_locations
+        );
+
+        // Reverse DFS. But for drops, we do it a bit differently.
+        // The stack only ever stores *terminators of blocks*. Within
+        // a block, we walk back the statements in an inner loop.
+        'next_block: while let Some(term_point) = self.stack.pop() {
+            self.compute_drop_live_points_for_block(mpi, term_point);
+        }
+    }
+
+    /// Executes one iteration of the drop-live analysis loop.
+    ///
+    /// The parameter `mpi` is the `MovePathIndex` of the local variable
+    /// we are currently analyzing.
+    ///
+    /// The point `term_point` represents some terminator in the MIR,
+    /// where the local `mpi` is drop-live on entry to that terminator.
+    ///
+    /// This method adds all drop-live points within the block and --
+    /// where applicable -- pushes the terminators of preceding blocks
+    /// onto `self.stack`.
+    fn compute_drop_live_points_for_block(&mut self, mpi: MovePathIndex, term_point: PointIndex) {
+        debug!(
+            "compute_drop_live_points_for_block(mpi={:?}, term_point={:?})",
+            self.cx.move_data.move_paths[mpi].place,
+            self.cx.elements.to_location(term_point),
+        );
+
+        // We are only invoked with terminators where `mpi` is
+        // drop-live on entry.
+        debug_assert!(self.drop_live_at.contains(term_point));
+
+        // Otherwise, scan backwards through the statements in the
+        // block.  One of them may be either a definition or use
+        // live point.
+        let term_location = self.cx.elements.to_location(term_point);
+        debug_assert_eq!(
+            self.cx.mir.terminator_loc(term_location.block),
+            term_location,
+        );
+        let block = term_location.block;
+        let entry_point = self.cx.elements.entry_point(term_location.block);
+        for p in (entry_point..term_point).rev() {
+            debug!(
+                "compute_drop_live_points_for_block: p = {:?}",
+                self.cx.elements.to_location(p),
+            );
+
+            if self.defs.contains(p) {
+                debug!("compute_drop_live_points_for_block: def site");
+                return;
+            }
+
+            if self.use_live_at.contains(p) {
+                debug!("compute_drop_live_points_for_block: use-live at {:?}", p);
+                return;
+            }
+
+            if !self.drop_live_at.insert(p) {
+                debug!("compute_drop_live_points_for_block: already drop-live");
+                return;
+            }
+        }
+
+        for &pred_block in self.cx.mir.predecessors_for(block).iter() {
+            debug!(
+                "compute_drop_live_points_for_block: pred_block = {:?}",
+                pred_block,
+            );
+
+            // Check whether the variable is (at least partially)
+            // initialized at the exit of this predecessor. If so, we
+            // want to enqueue it on our list. If not, go check the
+            // next block.
+            //
+            // Note that we only need to check whether `live_local`
+            // became de-initialized at basic block boundaries. If it
+            // were to become de-initialized within the block, that
+            // would have been a "use-live" transition in the earlier
+            // loop, and we'd have returned already.
+            //
+            // NB. It's possible that the pred-block ends in a call
+            // which stores to the variable; in that case, the
+            // variable may be uninitialized "at exit" because this
+            // call only considers the *unconditional effects* of the
+            // terminator. *But*, in that case, the terminator is also
+            // a *definition* of the variable, in which case we want
+            // to stop the search anyhow. (But see Note 1 below.)
+            if !self.cx.initialized_at_exit(pred_block, mpi) {
+                debug!("compute_drop_live_points_for_block: not initialized");
+                continue;
+            }
+
+            let pred_term_loc = self.cx.mir.terminator_loc(pred_block);
+            let pred_term_point = self.cx.elements.point_from_location(pred_term_loc);
+
+            // If the terminator of this predecessor either *assigns*
+            // our value or is a "normal use", then stop.
+            if self.defs.contains(pred_term_point) {
+                debug!(
+                    "compute_drop_live_points_for_block: defined at {:?}",
+                    pred_term_loc
+                );
+                continue;
+            }
+
+            if self.use_live_at.contains(pred_term_point) {
+                debug!(
+                    "compute_drop_live_points_for_block: use-live at {:?}",
+                    pred_term_loc
+                );
+                continue;
+            }
+
+            // Otherwise, we are drop-live on entry to the terminator,
+            // so walk it.
+            if self.drop_live_at.insert(pred_term_point) {
+                debug!("compute_drop_live_points_for_block: pushed to stack");
+                self.stack.push(pred_term_point);
+            }
+        }
+
+        // Note 1. There is a weird scenario that you might imagine
+        // being problematic here, but which actually cannot happen.
+        // The problem would be if we had a variable that *is* initialized
+        // (but dead) on entry to the terminator, and where the current value
+        // will be dropped in the case of unwind. In that case, we ought to
+        // consider `X` to be drop-live in between the last use and call.
+        // Here is the example:
+        //
+        // ```
+        // BB0 {
+        //   X = ...
+        //   use(X); // last use
+        //   ...     // <-- X ought to be drop-live here
+        //   X = call() goto BB1 unwind BB2
+        // }
+        //
+        // BB1 {
+        //   DROP(X)
+        // }
+        //
+        // BB2 {
+        //   DROP(X)
+        // }
+        // ```
+        //
+        // However, the current code would, when walking back from BB2,
+        // simply stop and never explore BB0. This seems bad! But it turns
+        // out this code is flawed anyway -- note that the existing value of
+        // `X` would leak in the case where unwinding did *not* occur.
+        //
+        // What we *actually* generate is a store to a temporary
+        // for the call (`TMP = call()...`) and then a
+        // `DropAndReplace` to swap that with `X`
+        // (`DropAndReplace` has very particular semantics).
+    }
+}
+
+impl LivenessContext<'_, '_, '_, '_, 'tcx> {
+    /// True if the local variable (or some part of it) is initialized in
+    /// the terminator of `block`. We need to check this to determine if a
+    /// DROP of some local variable will have an effect -- note that
+    /// drops, as they may unwind, are always terminators.
+    fn initialized_at_terminator(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool {
+        // Compute the set of initialized paths at terminator of block
+        // by resetting to the start of the block and then applying
+        // the effects of all statements. This is the only way to get
+        // "just ahead" of a terminator.
+        self.flow_inits.reset_to_entry_of(block);
+        for statement_index in 0..self.mir[block].statements.len() {
+            let location = Location {
+                block,
+                statement_index,
+            };
+            self.flow_inits.reconstruct_statement_effect(location);
+            self.flow_inits.apply_local_effect(location);
+        }
+
+        self.flow_inits.has_any_child_of(mpi).is_some()
+    }
+
+    /// True if the path `mpi` (or some part of it) is initialized at
+    /// the exit of `block`.
+    ///
+    /// **Warning:** Does not account for the result of `Call`
+    /// instructions.
+    fn initialized_at_exit(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool {
+        self.flow_inits.reset_to_exit_of(block);
+        self.flow_inits.has_any_child_of(mpi).is_some()
+    }
+
+    /// Store the result that all regions in `value` are live for the
+    /// points `live_at`.
+    fn add_use_live_facts_for(
+        &mut self,
+        value: impl TypeFoldable<'tcx>,
+        live_at: &BitArray<PointIndex>,
+    ) {
+        debug!("add_use_live_facts_for(value={:?})", value);
+
+        Self::make_all_regions_live(self.elements, &mut self.typeck, value, live_at)
+    }
+
+    /// Some variable with type `live_ty` is "drop live" at `location`
+    /// -- i.e., it may be dropped later. This means that *some* of
+    /// the regions in its type must be live at `location`. The
+    /// precise set will depend on the dropck constraints, and in
+    /// particular this takes `#[may_dangle]` into account.
+    fn add_drop_live_facts_for(
+        &mut self,
+        dropped_local: Local,
+        dropped_ty: Ty<'tcx>,
+        drop_locations: &[Location],
+        live_at: &BitArray<PointIndex>,
+    ) {
+        debug!(
+            "add_drop_live_constraint(\
+             dropped_local={:?}, \
+             dropped_ty={:?}, \
+             drop_locations={:?}, \
+             live_at={:?})",
+            dropped_local,
+            dropped_ty,
+            drop_locations,
+            values::location_set_str(self.elements, live_at.iter()),
+        );
+
+        let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({
+            let typeck = &mut self.typeck;
+            move || Self::compute_drop_data(typeck, dropped_ty)
+        });
+
+        if let Some(data) = &drop_data.region_constraint_data {
+            for &drop_location in drop_locations {
+                self.typeck
+                    .push_region_constraints(drop_location.boring(), data);
+            }
+        }
+
+        drop_data.dropck_result.report_overflows(
+            self.typeck.infcx.tcx,
+            self.mir.source_info(*drop_locations.first().unwrap()).span,
+            dropped_ty,
+        );
+
+        // All things in the `outlives` array may be touched by
+        // the destructor and must be live at this point.
+        for &kind in &drop_data.dropck_result.kinds {
+            Self::make_all_regions_live(self.elements, &mut self.typeck, kind, live_at);
+        }
+    }
+
+    fn make_all_regions_live(
+        elements: &RegionValueElements,
+        typeck: &mut TypeChecker<'_, '_, 'tcx>,
+        value: impl TypeFoldable<'tcx>,
+        live_at: &BitArray<PointIndex>,
+    ) {
+        debug!("make_all_regions_live(value={:?})", value);
+        debug!(
+            "make_all_regions_live: live_at={}",
+            values::location_set_str(elements, live_at.iter()),
+        );
+
+        let tcx = typeck.tcx();
+        tcx.for_each_free_region(&value, |live_region| {
+            let borrowck_context = typeck.borrowck_context.as_mut().unwrap();
+            let live_region_vid = borrowck_context
+                .universal_regions
+                .to_region_vid(live_region);
+            borrowck_context
+                .constraints
+                .liveness_constraints
+                .add_elements(live_region_vid, live_at);
+
+            if let Some(_) = borrowck_context.all_facts {
+                bug!("polonius liveness facts not implemented yet")
+            }
+        });
+    }
+
+    fn compute_drop_data(
+        typeck: &mut TypeChecker<'_, 'gcx, 'tcx>,
+        dropped_ty: Ty<'tcx>,
+    ) -> DropData<'tcx> {
+        debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
+
+        let param_env = typeck.param_env;
+        let (dropck_result, region_constraint_data) = param_env
+            .and(DropckOutlives::new(dropped_ty))
+            .fully_perform(typeck.infcx)
+            .unwrap();
+
+        DropData {
+            dropck_result,
+            region_constraint_data,
+        }
+    }
+}
index ab83cfe25b590b92a1f9c7b42566905be70e5015..3a5857f775fa458b1be915c99cf2130a1fb5aee2 100644 (file)
 use borrow_check::location::LocationTable;
 use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
 use borrow_check::nll::facts::AllFacts;
-use borrow_check::nll::region_infer::values::{RegionValueElements, LivenessValues};
+use borrow_check::nll::region_infer::values::{LivenessValues, RegionValueElements};
 use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest};
 use borrow_check::nll::type_check::free_region_relations::{CreateResult, UniversalRegionRelations};
-use borrow_check::nll::type_check::liveness::liveness_map::NllLivenessMap;
 use borrow_check::nll::universal_regions::UniversalRegions;
-use borrow_check::nll::LocalWithRegion;
 use borrow_check::nll::ToRegionVid;
 use dataflow::move_paths::MoveData;
 use dataflow::FlowAtLocation;
 use rustc::traits::query::type_op;
 use rustc::traits::query::{Fallible, NoSolution};
 use rustc::ty::fold::TypeFoldable;
-use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TypeVariants};
+use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
 use rustc_errors::Diagnostic;
 use std::fmt;
 use std::rc::Rc;
 use syntax_pos::{Span, DUMMY_SP};
 use transform::{MirPass, MirSource};
-use util::liveness::LivenessResults;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::Idx;
@@ -135,7 +132,6 @@ pub(crate) fn type_check<'gcx, 'tcx>(
         normalized_inputs_and_output,
     } = free_region_relations::create(
         infcx,
-        mir_def_id,
         param_env,
         location_table,
         Some(implicit_region_bound),
@@ -144,7 +140,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
         all_facts,
     );
 
-    let (liveness, liveness_map) = {
+    {
         let mut borrowck_context = BorrowCheckContext {
             universal_regions,
             location_table,
@@ -170,16 +166,14 @@ pub(crate) fn type_check<'gcx, 'tcx>(
                     &universal_region_relations,
                     &normalized_inputs_and_output,
                 );
-                liveness::generate(cx, mir, flow_inits, move_data)
+                liveness::generate(cx, mir, elements, flow_inits, move_data);
             },
-        )
-    };
+        );
+    }
 
     MirTypeckResults {
         constraints,
         universal_region_relations,
-        liveness,
-        liveness_map,
     }
 }
 
@@ -256,6 +250,22 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
         self.super_constant(constant, location);
         self.sanitize_constant(constant, location);
         self.sanitize_type(constant, constant.ty);
+
+        if let Some(user_ty) = constant.user_ty {
+            if let Err(terr) =
+                self.cx
+                    .eq_canonical_type_and_type(user_ty, constant.ty, location.boring())
+            {
+                span_mirbug!(
+                    self,
+                    constant,
+                    "bad constant user type {:?} vs {:?}: {:?}",
+                    user_ty,
+                    constant.ty,
+                    terr,
+                );
+            }
+        }
     }
 
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
@@ -320,7 +330,7 @@ fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
         // constraints on `'a` and `'b`. These constraints
         // would be lost if we just look at the normalized
         // value.
-        if let ty::TyFnDef(def_id, substs) = constant.literal.ty.sty {
+        if let ty::FnDef(def_id, substs) = constant.literal.ty.sty {
             let tcx = self.tcx();
             let type_checker = &mut self.cx;
 
@@ -343,8 +353,7 @@ fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
 
         debug!("sanitize_constant: expected_ty={:?}", constant.literal.ty);
 
-        if let Err(terr) = self
-            .cx
+        if let Err(terr) = self.cx
             .eq_types(constant.literal.ty, constant.ty, location.boring())
         {
             span_mirbug!(
@@ -483,7 +492,7 @@ fn sanitize_projection(
             }
             ProjectionElem::Subslice { from, to } => PlaceTy::Ty {
                 ty: match base_ty.sty {
-                    ty::TyArray(inner, size) => {
+                    ty::Array(inner, size) => {
                         let size = size.unwrap_usize(tcx);
                         let min_size = (from as u64) + (to as u64);
                         if let Some(rest_size) = size.checked_sub(min_size) {
@@ -497,12 +506,12 @@ fn sanitize_projection(
                             )
                         }
                     }
-                    ty::TySlice(..) => base_ty,
+                    ty::Slice(..) => base_ty,
                     _ => span_mirbug_and_err!(self, place, "slice of non-array {:?}", base_ty),
                 },
             },
             ProjectionElem::Downcast(adt_def1, index) => match base_ty.sty {
-                ty::TyAdt(adt_def, substs) if adt_def.is_enum() && adt_def == adt_def1 => {
+                ty::Adt(adt_def, substs) if adt_def.is_enum() && adt_def == adt_def1 => {
                     if index >= adt_def.variants.len() {
                         PlaceTy::Ty {
                             ty: span_mirbug_and_err!(
@@ -578,8 +587,8 @@ fn field_ty(
                 variant_index,
             } => (&adt_def.variants[variant_index], substs),
             PlaceTy::Ty { ty } => match ty.sty {
-                ty::TyAdt(adt_def, substs) if !adt_def.is_enum() => (&adt_def.variants[0], substs),
-                ty::TyClosure(def_id, substs) => {
+                ty::Adt(adt_def, substs) if !adt_def.is_enum() => (&adt_def.variants[0], substs),
+                ty::Closure(def_id, substs) => {
                     return match substs.upvar_tys(def_id, tcx).nth(field.index()) {
                         Some(ty) => Ok(ty),
                         None => Err(FieldAccessError::OutOfRange {
@@ -587,7 +596,7 @@ fn field_ty(
                         }),
                     }
                 }
-                ty::TyGenerator(def_id, substs, _) => {
+                ty::Generator(def_id, substs, _) => {
                     // Try pre-transform fields first (upvars and current state)
                     if let Some(ty) = substs.pre_transforms_tys(def_id, tcx).nth(field.index()) {
                         return Ok(ty);
@@ -602,7 +611,7 @@ fn field_ty(
                         }),
                     };
                 }
-                ty::TyTuple(tys) => {
+                ty::Tuple(tys) => {
                     return match tys.get(field.index()) {
                         Some(&ty) => Ok(ty),
                         None => Err(FieldAccessError::OutOfRange {
@@ -658,8 +667,6 @@ struct BorrowCheckContext<'a, 'tcx: 'a> {
 crate struct MirTypeckResults<'tcx> {
     crate constraints: MirTypeckRegionConstraints<'tcx>,
     crate universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
-    crate liveness: LivenessResults<LocalWithRegion>,
-    crate liveness_map: NllLivenessMap,
 }
 
 /// A collection of region constraints that must be satisfied for the
@@ -783,7 +790,7 @@ fn new(
     /// predicates, or otherwise uses the inference context, executes
     /// `op` and then executes all the further obligations that `op`
     /// returns. This will yield a set of outlives constraints amongst
-    /// regions which are extracted and stored as having occured at
+    /// regions which are extracted and stored as having occurred at
     /// `locations`.
     ///
     /// **Any `rustc::infer` operations that might generate region
@@ -902,6 +909,24 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Loca
                         terr
                     );
                 }
+
+                if let Some(user_ty) = self.rvalue_user_ty(rv) {
+                    if let Err(terr) = self.eq_canonical_type_and_type(
+                        user_ty,
+                        rv_ty,
+                        location.boring(),
+                    ) {
+                        span_mirbug!(
+                            self,
+                            stmt,
+                            "bad user type on rvalue ({:?} = {:?}): {:?}",
+                            user_ty,
+                            rv_ty,
+                            terr
+                        );
+                    }
+                }
+
                 self.check_rvalue(mir, rv, location);
                 if !self.tcx().features().unsized_locals {
                     let trait_ref = ty::TraitRef {
@@ -917,7 +942,7 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Loca
             } => {
                 let place_type = place.ty(mir, tcx).to_ty(tcx);
                 let adt = match place_type.sty {
-                    TypeVariants::TyAdt(adt, _) if adt.is_enum() => adt,
+                    TyKind::Adt(adt, _) if adt.is_enum() => adt,
                     _ => {
                         span_bug!(
                             stmt.source_info.span,
@@ -1032,7 +1057,7 @@ fn check_terminator(
                 let func_ty = func.ty(mir, tcx);
                 debug!("check_terminator: call, func_ty={:?}", func_ty);
                 let sig = match func_ty.sty {
-                    ty::TyFnDef(..) | ty::TyFnPtr(_) => func_ty.fn_sig(tcx),
+                    ty::FnDef(..) | ty::FnPtr(_) => func_ty.fn_sig(tcx),
                     _ => {
                         span_mirbug!(self, term, "call to non-function {:?}", func_ty);
                         return;
@@ -1376,7 +1401,7 @@ fn aggregate_field_ty(
         let tcx = self.tcx();
 
         match *ak {
-            AggregateKind::Adt(def, variant_index, substs, active_field_index) => {
+            AggregateKind::Adt(def, variant_index, substs, _, active_field_index) => {
                 let variant = &def.variants[variant_index];
                 let adj_field_index = active_field_index.unwrap_or(field_index);
                 if let Some(field) = variant.fields.get(adj_field_index) {
@@ -1472,7 +1497,7 @@ fn check_rvalue(&mut self, mir: &Mir<'tcx>, rvalue: &Rvalue<'tcx>, location: Loc
 
                 CastKind::ClosureFnPointer => {
                     let sig = match op.ty(mir, tcx).sty {
-                        ty::TyClosure(def_id, substs) => {
+                        ty::Closure(def_id, substs) => {
                             substs.closure_sig_ty(def_id, tcx).fn_sig(tcx)
                         }
                         _ => bug!(),
@@ -1542,6 +1567,36 @@ fn check_rvalue(&mut self, mir: &Mir<'tcx>, rvalue: &Rvalue<'tcx>, location: Loc
         }
     }
 
+    /// If this rvalue supports a user-given type annotation, then
+    /// extract and return it. This represents the final type of the
+    /// rvalue and will be unified with the inferred type.
+    fn rvalue_user_ty(
+        &self,
+        rvalue: &Rvalue<'tcx>,
+    ) -> Option<CanonicalTy<'tcx>> {
+        match rvalue {
+            Rvalue::Use(_) |
+            Rvalue::Repeat(..) |
+            Rvalue::Ref(..) |
+            Rvalue::Len(..) |
+            Rvalue::Cast(..) |
+            Rvalue::BinaryOp(..) |
+            Rvalue::CheckedBinaryOp(..) |
+            Rvalue::NullaryOp(..) |
+            Rvalue::UnaryOp(..) |
+            Rvalue::Discriminant(..) =>
+                None,
+
+            Rvalue::Aggregate(aggregate, _) => match **aggregate {
+                AggregateKind::Adt(_, _, _, user_ty, _) => user_ty,
+                AggregateKind::Array(_) => None,
+                AggregateKind::Tuple => None,
+                AggregateKind::Closure(_, _) => None,
+                AggregateKind::Generator(_, _, _) => None,
+            }
+        }
+    }
+
     fn check_aggregate_rvalue(
         &mut self,
         mir: &Mir<'tcx>,
@@ -1650,7 +1705,7 @@ fn add_reborrow_constraint(
 
                     debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
                     match base_ty.sty {
-                        ty::TyRef(ref_region, _, mutbl) => {
+                        ty::Ref(ref_region, _, mutbl) => {
                             constraints.outlives_constraints.push(OutlivesConstraint {
                                 sup: ref_region.to_region_vid(),
                                 sub: borrow_region.to_region_vid(),
@@ -1697,11 +1752,11 @@ fn add_reborrow_constraint(
                                 }
                             }
                         }
-                        ty::TyRawPtr(..) => {
+                        ty::RawPtr(..) => {
                             // deref of raw pointer, guaranteed to be valid
                             break;
                         }
-                        ty::TyAdt(def, _) if def.is_box() => {
+                        ty::Adt(def, _) if def.is_box() => {
                             // deref of `Box`, need the base to be valid - propagate
                         }
                         _ => bug!("unexpected deref ty {:?} in {:?}", base_ty, borrowed_place),
@@ -1735,7 +1790,7 @@ fn prove_aggregate_predicates(
         );
 
         let instantiated_predicates = match aggregate_kind {
-            AggregateKind::Adt(def, _, substs, _) => {
+            AggregateKind::Adt(def, _, substs, _, _) => {
                 tcx.predicates_of(def.did).instantiate(tcx, substs)
             }
 
index ac9bf65b61b0fb9b80dc43d1ba2ddac73226c9cc..deb972ee04611058d6bb339bcde1b6f248ec2988 100644 (file)
@@ -36,7 +36,7 @@ pub(super) fn sub_types<'tcx>(
         ty::Variance::Covariant,
         locations,
         borrowck_context,
-        ty::Slice::empty(),
+        ty::List::empty(),
     ).relate(&a, &b)?;
     Ok(())
 }
@@ -54,7 +54,7 @@ pub(super) fn eq_types<'tcx>(
         ty::Variance::Invariant,
         locations,
         borrowck_context,
-        ty::Slice::empty(),
+        ty::List::empty(),
     ).relate(&a, &b)?;
     Ok(())
 }
@@ -325,7 +325,7 @@ fn relate_with_variance<T: Relate<'tcx>>(
     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         // Watch out for the case that we are matching a `?T` against the
         // right-hand side.
-        if let ty::TyInfer(ty::CanonicalTy(var)) = a.sty {
+        if let ty::Infer(ty::CanonicalTy(var)) = a.sty {
             self.equate_var(var, b.into())?;
             Ok(a)
         } else {
index 765c4cf906e68a4c4a89ba524e52317df654d88d..8112b71b127527f1a9d38a1bb67875a840bdcd2e 100644 (file)
@@ -64,7 +64,7 @@ pub struct UniversalRegions<'tcx> {
 
     /// The "defining" type for this function, with all universal
     /// regions instantiated.  For a closure or generator, this is the
-    /// closure type, but for a top-level function it's the `TyFnDef`.
+    /// closure type, but for a top-level function it's the `FnDef`.
     pub defining_ty: DefiningTy<'tcx>,
 
     /// The return type of this function, with all regions replaced by
@@ -437,11 +437,11 @@ fn defining_ty(&self) -> DefiningTy<'tcx> {
                     .replace_free_regions_with_nll_infer_vars(FR, &defining_ty);
 
                 match defining_ty.sty {
-                    ty::TyClosure(def_id, substs) => DefiningTy::Closure(def_id, substs),
-                    ty::TyGenerator(def_id, substs, movability) => {
+                    ty::Closure(def_id, substs) => DefiningTy::Closure(def_id, substs),
+                    ty::Generator(def_id, substs, movability) => {
                         DefiningTy::Generator(def_id, substs, movability)
                     }
-                    ty::TyFnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs),
+                    ty::FnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs),
                     _ => span_bug!(
                         tcx.def_span(self.mir_def_id),
                         "expected defining type for `{:?}`: `{:?}`",
@@ -506,7 +506,7 @@ fn compute_inputs_and_output(
         &self,
         indices: &UniversalRegionIndices<'tcx>,
         defining_ty: DefiningTy<'tcx>,
-    ) -> ty::Binder<&'tcx ty::Slice<Ty<'tcx>>> {
+    ) -> ty::Binder<&'tcx ty::List<Ty<'tcx>>> {
         let tcx = self.infcx.tcx;
         match defining_ty {
             DefiningTy::Closure(def_id, substs) => {
@@ -524,7 +524,7 @@ fn compute_inputs_and_output(
                         let (&output, tuplized_inputs) = inputs_and_output.split_last().unwrap();
                         assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs");
                         let inputs = match tuplized_inputs[0].sty {
-                            ty::TyTuple(inputs) => inputs,
+                            ty::Tuple(inputs) => inputs,
                             _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]),
                         };
 
index be0091068c2e20326f77e64b1bc9d8e2d21cf7ce..2b4a1553e1a893d3054e048105b3b1937493fe03 100644 (file)
@@ -54,7 +54,7 @@ fn ignore_borrow(&self, tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> bool {
                         // original path into a new variable and
                         // borrowed *that* one, leaving the original
                         // path unborrowed.
-                        ty::TyRawPtr(..) | ty::TyRef(_, _, hir::MutImmutable) => true,
+                        ty::RawPtr(..) | ty::Ref(_, _, hir::MutImmutable) => true,
                         _ => proj.base.ignore_borrow(tcx, mir),
                     }
                 }
index 640ae31d45b349db89028614c438daca19eca80e..3f055283e0c3f71a7389cc928a8c4c98034d1254 100644 (file)
@@ -29,6 +29,14 @@ pub(super) fn places_conflict<'gcx, 'tcx>(
         borrow_place, access_place, access
     );
 
+    // This Local/Local case is handled by the more general code below, but
+    // it's so common that it's a speed win to check for it first.
+    if let Place::Local(l1) = borrow_place {
+        if let Place::Local(l2) = access_place {
+            return l1 == l2;
+        }
+    }
+
     unroll_place(borrow_place, None, |borrow_components| {
         unroll_place(access_place, None, |access_components| {
             place_components_conflict(tcx, mir, borrow_components, access_components, access)
@@ -83,7 +91,7 @@ fn place_components_conflict<'gcx, 'tcx>(
     // Our invariant is, that at each step of the iteration:
     //  - If we didn't run out of access to match, our borrow and access are comparable
     //    and either equal or disjoint.
-    //  - If we did run out of accesss, the borrow can access a part of it.
+    //  - If we did run out of access, the borrow can access a part of it.
     loop {
         // loop invariant: borrow_c is always either equal to access_c or disjoint from it.
         if let Some(borrow_c) = borrow_components.next() {
@@ -170,7 +178,7 @@ fn place_components_conflict<'gcx, 'tcx>(
                         debug!("places_conflict: shallow access behind ptr");
                         return false;
                     }
-                    (ProjectionElem::Deref, ty::TyRef(_, _, hir::MutImmutable), _) => {
+                    (ProjectionElem::Deref, ty::Ref(_, _, hir::MutImmutable), _) => {
                         // the borrow goes through a dereference of a shared reference.
                         //
                         // I'm not sure why we are tracking these borrows - shared
@@ -329,7 +337,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
         }
         (Place::Promoted(p1), Place::Promoted(p2)) => {
             if p1.0 == p2.0 {
-                if let ty::TyArray(_, size) = p1.1.sty {
+                if let ty::Array(_, size) = p1.1.sty {
                     if size.unwrap_usize(tcx) == 0 {
                         // Ignore conflicts with promoted [T; 0].
                         debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
@@ -366,7 +374,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
                     } else {
                         let ty = pi1.base.ty(mir, tcx).to_ty(tcx);
                         match ty.sty {
-                            ty::TyAdt(def, _) if def.is_union() => {
+                            ty::Adt(def, _) if def.is_union() => {
                                 // Different fields of a union, we are basically stuck.
                                 debug!("place_element_conflict: STUCK-UNION");
                                 Overlap::Arbitrary
index 9b16130d25ec4c5dff032a53526212969a014bbe..8dcc1143306212079b1b8178a4254c4da22bc9ba 100644 (file)
@@ -155,8 +155,8 @@ fn next(&mut self) -> Option<Self::Item> {
 
             let ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
             match ty.sty {
-                ty::TyRawPtr(_) |
-                ty::TyRef(
+                ty::RawPtr(_) |
+                ty::Ref(
                     _, /*rgn*/
                     _, /*ty*/
                     hir::MutImmutable
@@ -166,7 +166,7 @@ fn next(&mut self) -> Option<Self::Item> {
                     return Some(cursor);
                 }
 
-                ty::TyRef(
+                ty::Ref(
                     _, /*rgn*/
                     _, /*ty*/
                     hir::MutMutable,
@@ -175,7 +175,7 @@ fn next(&mut self) -> Option<Self::Item> {
                     return Some(cursor);
                 }
 
-                ty::TyAdt(..) if ty.is_box() => {
+                ty::Adt(..) if ty.is_box() => {
                     self.next = Some(&proj.base);
                     return Some(cursor);
                 }
index a57f1b95494855ca36d814b7ae7b2b3e1caec134..1106f750d6d24b4c0722f955defbcdf25a77318e 100644 (file)
@@ -31,8 +31,8 @@ fn expr_as_constant(&mut self, expr: Expr<'tcx>) -> Constant<'tcx> {
         match kind {
             ExprKind::Scope { region_scope: _, lint_level: _, value } =>
                 this.as_constant(value),
-            ExprKind::Literal { literal } =>
-                Constant { span: span, ty: ty, literal: literal },
+            ExprKind::Literal { literal, user_ty } =>
+                Constant { span, ty, user_ty, literal },
             _ =>
                 span_bug!(
                     span,
index 68009e962a302f3dce9f4ce8eae98f01f47aa5d5..b90a58f2a7ec040f8c48cd102d657805fcd45f5c 100644 (file)
@@ -239,6 +239,7 @@ fn expr_as_rvalue(&mut self,
                         operands.push(Operand::Constant(box Constant {
                             span: expr_span,
                             ty: this.hir.tcx().types.u32,
+                            user_ty: None,
                             literal: ty::Const::from_bits(
                                 this.hir.tcx(),
                                 0,
@@ -254,7 +255,7 @@ fn expr_as_rvalue(&mut self,
                 block.and(Rvalue::Aggregate(result, operands))
             }
             ExprKind::Adt {
-                adt_def, variant_index, substs, fields, base
+                adt_def, variant_index, substs, user_ty, fields, base
             } => { // see (*) above
                 let is_union = adt_def.is_union();
                 let active_field_index = if is_union { Some(fields[0].name.index()) } else { None };
@@ -284,8 +285,13 @@ fn expr_as_rvalue(&mut self,
                     field_names.iter().filter_map(|n| fields_map.get(n).cloned()).collect()
                 };
 
-                let adt =
-                    box AggregateKind::Adt(adt_def, variant_index, substs, active_field_index);
+                let adt = box AggregateKind::Adt(
+                    adt_def,
+                    variant_index,
+                    substs,
+                    user_ty,
+                    active_field_index,
+                );
                 block.and(Rvalue::Aggregate(adt, fields))
             }
             ExprKind::Assign { .. } |
index 59a7f49af80746ff955b62d14e37b544384e37f8..3cd1270d7ef11698baa93a71938559d1b549ab05 100644 (file)
@@ -128,6 +128,7 @@ pub fn into_expr(&mut self,
                     Constant {
                         span: expr_span,
                         ty: this.hir.bool_ty(),
+                        user_ty: None,
                         literal: this.hir.true_literal(),
                     });
 
@@ -136,6 +137,7 @@ pub fn into_expr(&mut self,
                     Constant {
                         span: expr_span,
                         ty: this.hir.bool_ty(),
+                        user_ty: None,
                         literal: this.hir.false_literal(),
                     });
 
@@ -216,7 +218,7 @@ pub fn into_expr(&mut self,
                 // FIXME(canndrew): This is_never should probably be an is_uninhabited
                 let diverges = expr.ty.is_never();
                 let intrinsic = match ty.sty {
-                    ty::TyFnDef(def_id, _)  => {
+                    ty::FnDef(def_id, _)  => {
                         let f = ty.fn_sig(this.hir.tcx());
                         if f.abi() == Abi::RustIntrinsic ||
                            f.abi() == Abi::PlatformIntrinsic {
index 7106e02284da3888cd219b61d17fe23ce5076bb6..4a0b4b0c88580ffcd8f822333acdd72f788c8ed8 100644 (file)
@@ -227,7 +227,7 @@ pub fn perform_test(&mut self,
             }
 
             TestKind::SwitchInt { switch_ty, ref options, indices: _ } => {
-                let (ret, terminator) = if switch_ty.sty == ty::TyBool {
+                let (ret, terminator) = if switch_ty.sty == ty::Bool {
                     assert!(options.len() > 0 && options.len() <= 2);
                     let (true_bb, false_bb) = (self.cfg.start_new_block(),
                                                self.cfg.start_new_block());
@@ -272,8 +272,8 @@ pub fn perform_test(&mut self,
                     // array, so we can call `<[u8]>::eq` rather than having to find an
                     // `<[u8; N]>::eq`.
                     let unsize = |ty: Ty<'tcx>| match ty.sty {
-                        ty::TyRef(region, rty, _) => match rty.sty {
-                            ty::TyArray(inner_ty, n) => Some((region, inner_ty, n)),
+                        ty::Ref(region, rty, _) => match rty.sty {
+                            ty::Array(inner_ty, n) => Some((region, inner_ty, n)),
                             _ => None,
                         },
                         _ => None,
@@ -344,7 +344,16 @@ pub fn perform_test(&mut self,
                         func: Operand::Constant(box Constant {
                             span: test.span,
                             ty: mty,
-                            literal: method
+
+                            // FIXME(#47184): This constant comes from user
+                            // input (a constant in a pattern).  Are
+                            // there forms where users can add type
+                            // annotations here?  For example, an
+                            // associated constant? Need to
+                            // experiment.
+                            user_ty: None,
+
+                            literal: method,
                         }),
                         args: vec![val, expect],
                         destination: Some((eq_result.clone(), eq_block)),
index ae8070698c299b434575fbfc3ff36007c54cbeff..9405f43c056b7a6e72352d89e47b192825c4456d 100644 (file)
@@ -32,6 +32,8 @@ pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
         place
     }
 
+    /// Convenience function for creating a literal operand, one
+    /// without any user type annotation.
     pub fn literal_operand(&mut self,
                            span: Span,
                            ty: Ty<'tcx>,
@@ -40,6 +42,7 @@ pub fn literal_operand(&mut self,
         let constant = box Constant {
             span,
             ty,
+            user_ty: None,
             literal,
         };
         Operand::Constant(constant)
@@ -69,6 +72,7 @@ pub fn push_usize(&mut self,
             Constant {
                 span: source_info.span,
                 ty: self.hir.usize_ty(),
+                user_ty: None,
                 literal: self.hir.usize_literal(value),
             });
         temp
index c0c431804d8c1ea52fcf1716084e06c761586e55..f178ea8bdbab12c63d5ca8eaeb7450993b200f4b 100644 (file)
@@ -14,6 +14,7 @@
 use hair::cx::Cx;
 use hair::{LintLevel, BindingMode, PatternKind};
 use rustc::hir;
+use rustc::hir::Node;
 use rustc::hir::def_id::{DefId, LocalDefId};
 use rustc::middle::region;
 use rustc::mir::*;
 /// Construct the MIR for a given def-id.
 pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'tcx> {
     let id = tcx.hir.as_local_node_id(def_id).unwrap();
-    let unsupported = || {
-        span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id);
-    };
 
     // Figure out what primary body this item has.
     let body_id = match tcx.hir.get(id) {
-        hir::map::NodeVariant(variant) =>
+        Node::Variant(variant) =>
             return create_constructor_shim(tcx, id, &variant.node.data),
-        hir::map::NodeStructCtor(ctor) =>
+        Node::StructCtor(ctor) =>
             return create_constructor_shim(tcx, id, ctor),
 
         _ => match tcx.hir.maybe_body_owned_by(id) {
             Some(body) => body,
-            None => unsupported(),
+            None => span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id),
         },
     };
 
@@ -67,13 +65,13 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
             let ty = tcx.type_of(tcx.hir.local_def_id(id));
             let mut abi = fn_sig.abi;
             let implicit_argument = match ty.sty {
-                ty::TyClosure(..) => {
+                ty::Closure(..) => {
                     // HACK(eddyb) Avoid having RustCall on closures,
                     // as it adds unnecessary (and wrong) auto-tupling.
                     abi = Abi::Rust;
                     Some(ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None))
                 }
-                ty::TyGenerator(..) => {
+                ty::Generator(..) => {
                     let gen_ty = tcx.body_tables(body_id).node_id_to_type(fn_hir_id);
                     Some(ArgInfo(gen_ty, None, None, None))
                 }
@@ -115,7 +113,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
 
             let (yield_ty, return_ty) = if body.is_generator {
                 let gen_sig = match ty.sty {
-                    ty::TyGenerator(gen_def_id, gen_substs, ..) =>
+                    ty::Generator(gen_def_id, gen_substs, ..) =>
                         gen_substs.sig(gen_def_id, tcx),
                     _ =>
                         span_bug!(tcx.hir.span(id), "generator w/o generator type: {:?}", ty),
@@ -241,7 +239,7 @@ fn liberated_closure_env_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
     let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_hir_id);
 
     let (closure_def_id, closure_substs) = match closure_ty.sty {
-        ty::TyClosure(closure_def_id, closure_substs) => (closure_def_id, closure_substs),
+        ty::Closure(closure_def_id, closure_substs) => (closure_def_id, closure_substs),
         _ => bug!("closure expr does not have closure type: {:?}", closure_ty)
     };
 
@@ -523,7 +521,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
                 by_ref,
                 mutability: Mutability::Not,
             };
-            if let Some(hir::map::NodeBinding(pat)) = tcx.hir.find(var_id) {
+            if let Some(Node::Binding(pat)) = tcx.hir.find(var_id) {
                 if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
                     decl.debug_name = ident.name;
 
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
new file mode 100644 (file)
index 0000000..70addf2
--- /dev/null
@@ -0,0 +1,445 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Not in interpret to make sure we do not use private implementation details
+
+use std::fmt;
+use std::error::Error;
+
+use rustc::hir::{self, def_id::DefId};
+use rustc::mir::interpret::ConstEvalErr;
+use rustc::mir;
+use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt};
+use rustc::ty::layout::{LayoutOf, TyLayout};
+use rustc::ty::subst::Subst;
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+
+use syntax::ast::Mutability;
+use syntax::source_map::Span;
+
+use rustc::mir::interpret::{
+    EvalResult, EvalError, EvalErrorKind, GlobalId,
+    Scalar, Allocation, ConstValue,
+};
+use interpret::{self,
+    Place, PlaceTy, MemPlace, OpTy, Operand, Value,
+    EvalContext, StackPopCleanup, MemoryKind,
+};
+
+pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    instance: Instance<'tcx>,
+    mir: &'mir mir::Mir<'tcx>,
+    span: Span,
+) -> EvalResult<'tcx, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>> {
+    debug!("mk_borrowck_eval_cx: {:?}", instance);
+    let param_env = tcx.param_env(instance.def_id());
+    let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ());
+    // insert a stack frame so any queries have the correct substs
+    ecx.stack.push(interpret::Frame {
+        block: mir::START_BLOCK,
+        locals: IndexVec::new(),
+        instance,
+        span,
+        mir,
+        return_place: Place::null(tcx),
+        return_to_block: StackPopCleanup::Goto(None), // never pop
+        stmt: 0,
+    });
+    Ok(ecx)
+}
+
+pub fn mk_eval_cx<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    instance: Instance<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+) -> EvalResult<'tcx, EvalContext<'a, 'tcx, 'tcx, CompileTimeEvaluator>> {
+    debug!("mk_eval_cx: {:?}, {:?}", instance, param_env);
+    let span = tcx.def_span(instance.def_id());
+    let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ());
+    let mir = ecx.load_mir(instance.def)?;
+    // insert a stack frame so any queries have the correct substs
+    ecx.push_stack_frame(
+        instance,
+        mir.span,
+        mir,
+        Place::null(tcx),
+        StackPopCleanup::Goto(None), // never pop
+    )?;
+    Ok(ecx)
+}
+
+pub fn eval_promoted<'a, 'mir, 'tcx>(
+    ecx: &mut EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>,
+    cid: GlobalId<'tcx>,
+    mir: &'mir mir::Mir<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+) -> EvalResult<'tcx, OpTy<'tcx>> {
+    ecx.with_fresh_body(|ecx| {
+        eval_body_using_ecx(ecx, cid, Some(mir), param_env)
+    })
+}
+
+pub fn op_to_const<'tcx>(
+    ecx: &EvalContext<'_, '_, 'tcx, CompileTimeEvaluator>,
+    op: OpTy<'tcx>,
+    normalize: bool,
+) -> EvalResult<'tcx, &'tcx ty::Const<'tcx>> {
+    let normalized_op = if normalize {
+        ecx.try_read_value(op)?
+    } else {
+        match op.op {
+            Operand::Indirect(mplace) => Err(mplace),
+            Operand::Immediate(val) => Ok(val)
+        }
+    };
+    let val = match normalized_op {
+        Err(MemPlace { ptr, align, extra }) => {
+            // extract alloc-offset pair
+            assert!(extra.is_none());
+            let ptr = ptr.to_ptr()?;
+            let alloc = ecx.memory.get(ptr.alloc_id)?;
+            assert!(alloc.align.abi() >= align.abi());
+            assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= op.layout.size.bytes());
+            let mut alloc = alloc.clone();
+            alloc.align = align;
+            // FIXME shouldnt it be the case that `mark_static_initialized` has already
+            // interned this?  I thought that is the entire point of that `FinishStatic` stuff?
+            let alloc = ecx.tcx.intern_const_alloc(alloc);
+            ConstValue::ByRef(ptr.alloc_id, alloc, ptr.offset)
+        },
+        Ok(Value::Scalar(x)) =>
+            ConstValue::Scalar(x.not_undef()?),
+        Ok(Value::ScalarPair(a, b)) =>
+            ConstValue::ScalarPair(a.not_undef()?, b),
+    };
+    Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, op.layout.ty))
+}
+
+fn eval_body_and_ecx<'a, 'mir, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    cid: GlobalId<'tcx>,
+    mir: Option<&'mir mir::Mir<'tcx>>,
+    param_env: ty::ParamEnv<'tcx>,
+) -> (EvalResult<'tcx, OpTy<'tcx>>, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>) {
+    // we start out with the best span we have
+    // and try improving it down the road when more information is available
+    let span = tcx.def_span(cid.instance.def_id());
+    let span = mir.map(|mir| mir.span).unwrap_or(span);
+    let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ());
+    let r = eval_body_using_ecx(&mut ecx, cid, mir, param_env);
+    (r, ecx)
+}
+
+// Returns a pointer to where the result lives
+fn eval_body_using_ecx<'a, 'mir, 'tcx>(
+    ecx: &mut EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>,
+    cid: GlobalId<'tcx>,
+    mir: Option<&'mir mir::Mir<'tcx>>,
+    param_env: ty::ParamEnv<'tcx>,
+) -> EvalResult<'tcx, OpTy<'tcx>> {
+    debug!("eval_body_using_ecx: {:?}, {:?}", cid, param_env);
+    let tcx = ecx.tcx.tcx;
+    let mut mir = match mir {
+        Some(mir) => mir,
+        None => ecx.load_mir(cid.instance.def)?,
+    };
+    if let Some(index) = cid.promoted {
+        mir = &mir.promoted[index];
+    }
+    let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
+    assert!(!layout.is_unsized());
+    let ret = ecx.allocate(layout, MemoryKind::Stack)?;
+
+    let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id()));
+    let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
+    trace!("eval_body_using_ecx: pushing stack frame for global: {}{}", name, prom);
+    assert!(mir.arg_count == 0);
+    ecx.push_stack_frame(
+        cid.instance,
+        mir.span,
+        mir,
+        Place::Ptr(*ret),
+        StackPopCleanup::None { cleanup: false },
+    )?;
+
+    // The main interpreter loop.
+    ecx.run()?;
+
+    // Intern the result
+    let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span);
+    let is_static = tcx.is_static(cid.instance.def_id());
+    let mutability = if is_static == Some(hir::Mutability::MutMutable) || internally_mutable {
+        Mutability::Mutable
+    } else {
+        Mutability::Immutable
+    };
+    ecx.memory.intern_static(ret.ptr.to_ptr()?.alloc_id, mutability)?;
+
+    debug!("eval_body_using_ecx done: {:?}", *ret);
+    Ok(ret.into())
+}
+
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
+pub struct CompileTimeEvaluator;
+
+impl<'tcx> Into<EvalError<'tcx>> for ConstEvalError {
+    fn into(self) -> EvalError<'tcx> {
+        EvalErrorKind::MachineError(self.to_string()).into()
+    }
+}
+
+#[derive(Clone, Debug)]
+enum ConstEvalError {
+    NeedsRfc(String),
+    NotConst(String),
+}
+
+impl fmt::Display for ConstEvalError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use self::ConstEvalError::*;
+        match *self {
+            NeedsRfc(ref msg) => {
+                write!(
+                    f,
+                    "\"{}\" needs an rfc before being allowed inside constants",
+                    msg
+                )
+            }
+            NotConst(ref msg) => write!(f, "{}", msg),
+        }
+    }
+}
+
+impl Error for ConstEvalError {
+    fn description(&self) -> &str {
+        use self::ConstEvalError::*;
+        match *self {
+            NeedsRfc(_) => "this feature needs an rfc before being allowed inside constants",
+            NotConst(_) => "this feature is not compatible with constant evaluation",
+        }
+    }
+
+    fn cause(&self) -> Option<&dyn Error> {
+        None
+    }
+}
+
+impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeEvaluator {
+    type MemoryData = ();
+    type MemoryKinds = !;
+
+    const MUT_STATIC_KIND: Option<!> = None; // no mutating of statics allowed
+
+    fn find_fn<'a>(
+        ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+        instance: ty::Instance<'tcx>,
+        args: &[OpTy<'tcx>],
+        dest: Option<PlaceTy<'tcx>>,
+        ret: Option<mir::BasicBlock>,
+    ) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>> {
+        debug!("eval_fn_call: {:?}", instance);
+        if !ecx.tcx.is_const_fn(instance.def_id()) {
+            // Some functions we support even if they are non-const -- but avoid testing
+            // that for const fn!
+            if ecx.hook_fn(instance, args, dest)? {
+                ecx.goto_block(ret)?; // fully evaluated and done
+                return Ok(None);
+            }
+            return Err(
+                ConstEvalError::NotConst(format!("calling non-const fn `{}`", instance)).into(),
+            );
+        }
+        // This is a const fn. Call it.
+        Ok(Some(match ecx.load_mir(instance.def) {
+            Ok(mir) => mir,
+            Err(err) => {
+                if let EvalErrorKind::NoMirFor(ref path) = err.kind {
+                    return Err(
+                        ConstEvalError::NeedsRfc(format!("calling extern function `{}`", path))
+                            .into(),
+                    );
+                }
+                return Err(err);
+            }
+        }))
+    }
+
+    fn call_intrinsic<'a>(
+        ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+        instance: ty::Instance<'tcx>,
+        args: &[OpTy<'tcx>],
+        dest: PlaceTy<'tcx>,
+    ) -> EvalResult<'tcx> {
+        if ecx.emulate_intrinsic(instance, args, dest)? {
+            return Ok(());
+        }
+        // An intrinsic that we do not support
+        let intrinsic_name = &ecx.tcx.item_name(instance.def_id()).as_str()[..];
+        Err(
+            ConstEvalError::NeedsRfc(format!("calling intrinsic `{}`", intrinsic_name)).into()
+        )
+    }
+
+    fn ptr_op<'a>(
+        _ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
+        _bin_op: mir::BinOp,
+        _left: Scalar,
+        _left_layout: TyLayout<'tcx>,
+        _right: Scalar,
+        _right_layout: TyLayout<'tcx>,
+    ) -> EvalResult<'tcx, (Scalar, bool)> {
+        Err(
+            ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into(),
+        )
+    }
+
+    fn find_foreign_static<'a>(
+        _tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
+        _def_id: DefId,
+    ) -> EvalResult<'tcx, &'tcx Allocation> {
+        err!(ReadForeignStatic)
+    }
+
+    fn box_alloc<'a>(
+        _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+        _dest: PlaceTy<'tcx>,
+    ) -> EvalResult<'tcx> {
+        Err(
+            ConstEvalError::NeedsRfc("heap allocations via `box` keyword".to_string()).into(),
+        )
+    }
+}
+
+/// Project to a field of a (variant of a) const
+pub fn const_field<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    instance: ty::Instance<'tcx>,
+    variant: Option<usize>,
+    field: mir::Field,
+    value: &'tcx ty::Const<'tcx>,
+) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
+    trace!("const_field: {:?}, {:?}, {:?}", instance, field, value);
+    let ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
+    let result = (|| {
+        // get the operand again
+        let op = ecx.const_to_op(value)?;
+        // downcast
+        let down = match variant {
+            None => op,
+            Some(variant) => ecx.operand_downcast(op, variant)?
+        };
+        // then project
+        let field = ecx.operand_field(down, field.index() as u64)?;
+        // and finally move back to the const world, always normalizing because
+        // this is not called for statics.
+        op_to_const(&ecx, field, true)
+    })();
+    result.map_err(|err| {
+        let (trace, span) = ecx.generate_stacktrace(None);
+        ConstEvalErr {
+            error: err,
+            stacktrace: trace,
+            span,
+        }.into()
+    })
+}
+
+pub fn const_variant_index<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    instance: ty::Instance<'tcx>,
+    val: &'tcx ty::Const<'tcx>,
+) -> EvalResult<'tcx, usize> {
+    trace!("const_variant_index: {:?}, {:?}", instance, val);
+    let ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
+    let op = ecx.const_to_op(val)?;
+    Ok(ecx.read_discriminant(op)?.1)
+}
+
+pub fn const_to_allocation_provider<'a, 'tcx>(
+    _tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    val: &'tcx ty::Const<'tcx>,
+) -> &'tcx Allocation {
+    // FIXME: This really does not need to be a query.  Instead, we should have a query for statics
+    // that returns an allocation directly (or an `AllocId`?), after doing a sanity check of the
+    // value and centralizing error reporting.
+    match val.val {
+        ConstValue::ByRef(_, alloc, offset) => {
+            assert_eq!(offset.bytes(), 0);
+            return alloc;
+        },
+        _ => bug!("const_to_allocation called on non-static"),
+    }
+}
+
+pub fn const_eval_provider<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
+) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
+    trace!("const eval: {:?}", key);
+    let cid = key.value;
+    let def_id = cid.instance.def.def_id();
+
+    if let Some(id) = tcx.hir.as_local_node_id(def_id) {
+        let tables = tcx.typeck_tables_of(def_id);
+        let span = tcx.def_span(def_id);
+
+        // Do match-check before building MIR
+        if tcx.check_match(def_id).is_err() {
+            return Err(ConstEvalErr {
+                error: EvalErrorKind::CheckMatchError.into(),
+                stacktrace: vec![],
+                span,
+            }.into());
+        }
+
+        if let hir::BodyOwnerKind::Const = tcx.hir.body_owner_kind(id) {
+            tcx.mir_const_qualif(def_id);
+        }
+
+        // Do not continue into miri if typeck errors occurred; it will fail horribly
+        if tables.tainted_by_errors {
+            return Err(ConstEvalErr {
+                error: EvalErrorKind::CheckMatchError.into(),
+                stacktrace: vec![],
+                span,
+            }.into());
+        }
+    };
+
+    let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env);
+    res.and_then(|op| {
+        let normalize = tcx.is_static(def_id).is_none() && cid.promoted.is_none();
+        if !normalize {
+            // Sanity check: These must always be a MemPlace
+            match op.op {
+                Operand::Indirect(_) => { /* all is good */ },
+                Operand::Immediate(_) => bug!("const eval gave us an Immediate"),
+            }
+        }
+        op_to_const(&ecx, op, normalize)
+    }).map_err(|err| {
+        let (trace, span) = ecx.generate_stacktrace(None);
+        let err = ConstEvalErr {
+            error: err,
+            stacktrace: trace,
+            span,
+        };
+        if tcx.is_static(def_id).is_some() {
+            err.report_as_error(ecx.tcx, "could not evaluate static initializer");
+            if tcx.sess.err_count() == 0 {
+                span_bug!(span, "static eval failure didn't emit an error: {:#?}", err);
+            }
+        }
+        err.into()
+    })
+}
index d2a8a9dcf4ba2c987b501a952e80e5a041ef3613..d97c0c9b430197a53b800cfc2e6f573b15e9b6d8 100644 (file)
@@ -12,7 +12,7 @@
 //! locations.
 
 use rustc::mir::{BasicBlock, Location};
-use rustc_data_structures::indexed_set::{HybridIdxSetBuf, IdxSetBuf, Iter};
+use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet, Iter};
 use rustc_data_structures::indexed_vec::Idx;
 
 use dataflow::{BitDenotation, BlockSets, DataflowResults};
@@ -28,6 +28,15 @@ pub trait FlowsAtLocation {
     /// Reset the state bitvector to represent the entry to block `bb`.
     fn reset_to_entry_of(&mut self, bb: BasicBlock);
 
+    /// Reset the state bitvector to represent the exit of the
+    /// terminator of block `bb`.
+    ///
+    /// **Important:** In the case of a `Call` terminator, these
+    /// effects do *not* include the result of storing the destination
+    /// of the call, since that is edge-dependent (in other words, the
+    /// effects don't apply to the unwind edge).
+    fn reset_to_exit_of(&mut self, bb: BasicBlock);
+
     /// Build gen + kill sets for statement at `loc`.
     ///
     /// Note that invoking this method alone does not change the
@@ -67,9 +76,9 @@ pub struct FlowAtLocation<BD>
     BD: BitDenotation,
 {
     base_results: DataflowResults<BD>,
-    curr_state: IdxSetBuf<BD::Idx>,
-    stmt_gen: HybridIdxSetBuf<BD::Idx>,
-    stmt_kill: HybridIdxSetBuf<BD::Idx>,
+    curr_state: IdxSet<BD::Idx>,
+    stmt_gen: HybridIdxSet<BD::Idx>,
+    stmt_kill: HybridIdxSet<BD::Idx>,
 }
 
 impl<BD> FlowAtLocation<BD>
@@ -96,9 +105,9 @@ pub fn each_gen_bit<F>(&self, f: F)
 
     pub fn new(results: DataflowResults<BD>) -> Self {
         let bits_per_block = results.sets().bits_per_block();
-        let curr_state = IdxSetBuf::new_empty(bits_per_block);
-        let stmt_gen = HybridIdxSetBuf::new_empty(bits_per_block);
-        let stmt_kill = HybridIdxSetBuf::new_empty(bits_per_block);
+        let curr_state = IdxSet::new_empty(bits_per_block);
+        let stmt_gen = HybridIdxSet::new_empty(bits_per_block);
+        let stmt_kill = HybridIdxSet::new_empty(bits_per_block);
         FlowAtLocation {
             base_results: results,
             curr_state: curr_state,
@@ -129,8 +138,8 @@ pub fn with_iter_outgoing<F>(&self, f: F)
         F: FnOnce(Iter<BD::Idx>),
     {
         let mut curr_state = self.curr_state.clone();
-        curr_state.union_hybrid(&self.stmt_gen);
-        curr_state.subtract_hybrid(&self.stmt_kill);
+        curr_state.union(&self.stmt_gen);
+        curr_state.subtract(&self.stmt_kill);
         f(curr_state.iter());
     }
 }
@@ -142,6 +151,12 @@ fn reset_to_entry_of(&mut self, bb: BasicBlock) {
         self.curr_state.overwrite(self.base_results.sets().on_entry_set_for(bb.index()));
     }
 
+    fn reset_to_exit_of(&mut self, bb: BasicBlock) {
+        self.reset_to_entry_of(bb);
+        self.curr_state.union(self.base_results.sets().gen_set_for(bb.index()));
+        self.curr_state.subtract(self.base_results.sets().kill_set_for(bb.index()));
+    }
+
     fn reconstruct_statement_effect(&mut self, loc: Location) {
         self.stmt_gen.clear();
         self.stmt_kill.clear();
@@ -193,8 +208,8 @@ fn reconstruct_terminator_effect(&mut self, loc: Location) {
     }
 
     fn apply_local_effect(&mut self, _loc: Location) {
-        self.curr_state.union_hybrid(&self.stmt_gen);
-        self.curr_state.subtract_hybrid(&self.stmt_kill);
+        self.curr_state.union(&self.stmt_gen);
+        self.curr_state.subtract(&self.stmt_kill);
     }
 }
 
index 1cbe0dcc017f9150361c68e56da0c158766f4cf7..7af1daae4cad50602142cbab1a96dc5a80725102 100644 (file)
@@ -61,17 +61,17 @@ fn place_contents_drop_state_cannot_differ<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx,
                                                             place: &mir::Place<'tcx>) -> bool {
     let ty = place.ty(mir, tcx).to_ty(tcx);
     match ty.sty {
-        ty::TyArray(..) => {
+        ty::Array(..) => {
             debug!("place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false",
                    place, ty);
             false
         }
-        ty::TySlice(..) | ty::TyRef(..) | ty::TyRawPtr(..) => {
+        ty::Slice(..) | ty::Ref(..) | ty::RawPtr(..) => {
             debug!("place_contents_drop_state_cannot_differ place: {:?} ty: {:?} refd => true",
                    place, ty);
             true
         }
-        ty::TyAdt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => {
+        ty::Adt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => {
             debug!("place_contents_drop_state_cannot_differ place: {:?} ty: {:?} Drop => true",
                    place, ty);
             true
index ee3bba840c67bfbfe19d79074103aee29501524e..62c6018809f39ef161b8407d8b0c26b0c4c657c1 100644 (file)
 
 use util::elaborate_drops::DropFlagState;
 
-use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex, InitIndex};
+use super::move_paths::{HasMoveData, MoveData, MovePathIndex, InitIndex};
 use super::move_paths::{LookupResult, InitKind};
 use super::{BitDenotation, BlockSets, InitialFlow};
 
 use super::drop_flag_effects_for_function_entry;
 use super::drop_flag_effects_for_location;
-use super::{on_lookup_result_bits, for_location_inits};
+use super::on_lookup_result_bits;
 
 mod storage_liveness;
 
@@ -211,40 +211,6 @@ impl<'a, 'gcx, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, '
     fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
 }
 
-/// `MovingOutStatements` tracks the statements that perform moves out
-/// of particular places. More precisely, it tracks whether the
-/// *effect* of such moves (namely, the uninitialization of the
-/// place in question) can reach some point in the control-flow of
-/// the function, or if that effect is "killed" by some intervening
-/// operation reinitializing that place.
-///
-/// The resulting dataflow is a more enriched version of
-/// `MaybeUninitializedPlaces`. Both structures on their own only tell
-/// you if a place *might* be uninitialized at a given point in the
-/// control flow. But `MovingOutStatements` also includes the added
-/// data of *which* particular statement causing the deinitialization
-/// that the borrow checker's error message may need to report.
-#[allow(dead_code)]
-pub struct MovingOutStatements<'a, 'gcx: 'tcx, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
-    mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
-}
-
-impl<'a, 'gcx: 'tcx, 'tcx: 'a> MovingOutStatements<'a, 'gcx, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-               mir: &'a Mir<'tcx>,
-               mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
-               -> Self
-    {
-        MovingOutStatements { tcx: tcx, mir: mir, mdpe: mdpe }
-    }
-}
-
-impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'gcx, 'tcx> {
-    fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
-}
-
 /// `EverInitializedPlaces` tracks all places that might have ever been
 /// initialized upon reaching a particular point in the control flow
 /// for a function, without an intervening `Storage Dead`.
@@ -488,83 +454,6 @@ fn propagate_call_return(&self,
     }
 }
 
-impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> {
-    type Idx = MoveOutIndex;
-    fn name() -> &'static str { "moving_out" }
-    fn bits_per_block(&self) -> usize {
-        self.move_data().moves.len()
-    }
-
-    fn start_block_effect(&self, _sets: &mut IdxSet<MoveOutIndex>) {
-        // no move-statements have been executed prior to function
-        // execution, so this method has no effect on `_sets`.
-    }
-
-    fn statement_effect(&self,
-                        sets: &mut BlockSets<MoveOutIndex>,
-                        location: Location) {
-        let (tcx, mir, move_data) = (self.tcx, self.mir, self.move_data());
-        let stmt = &mir[location.block].statements[location.statement_index];
-        let loc_map = &move_data.loc_map;
-        let path_map = &move_data.path_map;
-
-        match stmt.kind {
-            // this analysis only tries to find moves explicitly
-            // written by the user, so we ignore the move-outs
-            // created by `StorageDead` and at the beginning
-            // of a function.
-            mir::StatementKind::StorageDead(_) => {}
-            _ => {
-                debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}",
-                       stmt, location, &loc_map[location]);
-                // Every path deinitialized by a *particular move*
-                // has corresponding bit, "gen'ed" (i.e. set)
-                // here, in dataflow vector
-                sets.gen_all_and_assert_dead(&loc_map[location]);
-            }
-        }
-
-        for_location_inits(tcx, mir, move_data, location,
-                           |mpi| sets.kill_all(&path_map[mpi]));
-    }
-
-    fn terminator_effect(&self,
-                         sets: &mut BlockSets<MoveOutIndex>,
-                         location: Location)
-    {
-        let (tcx, mir, move_data) = (self.tcx, self.mir, self.move_data());
-        let term = mir[location.block].terminator();
-        let loc_map = &move_data.loc_map;
-        let path_map = &move_data.path_map;
-
-        debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}",
-               term, location, &loc_map[location]);
-        sets.gen_all_and_assert_dead(&loc_map[location]);
-
-        for_location_inits(tcx, mir, move_data, location,
-                           |mpi| sets.kill_all(&path_map[mpi]));
-    }
-
-    fn propagate_call_return(&self,
-                             in_out: &mut IdxSet<MoveOutIndex>,
-                             _call_bb: mir::BasicBlock,
-                             _dest_bb: mir::BasicBlock,
-                             dest_place: &mir::Place) {
-        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,
-                              self.mir,
-                              move_data,
-                              move_data.rev_lookup.find(dest_place),
-                              |mpi| for moi in &path_map[mpi] {
-                                  assert!(moi.index() < bits_per_block);
-                                  in_out.remove(&moi);
-                              });
-    }
-}
-
 impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedPlaces<'a, 'gcx, 'tcx> {
     type Idx = InitIndex;
     fn name() -> &'static str { "ever_init" }
@@ -682,13 +571,6 @@ fn join(&self, pred1: Word, pred2: Word) -> Word {
     }
 }
 
-impl<'a, 'gcx, 'tcx> BitwiseOperator for MovingOutStatements<'a, 'gcx, 'tcx> {
-    #[inline]
-    fn join(&self, pred1: Word, pred2: Word) -> Word {
-        pred1 | pred2 // moves from both preds are in scope
-    }
-}
-
 impl<'a, 'gcx, 'tcx> BitwiseOperator for EverInitializedPlaces<'a, 'gcx, 'tcx> {
     #[inline]
     fn join(&self, pred1: Word, pred2: Word) -> Word {
@@ -727,13 +609,6 @@ fn bottom_value() -> bool {
     }
 }
 
-impl<'a, 'gcx, 'tcx> InitialFlow for MovingOutStatements<'a, 'gcx, 'tcx> {
-    #[inline]
-    fn bottom_value() -> bool {
-        false // bottom = no loans in scope by default
-    }
-}
-
 impl<'a, 'gcx, 'tcx> InitialFlow for EverInitializedPlaces<'a, 'gcx, 'tcx> {
     #[inline]
     fn bottom_value() -> bool {
index 56c4dac19e5049f64e4dba05fec6d6b8678693f5..bee7d443c85408b430520fd4abc9612f3468e5cd 100644 (file)
@@ -10,8 +10,8 @@
 
 use syntax::ast::{self, MetaItem};
 
-use rustc_data_structures::bitslice::{bitwise, BitwiseOperator, Word};
-use rustc_data_structures::indexed_set::{HybridIdxSetBuf, IdxSet, IdxSetBuf};
+use rustc_data_structures::bitslice::{bitwise, BitwiseOperator};
+use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet};
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::work_queue::WorkQueue;
 
 use std::borrow::Borrow;
 use std::fmt;
 use std::io;
-use std::mem;
 use std::path::PathBuf;
 use std::usize;
 
 pub use self::impls::{MaybeStorageLive};
 pub use self::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
-pub use self::impls::{DefinitelyInitializedPlaces, MovingOutStatements};
+pub use self::impls::DefinitelyInitializedPlaces;
 pub use self::impls::EverInitializedPlaces;
 pub use self::impls::borrows::Borrows;
 pub use self::impls::HaveBeenBorrowedLocals;
@@ -39,7 +38,7 @@
 use self::move_paths::MoveData;
 
 mod at_location;
-mod drop_flag_effects;
+pub mod drop_flag_effects;
 mod graphviz;
 mod impls;
 pub mod move_paths;
@@ -183,7 +182,7 @@ struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O> where O: 'b + BitDenotation
 impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation
 {
     fn propagate(&mut self) {
-        let mut temp = IdxSetBuf::new_empty(self.flow_state.sets.bits_per_block);
+        let mut temp = IdxSet::new_empty(self.flow_state.sets.bits_per_block);
         let mut propcx = PropagationContext {
             builder: self,
         };
@@ -242,8 +241,8 @@ fn walk_cfg(&mut self, in_out: &mut IdxSet<BD::Idx>) {
                 let sets = self.builder.flow_state.sets.for_block(bb.index());
                 debug_assert!(in_out.words().len() == sets.on_entry.words().len());
                 in_out.overwrite(sets.on_entry);
-                in_out.union_hybrid(sets.gen_set);
-                in_out.subtract_hybrid(sets.kill_set);
+                in_out.union(sets.gen_set);
+                in_out.subtract(sets.kill_set);
             }
             self.builder.propagate_bits_into_graph_successors_of(
                 in_out, (bb, bb_data), &mut dirty_queue);
@@ -287,18 +286,6 @@ fn post_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
     }
 }
 
-/// Maps each block to a set of bits
-#[derive(Clone, Debug)]
-pub(crate) struct Bits<E:Idx> {
-    bits: IdxSetBuf<E>,
-}
-
-impl<E:Idx> Bits<E> {
-    fn new(bits: IdxSetBuf<E>) -> Self {
-        Bits { bits: bits }
-    }
-}
-
 /// DataflowResultsConsumer abstracts over walking the MIR with some
 /// already constructed dataflow results.
 ///
@@ -366,7 +353,7 @@ pub fn state_for_location<'tcx, T: BitDenotation>(loc: Location,
                                                   analysis: &T,
                                                   result: &DataflowResults<T>,
                                                   mir: &Mir<'tcx>)
-    -> IdxSetBuf<T::Idx> {
+    -> IdxSet<T::Idx> {
     let mut on_entry = result.sets().on_entry_set_for(loc.block.index()).to_owned();
     let mut kill_set = on_entry.to_hybrid();
     let mut gen_set = kill_set.clone();
@@ -450,7 +437,7 @@ pub(crate) fn interpret_set<'c, P>(&self,
 
     pub(crate) fn interpret_hybrid_set<'c, P>(&self,
                                               o: &'c O,
-                                              set: &HybridIdxSetBuf<O::Idx>,
+                                              set: &HybridIdxSet<O::Idx>,
                                               render_idx: &P)
                                               -> Vec<DebugFormatted>
         where P: Fn(&O, O::Idx) -> DebugFormatted
@@ -464,22 +451,22 @@ pub struct AllSets<E: Idx> {
     /// Analysis bitwidth for each block.
     bits_per_block: usize,
 
-    /// Number of words associated with each block entry
-    /// equal to bits_per_block / (mem::size_of::<Word> * 8), rounded up.
-    words_per_block: usize,
-
     /// For each block, bits valid on entry to the block.
-    on_entry_sets: Bits<E>,
-
-    /// For each block, bits generated by executing the statements in
-    /// the block. (For comparison, the Terminator for each block is
-    /// handled in a flow-specific manner during propagation.)
-    gen_sets: Vec<HybridIdxSetBuf<E>>,
-
-    /// For each block, bits killed by executing the statements in the
-    /// block. (For comparison, the Terminator for each block is
-    /// handled in a flow-specific manner during propagation.)
-    kill_sets: Vec<HybridIdxSetBuf<E>>,
+    on_entry_sets: Vec<IdxSet<E>>,
+
+    /// For each block, bits generated by executing the statements +
+    /// terminator in the block -- with one caveat. In particular, for
+    /// *call terminators*, the effect of storing the destination is
+    /// not included, since that only takes effect on the **success**
+    /// edge (and not the unwind edge).
+    gen_sets: Vec<HybridIdxSet<E>>,
+
+    /// For each block, bits killed by executing the statements +
+    /// terminator in the block -- with one caveat. In particular, for
+    /// *call terminators*, the effect of storing the destination is
+    /// not included, since that only takes effect on the **success**
+    /// edge (and not the unwind edge).
+    kill_sets: Vec<HybridIdxSet<E>>,
 }
 
 /// Triple of sets associated with a given block.
@@ -503,11 +490,11 @@ pub struct BlockSets<'a, E: Idx> {
 
     /// Bits that are set to 1 by the time we exit the given block. Hybrid
     /// because it usually contains only 0 or 1 elements.
-    pub(crate) gen_set: &'a mut HybridIdxSetBuf<E>,
+    pub(crate) gen_set: &'a mut HybridIdxSet<E>,
 
     /// Bits that are set to 0 by the time we exit the given block. Hybrid
     /// because it usually contains only 0 or 1 elements.
-    pub(crate) kill_set: &'a mut HybridIdxSetBuf<E>,
+    pub(crate) kill_set: &'a mut HybridIdxSet<E>,
 }
 
 impl<'a, E:Idx> BlockSets<'a, E> {
@@ -524,18 +511,6 @@ fn gen_all<I>(&mut self, i: I)
         }
     }
 
-    fn gen_all_and_assert_dead<I>(&mut self, i: I)
-        where I: IntoIterator,
-        I::Item: Borrow<E>
-    {
-        for j in i {
-            let j = j.borrow();
-            let retval = self.gen_set.add(j);
-            self.kill_set.remove(j);
-            assert!(retval);
-        }
-    }
-
     fn kill(&mut self, e: &E) {
         self.gen_set.remove(e);
         self.kill_set.add(e);
@@ -551,32 +526,28 @@ fn kill_all<I>(&mut self, i: I)
     }
 
     fn apply_local_effect(&mut self) {
-        self.on_entry.union_hybrid(&self.gen_set);
-        self.on_entry.subtract_hybrid(&self.kill_set);
+        self.on_entry.union(self.gen_set);
+        self.on_entry.subtract(self.kill_set);
     }
 }
 
 impl<E:Idx> AllSets<E> {
     pub fn bits_per_block(&self) -> usize { self.bits_per_block }
     pub fn for_block(&mut self, block_idx: usize) -> BlockSets<E> {
-        let offset = self.words_per_block * block_idx;
-        let range = E::new(offset)..E::new(offset + self.words_per_block);
         BlockSets {
-            on_entry: self.on_entry_sets.bits.range_mut(&range),
+            on_entry: &mut self.on_entry_sets[block_idx],
             gen_set: &mut self.gen_sets[block_idx],
             kill_set: &mut self.kill_sets[block_idx],
         }
     }
 
     pub fn on_entry_set_for(&self, block_idx: usize) -> &IdxSet<E> {
-        let offset = self.words_per_block * block_idx;
-        let range = E::new(offset)..E::new(offset + self.words_per_block);
-        self.on_entry_sets.bits.range(&range)
+        &self.on_entry_sets[block_idx]
     }
-    pub fn gen_set_for(&self, block_idx: usize) -> &HybridIdxSetBuf<E> {
+    pub fn gen_set_for(&self, block_idx: usize) -> &HybridIdxSet<E> {
         &self.gen_sets[block_idx]
     }
-    pub fn kill_set_for(&self, block_idx: usize) -> &HybridIdxSetBuf<E> {
+    pub fn kill_set_for(&self, block_idx: usize) -> &HybridIdxSet<E> {
         &self.kill_sets[block_idx]
     }
 }
@@ -605,7 +576,7 @@ pub trait BitDenotation: BitwiseOperator {
     /// `sets.on_entry` to that local clone into `statement_effect` and
     /// `terminator_effect`).
     ///
-    /// When its false, no local clone is constucted; instead a
+    /// When it's false, no local clone is constructed; instead a
     /// reference directly into `on_entry` is passed along via
     /// `sets.on_entry` instead, which represents the flow state at
     /// the block's start, not necessarily the state immediately prior
@@ -731,18 +702,15 @@ pub fn new(mir: &'a Mir<'tcx>,
                dead_unwinds: &'a IdxSet<mir::BasicBlock>,
                denotation: D) -> Self where D: InitialFlow {
         let bits_per_block = denotation.bits_per_block();
-        let bits_per_word = mem::size_of::<Word>() * 8;
-        let words_per_block = (bits_per_block + bits_per_word - 1) / bits_per_word;
-        let bits_per_block_rounded_up = words_per_block * bits_per_word; // a multiple of word size
         let num_blocks = mir.basic_blocks().len();
-        let num_overall = num_blocks * bits_per_block_rounded_up;
 
-        let on_entry = Bits::new(if D::bottom_value() {
-            IdxSetBuf::new_filled(num_overall)
+        let on_entry_sets = if D::bottom_value() {
+            vec![IdxSet::new_filled(bits_per_block); num_blocks]
         } else {
-            IdxSetBuf::new_empty(num_overall)
-        });
-        let empties = vec![HybridIdxSetBuf::new_empty(bits_per_block); num_blocks];
+            vec![IdxSet::new_empty(bits_per_block); num_blocks]
+        };
+        let gen_sets = vec![HybridIdxSet::new_empty(bits_per_block); num_blocks];
+        let kill_sets = gen_sets.clone();
 
         DataflowAnalysis {
             mir,
@@ -750,10 +718,9 @@ pub fn new(mir: &'a Mir<'tcx>,
             flow_state: DataflowState {
                 sets: AllSets {
                     bits_per_block,
-                    words_per_block,
-                    on_entry_sets: on_entry,
-                    gen_sets: empties.clone(),
-                    kill_sets: empties,
+                    on_entry_sets,
+                    gen_sets,
+                    kill_sets,
                 },
                 operator: denotation,
             }
@@ -873,5 +840,4 @@ fn propagate_bits_into_entry_set_for(&mut self,
             dirty_queue.insert(bb);
         }
     }
-
 }
index 60030f270205523937958bbb7f78ab341002015c..2148363c79712ee7ab17c0ae86c5cfaaef903491 100644 (file)
@@ -134,19 +134,19 @@ fn move_path_for_projection(&mut self,
         let tcx = self.builder.tcx;
         let place_ty = proj.base.ty(mir, tcx).to_ty(tcx);
         match place_ty.sty {
-            ty::TyRef(..) | ty::TyRawPtr(..) =>
+            ty::Ref(..) | ty::RawPtr(..) =>
                 return Err(MoveError::cannot_move_out_of(
                     self.loc,
                     BorrowedContent { target_place: place.clone() })),
-            ty::TyAdt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() =>
+            ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() =>
                 return Err(MoveError::cannot_move_out_of(self.loc,
                                                          InteriorOfTypeWithDestructor {
                     container_ty: place_ty
                 })),
             // move out of union - always move the entire union
-            ty::TyAdt(adt, _) if adt.is_union() =>
+            ty::Adt(adt, _) if adt.is_union() =>
                 return Err(MoveError::UnionMove { path: base }),
-            ty::TySlice(_) =>
+            ty::Slice(_) =>
                 return Err(MoveError::cannot_move_out_of(
                     self.loc,
                     InteriorOfSliceOrArray {
@@ -155,7 +155,7 @@ fn move_path_for_projection(&mut self,
                             _ => false
                         },
                     })),
-            ty::TyArray(..) => match proj.elem {
+            ty::Array(..) => match proj.elem {
                 ProjectionElem::Index(..) =>
                     return Err(MoveError::cannot_move_out_of(
                         self.loc,
index d90e9ed329b57192bf31d17578dd19c0787a561b..055f238e5db4ea12f2c03d6a079d7ff2fe70b5ea 100644 (file)
@@ -78,7 +78,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                     mut expr: Expr<'tcx>,
                                     adjustment: &Adjustment<'tcx>)
                                     -> Expr<'tcx> {
-    let Expr { temp_lifetime, span, .. } = expr;
+    let Expr { temp_lifetime, mut span, .. } = expr;
     let kind = match adjustment.kind {
         Adjust::ReifyFnPointer => {
             ExprKind::ReifyFnPointer { source: expr.to_ref() }
@@ -96,6 +96,25 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             ExprKind::Cast { source: expr.to_ref() }
         }
         Adjust::Deref(None) => {
+            // Adjust the span from the block, to the last expression of the
+            // block. This is a better span when returning a mutable reference
+            // with too short a lifetime. The error message will use the span
+            // from the assignment to the return place, which should only point
+            // at the returned value, not the entire function body.
+            //
+            // fn return_short_lived<'a>(x: &'a mut i32) -> &'static mut i32 {
+            //      x
+            //   // ^ error message points at this expression.
+            // }
+            //
+            // We don't need to do this adjustment in the next match arm since
+            // deref coercions always start with a built-in deref.
+            if let ExprKind::Block { body } = expr.kind {
+                if let Some(ref last_expr) = body.expr {
+                    span = last_expr.span;
+                    expr.span = span;
+                }
+            }
             ExprKind::Deref { arg: expr.to_ref() }
         }
         Adjust::Deref(Some(deref)) => {
@@ -180,6 +199,13 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             ExprKind::Use { source: cast_expr.to_ref() }
         }
         Adjust::Unsize => {
+            // See the above comment for Adjust::Deref
+            if let ExprKind::Block { body } = expr.kind {
+                if let Some(ref last_expr) = body.expr {
+                    span = last_expr.span;
+                    expr.span = span;
+                }
+            }
             ExprKind::Unsize { source: expr.to_ref() }
         }
     };
@@ -256,6 +282,16 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 };
                 if let Some((adt_def, index)) = adt_data {
                     let substs = cx.tables().node_substs(fun.hir_id);
+
+                    let user_ty = cx.tables().user_substs(fun.hir_id)
+                        .map(|user_substs| {
+                            user_substs.unchecked_map(|user_substs| {
+                                // Here, we just pair an `AdtDef` with the
+                                // `user_substs`, so no new types etc are introduced.
+                                cx.tcx().mk_adt(adt_def, user_substs)
+                            })
+                        });
+
                     let field_refs = args.iter()
                         .enumerate()
                         .map(|(idx, e)| {
@@ -270,6 +306,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         substs,
                         variant_index: index,
                         fields: field_refs,
+                        user_ty,
                         base: None,
                     }
                 } else {
@@ -284,7 +321,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
         hir::ExprKind::AddrOf(mutbl, ref expr) => {
             let region = match expr_ty.sty {
-                ty::TyRef(r, _, _) => r,
+                ty::Ref(r, _, _) => r,
                 _ => span_bug!(expr.span, "type of & not region"),
             };
             ExprKind::Borrow {
@@ -317,6 +354,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
         hir::ExprKind::Lit(ref lit) => ExprKind::Literal {
             literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, false),
+            user_ty: None,
         },
 
         hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
@@ -406,6 +444,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 if let hir::ExprKind::Lit(ref lit) = arg.node {
                     ExprKind::Literal {
                         literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, true),
+                        user_ty: None,
                     }
                 } else {
                     ExprKind::Unary {
@@ -418,13 +457,14 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
         hir::ExprKind::Struct(ref qpath, ref fields, ref base) => {
             match expr_ty.sty {
-                ty::TyAdt(adt, substs) => {
+                ty::Adt(adt, substs) => {
                     match adt.adt_kind() {
                         AdtKind::Struct | AdtKind::Union => {
                             ExprKind::Adt {
                                 adt_def: adt,
                                 variant_index: 0,
                                 substs,
+                                user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt),
                                 fields: field_refs(cx, fields),
                                 base: base.as_ref().map(|base| {
                                     FruInfo {
@@ -450,6 +490,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                         adt_def: adt,
                                         variant_index: index,
                                         substs,
+                                        user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt),
                                         fields: field_refs(cx, fields),
                                         base: None,
                                     }
@@ -472,8 +513,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         hir::ExprKind::Closure(..) => {
             let closure_ty = cx.tables().expr_ty(expr);
             let (def_id, substs, movability) = match closure_ty.sty {
-                ty::TyClosure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None),
-                ty::TyGenerator(def_id, substs, movability) => {
+                ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None),
+                ty::Generator(def_id, substs, movability) => {
                     (def_id, UpvarSubsts::Generator(substs), Some(movability))
                 }
                 _ => {
@@ -631,7 +672,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         temp_lifetime,
                         ty,
                         span: expr.span,
-                        kind: ExprKind::Literal { literal },
+                        kind: ExprKind::Literal { literal, user_ty: None },
                     }.to_ref();
                     let offset = mk_const(ty::Const::from_bits(
                         cx.tcx,
@@ -684,18 +725,77 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     }
 }
 
-fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
-                                 expr: &hir::Expr,
-                                 custom_callee: Option<(DefId, &'tcx Substs<'tcx>)>)
-                                 -> Expr<'tcx> {
+fn user_annotated_ty_for_def(
+    cx: &mut Cx<'a, 'gcx, 'tcx>,
+    hir_id: hir::HirId,
+    def: &Def,
+) -> Option<CanonicalTy<'tcx>> {
+    match def {
+        // A reference to something callable -- e.g., a fn, method, or
+        // a tuple-struct or tuple-variant. This has the type of a
+        // `Fn` but with the user-given substitutions.
+        Def::Fn(_) |
+        Def::Method(_) |
+        Def::StructCtor(_, CtorKind::Fn) |
+        Def::VariantCtor(_, CtorKind::Fn) =>
+            Some(cx.tables().user_substs(hir_id)?.unchecked_map(|user_substs| {
+                // Here, we just pair a `DefId` with the
+                // `user_substs`, so no new types etc are introduced.
+                cx.tcx().mk_fn_def(def.def_id(), user_substs)
+            })),
+
+        Def::Const(_def_id) |
+        Def::AssociatedConst(_def_id) =>
+            bug!("unimplemented"),
+
+        // A unit struct/variant which is used as a value (e.g.,
+        // `None`). This has the type of the enum/struct that defines
+        // this variant -- but with the substitutions given by the
+        // user.
+        Def::StructCtor(_def_id, CtorKind::Const) |
+        Def::VariantCtor(_def_id, CtorKind::Const) =>
+            match &cx.tables().node_id_to_type(hir_id).sty {
+                ty::Adt(adt_def, _) => user_annotated_ty_for_adt(cx, hir_id, adt_def),
+                sty => bug!("unexpected sty: {:?}", sty),
+            },
+
+        _ =>
+            bug!("user_annotated_ty_for_def: unexpected def {:?} at {:?}", def, hir_id)
+    }
+}
+
+fn user_annotated_ty_for_adt(
+    cx: &mut Cx<'a, 'gcx, 'tcx>,
+    hir_id: hir::HirId,
+    adt_def: &'tcx AdtDef,
+) -> Option<CanonicalTy<'tcx>> {
+    let user_substs = cx.tables().user_substs(hir_id)?;
+    Some(user_substs.unchecked_map(|user_substs| {
+        // Here, we just pair an `AdtDef` with the
+        // `user_substs`, so no new types etc are introduced.
+        cx.tcx().mk_adt(adt_def, user_substs)
+    }))
+}
+
+fn method_callee<'a, 'gcx, 'tcx>(
+    cx: &mut Cx<'a, 'gcx, 'tcx>,
+    expr: &hir::Expr,
+    overloaded_callee: Option<(DefId, &'tcx Substs<'tcx>)>,
+) -> Expr<'tcx> {
     let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
-    let (def_id, substs) = custom_callee.unwrap_or_else(|| {
-        if let Some(def) = cx.tables().type_dependent_defs().get(expr.hir_id) {
-            (def.def_id(), cx.tables().node_substs(expr.hir_id))
-        } else {
-            span_bug!(expr.span, "no type-dependent def for method callee")
+    let (def_id, substs, user_ty) = match overloaded_callee {
+        Some((def_id, substs)) => (def_id, substs, None),
+        None => {
+            let type_dependent_defs = cx.tables().type_dependent_defs();
+            let def = type_dependent_defs
+                .get(expr.hir_id)
+                .unwrap_or_else(|| {
+                    span_bug!(expr.span, "no type-dependent def for method callee")
+                });
+            let user_ty = user_annotated_ty_for_def(cx, expr.hir_id, def);
+            (def.def_id(), cx.tables().node_substs(expr.hir_id), user_ty)
         }
-    });
+    };
     let ty = cx.tcx().mk_fn_def(def_id, substs);
     Expr {
         temp_lifetime,
@@ -703,6 +803,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         span: expr.span,
         kind: ExprKind::Literal {
             literal: ty::Const::zero_sized(cx.tcx(), ty),
+            user_ty,
         },
     }
 }
@@ -756,11 +857,15 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         Def::Fn(_) |
         Def::Method(_) |
         Def::StructCtor(_, CtorKind::Fn) |
-        Def::VariantCtor(_, CtorKind::Fn) => ExprKind::Literal {
-            literal: ty::Const::zero_sized(
-                cx.tcx,
-                cx.tables().node_id_to_type(expr.hir_id),
-            ),
+        Def::VariantCtor(_, CtorKind::Fn) => {
+            let user_ty = user_annotated_ty_for_def(cx, expr.hir_id, &def);
+            ExprKind::Literal {
+                literal: ty::Const::zero_sized(
+                    cx.tcx,
+                    cx.tables().node_id_to_type(expr.hir_id),
+                ),
+                user_ty,
+            }
         },
 
         Def::Const(def_id) |
@@ -771,6 +876,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 substs,
                 cx.tables().node_id_to_type(expr.hir_id),
             ),
+            user_ty: None, // FIXME(#47184) -- user given type annot on constants
         },
 
         Def::StructCtor(def_id, CtorKind::Const) |
@@ -778,11 +884,12 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             match cx.tables().node_id_to_type(expr.hir_id).sty {
                 // A unit struct/variant which is used as a value.
                 // We return a completely different ExprKind here to account for this special case.
-                ty::TyAdt(adt_def, substs) => {
+                ty::Adt(adt_def, substs) => {
                     ExprKind::Adt {
                         adt_def,
                         variant_index: adt_def.variant_index_with_id(def_id),
                         substs,
+                        user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt_def),
                         fields: vec![],
                         base: None,
                     }
@@ -830,7 +937,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             });
             let region = cx.tcx.mk_region(region);
 
-            let self_expr = if let ty::TyClosure(_, closure_substs) = closure_ty.sty {
+            let self_expr = if let ty::Closure(_, closure_substs) = closure_ty.sty {
                 match cx.infcx.closure_kind(closure_def_id, closure_substs).unwrap() {
                     ty::ClosureKind::Fn => {
                         let ref_closure_ty = cx.tcx.mk_ref(region,
@@ -961,12 +1068,13 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     }
 }
 
-fn overloaded_place<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
-                                     expr: &'tcx hir::Expr,
-                                     place_ty: Ty<'tcx>,
-                                     custom_callee: Option<(DefId, &'tcx Substs<'tcx>)>,
-                                     args: Vec<ExprRef<'tcx>>)
-                                     -> ExprKind<'tcx> {
+fn overloaded_place<'a, 'gcx, 'tcx>(
+    cx: &mut Cx<'a, 'gcx, 'tcx>,
+    expr: &'tcx hir::Expr,
+    place_ty: Ty<'tcx>,
+    overloaded_callee: Option<(DefId, &'tcx Substs<'tcx>)>,
+    args: Vec<ExprRef<'tcx>>,
+) -> ExprKind<'tcx> {
     // For an overloaded *x or x[y] expression of type T, the method
     // call returns an &T and we must add the deref so that the types
     // line up (this is because `*x` and `x[y]` represent places):
@@ -980,7 +1088,7 @@ fn overloaded_place<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     // same region and mutability as the receiver. This holds for
     // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
     let (region, mutbl) = match recv_ty.sty {
-        ty::TyRef(region, _, mutbl) => (region, mutbl),
+        ty::Ref(region, _, mutbl) => (region, mutbl),
         _ => span_bug!(expr.span, "overloaded_place: receiver is not a reference"),
     };
     let ref_ty = cx.tcx.mk_ref(region, ty::TypeAndMut {
@@ -991,7 +1099,7 @@ fn overloaded_place<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     // construct the complete expression `foo()` for the overloaded call,
     // which will yield the &T type
     let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
-    let fun = method_callee(cx, expr, custom_callee);
+    let fun = method_callee(cx, expr, overloaded_callee);
     let ref_expr = Expr {
         temp_lifetime,
         ty: ref_ty,
index 70148fc91760443bb6d31b18de8988fa5eb6ac21..b4257a40e38af0dd0ea3ff3de467b5d4cd080ca6 100644 (file)
@@ -18,7 +18,7 @@
 
 use rustc_data_structures::indexed_vec::Idx;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::hir::map::blocks::FnLikeNode;
+use rustc::hir::Node;
 use rustc::middle::region;
 use rustc::infer::InferCtxt;
 use rustc::ty::subst::Subst;
@@ -66,10 +66,7 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
         let constness = match body_owner_kind {
             hir::BodyOwnerKind::Const |
             hir::BodyOwnerKind::Static(_) => hir::Constness::Const,
-            hir::BodyOwnerKind::Fn => {
-                let fn_like = FnLikeNode::from_node(infcx.tcx.hir.get(src_id));
-                fn_like.map_or(hir::Constness::NotConst, |f| f.constness())
-            }
+            hir::BodyOwnerKind::Fn => hir::Constness::NotConst,
         };
 
         let attrs = tcx.hir.attrs(src_id);
@@ -82,7 +79,7 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
         // Respect -C overflow-checks.
         check_overflow |= tcx.sess.overflow_checks();
 
-        // Constants and const fn's always need overflow checks.
+        // Constants always need overflow checks.
         check_overflow |= constness == hir::Constness::Const;
 
         let lint_level = lint_level_for_hir_id(tcx, src_id);
@@ -167,8 +164,7 @@ pub fn const_eval_literal(
             LitKind::Str(ref s, _) => {
                 let s = s.as_str();
                 let id = self.tcx.allocate_bytes(s.as_bytes());
-                let value = Scalar::Ptr(id.into()).to_value_with_len(s.len() as u64, self.tcx);
-                ConstValue::from_byval_value(value).unwrap()
+                ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, self.tcx)
             },
             LitKind::ByteStr(ref data) => {
                 let id = self.tcx.allocate_bytes(data);
@@ -189,7 +185,7 @@ pub fn const_eval_literal(
             }
             LitKind::FloatUnsuffixed(n) => {
                 let fty = match ty.sty {
-                    ty::TyFloat(fty) => fty,
+                    ty::Float(fty) => fty,
                     _ => bug!()
                 };
                 parse_float(n, fty)
@@ -203,7 +199,7 @@ pub fn const_eval_literal(
     pub fn pattern_from_hir(&mut self, p: &hir::Pat) -> Pattern<'tcx> {
         let tcx = self.tcx.global_tcx();
         let p = match tcx.hir.get(p.id) {
-            hir::map::NodePat(p) | hir::map::NodeBinding(p) => p,
+            Node::Pat(p) | Node::Binding(p) => p,
             node => bug!("pattern became {:?}", node)
         };
         Pattern::from_hir(tcx,
index ab272763d8e8a53b68cf93d7ae7076f36ff5840d..2ddb810f4914817e7640e6bdf92cd1a78750ae67 100644 (file)
@@ -18,7 +18,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::middle::region;
 use rustc::ty::subst::Substs;
-use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const};
+use rustc::ty::{AdtDef, CanonicalTy, UpvarSubsts, Region, Ty, Const};
 use rustc::hir;
 use syntax::ast;
 use syntax_pos::Span;
@@ -261,6 +261,11 @@ pub enum ExprKind<'tcx> {
         adt_def: &'tcx AdtDef,
         variant_index: usize,
         substs: &'tcx Substs<'tcx>,
+
+        /// Optional user-given substs: for something like `let x =
+        /// Bar::<T> { ... }`.
+        user_ty: Option<CanonicalTy<'tcx>>,
+
         fields: Vec<FieldExprRef<'tcx>>,
         base: Option<FruInfo<'tcx>>
     },
@@ -272,6 +277,13 @@ pub enum ExprKind<'tcx> {
     },
     Literal {
         literal: &'tcx Const<'tcx>,
+
+        /// Optional user-given type: for something like
+        /// `collect::<Vec<_>>`, this would be present and would
+        /// indicate that `Vec<_>` was explicitly specified.
+        ///
+        /// Needed for NLL to impose user-given type constraints.
+        user_ty: Option<CanonicalTy<'tcx>>,
     },
     InlineAsm {
         asm: &'tcx hir::InlineAsm,
index 5d459557711854f03c8a71a2efd9d82307cf546a..e9d65caf08743ac486b4624c8b3d516e53af04da 100644 (file)
@@ -8,6 +8,164 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+/// This file includes the logic for exhaustiveness and usefulness checking for
+/// pattern-matching. Specifically, given a list of patterns for a type, we can
+/// tell whether:
+/// (a) the patterns cover every possible constructor for the type [exhaustiveness]
+/// (b) each pattern is necessary [usefulness]
+///
+/// The algorithm implemented here is a modified version of the one described in:
+/// http://moscova.inria.fr/~maranget/papers/warn/index.html
+/// However, to save future implementors from reading the original paper, I'm going
+/// to summarise the algorithm here to hopefully save time and be a little clearer
+/// (without being so rigorous).
+///
+/// The core of the algorithm revolves about a "usefulness" check. In particular, we
+/// are trying to compute a predicate `U(P, p_{m + 1})` where `P` is a list of patterns
+/// of length `m` for a compound (product) type with `n` components (we refer to this as
+/// a matrix). `U(P, p_{m + 1})` represents whether, given an existing list of patterns
+/// `p_1 ..= p_m`, adding a new pattern will be "useful" (that is, cover previously-
+/// uncovered values of the type).
+///
+/// If we have this predicate, then we can easily compute both exhaustiveness of an
+/// entire set of patterns and the individual usefulness of each one.
+/// (a) the set of patterns is exhaustive iff `U(P, _)` is false (i.e. adding a wildcard
+/// match doesn't increase the number of values we're matching)
+/// (b) a pattern `p_i` is not useful if `U(P[0..=(i-1), p_i)` is false (i.e. adding a
+/// pattern to those that have come before it doesn't increase the number of values
+/// we're matching).
+///
+/// For example, say we have the following:
+/// ```
+///     // x: (Option<bool>, Result<()>)
+///     match x {
+///         (Some(true), _) => {}
+///         (None, Err(())) => {}
+///         (None, Err(_)) => {}
+///     }
+/// ```
+/// Here, the matrix `P` is 3 x 2 (rows x columns).
+/// [
+///     [Some(true), _],
+///     [None, Err(())],
+///     [None, Err(_)],
+/// ]
+/// We can tell it's not exhaustive, because `U(P, _)` is true (we're not covering
+/// `[Some(false), _]`, for instance). In addition, row 3 is not useful, because
+/// all the values it covers are already covered by row 2.
+///
+/// To compute `U`, we must have two other concepts.
+///     1. `S(c, P)` is a "specialised matrix", where `c` is a constructor (like `Some` or
+///        `None`). You can think of it as filtering `P` to just the rows whose *first* pattern
+///        can cover `c` (and expanding OR-patterns into distinct patterns), and then expanding
+///        the constructor into all of its components.
+///        The specialisation of a row vector is computed by `specialize`.
+///
+///        It is computed as follows. For each row `p_i` of P, we have four cases:
+///             1.1. `p_(i,1) = c(r_1, .., r_a)`. Then `S(c, P)` has a corresponding row:
+///                     r_1, .., r_a, p_(i,2), .., p_(i,n)
+///             1.2. `p_(i,1) = c'(r_1, .., r_a')` where `c â‰  c'`. Then `S(c, P)` has no
+///                  corresponding row.
+///             1.3. `p_(i,1) = _`. Then `S(c, P)` has a corresponding row:
+///                     _, .., _, p_(i,2), .., p_(i,n)
+///             1.4. `p_(i,1) = r_1 | r_2`. Then `S(c, P)` has corresponding rows inlined from:
+///                     S(c, (r_1, p_(i,2), .., p_(i,n)))
+///                     S(c, (r_2, p_(i,2), .., p_(i,n)))
+///
+///     2. `D(P)` is a "default matrix". This is used when we know there are missing
+///        constructor cases, but there might be existing wildcard patterns, so to check the
+///        usefulness of the matrix, we have to check all its *other* components.
+///        The default matrix is computed inline in `is_useful`.
+///
+///         It is computed as follows. For each row `p_i` of P, we have three cases:
+///             1.1. `p_(i,1) = c(r_1, .., r_a)`. Then `D(P)` has no corresponding row.
+///             1.2. `p_(i,1) = _`. Then `D(P)` has a corresponding row:
+///                     p_(i,2), .., p_(i,n)
+///             1.3. `p_(i,1) = r_1 | r_2`. Then `D(P)` has corresponding rows inlined from:
+///                     D((r_1, p_(i,2), .., p_(i,n)))
+///                     D((r_2, p_(i,2), .., p_(i,n)))
+///
+///     Note that the OR-patterns are not always used directly in Rust, but are used to derive
+///     the exhaustive integer matching rules, so they're written here for posterity.
+///
+/// The algorithm for computing `U`
+/// -------------------------------
+/// The algorithm is inductive (on the number of columns: i.e. components of tuple patterns).
+/// That means we're going to check the components from left-to-right, so the algorithm
+/// operates principally on the first component of the matrix and new pattern `p_{m + 1}`.
+/// This algorithm is realised in the `is_useful` function.
+///
+/// Base case. (`n = 0`, i.e. an empty tuple pattern)
+///     - If `P` already contains an empty pattern (i.e. if the number of patterns `m > 0`),
+///       then `U(P, p_{m + 1})` is false.
+///     - Otherwise, `P` must be empty, so `U(P, p_{m + 1})` is true.
+///
+/// Inductive step. (`n > 0`, i.e. whether there's at least one column
+///                  [which may then be expanded into further columns later])
+///     We're going to match on the new pattern, `p_{m + 1}`.
+///         - If `p_{m + 1} == c(r_1, .., r_a)`, then we have a constructor pattern.
+///           Thus, the usefulness of `p_{m + 1}` can be reduced to whether it is useful when
+///           we ignore all the patterns in `P` that involve other constructors. This is where
+///           `S(c, P)` comes in:
+///           `U(P, p_{m + 1}) := U(S(c, P), S(c, p_{m + 1}))`
+///           This special case is handled in `is_useful_specialized`.
+///         - If `p_{m + 1} == _`, then we have two more cases:
+///             + All the constructors of the first component of the type exist within
+///               all the rows (after having expanded OR-patterns). In this case:
+///               `U(P, p_{m + 1}) := âˆ¨(k Ïµ constructors) U(S(k, P), S(k, p_{m + 1}))`
+///               I.e. the pattern `p_{m + 1}` is only useful when all the constructors are
+///               present *if* its later components are useful for the respective constructors
+///               covered by `p_{m + 1}` (usually a single constructor, but all in the case of `_`).
+///             + Some constructors are not present in the existing rows (after having expanded
+///               OR-patterns). However, there might be wildcard patterns (`_`) present. Thus, we
+///               are only really concerned with the other patterns leading with wildcards. This is
+///               where `D` comes in:
+///               `U(P, p_{m + 1}) := U(D(P), p_({m + 1},2), ..,  p_({m + 1},n))`
+///         - If `p_{m + 1} == r_1 | r_2`, then the usefulness depends on each separately:
+///           `U(P, p_{m + 1}) := U(P, (r_1, p_({m + 1},2), .., p_({m + 1},n)))
+///                            || U(P, (r_2, p_({m + 1},2), .., p_({m + 1},n)))`
+///
+/// Modifications to the algorithm
+/// ------------------------------
+/// The algorithm in the paper doesn't cover some of the special cases that arise in Rust, for
+/// example uninhabited types and variable-length slice patterns. These are drawn attention to
+/// throughout the code below. I'll make a quick note here about how exhaustive integer matching
+/// is accounted for, though.
+///
+/// Exhaustive integer matching
+/// ---------------------------
+/// An integer type can be thought of as a (huge) sum type: 1 | 2 | 3 | ...
+/// So to support exhaustive integer matching, we can make use of the logic in the paper for
+/// OR-patterns. However, we obviously can't just treat ranges x..=y as individual sums, because
+/// they are likely gigantic. So we instead treat ranges as constructors of the integers. This means
+/// that we have a constructor *of* constructors (the integers themselves). We then need to work
+/// through all the inductive step rules above, deriving how the ranges would be treated as
+/// OR-patterns, and making sure that they're treated in the same way even when they're ranges.
+/// There are really only four special cases here:
+/// - When we match on a constructor that's actually a range, we have to treat it as if we would
+///   an OR-pattern.
+///     + It turns out that we can simply extend the case for single-value patterns in
+///      `specialize` to either be *equal* to a value constructor, or *contained within* a range
+///      constructor.
+///     + When the pattern itself is a range, you just want to tell whether any of the values in
+///       the pattern range coincide with values in the constructor range, which is precisely
+///       intersection.
+///   Since when encountering a range pattern for a value constructor, we also use inclusion, it
+///   means that whenever the constructor is a value/range and the pattern is also a value/range,
+///   we can simply use intersection to test usefulness.
+/// - When we're testing for usefulness of a pattern and the pattern's first component is a
+///   wildcard.
+///     + If all the constructors appear in the matrix, we have a slight complication. By default,
+///       the behaviour (i.e. a disjunction over specialised matrices for each constructor) is
+///       invalid, because we want a disjunction over every *integer* in each range, not just a
+///       disjunction over every range. This is a bit more tricky to deal with: essentially we need
+///       to form equivalence classes of subranges of the constructor range for which the behaviour
+///       of the matrix `P` and new pattern `p_{m + 1}` are the same. This is described in more
+///       detail in `split_grouped_constructors`.
+///     + If some constructors are missing from the matrix, it turns out we don't need to do
+///       anything special (because we know none of the integers are actually wildcards: i.e. we
+///       can't span wildcards using ranges).
+
 use self::Constructor::*;
 use self::Usefulness::*;
 use self::WitnessPreference::*;
 use rustc::hir::def_id::DefId;
 use rustc::hir::RangeEnd;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::layout::{Integer, IntegerExt};
 
 use rustc::mir::Field;
 use rustc::mir::interpret::ConstValue;
 use rustc::util::common::ErrorReported;
 
+use syntax::attr::{SignedInt, UnsignedInt};
 use syntax_pos::{Span, DUMMY_SP};
 
 use arena::TypedArena;
 
-use std::cmp::{self, Ordering};
+use std::cmp::{self, Ordering, min, max};
 use std::fmt;
 use std::iter::{FromIterator, IntoIterator};
+use std::ops::RangeInclusive;
+use std::u128;
 
 pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pattern<'tcx>)
                                 -> &'a Pattern<'tcx>
@@ -44,7 +206,7 @@ pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pattern<'tcx
 impl<'tcx> PatternFolder<'tcx> for LiteralExpander {
     fn fold_pattern(&mut self, pat: &Pattern<'tcx>) -> Pattern<'tcx> {
         match (&pat.ty.sty, &*pat.kind) {
-            (&ty::TyRef(_, rty, _), &PatternKind::Constant { ref value }) => {
+            (&ty::Ref(_, rty, _), &PatternKind::Constant { ref value }) => {
                 Pattern {
                     ty: pat.ty,
                     span: pat.span,
@@ -138,7 +300,6 @@ fn from_iter<T: IntoIterator<Item=Vec<&'a Pattern<'tcx>>>>(iter: T) -> Self
     }
 }
 
-//NOTE: appears to be the only place other then InferCtxt to contain a ParamEnv
 pub struct MatchCheckCtxt<'a, 'tcx: 'a> {
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     /// The module in which the match occurs. This is necessary for
@@ -165,7 +326,7 @@ pub fn create_and_enter<F, R>(
             tcx,
             module,
             pattern_arena: &pattern_arena,
-            byte_array_map: FxHashMap(),
+            byte_array_map: FxHashMap::default(),
         })
     }
 
@@ -220,14 +381,14 @@ fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
 
     fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
         match ty.sty {
-            ty::TyAdt(adt_def, ..) => adt_def.is_enum() && adt_def.is_non_exhaustive(),
+            ty::Adt(adt_def, ..) => adt_def.is_enum() && adt_def.is_non_exhaustive(),
             _ => false,
         }
     }
 
     fn is_local(&self, ty: Ty<'tcx>) -> bool {
         match ty.sty {
-            ty::TyAdt(adt_def, ..) => adt_def.did.is_local(),
+            ty::Adt(adt_def, ..) => adt_def.did.is_local(),
             _ => false,
         }
     }
@@ -273,7 +434,7 @@ fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> usize {
     }
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub enum Usefulness<'tcx> {
     Useful,
     UsefulWithWitness(Vec<Witness<'tcx>>),
@@ -289,7 +450,7 @@ fn is_useful(&self) -> bool {
     }
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub enum WitnessPreference {
     ConstructWitness,
     LeaveOutWitness
@@ -301,8 +462,39 @@ struct PatternContext<'tcx> {
     max_slice_length: u64,
 }
 
-/// A stack of patterns in reverse order of construction
-#[derive(Clone)]
+/// A witness of non-exhaustiveness for error reporting, represented
+/// as a list of patterns (in reverse order of construction) with
+/// wildcards inside to represent elements that can take any inhabitant
+/// of the type as a value.
+///
+/// A witness against a list of patterns should have the same types
+/// and length as the pattern matched against. Because Rust `match`
+/// is always against a single pattern, at the end the witness will
+/// have length 1, but in the middle of the algorithm, it can contain
+/// multiple patterns.
+///
+/// For example, if we are constructing a witness for the match against
+/// ```
+/// struct Pair(Option<(u32, u32)>, bool);
+///
+/// match (p: Pair) {
+///    Pair(None, _) => {}
+///    Pair(_, false) => {}
+/// }
+/// ```
+///
+/// We'll perform the following steps:
+/// 1. Start with an empty witness
+///     `Witness(vec![])`
+/// 2. Push a witness `Some(_)` against the `None`
+///     `Witness(vec![Some(_)])`
+/// 3. Push a witness `true` against the `false`
+///     `Witness(vec![Some(_), true])`
+/// 4. Apply the `Pair` constructor to the witnesses
+///     `Witness(vec![Pair(Some(_), true)])`
+///
+/// The final `Pair(Some(_), true)` is then the resulting witness.
+#[derive(Clone, Debug)]
 pub struct Witness<'tcx>(Vec<Pattern<'tcx>>);
 
 impl<'tcx> Witness<'tcx> {
@@ -353,11 +545,11 @@ fn apply_constructor<'a>(
         let arity = constructor_arity(cx, ctor, ty);
         let pat = {
             let len = self.0.len() as u64;
-            let mut pats = self.0.drain((len-arity) as usize..).rev();
+            let mut pats = self.0.drain((len - arity) as usize..).rev();
 
             match ty.sty {
-                ty::TyAdt(..) |
-                ty::TyTuple(..) => {
+                ty::Adt(..) |
+                ty::Tuple(..) => {
                     let pats = pats.enumerate().map(|(i, p)| {
                         FieldPattern {
                             field: Field::new(i),
@@ -365,7 +557,7 @@ fn apply_constructor<'a>(
                         }
                     }).collect();
 
-                    if let ty::TyAdt(adt, substs) = ty.sty {
+                    if let ty::Adt(adt, substs) = ty.sty {
                         if adt.is_enum() {
                             PatternKind::Variant {
                                 adt_def: adt,
@@ -381,11 +573,11 @@ fn apply_constructor<'a>(
                     }
                 }
 
-                ty::TyRef(..) => {
+                ty::Ref(..) => {
                     PatternKind::Deref { subpattern: pats.nth(0).unwrap() }
                 }
 
-                ty::TySlice(_) | ty::TyArray(..) => {
+                ty::Slice(_) | ty::Array(..) => {
                     PatternKind::Slice {
                         prefix: pats.collect(),
                         slice: None,
@@ -396,6 +588,7 @@ fn apply_constructor<'a>(
                 _ => {
                     match *ctor {
                         ConstantValue(value) => PatternKind::Constant { value },
+                        ConstantRange(lo, hi, end) => PatternKind::Range { lo, hi, end },
                         _ => PatternKind::Wild,
                     }
                 }
@@ -417,10 +610,6 @@ fn apply_constructor<'a>(
 /// but is instead bounded by the maximum fixed length of slice patterns in
 /// the column of patterns being analyzed.
 ///
-/// This intentionally does not list ConstantValue specializations for
-/// non-booleans, because we currently assume that there is always a
-/// "non-standard constant" that matches. See issue #12483.
-///
 /// We make sure to omit constructors that are statically impossible. eg for
 /// Option<!> we do not include Some(_) in the returned list of constructors.
 fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
@@ -428,13 +617,14 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                                   -> Vec<Constructor<'tcx>>
 {
     debug!("all_constructors({:?})", pcx.ty);
-    match pcx.ty.sty {
-        ty::TyBool => {
+    let exhaustive_integer_patterns = cx.tcx.features().exhaustive_integer_patterns;
+    let ctors = match pcx.ty.sty {
+        ty::Bool => {
             [true, false].iter().map(|&b| {
                 ConstantValue(ty::Const::from_bool(cx.tcx, b))
             }).collect()
         }
-        ty::TyArray(ref sub_ty, len) if len.assert_usize(cx.tcx).is_some() => {
+        ty::Array(ref sub_ty, len) if len.assert_usize(cx.tcx).is_some() => {
             let len = len.unwrap_usize(cx.tcx);
             if len != 0 && cx.is_uninhabited(sub_ty) {
                 vec![]
@@ -443,20 +633,50 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
             }
         }
         // Treat arrays of a constant but unknown length like slices.
-        ty::TyArray(ref sub_ty, _) |
-        ty::TySlice(ref sub_ty) => {
+        ty::Array(ref sub_ty, _) |
+        ty::Slice(ref sub_ty) => {
             if cx.is_uninhabited(sub_ty) {
                 vec![Slice(0)]
             } else {
                 (0..pcx.max_slice_length+1).map(|length| Slice(length)).collect()
             }
         }
-        ty::TyAdt(def, substs) if def.is_enum() => {
+        ty::Adt(def, substs) if def.is_enum() => {
             def.variants.iter()
                 .filter(|v| !cx.is_variant_uninhabited(v, substs))
                 .map(|v| Variant(v.did))
                 .collect()
         }
+        ty::Char if exhaustive_integer_patterns => {
+            let endpoint = |c: char| {
+                let ty = ty::ParamEnv::empty().and(cx.tcx.types.char);
+                ty::Const::from_bits(cx.tcx, c as u128, ty)
+            };
+            vec![
+                // The valid Unicode Scalar Value ranges.
+                ConstantRange(endpoint('\u{0000}'), endpoint('\u{D7FF}'), RangeEnd::Included),
+                ConstantRange(endpoint('\u{E000}'), endpoint('\u{10FFFF}'), RangeEnd::Included),
+            ]
+        }
+        ty::Int(ity) if exhaustive_integer_patterns => {
+            // FIXME(49937): refactor these bit manipulations into interpret.
+            let bits = Integer::from_attr(cx.tcx, SignedInt(ity)).size().bits() as u128;
+            let min = 1u128 << (bits - 1);
+            let max = (1u128 << (bits - 1)) - 1;
+            let ty = ty::ParamEnv::empty().and(pcx.ty);
+            vec![ConstantRange(ty::Const::from_bits(cx.tcx, min as u128, ty),
+                               ty::Const::from_bits(cx.tcx, max as u128, ty),
+                               RangeEnd::Included)]
+        }
+        ty::Uint(uty) if exhaustive_integer_patterns => {
+            // FIXME(49937): refactor these bit manipulations into interpret.
+            let bits = Integer::from_attr(cx.tcx, UnsignedInt(uty)).size().bits() as u128;
+            let max = !0u128 >> (128 - bits);
+            let ty = ty::ParamEnv::empty().and(pcx.ty);
+            vec![ConstantRange(ty::Const::from_bits(cx.tcx, 0, ty),
+                               ty::Const::from_bits(cx.tcx, max, ty),
+                               RangeEnd::Included)]
+        }
         _ => {
             if cx.is_uninhabited(pcx.ty) {
                 vec![]
@@ -464,7 +684,8 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                 vec![Single]
             }
         }
-    }
+    };
+    ctors
 }
 
 fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
@@ -497,7 +718,7 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
     //     `[true, ..]`
     //     `[.., false]`
     // Then any slice of length â‰¥1 that matches one of these two
-    // patterns can be  be trivially turned to a slice of any
+    // patterns can be trivially turned to a slice of any
     // other length â‰¥1 that matches them and vice-versa - for
     // but the slice from length 2 `[false, true]` that matches neither
     // of these patterns can't be turned to a slice from length 1 that
@@ -569,6 +790,189 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
     cmp::max(max_fixed_len + 1, max_prefix_len + max_suffix_len)
 }
 
+/// An inclusive interval, used for precise integer exhaustiveness checking.
+/// `IntRange`s always store a contiguous range. This means that values are
+/// encoded such that `0` encodes the minimum value for the integer,
+/// regardless of the signedness.
+/// For example, the pattern `-128...127i8` is encoded as `0..=255`.
+/// This makes comparisons and arithmetic on interval endpoints much more
+/// straightforward. See `signed_bias` for details.
+///
+/// `IntRange` is never used to encode an empty range or a "range" that wraps
+/// around the (offset) space: i.e. `range.lo <= range.hi`.
+#[derive(Clone)]
+struct IntRange<'tcx> {
+    pub range: RangeInclusive<u128>,
+    pub ty: Ty<'tcx>,
+}
+
+impl<'tcx> IntRange<'tcx> {
+    fn from_ctor(tcx: TyCtxt<'_, 'tcx, 'tcx>,
+                 ctor: &Constructor<'tcx>)
+                 -> Option<IntRange<'tcx>> {
+        match ctor {
+            ConstantRange(lo, hi, end) => {
+                assert_eq!(lo.ty, hi.ty);
+                let ty = lo.ty;
+                let env_ty = ty::ParamEnv::empty().and(ty);
+                if let Some(lo) = lo.assert_bits(tcx, env_ty) {
+                    if let Some(hi) = hi.assert_bits(tcx, env_ty) {
+                        // Perform a shift if the underlying types are signed,
+                        // which makes the interval arithmetic simpler.
+                        let bias = IntRange::signed_bias(tcx, ty);
+                        let (lo, hi) = (lo ^ bias, hi ^ bias);
+                        // Make sure the interval is well-formed.
+                        return if lo > hi || lo == hi && *end == RangeEnd::Excluded {
+                            None
+                        } else {
+                            let offset = (*end == RangeEnd::Excluded) as u128;
+                            Some(IntRange { range: lo..=(hi - offset), ty })
+                        };
+                    }
+                }
+                None
+            }
+            ConstantValue(val) => {
+                let ty = val.ty;
+                if let Some(val) = val.assert_bits(tcx, ty::ParamEnv::empty().and(ty)) {
+                    let bias = IntRange::signed_bias(tcx, ty);
+                    let val = val ^ bias;
+                    Some(IntRange { range: val..=val, ty })
+                } else {
+                    None
+                }
+            }
+            Single | Variant(_) | Slice(_) => {
+                None
+            }
+        }
+    }
+
+    fn from_pat(tcx: TyCtxt<'_, 'tcx, 'tcx>,
+                pat: &Pattern<'tcx>)
+                -> Option<IntRange<'tcx>> {
+        Self::from_ctor(tcx, &match pat.kind {
+            box PatternKind::Constant { value } => ConstantValue(value),
+            box PatternKind::Range { lo, hi, end } => ConstantRange(lo, hi, end),
+            _ => return None,
+        })
+    }
+
+    // The return value of `signed_bias` should be XORed with an endpoint to encode/decode it.
+    fn signed_bias(tcx: TyCtxt<'_, 'tcx, 'tcx>, ty: Ty<'tcx>) -> u128 {
+        match ty.sty {
+            ty::Int(ity) => {
+                let bits = Integer::from_attr(tcx, SignedInt(ity)).size().bits() as u128;
+                1u128 << (bits - 1)
+            }
+            _ => 0
+        }
+    }
+
+    /// Convert a `RangeInclusive` to a `ConstantValue` or inclusive `ConstantRange`.
+    fn range_to_ctor(
+        tcx: TyCtxt<'_, 'tcx, 'tcx>,
+        ty: Ty<'tcx>,
+        r: RangeInclusive<u128>,
+    ) -> Constructor<'tcx> {
+        let bias = IntRange::signed_bias(tcx, ty);
+        let ty = ty::ParamEnv::empty().and(ty);
+        let (lo, hi) = r.into_inner();
+        if lo == hi {
+            ConstantValue(ty::Const::from_bits(tcx, lo ^ bias, ty))
+        } else {
+            ConstantRange(ty::Const::from_bits(tcx, lo ^ bias, ty),
+                          ty::Const::from_bits(tcx, hi ^ bias, ty),
+                          RangeEnd::Included)
+        }
+    }
+
+    /// Return a collection of ranges that spans the values covered by `ranges`, subtracted
+    /// by the values covered by `self`: i.e. `ranges \ self` (in set notation).
+    fn subtract_from(self,
+                     tcx: TyCtxt<'_, 'tcx, 'tcx>,
+                     ranges: Vec<Constructor<'tcx>>)
+                     -> Vec<Constructor<'tcx>> {
+        let ranges = ranges.into_iter().filter_map(|r| {
+            IntRange::from_ctor(tcx, &r).map(|i| i.range)
+        });
+        let mut remaining_ranges = vec![];
+        let ty = self.ty;
+        let (lo, hi) = self.range.into_inner();
+        for subrange in ranges {
+            let (subrange_lo, subrange_hi) = subrange.into_inner();
+            if lo > subrange_hi || subrange_lo > hi  {
+                // The pattern doesn't intersect with the subrange at all,
+                // so the subrange remains untouched.
+                remaining_ranges.push(Self::range_to_ctor(tcx, ty, subrange_lo..=subrange_hi));
+            } else {
+                if lo > subrange_lo {
+                    // The pattern intersects an upper section of the
+                    // subrange, so a lower section will remain.
+                    remaining_ranges.push(Self::range_to_ctor(tcx, ty, subrange_lo..=(lo - 1)));
+                }
+                if hi < subrange_hi {
+                    // The pattern intersects a lower section of the
+                    // subrange, so an upper section will remain.
+                    remaining_ranges.push(Self::range_to_ctor(tcx, ty, (hi + 1)..=subrange_hi));
+                }
+            }
+        }
+        remaining_ranges
+    }
+
+    fn intersection(&self, other: &Self) -> Option<Self> {
+        let ty = self.ty;
+        let (lo, hi) = (*self.range.start(), *self.range.end());
+        let (other_lo, other_hi) = (*other.range.start(), *other.range.end());
+        if lo <= other_hi && other_lo <= hi {
+            Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty })
+        } else {
+            None
+        }
+    }
+}
+
+// Return a set of constructors equivalent to `all_ctors \ used_ctors`.
+fn compute_missing_ctors<'a, 'tcx: 'a>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    all_ctors: &Vec<Constructor<'tcx>>,
+    used_ctors: &Vec<Constructor<'tcx>>,
+) -> Vec<Constructor<'tcx>> {
+    let mut missing_ctors = vec![];
+
+    for req_ctor in all_ctors {
+        let mut refined_ctors = vec![req_ctor.clone()];
+        for used_ctor in used_ctors {
+            if used_ctor == req_ctor {
+                // If a constructor appears in a `match` arm, we can
+                // eliminate it straight away.
+                refined_ctors = vec![]
+            } else if tcx.features().exhaustive_integer_patterns {
+                if let Some(interval) = IntRange::from_ctor(tcx, used_ctor) {
+                    // Refine the required constructors for the type by subtracting
+                    // the range defined by the current constructor pattern.
+                    refined_ctors = interval.subtract_from(tcx, refined_ctors);
+                }
+            }
+
+            // If the constructor patterns that have been considered so far
+            // already cover the entire range of values, then we the
+            // constructor is not missing, and we can move on to the next one.
+            if refined_ctors.is_empty() {
+                break;
+            }
+        }
+        // If a constructor has not been matched, then it is missing.
+        // We add `refined_ctors` instead of `req_ctor`, because then we can
+        // provide more detailed error information about precisely which
+        // ranges have been omitted.
+        missing_ctors.extend(refined_ctors);
+    }
+
+    missing_ctors
+}
+
 /// Algorithm from http://moscova.inria.fr/~maranget/papers/warn/index.html
 /// The algorithm from the paper has been modified to correctly handle empty
 /// types. The changes are:
@@ -637,8 +1041,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         // FIXME: this might lead to "unstable" behavior with macro hygiene
         // introducing uninhabited patterns for inaccessible fields. We
         // need to figure out how to model that.
-        ty: rows.iter().map(|r| r[0].ty).find(|ty| !ty.references_error())
-            .unwrap_or(v[0].ty),
+        ty: rows.iter().map(|r| r[0].ty).find(|ty| !ty.references_error()).unwrap_or(v[0].ty),
         max_slice_length: max_slice_length(cx, rows.iter().map(|r| r[0]).chain(Some(v[0])))
     };
 
@@ -646,7 +1049,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
 
     if let Some(constructors) = pat_constructors(cx, v[0], pcx) {
         debug!("is_useful - expanding constructors: {:#?}", constructors);
-        constructors.into_iter().map(|c|
+        split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c|
             is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
         ).find(|result| result.is_useful()).unwrap_or(NotUseful)
     } else {
@@ -656,11 +1059,10 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
             pat_constructors(cx, row[0], pcx).unwrap_or(vec![])
         }).collect();
         debug!("used_ctors = {:#?}", used_ctors);
+        // `all_ctors` are all the constructors for the given type, which
+        // should all be represented (or caught with the wild pattern `_`).
         let all_ctors = all_constructors(cx, pcx);
         debug!("all_ctors = {:#?}", all_ctors);
-        let missing_ctors: Vec<Constructor> = all_ctors.iter().filter(|c| {
-            !used_ctors.contains(*c)
-        }).cloned().collect();
 
         // `missing_ctors` is the set of constructors from the same type as the
         // first column of `matrix` that are matched only by wildcard patterns
@@ -681,10 +1083,12 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         // feature flag is not present, so this is only
         // needed for that case.
 
-        let is_privately_empty =
-            all_ctors.is_empty() && !cx.is_uninhabited(pcx.ty);
-        let is_declared_nonexhaustive =
-            cx.is_non_exhaustive_enum(pcx.ty) && !cx.is_local(pcx.ty);
+        // Find those constructors that are not matched by any non-wildcard patterns in the
+        // current column.
+        let missing_ctors = compute_missing_ctors(cx.tcx, &all_ctors, &used_ctors);
+
+        let is_privately_empty = all_ctors.is_empty() && !cx.is_uninhabited(pcx.ty);
+        let is_declared_nonexhaustive = cx.is_non_exhaustive_enum(pcx.ty) && !cx.is_local(pcx.ty);
         debug!("missing_ctors={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}",
                missing_ctors, is_privately_empty, is_declared_nonexhaustive);
 
@@ -693,7 +1097,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         let is_non_exhaustive = is_privately_empty || is_declared_nonexhaustive;
 
         if missing_ctors.is_empty() && !is_non_exhaustive {
-            all_ctors.into_iter().map(|c| {
+            split_grouped_constructors(cx.tcx, all_ctors, matrix, pcx.ty).into_iter().map(|c| {
                 is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
             }).find(|result| result.is_useful()).unwrap_or(NotUseful)
         } else {
@@ -753,7 +1157,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                     // `used_ctors` is empty.
                     let new_witnesses = if is_non_exhaustive || used_ctors.is_empty() {
                         // All constructors are unused. Add wild patterns
-                        // rather than each individual constructor
+                        // rather than each individual constructor.
                         pats.into_iter().map(|mut witness| {
                             witness.0.push(Pattern {
                                 ty: pcx.ty,
@@ -765,6 +1169,10 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                     } else {
                         pats.into_iter().flat_map(|witness| {
                             missing_ctors.iter().map(move |ctor| {
+                                // Extends the witness with a "wild" version of this
+                                // constructor, that matches everything that can be built with
+                                // it. For example, if `ctor` is a `Constructor::Variant` for
+                                // `Option::Some`, this pushes the witness for `Some(_)`.
                                 witness.clone().push_wild_constructor(cx, ctor, pcx.ty)
                             })
                         }).collect()
@@ -777,14 +1185,16 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
     }
 }
 
+/// A shorthand for the `U(S(c, P), S(c, q))` operation from the paper. I.e. `is_useful` applied
+/// to the specialised version of both the pattern matrix `P` and the new pattern `q`.
 fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>(
     cx: &mut MatchCheckCtxt<'a, 'tcx>,
     &Matrix(ref m): &Matrix<'p, 'tcx>,
     v: &[&'p Pattern<'tcx>],
     ctor: Constructor<'tcx>,
     lty: Ty<'tcx>,
-    witness: WitnessPreference) -> Usefulness<'tcx>
-{
+    witness: WitnessPreference,
+) -> Usefulness<'tcx> {
     debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty);
     let sub_pat_tys = constructor_sub_pattern_tys(cx, &ctor, lty);
     let wild_patterns_owned: Vec<_> = sub_pat_tys.iter().map(|ty| {
@@ -806,7 +1216,7 @@ fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>(
                     .collect()
             ),
             result => result
-        },
+        }
         None => NotUseful
     }
 }
@@ -818,25 +1228,22 @@ fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>(
 /// Slice patterns, however, can match slices of different lengths. For instance,
 /// `[a, b, ..tail]` can match a slice of length 2, 3, 4 and so on.
 ///
-/// Returns None in case of a catch-all, which can't be specialized.
+/// Returns `None` in case of a catch-all, which can't be specialized.
 fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt,
                           pat: &Pattern<'tcx>,
                           pcx: PatternContext)
                           -> Option<Vec<Constructor<'tcx>>>
 {
     match *pat.kind {
-        PatternKind::Binding { .. } | PatternKind::Wild =>
-            None,
-        PatternKind::Leaf { .. } | PatternKind::Deref { .. } =>
-            Some(vec![Single]),
-        PatternKind::Variant { adt_def, variant_index, .. } =>
-            Some(vec![Variant(adt_def.variants[variant_index].did)]),
-        PatternKind::Constant { value } =>
-            Some(vec![ConstantValue(value)]),
-        PatternKind::Range { lo, hi, end } =>
-            Some(vec![ConstantRange(lo, hi, end)]),
+        PatternKind::Binding { .. } | PatternKind::Wild => None,
+        PatternKind::Leaf { .. } | PatternKind::Deref { .. } => Some(vec![Single]),
+        PatternKind::Variant { adt_def, variant_index, .. } => {
+            Some(vec![Variant(adt_def.variants[variant_index].did)])
+        }
+        PatternKind::Constant { value } => Some(vec![ConstantValue(value)]),
+        PatternKind::Range { lo, hi, end } => Some(vec![ConstantRange(lo, hi, end)]),
         PatternKind::Array { .. } => match pcx.ty.sty {
-            ty::TyArray(_, length) => Some(vec![
+            ty::Array(_, length) => Some(vec![
                 Slice(length.unwrap_usize(cx.tcx))
             ]),
             _ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty)
@@ -860,14 +1267,14 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt,
 fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 {
     debug!("constructor_arity({:#?}, {:?})", ctor, ty);
     match ty.sty {
-        ty::TyTuple(ref fs) => fs.len() as u64,
-        ty::TySlice(..) | ty::TyArray(..) => match *ctor {
+        ty::Tuple(ref fs) => fs.len() as u64,
+        ty::Slice(..) | ty::Array(..) => match *ctor {
             Slice(length) => length,
             ConstantValue(_) => 0,
             _ => bug!("bad slice pattern {:?} {:?}", ctor, ty)
         },
-        ty::TyRef(..) => 1,
-        ty::TyAdt(adt, _) => {
+        ty::Ref(..) => 1,
+        ty::Adt(adt, _) => {
             adt.variants[ctor.variant_index_for_adt(adt)].fields.len() as u64
         }
         _ => 0
@@ -884,14 +1291,14 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
 {
     debug!("constructor_sub_pattern_tys({:#?}, {:?})", ctor, ty);
     match ty.sty {
-        ty::TyTuple(ref fs) => fs.into_iter().map(|t| *t).collect(),
-        ty::TySlice(ty) | ty::TyArray(ty, _) => match *ctor {
+        ty::Tuple(ref fs) => fs.into_iter().map(|t| *t).collect(),
+        ty::Slice(ty) | ty::Array(ty, _) => match *ctor {
             Slice(length) => (0..length).map(|_| ty).collect(),
             ConstantValue(_) => vec![],
             _ => bug!("bad slice pattern {:?} {:?}", ctor, ty)
         },
-        ty::TyRef(_, rty, _) => vec![rty],
-        ty::TyAdt(adt, substs) => {
+        ty::Ref(_, rty, _) => vec![rty],
+        ty::Adt(adt, substs) => {
             if adt.is_box() {
                 // Use T as the sub pattern type of Box<T>.
                 vec![substs.type_at(0)]
@@ -970,13 +1377,167 @@ fn slice_pat_covered_by_constructor<'tcx>(
     Ok(true)
 }
 
+// Whether to evaluate a constructor using exhaustive integer matching. This is true if the
+// constructor is a range or constant with an integer type.
+fn should_treat_range_exhaustively(tcx: TyCtxt<'_, 'tcx, 'tcx>, ctor: &Constructor<'tcx>) -> bool {
+    if tcx.features().exhaustive_integer_patterns {
+        if let ConstantValue(value) | ConstantRange(value, _, _) = ctor {
+            if let ty::Char | ty::Int(_) | ty::Uint(_) = value.ty.sty {
+                return true;
+            }
+        }
+    }
+    false
+}
+
+/// For exhaustive integer matching, some constructors are grouped within other constructors
+/// (namely integer typed values are grouped within ranges). However, when specialising these
+/// constructors, we want to be specialising for the underlying constructors (the integers), not
+/// the groups (the ranges). Thus we need to split the groups up. Splitting them up naïvely would
+/// mean creating a separate constructor for every single value in the range, which is clearly
+/// impractical. However, observe that for some ranges of integers, the specialisation will be
+/// identical across all values in that range (i.e. there are equivalence classes of ranges of
+/// constructors based on their `is_useful_specialised` outcome). These classes are grouped by
+/// the patterns that apply to them (in the matrix `P`). We can split the range whenever the
+/// patterns that apply to that range (specifically: the patterns that *intersect* with that range)
+/// change.
+/// Our solution, therefore, is to split the range constructor into subranges at every single point
+/// the group of intersecting patterns changes (using the method described below).
+/// And voilà! We're testing precisely those ranges that we need to, without any exhaustive matching
+/// on actual integers. The nice thing about this is that the number of subranges is linear in the
+/// number of rows in the matrix (i.e. the number of cases in the `match` statement), so we don't
+/// need to be worried about matching over gargantuan ranges.
+///
+/// Essentially, given the first column of a matrix representing ranges, looking like the following:
+///
+/// |------|  |----------| |-------|    ||
+///    |-------| |-------|            |----| ||
+///       |---------|
+///
+/// We split the ranges up into equivalence classes so the ranges are no longer overlapping:
+///
+/// |--|--|||-||||--||---|||-------|  |-|||| ||
+///
+/// The logic for determining how to split the ranges is fairly straightforward: we calculate
+/// boundaries for each interval range, sort them, then create constructors for each new interval
+/// between every pair of boundary points. (This essentially sums up to performing the intuitive
+/// merging operation depicted above.)
+fn split_grouped_constructors<'p, 'a: 'p, 'tcx: 'a>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    ctors: Vec<Constructor<'tcx>>,
+    &Matrix(ref m): &Matrix<'p, 'tcx>,
+    ty: Ty<'tcx>,
+) -> Vec<Constructor<'tcx>> {
+    let mut split_ctors = Vec::with_capacity(ctors.len());
+
+    for ctor in ctors.into_iter() {
+        match ctor {
+            // For now, only ranges may denote groups of "subconstructors", so we only need to
+            // special-case constant ranges.
+            ConstantRange(..) if should_treat_range_exhaustively(tcx, &ctor) => {
+                // We only care about finding all the subranges within the range of the constructor
+                // range. Anything else is irrelevant, because it is guaranteed to result in
+                // `NotUseful`, which is the default case anyway, and can be ignored.
+                let ctor_range = IntRange::from_ctor(tcx, &ctor).unwrap();
+
+                /// Represents a border between 2 integers. Because the intervals spanning borders
+                /// must be able to cover every integer, we need to be able to represent
+                /// 2^128 + 1 such borders.
+                #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+                enum Border {
+                    JustBefore(u128),
+                    AfterMax,
+                }
+
+                // A function for extracting the borders of an integer interval.
+                fn range_borders(r: IntRange<'_>) -> impl Iterator<Item = Border> {
+                    let (lo, hi) = r.range.into_inner();
+                    let from = Border::JustBefore(lo);
+                    let to = match hi.checked_add(1) {
+                        Some(m) => Border::JustBefore(m),
+                        None => Border::AfterMax,
+                    };
+                    vec![from, to].into_iter()
+                }
+
+                // `borders` is the set of borders between equivalence classes: each equivalence
+                // class lies between 2 borders.
+                let row_borders = m.iter()
+                    .flat_map(|row| IntRange::from_pat(tcx, row[0]))
+                    .flat_map(|range| ctor_range.intersection(&range))
+                    .flat_map(|range| range_borders(range));
+                let ctor_borders = range_borders(ctor_range.clone());
+                let mut borders: Vec<_> = row_borders.chain(ctor_borders).collect();
+                borders.sort_unstable();
+
+                // We're going to iterate through every pair of borders, making sure that each
+                // represents an interval of nonnegative length, and convert each such interval
+                // into a constructor.
+                for IntRange { range, .. } in borders.windows(2).filter_map(|window| {
+                    match (window[0], window[1]) {
+                        (Border::JustBefore(n), Border::JustBefore(m)) => {
+                            if n < m {
+                                Some(IntRange { range: n..=(m - 1), ty })
+                            } else {
+                                None
+                            }
+                        }
+                        (Border::JustBefore(n), Border::AfterMax) => {
+                            Some(IntRange { range: n..=u128::MAX, ty })
+                        }
+                        (Border::AfterMax, _) => None,
+                    }
+                }) {
+                    split_ctors.push(IntRange::range_to_ctor(tcx, ty, range));
+                }
+            }
+            // Any other constructor can be used unchanged.
+            _ => split_ctors.push(ctor),
+        }
+    }
+
+    split_ctors
+}
+
+/// Check whether there exists any shared value in either `ctor` or `pat` by intersecting them.
+fn constructor_intersects_pattern<'p, 'a: 'p, 'tcx: 'a>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    ctor: &Constructor<'tcx>,
+    pat: &'p Pattern<'tcx>,
+) -> Option<Vec<&'p Pattern<'tcx>>> {
+    if should_treat_range_exhaustively(tcx, ctor) {
+        match (IntRange::from_ctor(tcx, ctor), IntRange::from_pat(tcx, pat)) {
+            (Some(ctor), Some(pat)) => {
+                ctor.intersection(&pat).map(|_| {
+                    let (pat_lo, pat_hi) = pat.range.into_inner();
+                    let (ctor_lo, ctor_hi) = ctor.range.into_inner();
+                    assert!(pat_lo <= ctor_lo && ctor_hi <= pat_hi);
+                    vec![]
+                })
+            }
+            _ => None,
+        }
+    } else {
+        // Fallback for non-ranges and ranges that involve floating-point numbers, which are not
+        // conveniently handled by `IntRange`. For these cases, the constructor may not be a range
+        // so intersection actually devolves into being covered by the pattern.
+        match constructor_covered_by_range(tcx, ctor, pat) {
+            Ok(true) => Some(vec![]),
+            Ok(false) | Err(ErrorReported) => None,
+        }
+    }
+}
+
 fn constructor_covered_by_range<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     ctor: &Constructor<'tcx>,
-    from: &'tcx ty::Const<'tcx>, to: &'tcx ty::Const<'tcx>,
-    end: RangeEnd,
-    ty: Ty<'tcx>,
+    pat: &Pattern<'tcx>,
 ) -> Result<bool, ErrorReported> {
+    let (from, to, end, ty) = match pat.kind {
+        box PatternKind::Constant { value } => (value, value, RangeEnd::Included, value.ty),
+        box PatternKind::Range { lo, hi, end } => (lo, hi, end, lo.ty),
+        _ => bug!("`constructor_covered_by_range` called with {:?}", pat),
+    };
     trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty);
     let cmp_from = |c_from| compare_const_vals(tcx, c_from, from, ty::ParamEnv::empty().and(ty))
         .map(|res| res != Ordering::Less);
@@ -1040,15 +1601,14 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
     cx: &mut MatchCheckCtxt<'a, 'tcx>,
     r: &[&'p Pattern<'tcx>],
     constructor: &Constructor<'tcx>,
-    wild_patterns: &[&'p Pattern<'tcx>])
-    -> Option<Vec<&'p Pattern<'tcx>>>
-{
+    wild_patterns: &[&'p Pattern<'tcx>],
+) -> Option<Vec<&'p Pattern<'tcx>>> {
     let pat = &r[0];
 
     let head: Option<Vec<&Pattern>> = match *pat.kind {
         PatternKind::Binding { .. } | PatternKind::Wild => {
             Some(wild_patterns.to_owned())
-        },
+        }
 
         PatternKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
             let ref variant = adt_def.variants[variant_index];
@@ -1062,6 +1622,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
         PatternKind::Leaf { ref subpatterns } => {
             Some(patterns_for_variant(subpatterns, wild_patterns))
         }
+
         PatternKind::Deref { ref subpattern } => {
             Some(vec![subpattern])
         }
@@ -1090,30 +1651,21 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
                         span_bug!(pat.span,
                         "unexpected const-val {:?} with ctor {:?}", value, constructor)
                     }
-                },
+                }
                 _ => {
-                    match constructor_covered_by_range(
-                        cx.tcx,
-                        constructor, value, value, RangeEnd::Included,
-                        value.ty,
-                            ) {
-                        Ok(true) => Some(vec![]),
-                        Ok(false) => None,
-                        Err(ErrorReported) => None,
-                    }
+                    // If the constructor is a:
+                    //      Single value: add a row if the constructor equals the pattern.
+                    //      Range: add a row if the constructor contains the pattern.
+                    constructor_intersects_pattern(cx.tcx, constructor, pat)
                 }
             }
         }
 
-        PatternKind::Range { lo, hi, ref end } => {
-            match constructor_covered_by_range(
-                cx.tcx,
-                constructor, lo, hi, end.clone(), lo.ty,
-            ) {
-                Ok(true) => Some(vec![]),
-                Ok(false) => None,
-                Err(ErrorReported) => None,
-            }
+        PatternKind::Range { .. } => {
+            // If the constructor is a:
+            //      Single value: add a row if the pattern contains the constructor.
+            //      Range: add a row if the constructor intersects the pattern.
+            constructor_intersects_pattern(cx.tcx, constructor, pat)
         }
 
         PatternKind::Array { ref prefix, ref slice, ref suffix } |
@@ -1123,14 +1675,12 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
                     let pat_len = prefix.len() + suffix.len();
                     if let Some(slice_count) = wild_patterns.len().checked_sub(pat_len) {
                         if slice_count == 0 || slice.is_some() {
-                            Some(
-                                prefix.iter().chain(
-                                wild_patterns.iter().map(|p| *p)
-                                                    .skip(prefix.len())
-                                                    .take(slice_count)
-                                                    .chain(
-                                suffix.iter()
-                            )).collect())
+                            Some(prefix.iter().chain(
+                                    wild_patterns.iter().map(|p| *p)
+                                                 .skip(prefix.len())
+                                                 .take(slice_count)
+                                                 .chain(suffix.iter())
+                            ).collect())
                         } else {
                             None
                         }
index 986bbced020bfc142dcf83e75f3b9943461c5fc5..3a518bad8ed7c20aff0b9ee4b90ebad1f97725f6 100644 (file)
@@ -260,8 +260,8 @@ fn check_match(
     fn conservative_is_uninhabited(&self, scrutinee_ty: Ty<'tcx>) -> bool {
         // "rustc-1.0-style" uncontentious uninhabitableness check
         match scrutinee_ty.sty {
-            ty::TyNever => true,
-            ty::TyAdt(def, _) => def.variants.is_empty(),
+            ty::Never => true,
+            ty::Adt(def, _) => def.variants.is_empty(),
             _ => false
         }
     }
@@ -274,7 +274,7 @@ fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str) {
                                                 self.tables);
             let pattern = patcx.lower_pattern(pat);
             let pattern_ty = pattern.ty;
-            let pats : Matrix = vec![vec![
+            let pats: Matrix = vec![vec![
                 expand_pattern(cx, pattern)
             ]].into_iter().collect();
 
@@ -317,7 +317,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchVisitor, pat: &Pat) {
                     return true;
                 }
                 let pat_ty = cx.tables.pat_ty(p);
-                if let ty::TyAdt(edef, _) = pat_ty.sty {
+                if let ty::Adt(edef, _) = pat_ty.sty {
                     if edef.is_enum() && edef.variants.iter().any(|variant| {
                         variant.name == ident.name && variant.ctor_kind == CtorKind::Const
                     }) {
@@ -393,7 +393,7 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                                     printed_if_let_err = true;
                                 }
                             }
-                        },
+                        }
 
                         hir::MatchSource::WhileLetDesugar => {
                             // check which arm we're on.
index d614131c526837623dbcae21965fb572b157206b..384ee0079dc84c70ec55b11169a9a8e63d18a143 100644 (file)
 pub use self::check_match::check_crate;
 pub(crate) use self::check_match::check_match;
 
-use interpret::{const_val_field, const_variant_index, self};
+use interpret::{const_field, const_variant_index};
 
 use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
-use rustc::mir::interpret::{Scalar, GlobalId, ConstValue};
+use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
 use rustc::ty::subst::{Substs, Kind};
 use rustc::hir::{self, PatKind, RangeEnd};
@@ -148,7 +148,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     PatternKind::Variant { adt_def, variant_index, .. } => {
                         Some(&adt_def.variants[variant_index])
                     }
-                    _ => if let ty::TyAdt(adt, _) = self.ty.sty {
+                    _ => if let ty::Adt(adt, _) = self.ty.sty {
                         if !adt.is_enum() {
                             Some(&adt.variants[0])
                         } else {
@@ -165,7 +165,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 if let Some(variant) = variant {
                     write!(f, "{}", variant.name)?;
 
-                    // Only for TyAdt we can have `S {...}`,
+                    // Only for Adt we can have `S {...}`,
                     // which we handle separately here.
                     if variant.ctor_kind == CtorKind::Fictive {
                         write!(f, " {{ ")?;
@@ -216,8 +216,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             }
             PatternKind::Deref { ref subpattern } => {
                 match self.ty.sty {
-                    ty::TyAdt(def, _) if def.is_box() => write!(f, "box ")?,
-                    ty::TyRef(_, _, mutbl) => {
+                    ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
+                    ty::Ref(_, _, mutbl) => {
                         write!(f, "&")?;
                         if mutbl == hir::MutMutable {
                             write!(f, "mut ")?;
@@ -233,7 +233,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             PatternKind::Range { lo, hi, end } => {
                 fmt_const_val(f, lo)?;
                 match end {
-                    RangeEnd::Included => write!(f, "...")?,
+                    RangeEnd::Included => write!(f, "..=")?,
                     RangeEnd::Excluded => write!(f, "..")?,
                 }
                 fmt_const_val(f, hi)
@@ -368,9 +368,14 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                                     "lower range bound must be less than upper",
                                 );
                                 PatternKind::Wild
-                            },
-                            (RangeEnd::Included, None) |
-                            (RangeEnd::Included, Some(Ordering::Greater)) => {
+                            }
+                            (RangeEnd::Included, Some(Ordering::Equal)) => {
+                                PatternKind::Constant { value: lo }
+                            }
+                            (RangeEnd::Included, Some(Ordering::Less)) => {
+                                PatternKind::Range { lo, hi, end }
+                            }
+                            (RangeEnd::Included, _) => {
                                 let mut err = struct_span_err!(
                                     self.tcx.sess,
                                     lo_expr.span,
@@ -390,8 +395,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                                 }
                                 err.emit();
                                 PatternKind::Wild
-                            },
-                            (RangeEnd::Included, Some(_)) => PatternKind::Range { lo, hi, end },
+                            }
                         }
                     }
                     _ => PatternKind::Wild
@@ -409,7 +413,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
 
             PatKind::Slice(ref prefix, ref slice, ref suffix) => {
                 match ty.sty {
-                    ty::TyRef(_, ty, _) =>
+                    ty::Ref(_, ty, _) =>
                         PatternKind::Deref {
                             subpattern: Pattern {
                                 ty,
@@ -418,10 +422,10 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                                     pat.span, ty, prefix, slice, suffix))
                             },
                         },
-                    ty::TySlice(..) |
-                    ty::TyArray(..) =>
+                    ty::Slice(..) |
+                    ty::Array(..) =>
                         self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix),
-                    ty::TyError => { // Avoid ICE
+                    ty::Error => { // Avoid ICE
                         return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
                     }
                     ref sty =>
@@ -434,7 +438,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
 
             PatKind::Tuple(ref subpatterns, ddpos) => {
                 match ty.sty {
-                    ty::TyTuple(ref tys) => {
+                    ty::Tuple(ref tys) => {
                         let subpatterns =
                             subpatterns.iter()
                                        .enumerate_and_adjust(tys.len(), ddpos)
@@ -446,7 +450,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
 
                         PatternKind::Leaf { subpatterns: subpatterns }
                     }
-                    ty::TyError => { // Avoid ICE (#50577)
+                    ty::Error => { // Avoid ICE (#50577)
                         return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
                     }
                     ref sty => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", sty),
@@ -456,8 +460,8 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
             PatKind::Binding(_, id, ident, ref sub) => {
                 let var_ty = self.tables.node_id_to_type(pat.hir_id);
                 let region = match var_ty.sty {
-                    ty::TyRef(r, _, _) => Some(r),
-                    ty::TyError => { // Avoid ICE
+                    ty::Ref(r, _, _) => Some(r),
+                    ty::Error => { // Avoid ICE
                         return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
                     }
                     _ => None,
@@ -480,7 +484,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                 // A ref x pattern is the same node used for x, and as such it has
                 // x's type, which is &T, where we want T (the type being matched).
                 if let ty::BindByReference(_) = bm {
-                    if let ty::TyRef(_, rty, _) = ty.sty {
+                    if let ty::Ref(_, rty, _) = ty.sty {
                         ty = rty;
                     } else {
                         bug!("`ref {}` has wrong type {}", ident, ty);
@@ -500,8 +504,8 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
             PatKind::TupleStruct(ref qpath, ref subpatterns, ddpos) => {
                 let def = self.tables.qpath_def(qpath, pat.hir_id);
                 let adt_def = match ty.sty {
-                    ty::TyAdt(adt_def, _) => adt_def,
-                    ty::TyError => { // Avoid ICE (#50585)
+                    ty::Adt(adt_def, _) => adt_def,
+                    ty::Error => { // Avoid ICE (#50585)
                         return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
                     }
                     _ => span_bug!(pat.span,
@@ -604,12 +608,12 @@ fn slice_or_array_pattern(
             self.flatten_nested_slice_patterns(prefix, slice, suffix);
 
         match ty.sty {
-            ty::TySlice(..) => {
+            ty::Slice(..) => {
                 // matching a slice or fixed-length array
                 PatternKind::Slice { prefix: prefix, slice: slice, suffix: suffix }
             }
 
-            ty::TyArray(_, len) => {
+            ty::Array(_, len) => {
                 // fixed-length array
                 let len = len.unwrap_usize(self.tcx);
                 assert!(len >= prefix.len() as u64 + suffix.len() as u64);
@@ -636,9 +640,9 @@ fn lower_variant_or_leaf(
                 let adt_def = self.tcx.adt_def(enum_id);
                 if adt_def.is_enum() {
                     let substs = match ty.sty {
-                        ty::TyAdt(_, substs) |
-                        ty::TyFnDef(_, substs) => substs,
-                        ty::TyError => {  // Avoid ICE (#50585)
+                        ty::Adt(_, substs) |
+                        ty::FnDef(_, substs) => substs,
+                        ty::Error => {  // Avoid ICE (#50585)
                             return PatternKind::Wild;
                         }
                         _ => bug!("inappropriate type for def: {:?}", ty.sty),
@@ -791,7 +795,7 @@ fn const_to_pat(
         debug!("const_to_pat: cv={:#?}", cv);
         let adt_subpattern = |i, variant_opt| {
             let field = Field::new(i);
-            let val = const_val_field(
+            let val = const_field(
                 self.tcx, self.param_env, instance,
                 variant_opt, field, cv,
             ).expect("field access failed");
@@ -807,7 +811,7 @@ fn const_to_pat(
             }).collect::<Vec<_>>()
         };
         let kind = match cv.ty.sty {
-            ty::TyFloat(_) => {
+            ty::Float(_) => {
                 let id = self.tcx.hir.hir_to_node_id(id);
                 self.tcx.lint_node(
                     ::rustc::lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
@@ -819,12 +823,12 @@ fn const_to_pat(
                     value: cv,
                 }
             },
-            ty::TyAdt(adt_def, _) if adt_def.is_union() => {
+            ty::Adt(adt_def, _) if adt_def.is_union() => {
                 // Matching on union fields is unsafe, we can't hide it in constants
                 self.tcx.sess.span_err(span, "cannot use unions in constant patterns");
                 PatternKind::Wild
             }
-            ty::TyAdt(adt_def, _) if !self.tcx.has_attr(adt_def.did, "structural_match") => {
+            ty::Adt(adt_def, _) if !self.tcx.has_attr(adt_def.did, "structural_match") => {
                 let msg = format!("to use a constant of type `{}` in a pattern, \
                                     `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
                                     self.tcx.item_path_str(adt_def.did),
@@ -832,7 +836,7 @@ fn const_to_pat(
                 self.tcx.sess.span_err(span, &msg);
                 PatternKind::Wild
             },
-            ty::TyAdt(adt_def, substs) if adt_def.is_enum() => {
+            ty::Adt(adt_def, substs) if adt_def.is_enum() => {
                 let variant_index = const_variant_index(
                     self.tcx, self.param_env, instance, cv
                 ).expect("const_variant_index failed");
@@ -847,18 +851,18 @@ fn const_to_pat(
                     subpatterns,
                 }
             },
-            ty::TyAdt(adt_def, _) => {
+            ty::Adt(adt_def, _) => {
                 let struct_var = adt_def.non_enum_variant();
                 PatternKind::Leaf {
                     subpatterns: adt_subpatterns(struct_var.fields.len(), None),
                 }
             }
-            ty::TyTuple(fields) => {
+            ty::Tuple(fields) => {
                 PatternKind::Leaf {
                     subpatterns: adt_subpatterns(fields.len(), None),
                 }
             }
-            ty::TyArray(_, n) => {
+            ty::Array(_, n) => {
                 PatternKind::Array {
                     prefix: (0..n.unwrap_usize(self.tcx))
                         .map(|i| adt_subpattern(i as usize, None))
@@ -1069,28 +1073,29 @@ pub fn compare_const_vals<'a, 'tcx>(
     if let (Some(a), Some(b)) = (a.to_bits(tcx, ty), b.to_bits(tcx, ty)) {
         use ::rustc_apfloat::Float;
         return match ty.value.sty {
-            ty::TyFloat(ast::FloatTy::F32) => {
+            ty::Float(ast::FloatTy::F32) => {
                 let l = ::rustc_apfloat::ieee::Single::from_bits(a);
                 let r = ::rustc_apfloat::ieee::Single::from_bits(b);
                 l.partial_cmp(&r)
             },
-            ty::TyFloat(ast::FloatTy::F64) => {
+            ty::Float(ast::FloatTy::F64) => {
                 let l = ::rustc_apfloat::ieee::Double::from_bits(a);
                 let r = ::rustc_apfloat::ieee::Double::from_bits(b);
                 l.partial_cmp(&r)
             },
-            ty::TyInt(_) => {
+            ty::Int(_) => {
                 let layout = tcx.layout_of(ty).ok()?;
-                let a = interpret::sign_extend(a, layout);
-                let b = interpret::sign_extend(b, layout);
+                assert!(layout.abi.is_signed());
+                let a = sign_extend(a, layout.size);
+                let b = sign_extend(b, layout.size);
                 Some((a as i128).cmp(&(b as i128)))
             },
             _ => Some(a.cmp(&b)),
         }
     }
 
-    if let ty::TyRef(_, rty, _) = ty.value.sty {
-        if let ty::TyStr = rty.sty {
+    if let ty::Ref(_, rty, _) = ty.value.sty {
+        if let ty::Str = rty.sty {
             match (a.val, b.val) {
                 (
                     ConstValue::ScalarPair(
@@ -1102,8 +1107,8 @@ pub fn compare_const_vals<'a, 'tcx>(
                         len_b,
                     ),
                 ) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => {
-                    let len_a = len_a.unwrap_or_err().ok();
-                    let len_b = len_b.unwrap_or_err().ok();
+                    let len_a = len_a.not_undef().ok();
+                    let len_b = len_b.not_undef().ok();
                     if len_a.is_none() || len_b.is_none() {
                         tcx.sess.struct_err("str slice len is undef").delay_as_bug();
                     }
@@ -1149,8 +1154,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
         LitKind::Str(ref s, _) => {
             let s = s.as_str();
             let id = tcx.allocate_bytes(s.as_bytes());
-            let value = Scalar::Ptr(id.into()).to_value_with_len(s.len() as u64, tcx);
-            ConstValue::from_byval_value(value).unwrap()
+            ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, tcx)
         },
         LitKind::ByteStr(ref data) => {
             let id = tcx.allocate_bytes(data);
@@ -1166,11 +1170,11 @@ enum Int {
                 Unsigned(UintTy),
             }
             let ity = match ty.sty {
-                ty::TyInt(IntTy::Isize) => Int::Signed(tcx.sess.target.isize_ty),
-                ty::TyInt(other) => Int::Signed(other),
-                ty::TyUint(UintTy::Usize) => Int::Unsigned(tcx.sess.target.usize_ty),
-                ty::TyUint(other) => Int::Unsigned(other),
-                ty::TyError => { // Avoid ICE (#51963)
+                ty::Int(IntTy::Isize) => Int::Signed(tcx.sess.target.isize_ty),
+                ty::Int(other) => Int::Signed(other),
+                ty::Uint(UintTy::Usize) => Int::Unsigned(tcx.sess.target.usize_ty),
+                ty::Uint(other) => Int::Unsigned(other),
+                ty::Error => { // Avoid ICE (#51963)
                     return Err(LitToConstError::Propagated);
                 }
                 _ => bug!("literal integer type with bad type ({:?})", ty.sty),
@@ -1207,7 +1211,7 @@ enum Int {
         }
         LitKind::FloatUnsuffixed(n) => {
             let fty = match ty.sty {
-                ty::TyFloat(fty) => fty,
+                ty::Float(fty) => fty,
                 _ => bug!()
             };
             parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)?
index 4e705254331a2f08a2d1eec5c724912ae5e58b71..83264acf76a31809d7d4047713c592be56c72700 100644 (file)
@@ -1,88 +1,92 @@
-use rustc::ty::{self, Ty};
-use rustc::ty::layout::{self, LayoutOf, TyLayout};
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::ty::{self, Ty, TypeAndMut};
+use rustc::ty::layout::{self, TyLayout, Size};
 use syntax::ast::{FloatTy, IntTy, UintTy};
 
 use rustc_apfloat::ieee::{Single, Double};
-use super::{EvalContext, Machine};
-use rustc::mir::interpret::{Scalar, EvalResult, Pointer, PointerArithmetic, Value, EvalErrorKind};
+use rustc::mir::interpret::{
+    Scalar, EvalResult, Pointer, PointerArithmetic, EvalErrorKind, truncate
+};
 use rustc::mir::CastKind;
 use rustc_apfloat::Float;
-use interpret::eval_context::ValTy;
-use interpret::Place;
+
+use super::{EvalContext, Machine, PlaceTy, OpTy, Value};
 
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
-    crate fn cast(
+    fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
+        match ty.sty {
+            ty::RawPtr(ty::TypeAndMut { ty, .. }) |
+            ty::Ref(_, ty, _) => !self.type_is_sized(ty),
+            ty::Adt(def, _) if def.is_box() => !self.type_is_sized(ty.boxed_ty()),
+            _ => false,
+        }
+    }
+
+    pub fn cast(
         &mut self,
-        src: ValTy<'tcx>,
+        src: OpTy<'tcx>,
         kind: CastKind,
-        dest_ty: Ty<'tcx>,
-        dest: Place,
+        dest: PlaceTy<'tcx>,
     ) -> EvalResult<'tcx> {
-        let src_layout = self.layout_of(src.ty)?;
-        let dst_layout = self.layout_of(dest_ty)?;
+        let src_layout = src.layout;
+        let dst_layout = dest.layout;
         use rustc::mir::CastKind::*;
         match kind {
             Unsize => {
-                self.unsize_into(src.value, src_layout, dest, dst_layout)?;
+                self.unsize_into(src, dest)?;
             }
 
             Misc => {
-                if self.type_is_fat_ptr(src.ty) {
-                    match (src.value, self.type_is_fat_ptr(dest_ty)) {
-                        (Value::ByRef { .. }, _) |
+                let src = self.read_value(src)?;
+                if self.type_is_fat_ptr(src_layout.ty) {
+                    match (*src, self.type_is_fat_ptr(dest.layout.ty)) {
                         // pointers to extern types
                         (Value::Scalar(_),_) |
                         // slices and trait objects to other slices/trait objects
                         (Value::ScalarPair(..), true) => {
-                            let valty = ValTy {
-                                value: src.value,
-                                ty: dest_ty,
-                            };
-                            self.write_value(valty, dest)?;
+                            // No change to value
+                            self.write_value(*src, dest)?;
                         }
                         // slices and trait objects to thin pointers (dropping the metadata)
                         (Value::ScalarPair(data, _), false) => {
-                            let valty = ValTy {
-                                value: Value::Scalar(data),
-                                ty: dest_ty,
-                            };
-                            self.write_value(valty, dest)?;
+                            self.write_scalar(data, dest)?;
                         }
                     }
                 } else {
-                    let src_layout = self.layout_of(src.ty)?;
                     match src_layout.variants {
                         layout::Variants::Single { index } => {
-                            if let Some(def) = src.ty.ty_adt_def() {
+                            if let Some(def) = src_layout.ty.ty_adt_def() {
                                 let discr_val = def
                                     .discriminant_for_variant(*self.tcx, index)
                                     .val;
                                 return self.write_scalar(
-                                    dest,
-                                    Scalar::Bits {
-                                        bits: discr_val,
-                                        size: dst_layout.size.bytes() as u8,
-                                    },
-                                    dest_ty);
+                                    Scalar::from_uint(discr_val, dst_layout.size),
+                                    dest);
                             }
                         }
                         layout::Variants::Tagged { .. } |
                         layout::Variants::NicheFilling { .. } => {},
                     }
 
-                    let src_val = self.value_to_scalar(src)?;
-                    let dest_val = self.cast_scalar(src_val, src_layout, dst_layout)?;
-                    let valty = ValTy {
-                        value: Value::Scalar(dest_val.into()),
-                        ty: dest_ty,
-                    };
-                    self.write_value(valty, dest)?;
+                    let src = src.to_scalar()?;
+                    let dest_val = self.cast_scalar(src, src_layout, dest.layout)?;
+                    self.write_scalar(dest_val, dest)?;
                 }
             }
 
             ReifyFnPointer => {
-                match src.ty.sty {
-                    ty::TyFnDef(def_id, substs) => {
+                // The src operand does not matter, just its type
+                match src_layout.ty.sty {
+                    ty::FnDef(def_id, substs) => {
                         if self.tcx.has_attr(def_id, "rustc_args_required_const") {
                             bug!("reifying a fn ptr that requires \
                                     const arguments");
@@ -94,30 +98,27 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                             substs,
                         ).ok_or_else(|| EvalErrorKind::TooGeneric.into());
                         let fn_ptr = self.memory.create_fn_alloc(instance?);
-                        let valty = ValTy {
-                            value: Value::Scalar(Scalar::Ptr(fn_ptr.into()).into()),
-                            ty: dest_ty,
-                        };
-                        self.write_value(valty, dest)?;
+                        self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?;
                     }
                     ref other => bug!("reify fn pointer on {:?}", other),
                 }
             }
 
             UnsafeFnPointer => {
-                match dest_ty.sty {
-                    ty::TyFnPtr(_) => {
-                        let mut src = src;
-                        src.ty = dest_ty;
-                        self.write_value(src, dest)?;
+                let src = self.read_value(src)?;
+                match dest.layout.ty.sty {
+                    ty::FnPtr(_) => {
+                        // No change to value
+                        self.write_value(*src, dest)?;
                     }
                     ref other => bug!("fn to unsafe fn cast on {:?}", other),
                 }
             }
 
             ClosureFnPointer => {
-                match src.ty.sty {
-                    ty::TyClosure(def_id, substs) => {
+                // The src operand does not matter, just its type
+                match src_layout.ty.sty {
+                    ty::Closure(def_id, substs) => {
                         let substs = self.tcx.subst_and_normalize_erasing_regions(
                             self.substs(),
                             ty::ParamEnv::reveal_all(),
@@ -130,11 +131,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                             ty::ClosureKind::FnOnce,
                         );
                         let fn_ptr = self.memory.create_fn_alloc(instance);
-                        let valty = ValTy {
-                            value: Value::Scalar(Scalar::Ptr(fn_ptr.into()).into()),
-                            ty: dest_ty,
-                        };
-                        self.write_value(valty, dest)?;
+                        let val = Value::Scalar(Scalar::Ptr(fn_ptr.into()).into());
+                        self.write_value(val, dest)?;
                     }
                     ref other => bug!("closure fn pointer on {:?}", other),
                 }
@@ -149,17 +147,32 @@ pub(super) fn cast_scalar(
         src_layout: TyLayout<'tcx>,
         dest_layout: TyLayout<'tcx>,
     ) -> EvalResult<'tcx, Scalar> {
-        use rustc::ty::TypeVariants::*;
+        use rustc::ty::TyKind::*;
         trace!("Casting {:?}: {:?} to {:?}", val, src_layout.ty, dest_layout.ty);
 
         match val {
             Scalar::Ptr(ptr) => self.cast_from_ptr(ptr, dest_layout.ty),
             Scalar::Bits { bits, size } => {
-                assert_eq!(size as u64, src_layout.size.bytes());
-                match src_layout.ty.sty {
-                    TyFloat(fty) => self.cast_from_float(bits, fty, dest_layout.ty),
-                    _ => self.cast_from_int(bits, src_layout, dest_layout),
+                debug_assert_eq!(size as u64, src_layout.size.bytes());
+                debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
+                    "Unexpected value of size {} before casting", size);
+
+                let res = match src_layout.ty.sty {
+                    Float(fty) => self.cast_from_float(bits, fty, dest_layout.ty)?,
+                    _ => self.cast_from_int(bits, src_layout, dest_layout)?,
+                };
+
+                // Sanity check
+                match res {
+                    Scalar::Ptr(_) => bug!("Fabricated a ptr value from an int...?"),
+                    Scalar::Bits { bits, size } => {
+                        debug_assert_eq!(size as u64, dest_layout.size.bytes());
+                        debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
+                            "Unexpected value of size {} after casting", size);
+                    }
                 }
+                // Done
+                Ok(res)
             }
         }
     }
@@ -177,44 +190,43 @@ fn cast_from_int(
             v
         };
         trace!("cast_from_int: {}, {}, {}", v, src_layout.ty, dest_layout.ty);
-        use rustc::ty::TypeVariants::*;
+        use rustc::ty::TyKind::*;
         match dest_layout.ty.sty {
-            TyInt(_) | TyUint(_) => {
+            Int(_) | Uint(_) => {
                 let v = self.truncate(v, dest_layout);
-                Ok(Scalar::Bits {
-                    bits: v,
-                    size: dest_layout.size.bytes() as u8,
-                })
+                Ok(Scalar::from_uint(v, dest_layout.size))
             }
 
-            TyFloat(FloatTy::F32) if signed => Ok(Scalar::Bits {
-                bits: Single::from_i128(v as i128).value.to_bits(),
-                size: 4,
-            }),
-            TyFloat(FloatTy::F64) if signed => Ok(Scalar::Bits {
-                bits: Double::from_i128(v as i128).value.to_bits(),
-                size: 8,
-            }),
-            TyFloat(FloatTy::F32) => Ok(Scalar::Bits {
-                bits: Single::from_u128(v).value.to_bits(),
-                size: 4,
-            }),
-            TyFloat(FloatTy::F64) => Ok(Scalar::Bits {
-                bits: Double::from_u128(v).value.to_bits(),
-                size: 8,
-            }),
+            Float(FloatTy::F32) if signed => Ok(Scalar::from_uint(
+                Single::from_i128(v as i128).value.to_bits(),
+                Size::from_bits(32)
+            )),
+            Float(FloatTy::F64) if signed => Ok(Scalar::from_uint(
+                Double::from_i128(v as i128).value.to_bits(),
+                Size::from_bits(64)
+            )),
+            Float(FloatTy::F32) => Ok(Scalar::from_uint(
+                Single::from_u128(v).value.to_bits(),
+                Size::from_bits(32)
+            )),
+            Float(FloatTy::F64) => Ok(Scalar::from_uint(
+                Double::from_u128(v).value.to_bits(),
+                Size::from_bits(64)
+            )),
 
-            TyChar => {
-                assert_eq!(v as u8 as u128, v);
-                Ok(Scalar::Bits { bits: v, size: 4 })
+            Char => {
+                // `u8` to `char` cast
+                debug_assert_eq!(v as u8 as u128, v);
+                Ok(Scalar::from_uint(v, Size::from_bytes(4)))
             },
 
-            // No alignment check needed for raw pointers.  But we have to truncate to target ptr size.
-            TyRawPtr(_) => {
-                Ok(Scalar::Bits {
-                    bits: self.memory.truncate_to_ptr(v).0 as u128,
-                    size: self.memory.pointer_size().bytes() as u8,
-                })
+            // No alignment check needed for raw pointers.
+            // But we have to truncate to target ptr size.
+            RawPtr(_) => {
+                Ok(Scalar::from_uint(
+                    self.truncate_to_ptr(v).0,
+                    self.pointer_size(),
+                ))
             },
 
             // Casts to bool are not permitted by rustc, no need to handle them here.
@@ -222,74 +234,172 @@ fn cast_from_int(
         }
     }
 
-    fn cast_from_float(&self, bits: u128, fty: FloatTy, dest_ty: Ty<'tcx>) -> EvalResult<'tcx, Scalar> {
-        use rustc::ty::TypeVariants::*;
+    fn cast_from_float(
+        &self,
+        bits: u128,
+        fty: FloatTy,
+        dest_ty: Ty<'tcx>
+    ) -> EvalResult<'tcx, Scalar> {
+        use rustc::ty::TyKind::*;
         use rustc_apfloat::FloatConvert;
         match dest_ty.sty {
             // float -> uint
-            TyUint(t) => {
-                let width = t.bit_width().unwrap_or(self.memory.pointer_size().bits() as usize);
-                match fty {
-                    FloatTy::F32 => Ok(Scalar::Bits {
-                        bits: Single::from_bits(bits).to_u128(width).value,
-                        size: (width / 8) as u8,
-                    }),
-                    FloatTy::F64 => Ok(Scalar::Bits {
-                        bits: Double::from_bits(bits).to_u128(width).value,
-                        size: (width / 8) as u8,
-                    }),
-                }
+            Uint(t) => {
+                let width = t.bit_width().unwrap_or(self.pointer_size().bits() as usize);
+                let v = match fty {
+                    FloatTy::F32 => Single::from_bits(bits).to_u128(width).value,
+                    FloatTy::F64 => Double::from_bits(bits).to_u128(width).value,
+                };
+                // This should already fit the bit width
+                Ok(Scalar::from_uint(v, Size::from_bits(width as u64)))
             },
             // float -> int
-            TyInt(t) => {
-                let width = t.bit_width().unwrap_or(self.memory.pointer_size().bits() as usize);
-                match fty {
-                    FloatTy::F32 => Ok(Scalar::Bits {
-                        bits: Single::from_bits(bits).to_i128(width).value as u128,
-                        size: (width / 8) as u8,
-                    }),
-                    FloatTy::F64 => Ok(Scalar::Bits {
-                        bits: Double::from_bits(bits).to_i128(width).value as u128,
-                        size: (width / 8) as u8,
-                    }),
-                }
+            Int(t) => {
+                let width = t.bit_width().unwrap_or(self.pointer_size().bits() as usize);
+                let v = match fty {
+                    FloatTy::F32 => Single::from_bits(bits).to_i128(width).value,
+                    FloatTy::F64 => Double::from_bits(bits).to_i128(width).value,
+                };
+                Ok(Scalar::from_int(v, Size::from_bits(width as u64)))
             },
             // f64 -> f32
-            TyFloat(FloatTy::F32) if fty == FloatTy::F64 => {
-                Ok(Scalar::Bits {
-                    bits: Single::to_bits(Double::from_bits(bits).convert(&mut false).value),
-                    size: 4,
-                })
+            Float(FloatTy::F32) if fty == FloatTy::F64 => {
+                Ok(Scalar::from_uint(
+                    Single::to_bits(Double::from_bits(bits).convert(&mut false).value),
+                    Size::from_bits(32),
+                ))
             },
             // f32 -> f64
-            TyFloat(FloatTy::F64) if fty == FloatTy::F32 => {
-                Ok(Scalar::Bits {
-                    bits: Double::to_bits(Single::from_bits(bits).convert(&mut false).value),
-                    size: 8,
-                })
+            Float(FloatTy::F64) if fty == FloatTy::F32 => {
+                Ok(Scalar::from_uint(
+                    Double::to_bits(Single::from_bits(bits).convert(&mut false).value),
+                    Size::from_bits(64),
+                ))
             },
             // identity cast
-            TyFloat(FloatTy:: F64) => Ok(Scalar::Bits {
-                bits,
-                size: 8,
-            }),
-            TyFloat(FloatTy:: F32) => Ok(Scalar::Bits {
-                bits,
-                size: 4,
-            }),
+            Float(FloatTy:: F64) => Ok(Scalar::from_uint(bits, Size::from_bits(64))),
+            Float(FloatTy:: F32) => Ok(Scalar::from_uint(bits, Size::from_bits(32))),
             _ => err!(Unimplemented(format!("float to {:?} cast", dest_ty))),
         }
     }
 
     fn cast_from_ptr(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Scalar> {
-        use rustc::ty::TypeVariants::*;
+        use rustc::ty::TyKind::*;
         match ty.sty {
-            // Casting to a reference or fn pointer is not permitted by rustc, no need to support it here.
-            TyRawPtr(_) |
-            TyInt(IntTy::Isize) |
-            TyUint(UintTy::Usize) => Ok(ptr.into()),
-            TyInt(_) | TyUint(_) => err!(ReadPointerAsBytes),
+            // Casting to a reference or fn pointer is not permitted by rustc,
+            // no need to support it here.
+            RawPtr(_) |
+            Int(IntTy::Isize) |
+            Uint(UintTy::Usize) => Ok(ptr.into()),
+            Int(_) | Uint(_) => err!(ReadPointerAsBytes),
             _ => err!(Unimplemented(format!("ptr to {:?} cast", ty))),
         }
     }
+
+    fn unsize_into_ptr(
+        &mut self,
+        src: OpTy<'tcx>,
+        dest: PlaceTy<'tcx>,
+        // The pointee types
+        sty: Ty<'tcx>,
+        dty: Ty<'tcx>,
+    ) -> EvalResult<'tcx> {
+        // A<Struct> -> A<Trait> conversion
+        let (src_pointee_ty, dest_pointee_ty) = self.tcx.struct_lockstep_tails(sty, dty);
+
+        match (&src_pointee_ty.sty, &dest_pointee_ty.sty) {
+            (&ty::Array(_, length), &ty::Slice(_)) => {
+                let ptr = self.read_value(src)?.to_scalar_ptr()?;
+                // u64 cast is from usize to u64, which is always good
+                let val = Value::new_slice(ptr, length.unwrap_usize(self.tcx.tcx), self.tcx.tcx);
+                self.write_value(val, dest)
+            }
+            (&ty::Dynamic(..), &ty::Dynamic(..)) => {
+                // For now, upcasts are limited to changes in marker
+                // traits, and hence never actually require an actual
+                // change to the vtable.
+                self.copy_op(src, dest)
+            }
+            (_, &ty::Dynamic(ref data, _)) => {
+                // Initial cast from sized to dyn trait
+                let trait_ref = data.principal().unwrap().with_self_ty(
+                    *self.tcx,
+                    src_pointee_ty,
+                );
+                let trait_ref = self.tcx.erase_regions(&trait_ref);
+                let vtable = self.get_vtable(src_pointee_ty, trait_ref)?;
+                let ptr = self.read_value(src)?.to_scalar_ptr()?;
+                let val = Value::new_dyn_trait(ptr, vtable);
+                self.write_value(val, dest)
+            }
+
+            _ => bug!("invalid unsizing {:?} -> {:?}", src.layout.ty, dest.layout.ty),
+        }
+    }
+
+    fn unsize_into(
+        &mut self,
+        src: OpTy<'tcx>,
+        dest: PlaceTy<'tcx>,
+    ) -> EvalResult<'tcx> {
+        match (&src.layout.ty.sty, &dest.layout.ty.sty) {
+            (&ty::Ref(_, s, _), &ty::Ref(_, d, _)) |
+            (&ty::Ref(_, s, _), &ty::RawPtr(TypeAndMut { ty: d, .. })) |
+            (&ty::RawPtr(TypeAndMut { ty: s, .. }),
+             &ty::RawPtr(TypeAndMut { ty: d, .. })) => {
+                self.unsize_into_ptr(src, dest, s, d)
+            }
+            (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
+                assert_eq!(def_a, def_b);
+                if def_a.is_box() || def_b.is_box() {
+                    if !def_a.is_box() || !def_b.is_box() {
+                        bug!("invalid unsizing between {:?} -> {:?}", src.layout, dest.layout);
+                    }
+                    return self.unsize_into_ptr(
+                        src,
+                        dest,
+                        src.layout.ty.boxed_ty(),
+                        dest.layout.ty.boxed_ty(),
+                    );
+                }
+
+                // unsizing of generic struct with pointer fields
+                // Example: `Arc<T>` -> `Arc<Trait>`
+                // here we need to increase the size of every &T thin ptr field to a fat ptr
+                for i in 0..src.layout.fields.count() {
+                    let dst_field = self.place_field(dest, i as u64)?;
+                    if dst_field.layout.is_zst() {
+                        continue;
+                    }
+                    let src_field = match src.try_as_mplace() {
+                        Ok(mplace) => {
+                            let src_field = self.mplace_field(mplace, i as u64)?;
+                            src_field.into()
+                        }
+                        Err(..) => {
+                            let src_field_layout = src.layout.field(&self, i)?;
+                            // this must be a field covering the entire thing
+                            assert_eq!(src.layout.fields.offset(i).bytes(), 0);
+                            assert_eq!(src_field_layout.size, src.layout.size);
+                            // just sawp out the layout
+                            OpTy { op: src.op, layout: src_field_layout }
+                        }
+                    };
+                    if src_field.layout.ty == dst_field.layout.ty {
+                        self.copy_op(src_field, dst_field)?;
+                    } else {
+                        self.unsize_into(src_field, dst_field)?;
+                    }
+                }
+                Ok(())
+            }
+            _ => {
+                bug!(
+                    "unsize_into: invalid conversion: {:?} -> {:?}",
+                    src.layout,
+                    dest.layout
+                )
+            }
+        }
+    }
 }
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
deleted file mode 100644 (file)
index dd298d9..0000000
+++ /dev/null
@@ -1,577 +0,0 @@
-use std::fmt;
-use std::error::Error;
-
-use rustc::hir;
-use rustc::mir::interpret::{ConstEvalErr, ScalarMaybeUndef};
-use rustc::mir;
-use rustc::ty::{self, TyCtxt, Ty, Instance};
-use rustc::ty::layout::{self, LayoutOf, Primitive, TyLayout};
-use rustc::ty::subst::Subst;
-use rustc_data_structures::indexed_vec::IndexVec;
-
-use syntax::ast::Mutability;
-use syntax::source_map::Span;
-use syntax::source_map::DUMMY_SP;
-
-use rustc::mir::interpret::{
-    EvalResult, EvalError, EvalErrorKind, GlobalId,
-    Value, Scalar, AllocId, Allocation, ConstValue,
-};
-use super::{Place, EvalContext, StackPopCleanup, ValTy, Memory, MemoryKind};
-
-pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    instance: Instance<'tcx>,
-    mir: &'mir mir::Mir<'tcx>,
-    span: Span,
-) -> EvalResult<'tcx, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>> {
-    debug!("mk_borrowck_eval_cx: {:?}", instance);
-    let param_env = tcx.param_env(instance.def_id());
-    let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ());
-    // insert a stack frame so any queries have the correct substs
-    ecx.stack.push(super::eval_context::Frame {
-        block: mir::START_BLOCK,
-        locals: IndexVec::new(),
-        instance,
-        span,
-        mir,
-        return_place: Place::undef(),
-        return_to_block: StackPopCleanup::None,
-        stmt: 0,
-    });
-    Ok(ecx)
-}
-
-pub fn mk_eval_cx<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    instance: Instance<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-) -> EvalResult<'tcx, EvalContext<'a, 'tcx, 'tcx, CompileTimeEvaluator>> {
-    debug!("mk_eval_cx: {:?}, {:?}", instance, param_env);
-    let span = tcx.def_span(instance.def_id());
-    let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ());
-    let mir = ecx.load_mir(instance.def)?;
-    // insert a stack frame so any queries have the correct substs
-    ecx.push_stack_frame(
-        instance,
-        mir.span,
-        mir,
-        Place::undef(),
-        StackPopCleanup::None,
-    )?;
-    Ok(ecx)
-}
-
-pub fn eval_promoted<'a, 'mir, 'tcx>(
-    ecx: &mut EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>,
-    cid: GlobalId<'tcx>,
-    mir: &'mir mir::Mir<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-) -> EvalResult<'tcx, (Value, Scalar, TyLayout<'tcx>)> {
-    ecx.with_fresh_body(|ecx| {
-        eval_body_using_ecx(ecx, cid, Some(mir), param_env)
-    })
-}
-
-pub fn value_to_const_value<'tcx>(
-    ecx: &EvalContext<'_, '_, 'tcx, CompileTimeEvaluator>,
-    val: Value,
-    layout: TyLayout<'tcx>,
-) -> EvalResult<'tcx, &'tcx ty::Const<'tcx>> {
-    match (val, &layout.abi) {
-        (Value::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits { size: 0, ..})), _) if layout.is_zst() => {},
-        (Value::ByRef(..), _) |
-        (Value::Scalar(_), &layout::Abi::Scalar(_)) |
-        (Value::ScalarPair(..), &layout::Abi::ScalarPair(..)) => {},
-        _ => bug!("bad value/layout combo: {:#?}, {:#?}", val, layout),
-    }
-    let val = match val {
-        Value::Scalar(val) => ConstValue::Scalar(val.unwrap_or_err()?),
-        Value::ScalarPair(a, b) => ConstValue::ScalarPair(a.unwrap_or_err()?, b),
-        Value::ByRef(ptr, align) => {
-            let ptr = ptr.to_ptr().unwrap();
-            let alloc = ecx.memory.get(ptr.alloc_id)?;
-            assert!(alloc.align.abi() >= align.abi());
-            assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= layout.size.bytes());
-            let mut alloc = alloc.clone();
-            alloc.align = align;
-            let alloc = ecx.tcx.intern_const_alloc(alloc);
-            ConstValue::ByRef(alloc, ptr.offset)
-        }
-    };
-    Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, layout.ty))
-}
-
-fn eval_body_and_ecx<'a, 'mir, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    cid: GlobalId<'tcx>,
-    mir: Option<&'mir mir::Mir<'tcx>>,
-    param_env: ty::ParamEnv<'tcx>,
-) -> (EvalResult<'tcx, (Value, Scalar, TyLayout<'tcx>)>, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>) {
-    debug!("eval_body_and_ecx: {:?}, {:?}", cid, param_env);
-    // we start out with the best span we have
-    // and try improving it down the road when more information is available
-    let span = tcx.def_span(cid.instance.def_id());
-    let span = mir.map(|mir| mir.span).unwrap_or(span);
-    let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ());
-    let r = eval_body_using_ecx(&mut ecx, cid, mir, param_env);
-    (r, ecx)
-}
-
-fn eval_body_using_ecx<'a, 'mir, 'tcx>(
-    ecx: &mut EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>,
-    cid: GlobalId<'tcx>,
-    mir: Option<&'mir mir::Mir<'tcx>>,
-    param_env: ty::ParamEnv<'tcx>,
-) -> EvalResult<'tcx, (Value, Scalar, TyLayout<'tcx>)> {
-    debug!("eval_body: {:?}, {:?}", cid, param_env);
-    let tcx = ecx.tcx.tcx;
-    let mut mir = match mir {
-        Some(mir) => mir,
-        None => ecx.load_mir(cid.instance.def)?,
-    };
-    if let Some(index) = cid.promoted {
-        mir = &mir.promoted[index];
-    }
-    let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
-    assert!(!layout.is_unsized());
-    let ptr = ecx.memory.allocate(
-        layout.size,
-        layout.align,
-        MemoryKind::Stack,
-    )?;
-    let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span);
-    let is_static = tcx.is_static(cid.instance.def_id());
-    let mutability = if is_static == Some(hir::Mutability::MutMutable) || internally_mutable {
-        Mutability::Mutable
-    } else {
-        Mutability::Immutable
-    };
-    let cleanup = StackPopCleanup::MarkStatic(mutability);
-    let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id()));
-    let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
-    trace!("const_eval: pushing stack frame for global: {}{}", name, prom);
-    assert!(mir.arg_count == 0);
-    ecx.push_stack_frame(
-        cid.instance,
-        mir.span,
-        mir,
-        Place::from_ptr(ptr, layout.align),
-        cleanup,
-    )?;
-
-    while ecx.step()? {}
-    let ptr = ptr.into();
-    // always try to read the value and report errors
-    let value = match ecx.try_read_value(ptr, layout.align, layout.ty)? {
-        Some(val) if is_static.is_none() && cid.promoted.is_none() => val,
-        // point at the allocation
-        _ => Value::ByRef(ptr, layout.align),
-    };
-    Ok((value, ptr, layout))
-}
-
-#[derive(Debug, Clone, Eq, PartialEq, Hash)]
-pub struct CompileTimeEvaluator;
-
-impl<'tcx> Into<EvalError<'tcx>> for ConstEvalError {
-    fn into(self) -> EvalError<'tcx> {
-        EvalErrorKind::MachineError(self.to_string()).into()
-    }
-}
-
-#[derive(Clone, Debug)]
-enum ConstEvalError {
-    NeedsRfc(String),
-    NotConst(String),
-}
-
-impl fmt::Display for ConstEvalError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        use self::ConstEvalError::*;
-        match *self {
-            NeedsRfc(ref msg) => {
-                write!(
-                    f,
-                    "\"{}\" needs an rfc before being allowed inside constants",
-                    msg
-                )
-            }
-            NotConst(ref msg) => write!(f, "{}", msg),
-        }
-    }
-}
-
-impl Error for ConstEvalError {
-    fn description(&self) -> &str {
-        use self::ConstEvalError::*;
-        match *self {
-            NeedsRfc(_) => "this feature needs an rfc before being allowed inside constants",
-            NotConst(_) => "this feature is not compatible with constant evaluation",
-        }
-    }
-
-    fn cause(&self) -> Option<&dyn Error> {
-        None
-    }
-}
-
-impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator {
-    type MemoryData = ();
-    type MemoryKinds = !;
-    fn eval_fn_call<'a>(
-        ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
-        instance: ty::Instance<'tcx>,
-        destination: Option<(Place, mir::BasicBlock)>,
-        args: &[ValTy<'tcx>],
-        span: Span,
-        sig: ty::FnSig<'tcx>,
-    ) -> EvalResult<'tcx, bool> {
-        debug!("eval_fn_call: {:?}", instance);
-        if !ecx.tcx.is_const_fn(instance.def_id()) {
-            let def_id = instance.def_id();
-            let (op, oflo) = if let Some(op) = ecx.tcx.is_binop_lang_item(def_id) {
-                op
-            } else {
-                return Err(
-                    ConstEvalError::NotConst(format!("calling non-const fn `{}`", instance)).into(),
-                );
-            };
-            let (dest, bb) = destination.expect("128 lowerings can't diverge");
-            let dest_ty = sig.output();
-            if oflo {
-                ecx.intrinsic_with_overflow(op, args[0], args[1], dest, dest_ty)?;
-            } else {
-                ecx.intrinsic_overflowing(op, args[0], args[1], dest, dest_ty)?;
-            }
-            ecx.goto_block(bb);
-            return Ok(true);
-        }
-        let mir = match ecx.load_mir(instance.def) {
-            Ok(mir) => mir,
-            Err(err) => {
-                if let EvalErrorKind::NoMirFor(ref path) = err.kind {
-                    return Err(
-                        ConstEvalError::NeedsRfc(format!("calling extern function `{}`", path))
-                            .into(),
-                    );
-                }
-                return Err(err);
-            }
-        };
-        let (return_place, return_to_block) = match destination {
-            Some((place, block)) => (place, StackPopCleanup::Goto(block)),
-            None => (Place::undef(), StackPopCleanup::None),
-        };
-
-        ecx.push_stack_frame(
-            instance,
-            span,
-            mir,
-            return_place,
-            return_to_block,
-        )?;
-
-        Ok(false)
-    }
-
-
-    fn call_intrinsic<'a>(
-        ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
-        instance: ty::Instance<'tcx>,
-        args: &[ValTy<'tcx>],
-        dest: Place,
-        dest_layout: layout::TyLayout<'tcx>,
-        target: mir::BasicBlock,
-    ) -> EvalResult<'tcx> {
-        let substs = instance.substs;
-
-        let intrinsic_name = &ecx.tcx.item_name(instance.def_id()).as_str()[..];
-        match intrinsic_name {
-            "min_align_of" => {
-                let elem_ty = substs.type_at(0);
-                let elem_align = ecx.layout_of(elem_ty)?.align.abi();
-                let align_val = Scalar::Bits {
-                    bits: elem_align as u128,
-                    size: dest_layout.size.bytes() as u8,
-                };
-                ecx.write_scalar(dest, align_val, dest_layout.ty)?;
-            }
-
-            "size_of" => {
-                let ty = substs.type_at(0);
-                let size = ecx.layout_of(ty)?.size.bytes() as u128;
-                let size_val = Scalar::Bits {
-                    bits: size,
-                    size: dest_layout.size.bytes() as u8,
-                };
-                ecx.write_scalar(dest, size_val, dest_layout.ty)?;
-            }
-
-            "type_id" => {
-                let ty = substs.type_at(0);
-                let type_id = ecx.tcx.type_id_hash(ty) as u128;
-                let id_val = Scalar::Bits {
-                    bits: type_id,
-                    size: dest_layout.size.bytes() as u8,
-                };
-                ecx.write_scalar(dest, id_val, dest_layout.ty)?;
-            }
-            "ctpop" | "cttz" | "cttz_nonzero" | "ctlz" | "ctlz_nonzero" | "bswap" => {
-                let ty = substs.type_at(0);
-                let layout_of = ecx.layout_of(ty)?;
-                let bits = ecx.value_to_scalar(args[0])?.to_bits(layout_of.size)?;
-                let kind = match layout_of.abi {
-                    ty::layout::Abi::Scalar(ref scalar) => scalar.value,
-                    _ => Err(::rustc::mir::interpret::EvalErrorKind::TypeNotPrimitive(ty))?,
-                };
-                let out_val = if intrinsic_name.ends_with("_nonzero") {
-                    if bits == 0 {
-                        return err!(Intrinsic(format!("{} called on 0", intrinsic_name)));
-                    }
-                    numeric_intrinsic(intrinsic_name.trim_right_matches("_nonzero"), bits, kind)?
-                } else {
-                    numeric_intrinsic(intrinsic_name, bits, kind)?
-                };
-                ecx.write_scalar(dest, out_val, ty)?;
-            }
-
-            name => return Err(
-                ConstEvalError::NeedsRfc(format!("calling intrinsic `{}`", name)).into()
-            ),
-        }
-
-        ecx.goto_block(target);
-
-        // Since we pushed no stack frame, the main loop will act
-        // as if the call just completed and it's returning to the
-        // current frame.
-        Ok(())
-    }
-
-    fn try_ptr_op<'a>(
-        _ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
-        _bin_op: mir::BinOp,
-        left: Scalar,
-        _left_ty: Ty<'tcx>,
-        right: Scalar,
-        _right_ty: Ty<'tcx>,
-    ) -> EvalResult<'tcx, Option<(Scalar, bool)>> {
-        if left.is_bits() && right.is_bits() {
-            Ok(None)
-        } else {
-            Err(
-                ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into(),
-            )
-        }
-    }
-
-    fn mark_static_initialized<'a>(
-        _mem: &mut Memory<'a, 'mir, 'tcx, Self>,
-        _id: AllocId,
-        _mutability: Mutability,
-    ) -> EvalResult<'tcx, bool> {
-        Ok(false)
-    }
-
-    fn init_static<'a>(
-        ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
-        cid: GlobalId<'tcx>,
-    ) -> EvalResult<'tcx, AllocId> {
-        Ok(ecx
-            .tcx
-            .alloc_map
-            .lock()
-            .intern_static(cid.instance.def_id()))
-    }
-
-    fn box_alloc<'a>(
-        _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
-        _ty: Ty<'tcx>,
-        _dest: Place,
-    ) -> EvalResult<'tcx> {
-        Err(
-            ConstEvalError::NeedsRfc("heap allocations via `box` keyword".to_string()).into(),
-        )
-    }
-
-    fn global_item_with_linkage<'a>(
-        _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
-        _instance: ty::Instance<'tcx>,
-        _mutability: Mutability,
-    ) -> EvalResult<'tcx> {
-        Err(
-            ConstEvalError::NotConst("statics with `linkage` attribute".to_string()).into(),
-        )
-    }
-}
-
-pub fn const_val_field<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    instance: ty::Instance<'tcx>,
-    variant: Option<usize>,
-    field: mir::Field,
-    value: &'tcx ty::Const<'tcx>,
-) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
-    trace!("const_val_field: {:?}, {:?}, {:?}", instance, field, value);
-    let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
-    let result = (|| {
-        let ty = value.ty;
-        let value = ecx.const_to_value(value.val)?;
-        let layout = ecx.layout_of(ty)?;
-        let place = ecx.allocate_place_for_value(value, layout, variant)?;
-        let (place, layout) = ecx.place_field(place, field, layout)?;
-        let (ptr, align) = place.to_ptr_align();
-        let mut new_value = Value::ByRef(ptr.unwrap_or_err()?, align);
-        new_value = ecx.try_read_by_ref(new_value, layout.ty)?;
-        use rustc_data_structures::indexed_vec::Idx;
-        match (value, new_value) {
-            (Value::Scalar(_), Value::ByRef(..)) |
-            (Value::ScalarPair(..), Value::ByRef(..)) |
-            (Value::Scalar(_), Value::ScalarPair(..)) => bug!(
-                "field {} of {:?} yielded {:?}",
-                field.index(),
-                value,
-                new_value,
-            ),
-            _ => {},
-        }
-        value_to_const_value(&ecx, new_value, layout)
-    })();
-    result.map_err(|err| {
-        let (trace, span) = ecx.generate_stacktrace(None);
-        ConstEvalErr {
-            error: err,
-            stacktrace: trace,
-            span,
-        }.into()
-    })
-}
-
-pub fn const_variant_index<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    instance: ty::Instance<'tcx>,
-    val: &'tcx ty::Const<'tcx>,
-) -> EvalResult<'tcx, usize> {
-    trace!("const_variant_index: {:?}, {:?}", instance, val);
-    let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
-    let value = ecx.const_to_value(val.val)?;
-    let layout = ecx.layout_of(val.ty)?;
-    let (ptr, align) = match value {
-        Value::ScalarPair(..) | Value::Scalar(_) => {
-            let ptr = ecx.memory.allocate(layout.size, layout.align, MemoryKind::Stack)?.into();
-            ecx.write_value_to_ptr(value, ptr, layout.align, val.ty)?;
-            (ptr, layout.align)
-        },
-        Value::ByRef(ptr, align) => (ptr, align),
-    };
-    let place = Place::from_scalar_ptr(ptr.into(), align);
-    ecx.read_discriminant_as_variant_index(place, layout)
-}
-
-pub fn const_value_to_allocation_provider<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    val: &'tcx ty::Const<'tcx>,
-) -> &'tcx Allocation {
-    match val.val {
-        ConstValue::ByRef(alloc, offset) => {
-            assert_eq!(offset.bytes(), 0);
-            return alloc;
-        },
-        _ => ()
-    }
-    let result = || -> EvalResult<'tcx, &'tcx Allocation> {
-        let mut ecx = EvalContext::new(
-            tcx.at(DUMMY_SP),
-            ty::ParamEnv::reveal_all(),
-            CompileTimeEvaluator,
-            ());
-        let value = ecx.const_to_value(val.val)?;
-        let layout = ecx.layout_of(val.ty)?;
-        let ptr = ecx.memory.allocate(layout.size, layout.align, MemoryKind::Stack)?;
-        ecx.write_value_to_ptr(value, ptr.into(), layout.align, val.ty)?;
-        let alloc = ecx.memory.get(ptr.alloc_id)?;
-        Ok(tcx.intern_const_alloc(alloc.clone()))
-    };
-    result().expect("unable to convert ConstValue to Allocation")
-}
-
-pub fn const_eval_provider<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
-) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
-    trace!("const eval: {:?}", key);
-    let cid = key.value;
-    let def_id = cid.instance.def.def_id();
-
-    if let Some(id) = tcx.hir.as_local_node_id(def_id) {
-        let tables = tcx.typeck_tables_of(def_id);
-        let span = tcx.def_span(def_id);
-
-        // Do match-check before building MIR
-        if tcx.check_match(def_id).is_err() {
-            return Err(ConstEvalErr {
-                error: EvalErrorKind::CheckMatchError.into(),
-                stacktrace: vec![],
-                span,
-            }.into());
-        }
-
-        if let hir::BodyOwnerKind::Const = tcx.hir.body_owner_kind(id) {
-            tcx.mir_const_qualif(def_id);
-        }
-
-        // Do not continue into miri if typeck errors occurred; it will fail horribly
-        if tables.tainted_by_errors {
-            return Err(ConstEvalErr {
-                error: EvalErrorKind::CheckMatchError.into(),
-                stacktrace: vec![],
-                span,
-            }.into());
-        }
-    };
-
-    let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env);
-    res.and_then(|(mut val, _, layout)| {
-        if tcx.is_static(def_id).is_none() && cid.promoted.is_none() {
-            val = ecx.try_read_by_ref(val, layout.ty)?;
-        }
-        value_to_const_value(&ecx, val, layout)
-    }).map_err(|err| {
-        let (trace, span) = ecx.generate_stacktrace(None);
-        let err = ConstEvalErr {
-            error: err,
-            stacktrace: trace,
-            span,
-        };
-        if tcx.is_static(def_id).is_some() {
-            err.report_as_error(ecx.tcx, "could not evaluate static initializer");
-            if tcx.sess.err_count() == 0 {
-                span_bug!(span, "static eval failure didn't emit an error: {:#?}", err);
-            }
-        }
-        err.into()
-    })
-}
-
-fn numeric_intrinsic<'tcx>(
-    name: &str,
-    bits: u128,
-    kind: Primitive,
-) -> EvalResult<'tcx, Scalar> {
-    let size = match kind {
-        Primitive::Int(integer, _) => integer.size(),
-        _ => bug!("invalid `{}` argument: {:?}", name, bits),
-    };
-    let extra = 128 - size.bits() as u128;
-    let bits_out = match name {
-        "ctpop" => bits.count_ones() as u128,
-        "ctlz" => bits.leading_zeros() as u128 - extra,
-        "cttz" => (bits << extra).trailing_zeros() as u128 - extra,
-        "bswap" => (bits << extra).swap_bytes(),
-        _ => bug!("not a numeric intrinsic: {}", name),
-    };
-    Ok(Scalar::Bits { bits: bits_out, size: size.bytes() as u8 })
-}
index 3329a47759beae867f48b12c0f85132d82a14e75..6e144ba7ed2ee7627e74d0b9fd87f5518127f916 100644 (file)
@@ -1,3 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
 use std::fmt::Write;
 use std::hash::{Hash, Hasher};
 use std::mem;
 use rustc::hir::def::Def;
 use rustc::hir::map::definitions::DefPathData;
 use rustc::mir;
-use rustc::ty::layout::{self, Size, Align, HasDataLayout, IntegerExt, LayoutOf, TyLayout, Primitive};
+use rustc::ty::layout::{
+    self, Size, Align, HasDataLayout, LayoutOf, TyLayout
+};
 use rustc::ty::subst::{Subst, Substs};
-use rustc::ty::{self, Ty, TyCtxt, TypeAndMut};
+use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::query::TyCtxtAt;
 use rustc_data_structures::fx::{FxHashSet, FxHasher};
-use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::mir::interpret::{
-    GlobalId, Value, Scalar, FrameInfo, AllocType,
-    EvalResult, EvalErrorKind, Pointer, ConstValue,
+    GlobalId, Scalar, FrameInfo,
+    EvalResult, EvalErrorKind,
     ScalarMaybeUndef,
+    truncate, sign_extend,
 };
 
 use syntax::source_map::{self, Span};
-use syntax::ast::Mutability;
-
-use super::{Place, PlaceExtra, Memory,
-            HasMemory, MemoryKind,
-            Machine};
 
-macro_rules! validation_failure{
-    ($what:expr, $where:expr, $details:expr) => {{
-        let where_ = if $where.is_empty() {
-            String::new()
-        } else {
-            format!(" at {}", $where)
-        };
-        err!(ValidationFailure(format!(
-            "encountered {}{}, but expected {}",
-            $what, where_, $details,
-        )))
-    }};
-    ($what:expr, $where:expr) => {{
-        let where_ = if $where.is_empty() {
-            String::new()
-        } else {
-            format!(" at {}", $where)
-        };
-        err!(ValidationFailure(format!(
-            "encountered {}{}",
-            $what, where_,
-        )))
-    }};
-}
+use super::{
+    Value, Operand, MemPlace, MPlaceTy, Place,
+    Memory, Machine
+};
 
 pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
     /// Stores the `Machine` instance.
@@ -67,15 +55,15 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
     pub(crate) stack: Vec<Frame<'mir, 'tcx>>,
 
     /// The maximum number of stack frames allowed
-    pub(crate) stack_limit: usize,
+    pub(super) stack_limit: usize,
 
     /// When this value is negative, it indicates the number of interpreter
     /// steps *until* the loop detector is enabled. When it is positive, it is
     /// the number of steps after the detector has been enabled modulo the loop
     /// detector period.
-    pub(crate) steps_since_detector_enabled: isize,
+    pub(super) steps_since_detector_enabled: isize,
 
-    pub(crate) loop_detector: InfiniteLoopDetector<'a, 'mir, 'tcx, M>,
+    pub(super) loop_detector: InfiniteLoopDetector<'a, 'mir, 'tcx, M>,
 }
 
 /// A stack frame.
@@ -96,14 +84,15 @@ pub struct Frame<'mir, 'tcx: 'mir> {
     ////////////////////////////////////////////////////////////////////////////////
     // Return place and locals
     ////////////////////////////////////////////////////////////////////////////////
-    /// The block to return to when returning from the current stack frame
+    /// Work to perform when returning from this function
     pub return_to_block: StackPopCleanup,
 
     /// The location where the result of the current stack frame should be written to.
     pub return_place: Place,
 
     /// The list of locals for this stack frame, stored in order as
-    /// `[return_ptr, arguments..., variables..., temporaries...]`. The locals are stored as `Option<Value>`s.
+    /// `[return_ptr, arguments..., variables..., temporaries...]`.
+    /// The locals are stored as `Option<Value>`s.
     /// `None` represents a local that is currently dead, while a live local
     /// can either directly contain `Scalar` or refer to some part of an `Allocation`.
     pub locals: IndexVec<mir::Local, LocalValue>,
@@ -119,21 +108,6 @@ pub struct Frame<'mir, 'tcx: 'mir> {
     pub stmt: usize,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub enum LocalValue {
-    Dead,
-    Live(Value),
-}
-
-impl LocalValue {
-    pub fn access(self) -> EvalResult<'static, Value> {
-        match self {
-            LocalValue::Dead => err!(DeadLocal),
-            LocalValue::Live(val) => Ok(val),
-        }
-    }
-}
-
 impl<'mir, 'tcx: 'mir> Eq for Frame<'mir, 'tcx> {}
 
 impl<'mir, 'tcx: 'mir> PartialEq for Frame<'mir, 'tcx> {
@@ -182,11 +156,50 @@ fn hash<H: Hasher>(&self, state: &mut H) {
     }
 }
 
+#[derive(Clone, Debug, Eq, PartialEq, Hash)]
+pub enum StackPopCleanup {
+    /// Jump to the next block in the caller, or cause UB if None (that's a function
+    /// that may never return).
+    Goto(Option<mir::BasicBlock>),
+    /// Just do nohing: Used by Main and for the box_alloc hook in miri.
+    /// `cleanup` says whether locals are deallocated.  Static computation
+    /// wants them leaked to intern what they need (and just throw away
+    /// the entire `ecx` when it is done).
+    None { cleanup: bool },
+}
+
+// State of a local variable
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+pub enum LocalValue {
+    Dead,
+    // Mostly for convenience, we re-use the `Operand` type here.
+    // This is an optimization over just always having a pointer here;
+    // we can thus avoid doing an allocation when the local just stores
+    // immediate values *and* never has its address taken.
+    Live(Operand),
+}
+
+impl<'tcx> LocalValue {
+    pub fn access(&self) -> EvalResult<'tcx, &Operand> {
+        match self {
+            LocalValue::Dead => err!(DeadLocal),
+            LocalValue::Live(ref val) => Ok(val),
+        }
+    }
+
+    pub fn access_mut(&mut self) -> EvalResult<'tcx, &mut Operand> {
+        match self {
+            LocalValue::Dead => err!(DeadLocal),
+            LocalValue::Live(ref mut val) => Ok(val),
+        }
+    }
+}
+
 /// The virtual machine state during const-evaluation at a given point in time.
 type EvalSnapshot<'a, 'mir, 'tcx, M>
     = (M, Vec<Frame<'mir, 'tcx>>, Memory<'a, 'mir, 'tcx, M>);
 
-pub(crate) struct InfiniteLoopDetector<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
+pub(super) struct InfiniteLoopDetector<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
     /// The set of all `EvalSnapshot` *hashes* observed by this detector.
     ///
     /// When a collision occurs in this table, we store the full snapshot in
@@ -249,39 +262,6 @@ pub fn observe_and_analyze(
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq, Hash)]
-pub enum StackPopCleanup {
-    /// The stackframe existed to compute the initial value of a static/constant, make sure it
-    /// isn't modifyable afterwards in case of constants.
-    /// In case of `static mut`, mark the memory to ensure it's never marked as immutable through
-    /// references or deallocated
-    MarkStatic(Mutability),
-    /// A regular stackframe added due to a function call will need to get forwarded to the next
-    /// block
-    Goto(mir::BasicBlock),
-    /// The main function and diverging functions have nowhere to return to
-    None,
-}
-
-#[derive(Copy, Clone, Debug)]
-pub struct TyAndPacked<'tcx> {
-    pub ty: Ty<'tcx>,
-    pub packed: bool,
-}
-
-#[derive(Copy, Clone, Debug)]
-pub struct ValTy<'tcx> {
-    pub value: Value,
-    pub ty: Ty<'tcx>,
-}
-
-impl<'tcx> ::std::ops::Deref for ValTy<'tcx> {
-    type Target = Value;
-    fn deref(&self) -> &Value {
-        &self.value
-    }
-}
-
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for &'a EvalContext<'a, 'mir, 'tcx, M> {
     #[inline]
     fn data_layout(&self) -> &layout::TargetDataLayout {
@@ -290,14 +270,17 @@ fn data_layout(&self) -> &layout::TargetDataLayout {
 }
 
 impl<'c, 'b, 'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout
-    for &'c &'b mut EvalContext<'a, 'mir, 'tcx, M> {
+    for &'c &'b mut EvalContext<'a, 'mir, 'tcx, M>
+{
     #[inline]
     fn data_layout(&self) -> &layout::TargetDataLayout {
         &self.tcx.data_layout
     }
 }
 
-impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> layout::HasTyCtxt<'tcx> for &'a EvalContext<'a, 'mir, 'tcx, M> {
+impl<'a, 'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for &'a EvalContext<'a, 'mir, 'tcx, M>
+    where M: Machine<'mir, 'tcx>
+{
     #[inline]
     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
         *self.tcx
@@ -316,6 +299,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for &'a EvalContext<'a, 'm
     type Ty = Ty<'tcx>;
     type TyLayout = EvalResult<'tcx, TyLayout<'tcx>>;
 
+    #[inline]
     fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
         self.tcx.layout_of(self.param_env.and(ty))
             .map_err(|layout| EvalErrorKind::Layout(layout).into())
@@ -356,19 +340,14 @@ pub fn new(
 
     pub(crate) fn with_fresh_body<F: FnOnce(&mut Self) -> R, R>(&mut self, f: F) -> R {
         let stack = mem::replace(&mut self.stack, Vec::new());
-        let steps = mem::replace(&mut self.steps_since_detector_enabled, -STEPS_UNTIL_DETECTOR_ENABLED);
+        let steps = mem::replace(&mut self.steps_since_detector_enabled,
+                                 -STEPS_UNTIL_DETECTOR_ENABLED);
         let r = f(self);
         self.stack = stack;
         self.steps_since_detector_enabled = steps;
         r
     }
 
-    pub fn alloc_ptr(&mut self, layout: TyLayout<'tcx>) -> EvalResult<'tcx, Pointer> {
-        assert!(!layout.is_unsized(), "cannot alloc memory for unsized type");
-
-        self.memory.allocate(layout.size, layout.align, MemoryKind::Stack)
-    }
-
     pub fn memory(&self) -> &Memory<'a, 'mir, 'tcx, M> {
         &self.memory
     }
@@ -387,34 +366,35 @@ pub fn cur_frame(&self) -> usize {
         self.stack.len() - 1
     }
 
-    pub fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
-        let ptr = self.memory.allocate_bytes(s.as_bytes());
-        Ok(Scalar::Ptr(ptr).to_value_with_len(s.len() as u64, self.tcx.tcx))
+    /// Mark a storage as live, killing the previous content and returning it.
+    /// Remember to deallocate that!
+    pub fn storage_live(&mut self, local: mir::Local) -> EvalResult<'tcx, LocalValue> {
+        trace!("{:?} is now live", local);
+
+        let layout = self.layout_of_local(self.cur_frame(), local)?;
+        let init = LocalValue::Live(self.uninit_operand(layout)?);
+        // StorageLive *always* kills the value that's currently stored
+        Ok(mem::replace(&mut self.frame_mut().locals[local], init))
     }
 
-    pub fn const_to_value(
-        &mut self,
-        val: ConstValue<'tcx>,
-    ) -> EvalResult<'tcx, Value> {
-        match val {
-            ConstValue::Unevaluated(def_id, substs) => {
-                let instance = self.resolve(def_id, substs)?;
-                self.read_global_as_value(GlobalId {
-                    instance,
-                    promoted: None,
-                })
-            }
-            ConstValue::ByRef(alloc, offset) => {
-                // FIXME: Allocate new AllocId for all constants inside
-                let id = self.memory.allocate_value(alloc.clone(), MemoryKind::Stack)?;
-                Ok(Value::ByRef(Pointer::new(id, offset).into(), alloc.align))
-            },
-            ConstValue::ScalarPair(a, b) => Ok(Value::ScalarPair(a.into(), b.into())),
-            ConstValue::Scalar(val) => Ok(Value::Scalar(val.into())),
-        }
+    /// Returns the old value of the local.
+    /// Remember to deallocate that!
+    pub fn storage_dead(&mut self, local: mir::Local) -> LocalValue {
+        trace!("{:?} is now dead", local);
+
+        mem::replace(&mut self.frame_mut().locals[local], LocalValue::Dead)
+    }
+
+    pub fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
+        let ptr = self.memory.allocate_static_bytes(s.as_bytes());
+        Ok(Value::new_slice(Scalar::Ptr(ptr), s.len() as u64, self.tcx.tcx))
     }
 
-    pub(super) fn resolve(&self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> EvalResult<'tcx, ty::Instance<'tcx>> {
+    pub(super) fn resolve(
+        &self,
+        def_id: DefId,
+        substs: &'tcx Substs<'tcx>
+    ) -> EvalResult<'tcx, ty::Instance<'tcx>> {
         trace!("resolve: {:?}, {:#?}", def_id, substs);
         trace!("substs: {:#?}", self.substs());
         trace!("param_env: {:#?}", self.param_env);
@@ -441,7 +421,10 @@ pub fn load_mir(
     ) -> EvalResult<'tcx, &'tcx mir::Mir<'tcx>> {
         // do not continue if typeck errors occurred (can only occur in local crate)
         let did = instance.def_id();
-        if did.is_local() && self.tcx.has_typeck_tables(did) && self.tcx.typeck_tables_of(did).tainted_by_errors {
+        if did.is_local()
+            && self.tcx.has_typeck_tables(did)
+            && self.tcx.typeck_tables_of(did).tainted_by_errors
+        {
             return err!(TypeckError);
         }
         trace!("load mir {:?}", instance);
@@ -455,92 +438,119 @@ pub fn load_mir(
         }
     }
 
-    pub fn monomorphize(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
+    pub fn monomorphize<T: TypeFoldable<'tcx> + Subst<'tcx>>(
+        &self,
+        t: T,
+        substs: &'tcx Substs<'tcx>
+    ) -> T {
         // miri doesn't care about lifetimes, and will choke on some crazy ones
         // let's simply get rid of them
-        let substituted = ty.subst(*self.tcx, substs);
+        let substituted = t.subst(*self.tcx, substs);
         self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substituted)
     }
 
-    /// Return the size and aligment of the value at the given type.
-    /// Note that the value does not matter if the type is sized. For unsized types,
-    /// the value has to be a fat pointer, and we only care about the "extra" data in it.
-    pub fn size_and_align_of_dst(
+    pub fn layout_of_local(
+        &self,
+        frame: usize,
+        local: mir::Local
+    ) -> EvalResult<'tcx, TyLayout<'tcx>> {
+        let local_ty = self.stack[frame].mir.local_decls[local].ty;
+        let local_ty = self.monomorphize(
+            local_ty,
+            self.stack[frame].instance.substs
+        );
+        self.layout_of(local_ty)
+    }
+
+    /// Return the actual dynamic size and alignment of the place at the given type.
+    /// Only the "extra" (metadata) part of the place matters.
+    pub(super) fn size_and_align_of(
         &self,
-        ty: Ty<'tcx>,
-        value: Value,
+        metadata: Option<Scalar>,
+        layout: TyLayout<'tcx>,
     ) -> EvalResult<'tcx, (Size, Align)> {
-        let layout = self.layout_of(ty)?;
-        if !layout.is_unsized() {
-            Ok(layout.size_and_align())
-        } else {
-            match ty.sty {
-                ty::TyAdt(..) | ty::TyTuple(..) => {
-                    // First get the size of all statically known fields.
-                    // Don't use type_of::sizing_type_of because that expects t to be sized,
-                    // and it also rounds up to alignment, which we want to avoid,
-                    // as the unsized field's alignment could be smaller.
-                    assert!(!ty.is_simd());
-                    debug!("DST {} layout: {:?}", ty, layout);
-
-                    let sized_size = layout.fields.offset(layout.fields.count() - 1);
-                    let sized_align = layout.align;
-                    debug!(
-                        "DST {} statically sized prefix size: {:?} align: {:?}",
-                        ty,
-                        sized_size,
-                        sized_align
-                    );
-
-                    // Recurse to get the size of the dynamically sized field (must be
-                    // the last field).
-                    let field_ty = layout.field(self, layout.fields.count() - 1)?.ty;
-                    let (unsized_size, unsized_align) =
-                        self.size_and_align_of_dst(field_ty, value)?;
-
-                    // FIXME (#26403, #27023): We should be adding padding
-                    // to `sized_size` (to accommodate the `unsized_align`
-                    // required of the unsized field that follows) before
-                    // summing it with `sized_size`. (Note that since #26403
-                    // is unfixed, we do not yet add the necessary padding
-                    // here. But this is where the add would go.)
-
-                    // Return the sum of sizes and max of aligns.
-                    let size = sized_size + unsized_size;
-
-                    // Choose max of two known alignments (combined value must
-                    // be aligned according to more restrictive of the two).
-                    let align = sized_align.max(unsized_align);
-
-                    // Issue #27023: must add any necessary padding to `size`
-                    // (to make it a multiple of `align`) before returning it.
-                    //
-                    // Namely, the returned size should be, in C notation:
-                    //
-                    //   `size + ((size & (align-1)) ? align : 0)`
-                    //
-                    // emulated via the semi-standard fast bit trick:
-                    //
-                    //   `(size + (align-1)) & -align`
-
-                    Ok((size.abi_align(align), align))
-                }
-                ty::TyDynamic(..) => {
-                    let (_, vtable) = self.into_ptr_vtable_pair(value)?;
-                    // the second entry in the vtable is the dynamic size of the object.
-                    self.read_size_and_align_from_vtable(vtable)
-                }
+        let metadata = match metadata {
+            None => {
+                assert!(!layout.is_unsized());
+                return Ok(layout.size_and_align())
+            }
+            Some(metadata) => {
+                assert!(layout.is_unsized());
+                metadata
+            }
+        };
+        match layout.ty.sty {
+            ty::Adt(..) | ty::Tuple(..) => {
+                // First get the size of all statically known fields.
+                // Don't use type_of::sizing_type_of because that expects t to be sized,
+                // and it also rounds up to alignment, which we want to avoid,
+                // as the unsized field's alignment could be smaller.
+                assert!(!layout.ty.is_simd());
+                debug!("DST layout: {:?}", layout);
+
+                let sized_size = layout.fields.offset(layout.fields.count() - 1);
+                let sized_align = layout.align;
+                debug!(
+                    "DST {} statically sized prefix size: {:?} align: {:?}",
+                    layout.ty,
+                    sized_size,
+                    sized_align
+                );
 
-                ty::TySlice(_) | ty::TyStr => {
-                    let (elem_size, align) = layout.field(self, 0)?.size_and_align();
-                    let (_, len) = self.into_slice(value)?;
-                    Ok((elem_size * len, align))
-                }
+                // Recurse to get the size of the dynamically sized field (must be
+                // the last field).
+                let field = layout.field(self, layout.fields.count() - 1)?;
+                let (unsized_size, unsized_align) = self.size_and_align_of(Some(metadata), field)?;
+
+                // FIXME (#26403, #27023): We should be adding padding
+                // to `sized_size` (to accommodate the `unsized_align`
+                // required of the unsized field that follows) before
+                // summing it with `sized_size`. (Note that since #26403
+                // is unfixed, we do not yet add the necessary padding
+                // here. But this is where the add would go.)
+
+                // Return the sum of sizes and max of aligns.
+                let size = sized_size + unsized_size;
+
+                // Choose max of two known alignments (combined value must
+                // be aligned according to more restrictive of the two).
+                let align = sized_align.max(unsized_align);
 
-                _ => bug!("size_of_val::<{:?}>", ty),
+                // Issue #27023: must add any necessary padding to `size`
+                // (to make it a multiple of `align`) before returning it.
+                //
+                // Namely, the returned size should be, in C notation:
+                //
+                //   `size + ((size & (align-1)) ? align : 0)`
+                //
+                // emulated via the semi-standard fast bit trick:
+                //
+                //   `(size + (align-1)) & -align`
+
+                Ok((size.abi_align(align), align))
+            }
+            ty::Dynamic(..) => {
+                let vtable = metadata.to_ptr()?;
+                // the second entry in the vtable is the dynamic size of the object.
+                self.read_size_and_align_from_vtable(vtable)
+            }
+
+            ty::Slice(_) | ty::Str => {
+                let len = metadata.to_usize(self)?;
+                let (elem_size, align) = layout.field(self, 0)?.size_and_align();
+                Ok((elem_size * len, align))
             }
+
+            _ => bug!("size_and_align_of::<{:?}> not supported", layout.ty),
         }
     }
+    #[inline]
+    pub fn size_and_align_of_mplace(
+        &self,
+        mplace: MPlaceTy<'tcx>
+    ) -> EvalResult<'tcx, (Size, Align)> {
+        self.size_and_align_of(mplace.extra, mplace.layout)
+    }
 
     pub fn push_stack_frame(
         &mut self,
@@ -568,10 +578,13 @@ pub fn push_stack_frame(
 
         // don't allocate at all for trivial constants
         if mir.local_decls.len() > 1 {
-            let mut locals = IndexVec::from_elem(LocalValue::Dead, &mir.local_decls);
-            for (local, decl) in locals.iter_mut().zip(mir.local_decls.iter()) {
-                *local = LocalValue::Live(self.init_value(decl.ty)?);
-            }
+            // We put some marker value into the locals that we later want to initialize.
+            // This can be anything except for LocalValue::Dead -- because *that* is the
+            // value we use for things that we know are initially dead.
+            let dummy =
+                LocalValue::Live(Operand::Immediate(Value::Scalar(ScalarMaybeUndef::Undef)));
+            let mut locals = IndexVec::from_elem(dummy, &mir.local_decls);
+            // Now mark those locals as dead that we do not want to initialize
             match self.tcx.describe_def(instance.def_id()) {
                 // statics and constants don't have `Storage*` statements, no need to look for them
                 Some(Def::Static(..)) | Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {},
@@ -582,18 +595,32 @@ pub fn push_stack_frame(
                             use rustc::mir::StatementKind::{StorageDead, StorageLive};
                             match stmt.kind {
                                 StorageLive(local) |
-                                StorageDead(local) => locals[local] = LocalValue::Dead,
+                                StorageDead(local) => {
+                                    locals[local] = LocalValue::Dead;
+                                }
                                 _ => {}
                             }
                         }
                     }
                 },
             }
+            // Finally, properly initialize all those that still have the dummy value
+            for (local, decl) in locals.iter_mut().zip(mir.local_decls.iter()) {
+                match *local {
+                    LocalValue::Live(_) => {
+                        // This needs to be peoperly initialized.
+                        let layout = self.layout_of(self.monomorphize(decl.ty, instance.substs))?;
+                        *local = LocalValue::Live(self.uninit_operand(layout)?);
+                    }
+                    LocalValue::Dead => {
+                        // Nothing to do
+                    }
+                }
+            }
+            // done
             self.frame_mut().locals = locals;
         }
 
-        self.memory.cur_frame = self.cur_frame();
-
         if self.stack.len() > self.stack_limit {
             err!(StackFrameLimitReached)
         } else {
@@ -603,28 +630,19 @@ pub fn push_stack_frame(
 
     pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> {
         ::log_settings::settings().indentation -= 1;
-        M::end_region(self, None)?;
         let frame = self.stack.pop().expect(
             "tried to pop a stack frame, but there were none",
         );
-        if !self.stack.is_empty() {
-            // TODO: Is this the correct time to start considering these accesses as originating from the returned-to stack frame?
-            self.memory.cur_frame = self.cur_frame();
-        }
         match frame.return_to_block {
-            StackPopCleanup::MarkStatic(mutable) => {
-                if let Place::Ptr { ptr, .. } = frame.return_place {
-                    // FIXME: to_ptr()? might be too extreme here, static zsts might reach this under certain conditions
-                    self.memory.mark_static_initialized(
-                        ptr.unwrap_or_err()?.to_ptr()?.alloc_id,
-                        mutable,
-                    )?
-                } else {
-                    bug!("StackPopCleanup::MarkStatic on: {:?}", frame.return_place);
+            StackPopCleanup::Goto(block) => {
+                self.goto_block(block)?;
+            }
+            StackPopCleanup::None { cleanup } => {
+                if !cleanup {
+                    // Leak the locals
+                    return Ok(());
                 }
             }
-            StackPopCleanup::Goto(target) => self.goto_block(target),
-            StackPopCleanup::None => {}
         }
         // deallocate all locals that are backed by an allocation
         for local in frame.locals {
@@ -634,9 +652,9 @@ pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> {
         Ok(())
     }
 
-    pub fn deallocate_local(&mut self, local: LocalValue) -> EvalResult<'tcx> {
+    pub(super) fn deallocate_local(&mut self, local: LocalValue) -> EvalResult<'tcx> {
         // FIXME: should we tell the user that there was a local which was never written to?
-        if let LocalValue::Live(Value::ByRef(ptr, _align)) = local {
+        if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
             trace!("deallocating local");
             let ptr = ptr.to_ptr()?;
             self.memory.dump_alloc(ptr.alloc_id);
@@ -645,914 +663,22 @@ pub fn deallocate_local(&mut self, local: LocalValue) -> EvalResult<'tcx> {
         Ok(())
     }
 
-    /// Evaluate an assignment statement.
-    ///
-    /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
-    /// type writes its results directly into the memory specified by the place.
-    pub(super) fn eval_rvalue_into_place(
-        &mut self,
-        rvalue: &mir::Rvalue<'tcx>,
-        place: &mir::Place<'tcx>,
-    ) -> EvalResult<'tcx> {
-        let dest = self.eval_place(place)?;
-        let dest_ty = self.place_ty(place);
-        let dest_layout = self.layout_of(dest_ty)?;
-
-        use rustc::mir::Rvalue::*;
-        match *rvalue {
-            Use(ref operand) => {
-                let value = self.eval_operand(operand)?.value;
-                let valty = ValTy {
-                    value,
-                    ty: dest_ty,
-                };
-                self.write_value(valty, dest)?;
-            }
-
-            BinaryOp(bin_op, ref left, ref right) => {
-                let left = self.eval_operand(left)?;
-                let right = self.eval_operand(right)?;
-                self.intrinsic_overflowing(
-                    bin_op,
-                    left,
-                    right,
-                    dest,
-                    dest_ty,
-                )?;
-            }
-
-            CheckedBinaryOp(bin_op, ref left, ref right) => {
-                let left = self.eval_operand(left)?;
-                let right = self.eval_operand(right)?;
-                self.intrinsic_with_overflow(
-                    bin_op,
-                    left,
-                    right,
-                    dest,
-                    dest_ty,
-                )?;
-            }
-
-            UnaryOp(un_op, ref operand) => {
-                let val = self.eval_operand_to_scalar(operand)?;
-                let val = self.unary_op(un_op, val, dest_layout)?;
-                self.write_scalar(
-                    dest,
-                    val,
-                    dest_ty,
-                )?;
-            }
-
-            Aggregate(ref kind, ref operands) => {
-                let (dest, active_field_index) = match **kind {
-                    mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
-                        self.write_discriminant_value(dest_ty, dest, variant_index)?;
-                        if adt_def.is_enum() {
-                            (self.place_downcast(dest, variant_index)?, active_field_index)
-                        } else {
-                            (dest, active_field_index)
-                        }
-                    }
-                    _ => (dest, None)
-                };
-
-                let layout = self.layout_of(dest_ty)?;
-                for (i, operand) in operands.iter().enumerate() {
-                    let value = self.eval_operand(operand)?;
-                    // Ignore zero-sized fields.
-                    if !self.layout_of(value.ty)?.is_zst() {
-                        let field_index = active_field_index.unwrap_or(i);
-                        let (field_dest, _) = self.place_field(dest, mir::Field::new(field_index), layout)?;
-                        self.write_value(value, field_dest)?;
-                    }
-                }
-            }
-
-            Repeat(ref operand, _) => {
-                let (elem_ty, length) = match dest_ty.sty {
-                    ty::TyArray(elem_ty, n) => (elem_ty, n.unwrap_usize(self.tcx.tcx)),
-                    _ => {
-                        bug!(
-                            "tried to assign array-repeat to non-array type {:?}",
-                            dest_ty
-                        )
-                    }
-                };
-                let elem_size = self.layout_of(elem_ty)?.size;
-                let value = self.eval_operand(operand)?.value;
-
-                let (dest, dest_align) = self.force_allocation(dest)?.to_ptr_align();
-
-                if length > 0 {
-                    let dest = dest.unwrap_or_err()?;
-                    //write the first value
-                    self.write_value_to_ptr(value, dest, dest_align, elem_ty)?;
-
-                    if length > 1 {
-                        let rest = dest.ptr_offset(elem_size * 1 as u64, &self)?;
-                        self.memory.copy_repeatedly(dest, dest_align, rest, dest_align, elem_size, length - 1, false)?;
-                    }
-                }
-            }
-
-            Len(ref place) => {
-                // FIXME(CTFE): don't allow computing the length of arrays in const eval
-                let src = self.eval_place(place)?;
-                let ty = self.place_ty(place);
-                let (_, len) = src.elem_ty_and_len(ty, self.tcx.tcx);
-                let size = self.memory.pointer_size().bytes() as u8;
-                self.write_scalar(
-                    dest,
-                    Scalar::Bits {
-                        bits: len as u128,
-                        size,
-                    },
-                    dest_ty,
-                )?;
-            }
-
-            Ref(_, _, ref place) => {
-                let src = self.eval_place(place)?;
-                // We ignore the alignment of the place here -- special handling for packed structs ends
-                // at the `&` operator.
-                let (ptr, _align, extra) = self.force_allocation(src)?.to_ptr_align_extra();
-
-                let val = match extra {
-                    PlaceExtra::None => Value::Scalar(ptr),
-                    PlaceExtra::Length(len) => ptr.to_value_with_len(len, self.tcx.tcx),
-                    PlaceExtra::Vtable(vtable) => ptr.to_value_with_vtable(vtable),
-                    PlaceExtra::DowncastVariant(..) => {
-                        bug!("attempted to take a reference to an enum downcast place")
-                    }
-                };
-                let valty = ValTy {
-                    value: val,
-                    ty: dest_ty,
-                };
-                self.write_value(valty, dest)?;
-            }
-
-            NullaryOp(mir::NullOp::Box, ty) => {
-                let ty = self.monomorphize(ty, self.substs());
-                M::box_alloc(self, ty, dest)?;
-            }
-
-            NullaryOp(mir::NullOp::SizeOf, ty) => {
-                let ty = self.monomorphize(ty, self.substs());
-                let layout = self.layout_of(ty)?;
-                assert!(!layout.is_unsized(),
-                        "SizeOf nullary MIR operator called for unsized type");
-                let size = self.memory.pointer_size().bytes() as u8;
-                self.write_scalar(
-                    dest,
-                    Scalar::Bits {
-                        bits: layout.size.bytes() as u128,
-                        size,
-                    },
-                    dest_ty,
-                )?;
-            }
-
-            Cast(kind, ref operand, cast_ty) => {
-                debug_assert_eq!(self.monomorphize(cast_ty, self.substs()), dest_ty);
-                let src = self.eval_operand(operand)?;
-                self.cast(src, kind, dest_ty, dest)?;
-            }
-
-            Discriminant(ref place) => {
-                let ty = self.place_ty(place);
-                let layout = self.layout_of(ty)?;
-                let place = self.eval_place(place)?;
-                let discr_val = self.read_discriminant_value(place, layout)?;
-                let size = self.layout_of(dest_ty).unwrap().size.bytes() as u8;
-                self.write_scalar(dest, Scalar::Bits {
-                    bits: discr_val,
-                    size,
-                }, dest_ty)?;
-            }
-        }
-
-        self.dump_local(dest);
-
-        Ok(())
-    }
-
-    pub(super) fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
-        match ty.sty {
-            ty::TyRawPtr(ty::TypeAndMut { ty, .. }) |
-            ty::TyRef(_, ty, _) => !self.type_is_sized(ty),
-            ty::TyAdt(def, _) if def.is_box() => !self.type_is_sized(ty.boxed_ty()),
-            _ => false,
-        }
-    }
-
-    pub(super) fn eval_operand_to_scalar(
-        &mut self,
-        op: &mir::Operand<'tcx>,
-    ) -> EvalResult<'tcx, Scalar> {
-        let valty = self.eval_operand(op)?;
-        self.value_to_scalar(valty)
-    }
-
-    pub(crate) fn operands_to_args(
-        &mut self,
-        ops: &[mir::Operand<'tcx>],
-    ) -> EvalResult<'tcx, Vec<ValTy<'tcx>>> {
-        ops.into_iter()
-            .map(|op| self.eval_operand(op))
-            .collect()
-    }
-
-    pub fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<'tcx, ValTy<'tcx>> {
-        use rustc::mir::Operand::*;
-        let ty = self.monomorphize(op.ty(self.mir(), *self.tcx), self.substs());
-        match *op {
-            // FIXME: do some more logic on `move` to invalidate the old location
-            Copy(ref place) |
-            Move(ref place) => {
-                Ok(ValTy {
-                    value: self.eval_and_read_place(place)?,
-                    ty
-                })
-            },
-
-            Constant(ref constant) => {
-                let value = self.const_to_value(constant.literal.val)?;
-
-                Ok(ValTy {
-                    value,
-                    ty,
-                })
-            }
-        }
-    }
-
-    /// reads a tag and produces the corresponding variant index
-    pub fn read_discriminant_as_variant_index(
-        &self,
-        place: Place,
-        layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, usize> {
-        match layout.variants {
-            ty::layout::Variants::Single { index } => Ok(index),
-            ty::layout::Variants::Tagged { .. } => {
-                let discr_val = self.read_discriminant_value(place, layout)?;
-                layout
-                    .ty
-                    .ty_adt_def()
-                    .expect("tagged layout for non adt")
-                    .discriminants(self.tcx.tcx)
-                    .position(|var| var.val == discr_val)
-                    .ok_or_else(|| EvalErrorKind::InvalidDiscriminant.into())
-            }
-            ty::layout::Variants::NicheFilling { .. } => {
-                let discr_val = self.read_discriminant_value(place, layout)?;
-                assert_eq!(discr_val as usize as u128, discr_val);
-                Ok(discr_val as usize)
-            },
-        }
-    }
-
-    pub fn read_discriminant_value(
-        &self,
-        place: Place,
-        layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, u128> {
-        trace!("read_discriminant_value {:#?}", layout);
-        if layout.abi == layout::Abi::Uninhabited {
-            return Ok(0);
-        }
-
-        match layout.variants {
-            layout::Variants::Single { index } => {
-                let discr_val = layout.ty.ty_adt_def().map_or(
-                    index as u128,
-                    |def| def.discriminant_for_variant(*self.tcx, index).val);
-                return Ok(discr_val);
-            }
-            layout::Variants::Tagged { .. } |
-            layout::Variants::NicheFilling { .. } => {},
-        }
-        let discr_place_val = self.read_place(place)?;
-        let (discr_val, discr) = self.read_field(discr_place_val, None, mir::Field::new(0), layout)?;
-        trace!("discr value: {:?}, {:?}", discr_val, discr);
-        let raw_discr = self.value_to_scalar(ValTy {
-            value: discr_val,
-            ty: discr.ty
-        })?;
-        let discr_val = match layout.variants {
-            layout::Variants::Single { .. } => bug!(),
-            // FIXME: should we catch invalid discriminants here?
-            layout::Variants::Tagged { .. } => {
-                if discr.ty.is_signed() {
-                    let i = raw_discr.to_bits(discr.size)? as i128;
-                    // going from layout tag type to typeck discriminant type
-                    // requires first sign extending with the layout discriminant
-                    let shift = 128 - discr.size.bits();
-                    let sexted = (i << shift) >> shift;
-                    // and then zeroing with the typeck discriminant type
-                    let discr_ty = layout
-                        .ty
-                        .ty_adt_def().expect("tagged layout corresponds to adt")
-                        .repr
-                        .discr_type();
-                    let discr_ty = layout::Integer::from_attr(self.tcx.tcx, discr_ty);
-                    let shift = 128 - discr_ty.size().bits();
-                    let truncatee = sexted as u128;
-                    (truncatee << shift) >> shift
-                } else {
-                    raw_discr.to_bits(discr.size)?
-                }
-            },
-            layout::Variants::NicheFilling {
-                dataful_variant,
-                ref niche_variants,
-                niche_start,
-                ..
-            } => {
-                let variants_start = *niche_variants.start() as u128;
-                let variants_end = *niche_variants.end() as u128;
-                match raw_discr {
-                    Scalar::Ptr(_) => {
-                        assert!(niche_start == 0);
-                        assert!(variants_start == variants_end);
-                        dataful_variant as u128
-                    },
-                    Scalar::Bits { bits: raw_discr, size } => {
-                        assert_eq!(size as u64, discr.size.bytes());
-                        let discr = raw_discr.wrapping_sub(niche_start)
-                            .wrapping_add(variants_start);
-                        if variants_start <= discr && discr <= variants_end {
-                            discr
-                        } else {
-                            dataful_variant as u128
-                        }
-                    },
-                }
-            }
-        };
-
-        Ok(discr_val)
-    }
-
-
-    pub fn write_discriminant_value(
-        &mut self,
-        dest_ty: Ty<'tcx>,
-        dest: Place,
-        variant_index: usize,
-    ) -> EvalResult<'tcx> {
-        let layout = self.layout_of(dest_ty)?;
-
-        match layout.variants {
-            layout::Variants::Single { index } => {
-                if index != variant_index {
-                    // If the layout of an enum is `Single`, all
-                    // other variants are necessarily uninhabited.
-                    assert_eq!(layout.for_variant(&self, variant_index).abi,
-                               layout::Abi::Uninhabited);
-                }
-            }
-            layout::Variants::Tagged { ref tag, .. } => {
-                let discr_val = dest_ty.ty_adt_def().unwrap()
-                    .discriminant_for_variant(*self.tcx, variant_index)
-                    .val;
-
-                // raw discriminants for enums are isize or bigger during
-                // their computation, but the in-memory tag is the smallest possible
-                // representation
-                let size = tag.value.size(self.tcx.tcx);
-                let shift = 128 - size.bits();
-                let discr_val = (discr_val << shift) >> shift;
-
-                let (discr_dest, tag) = self.place_field(dest, mir::Field::new(0), layout)?;
-                self.write_scalar(discr_dest, Scalar::Bits {
-                    bits: discr_val,
-                    size: size.bytes() as u8,
-                }, tag.ty)?;
-            }
-            layout::Variants::NicheFilling {
-                dataful_variant,
-                ref niche_variants,
-                niche_start,
-                ..
-            } => {
-                if variant_index != dataful_variant {
-                    let (niche_dest, niche) =
-                        self.place_field(dest, mir::Field::new(0), layout)?;
-                    let niche_value = ((variant_index - niche_variants.start()) as u128)
-                        .wrapping_add(niche_start);
-                    self.write_scalar(niche_dest, Scalar::Bits {
-                        bits: niche_value,
-                        size: niche.size.bytes() as u8,
-                    }, niche.ty)?;
-                }
-            }
-        }
-
-        Ok(())
-    }
-
-    pub fn read_global_as_value(&mut self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, Value> {
-        let cv = self.const_eval(gid)?;
-        self.const_to_value(cv.val)
-    }
-
     pub fn const_eval(&self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, &'tcx ty::Const<'tcx>> {
         let param_env = if self.tcx.is_static(gid.instance.def_id()).is_some() {
             ty::ParamEnv::reveal_all()
         } else {
             self.param_env
         };
-        self.tcx.const_eval(param_env.and(gid)).map_err(|err| EvalErrorKind::ReferencedConstant(err).into())
-    }
-
-    pub fn allocate_place_for_value(
-        &mut self,
-        value: Value,
-        layout: TyLayout<'tcx>,
-        variant: Option<usize>,
-    ) -> EvalResult<'tcx, Place> {
-        let (ptr, align) = match value {
-            Value::ByRef(ptr, align) => (ptr, align),
-            Value::ScalarPair(..) | Value::Scalar(_) => {
-                let ptr = self.alloc_ptr(layout)?.into();
-                self.write_value_to_ptr(value, ptr, layout.align, layout.ty)?;
-                (ptr, layout.align)
-            },
-        };
-        Ok(Place::Ptr {
-            ptr: ptr.into(),
-            align,
-            extra: variant.map_or(PlaceExtra::None, PlaceExtra::DowncastVariant),
-        })
-    }
-
-    pub fn force_allocation(&mut self, place: Place) -> EvalResult<'tcx, Place> {
-        let new_place = match place {
-            Place::Local { frame, local } => {
-                match self.stack[frame].locals[local].access()? {
-                    Value::ByRef(ptr, align) => {
-                        Place::Ptr {
-                            ptr: ptr.into(),
-                            align,
-                            extra: PlaceExtra::None,
-                        }
-                    }
-                    val => {
-                        let ty = self.stack[frame].mir.local_decls[local].ty;
-                        let ty = self.monomorphize(ty, self.stack[frame].instance.substs);
-                        let layout = self.layout_of(ty)?;
-                        let ptr = self.alloc_ptr(layout)?;
-                        self.stack[frame].locals[local] =
-                            LocalValue::Live(Value::ByRef(ptr.into(), layout.align)); // it stays live
-
-                        let place = Place::from_ptr(ptr, layout.align);
-                        self.write_value(ValTy { value: val, ty }, place)?;
-                        place
-                    }
-                }
-            }
-            Place::Ptr { .. } => place,
-        };
-        Ok(new_place)
-    }
-
-    /// ensures this Value is not a ByRef
-    pub fn follow_by_ref_value(
-        &self,
-        value: Value,
-        ty: Ty<'tcx>,
-    ) -> EvalResult<'tcx, Value> {
-        match value {
-            Value::ByRef(ptr, align) => {
-                self.read_value(ptr, align, ty)
-            }
-            other => Ok(other),
-        }
-    }
-
-    pub fn value_to_scalar(
-        &self,
-        ValTy { value, ty } : ValTy<'tcx>,
-    ) -> EvalResult<'tcx, Scalar> {
-        match self.follow_by_ref_value(value, ty)? {
-            Value::ByRef { .. } => bug!("follow_by_ref_value can't result in `ByRef`"),
-
-            Value::Scalar(scalar) => scalar.unwrap_or_err(),
-
-            Value::ScalarPair(..) => bug!("value_to_scalar can't work with fat pointers"),
-        }
-    }
-
-    pub fn write_ptr(&mut self, dest: Place, val: Scalar, dest_ty: Ty<'tcx>) -> EvalResult<'tcx> {
-        let valty = ValTy {
-            value: val.to_value(),
-            ty: dest_ty,
-        };
-        self.write_value(valty, dest)
-    }
-
-    pub fn write_scalar(
-        &mut self,
-        dest: Place,
-        val: impl Into<ScalarMaybeUndef>,
-        dest_ty: Ty<'tcx>,
-    ) -> EvalResult<'tcx> {
-        let valty = ValTy {
-            value: Value::Scalar(val.into()),
-            ty: dest_ty,
-        };
-        self.write_value(valty, dest)
-    }
-
-    pub fn write_value(
-        &mut self,
-        ValTy { value: src_val, ty: dest_ty } : ValTy<'tcx>,
-        dest: Place,
-    ) -> EvalResult<'tcx> {
-        //trace!("Writing {:?} to {:?} at type {:?}", src_val, dest, dest_ty);
-        // Note that it is really important that the type here is the right one, and matches the type things are read at.
-        // In case `src_val` is a `ScalarPair`, we don't do any magic here to handle padding properly, which is only
-        // correct if we never look at this data with the wrong type.
-
-        match dest {
-            Place::Ptr { ptr, align, extra } => {
-                assert_eq!(extra, PlaceExtra::None);
-                self.write_value_to_ptr(src_val, ptr.unwrap_or_err()?, align, dest_ty)
-            }
-
-            Place::Local { frame, local } => {
-                let old_val = self.stack[frame].locals[local].access()?;
-                self.write_value_possibly_by_val(
-                    src_val,
-                    |this, val| this.stack[frame].set_local(local, val),
-                    old_val,
-                    dest_ty,
-                )
-            }
-        }
-    }
-
-    // The cases here can be a bit subtle. Read carefully!
-    fn write_value_possibly_by_val<F: FnOnce(&mut Self, Value) -> EvalResult<'tcx>>(
-        &mut self,
-        src_val: Value,
-        write_dest: F,
-        old_dest_val: Value,
-        dest_ty: Ty<'tcx>,
-    ) -> EvalResult<'tcx> {
-        // FIXME: this should be a layout check, not underlying value
-        if let Value::ByRef(dest_ptr, align) = old_dest_val {
-            // If the value is already `ByRef` (that is, backed by an `Allocation`),
-            // then we must write the new value into this allocation, because there may be
-            // other pointers into the allocation. These other pointers are logically
-            // pointers into the local variable, and must be able to observe the change.
-            //
-            // Thus, it would be an error to replace the `ByRef` with a `ByVal`, unless we
-            // knew for certain that there were no outstanding pointers to this allocation.
-            self.write_value_to_ptr(src_val, dest_ptr, align, dest_ty)?;
-        } else if let Value::ByRef(src_ptr, align) = src_val {
-            // If the value is not `ByRef`, then we know there are no pointers to it
-            // and we can simply overwrite the `Value` in the locals array directly.
-            //
-            // In this specific case, where the source value is `ByRef`, we must duplicate
-            // the allocation, because this is a by-value operation. It would be incorrect
-            // if they referred to the same allocation, since then a change to one would
-            // implicitly change the other.
-            //
-            // It is a valid optimization to attempt reading a primitive value out of the
-            // source and write that into the destination without making an allocation, so
-            // we do so here.
-            if let Ok(Some(src_val)) = self.try_read_value(src_ptr, align, dest_ty) {
-                write_dest(self, src_val)?;
-            } else {
-                let layout = self.layout_of(dest_ty)?;
-                let dest_ptr = self.alloc_ptr(layout)?.into();
-                self.memory.copy(src_ptr, align.min(layout.align), dest_ptr, layout.align, layout.size, false)?;
-                write_dest(self, Value::ByRef(dest_ptr, layout.align))?;
-            }
-        } else {
-            // Finally, we have the simple case where neither source nor destination are
-            // `ByRef`. We may simply copy the source value over the the destintion.
-            write_dest(self, src_val)?;
-        }
-        Ok(())
-    }
-
-    pub fn write_value_to_ptr(
-        &mut self,
-        value: Value,
-        dest: Scalar,
-        dest_align: Align,
-        dest_ty: Ty<'tcx>,
-    ) -> EvalResult<'tcx> {
-        let layout = self.layout_of(dest_ty)?;
-        trace!("write_value_to_ptr: {:#?}, {}, {:#?}", value, dest_ty, layout);
-        match value {
-            Value::ByRef(ptr, align) => {
-                self.memory.copy(ptr, align.min(layout.align), dest, dest_align.min(layout.align), layout.size, false)
-            }
-            Value::Scalar(scalar) => {
-                let signed = match layout.abi {
-                    layout::Abi::Scalar(ref scal) => match scal.value {
-                        layout::Primitive::Int(_, signed) => signed,
-                        _ => false,
-                    },
-                    _ => false,
-                };
-                self.memory.write_scalar(dest, dest_align, scalar, layout.size, layout.align, signed)
-            }
-            Value::ScalarPair(a_val, b_val) => {
-                trace!("write_value_to_ptr valpair: {:#?}", layout);
-                let (a, b) = match layout.abi {
-                    layout::Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value),
-                    _ => bug!("write_value_to_ptr: invalid ScalarPair layout: {:#?}", layout)
-                };
-                let (a_size, b_size) = (a.size(&self), b.size(&self));
-                let (a_align, b_align) = (a.align(&self), b.align(&self));
-                let a_ptr = dest;
-                let b_offset = a_size.abi_align(b_align);
-                let b_ptr = dest.ptr_offset(b_offset, &self)?.into();
-                // TODO: What about signedess?
-                self.memory.write_scalar(a_ptr, dest_align, a_val, a_size, a_align, false)?;
-                self.memory.write_scalar(b_ptr, dest_align, b_val, b_size, b_align, false)
-            }
-        }
-    }
-
-    pub fn read_value(&self, ptr: Scalar, align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
-        if let Some(val) = self.try_read_value(ptr, align, ty)? {
-            Ok(val)
-        } else {
-            bug!("primitive read failed for type: {:?}", ty);
-        }
-    }
-
-    fn validate_scalar(
-        &self,
-        value: ScalarMaybeUndef,
-        size: Size,
-        scalar: &layout::Scalar,
-        path: &str,
-        ty: Ty,
-    ) -> EvalResult<'tcx> {
-        trace!("validate scalar: {:#?}, {:#?}, {:#?}, {}", value, size, scalar, ty);
-        let (lo, hi) = scalar.valid_range.clone().into_inner();
-
-        let value = match value {
-            ScalarMaybeUndef::Scalar(scalar) => scalar,
-            ScalarMaybeUndef::Undef => return validation_failure!("undefined bytes", path),
-        };
-
-        let bits = match value {
-            Scalar::Bits { bits, size: value_size } => {
-                assert_eq!(value_size as u64, size.bytes());
-                bits
-            },
-            Scalar::Ptr(_) => {
-                let ptr_size = self.memory.pointer_size();
-                let ptr_max = u128::max_value() >> (128 - ptr_size.bits());
-                return if lo > hi {
-                    if lo - hi == 1 {
-                        // no gap, all values are ok
-                        Ok(())
-                    } else if hi < ptr_max || lo > 1 {
-                        let max = u128::max_value() >> (128 - size.bits());
-                        validation_failure!(
-                            "pointer",
-                            path,
-                            format!("something in the range {:?} or {:?}", 0..=lo, hi..=max)
-                        )
-                    } else {
-                        Ok(())
-                    }
-                } else if hi < ptr_max || lo > 1 {
-                    validation_failure!(
-                        "pointer",
-                        path,
-                        format!("something in the range {:?}", scalar.valid_range)
-                    )
-                } else {
-                    Ok(())
-                };
-            },
-        };
-
-        // char gets a special treatment, because its number space is not contiguous so `TyLayout`
-        // has no special checks for chars
-        match ty.sty {
-            ty::TyChar => {
-                debug_assert_eq!(size.bytes(), 4);
-                if ::std::char::from_u32(bits as u32).is_none() {
-                    return err!(InvalidChar(bits));
-                }
-            }
-            _ => {},
-        }
-
-        use std::ops::RangeInclusive;
-        let in_range = |bound: RangeInclusive<u128>| bound.contains(&bits);
-        if lo > hi {
-            if in_range(0..=hi) || in_range(lo..=u128::max_value()) {
-                Ok(())
-            } else {
-                validation_failure!(
-                    bits,
-                    path,
-                    format!("something in the range {:?} or {:?}", ..=hi, lo..)
-                )
-            }
-        } else {
-            if in_range(scalar.valid_range.clone()) {
-                Ok(())
-            } else {
-                validation_failure!(
-                    bits,
-                    path,
-                    format!("something in the range {:?}", scalar.valid_range)
-                )
-            }
-        }
-    }
-
-    /// This function checks the memory where `ptr` points to.
-    /// It will error if the bits at the destination do not match the ones described by the layout.
-    pub fn validate_ptr_target(
-        &self,
-        ptr: Pointer,
-        ptr_align: Align,
-        mut layout: TyLayout<'tcx>,
-        path: String,
-        seen: &mut FxHashSet<(Pointer, Ty<'tcx>)>,
-        todo: &mut Vec<(Pointer, Ty<'tcx>, String)>,
-    ) -> EvalResult<'tcx> {
-        self.memory.dump_alloc(ptr.alloc_id);
-        trace!("validate_ptr_target: {:?}, {:#?}", ptr, layout);
-
-        let variant;
-        match layout.variants {
-            layout::Variants::NicheFilling { niche: ref tag, .. } |
-            layout::Variants::Tagged { ref tag, .. } => {
-                let size = tag.value.size(self);
-                let (tag_value, tag_layout) = self.read_field(
-                    Value::ByRef(ptr.into(), ptr_align),
-                    None,
-                    mir::Field::new(0),
-                    layout,
-                )?;
-                let tag_value = match self.follow_by_ref_value(tag_value, tag_layout.ty)? {
-                    Value::Scalar(val) => val,
-                    _ => bug!("tag must be scalar"),
-                };
-                let path = format!("{}.TAG", path);
-                self.validate_scalar(tag_value, size, tag, &path, tag_layout.ty)?;
-                let variant_index = self.read_discriminant_as_variant_index(
-                    Place::from_ptr(ptr, ptr_align),
-                    layout,
-                )?;
-                variant = variant_index;
-                layout = layout.for_variant(self, variant_index);
-                trace!("variant layout: {:#?}", layout);
-            },
-            layout::Variants::Single { index } => variant = index,
-        }
-        match layout.fields {
-            // primitives are unions with zero fields
-            layout::FieldPlacement::Union(0) => {
-                match layout.abi {
-                    // nothing to do, whatever the pointer points to, it is never going to be read
-                    layout::Abi::Uninhabited => validation_failure!("a value of an uninhabited type", path),
-                    // check that the scalar is a valid pointer or that its bit range matches the
-                    // expectation.
-                    layout::Abi::Scalar(ref scalar) => {
-                        let size = scalar.value.size(self);
-                        let value = self.memory.read_scalar(ptr, ptr_align, size)?;
-                        self.validate_scalar(value, size, scalar, &path, layout.ty)?;
-                        if scalar.value == Primitive::Pointer {
-                            // ignore integer pointers, we can't reason about the final hardware
-                            if let Scalar::Ptr(ptr) = value.unwrap_or_err()? {
-                                let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id);
-                                if let Some(AllocType::Static(did)) = alloc_kind {
-                                    // statics from other crates are already checked
-                                    // extern statics should not be validated as they have no body
-                                    if !did.is_local() || self.tcx.is_foreign_item(did) {
-                                        return Ok(());
-                                    }
-                                }
-                                if let Some(tam) = layout.ty.builtin_deref(false) {
-                                    // we have not encountered this pointer+layout combination before
-                                    if seen.insert((ptr, tam.ty)) {
-                                        todo.push((ptr, tam.ty, format!("(*{})", path)))
-                                    }
-                                }
-                            }
-                        }
-                        Ok(())
-                    },
-                    _ => bug!("bad abi for FieldPlacement::Union(0): {:#?}", layout.abi),
-                }
-            }
-            layout::FieldPlacement::Union(_) => {
-                // We can't check unions, their bits are allowed to be anything.
-                // The fields don't need to correspond to any bit pattern of the union's fields.
-                // See https://github.com/rust-lang/rust/issues/32836#issuecomment-406875389
-                Ok(())
-            },
-            layout::FieldPlacement::Array { stride, count } => {
-                let elem_layout = layout.field(self, 0)?;
-                for i in 0..count {
-                    let mut path = path.clone();
-                    self.write_field_name(&mut path, layout.ty, i as usize, variant).unwrap();
-                    self.validate_ptr_target(ptr.offset(stride * i, self)?, ptr_align, elem_layout, path, seen, todo)?;
-                }
-                Ok(())
-            },
-            layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
-
-                // check length field and vtable field
-                match layout.ty.builtin_deref(false).map(|tam| &tam.ty.sty) {
-                    | Some(ty::TyStr)
-                    | Some(ty::TySlice(_)) => {
-                        let (len, len_layout) = self.read_field(
-                            Value::ByRef(ptr.into(), ptr_align),
-                            None,
-                            mir::Field::new(1),
-                            layout,
-                        )?;
-                        let len = self.value_to_scalar(ValTy { value: len, ty: len_layout.ty })?;
-                        if len.to_bits(len_layout.size).is_err() {
-                            return validation_failure!("length is not a valid integer", path);
-                        }
-                    },
-                    Some(ty::TyDynamic(..)) => {
-                        let (vtable, vtable_layout) = self.read_field(
-                            Value::ByRef(ptr.into(), ptr_align),
-                            None,
-                            mir::Field::new(1),
-                            layout,
-                        )?;
-                        let vtable = self.value_to_scalar(ValTy { value: vtable, ty: vtable_layout.ty })?;
-                        if vtable.to_ptr().is_err() {
-                            return validation_failure!("vtable address is not a pointer", path);
-                        }
-                    }
-                    _ => {},
-                }
-                for (i, &offset) in offsets.iter().enumerate() {
-                    let field_layout = layout.field(self, i)?;
-                    let mut path = path.clone();
-                    self.write_field_name(&mut path, layout.ty, i, variant).unwrap();
-                    self.validate_ptr_target(ptr.offset(offset, self)?, ptr_align, field_layout, path, seen, todo)?;
-                }
-                Ok(())
-            }
-        }
-    }
-
-    pub fn try_read_by_ref(&self, mut val: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
-        // Convert to ByVal or ScalarPair if possible
-        if let Value::ByRef(ptr, align) = val {
-            if let Some(read_val) = self.try_read_value(ptr, align, ty)? {
-                val = read_val;
-            }
-        }
-        Ok(val)
-    }
-
-    pub fn try_read_value(&self, ptr: Scalar, ptr_align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
-        let layout = self.layout_of(ty)?;
-        self.memory.check_align(ptr, ptr_align)?;
-
-        if layout.size.bytes() == 0 {
-            return Ok(Some(Value::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits { bits: 0, size: 0 }))));
-        }
-
-        let ptr = ptr.to_ptr()?;
-
-        match layout.abi {
-            layout::Abi::Scalar(..) => {
-                let scalar = self.memory.read_scalar(ptr, ptr_align, layout.size)?;
-                Ok(Some(Value::Scalar(scalar)))
-            }
-            layout::Abi::ScalarPair(ref a, ref b) => {
-                let (a, b) = (&a.value, &b.value);
-                let (a_size, b_size) = (a.size(self), b.size(self));
-                let a_ptr = ptr;
-                let b_offset = a_size.abi_align(b.align(self));
-                let b_ptr = ptr.offset(b_offset, self)?.into();
-                let a_val = self.memory.read_scalar(a_ptr, ptr_align, a_size)?;
-                let b_val = self.memory.read_scalar(b_ptr, ptr_align, b_size)?;
-                Ok(Some(Value::ScalarPair(a_val, b_val)))
-            }
-            _ => Ok(None),
-        }
+        self.tcx.const_eval(param_env.and(gid))
+            .map_err(|err| EvalErrorKind::ReferencedConstant(err).into())
     }
 
+    #[inline(always)]
     pub fn frame(&self) -> &Frame<'mir, 'tcx> {
         self.stack.last().expect("no call frames exist")
     }
 
+    #[inline(always)]
     pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx> {
         self.stack.last_mut().expect("no call frames exist")
     }
@@ -1569,132 +695,7 @@ pub fn substs(&self) -> &'tcx Substs<'tcx> {
         }
     }
 
-    fn unsize_into_ptr(
-        &mut self,
-        src: Value,
-        src_ty: Ty<'tcx>,
-        dest: Place,
-        dest_ty: Ty<'tcx>,
-        sty: Ty<'tcx>,
-        dty: Ty<'tcx>,
-    ) -> EvalResult<'tcx> {
-        // A<Struct> -> A<Trait> conversion
-        let (src_pointee_ty, dest_pointee_ty) = self.tcx.struct_lockstep_tails(sty, dty);
-
-        match (&src_pointee_ty.sty, &dest_pointee_ty.sty) {
-            (&ty::TyArray(_, length), &ty::TySlice(_)) => {
-                let ptr = self.into_ptr(src)?;
-                // u64 cast is from usize to u64, which is always good
-                let valty = ValTy {
-                    value: ptr.to_value_with_len(length.unwrap_usize(self.tcx.tcx), self.tcx.tcx),
-                    ty: dest_ty,
-                };
-                self.write_value(valty, dest)
-            }
-            (&ty::TyDynamic(..), &ty::TyDynamic(..)) => {
-                // For now, upcasts are limited to changes in marker
-                // traits, and hence never actually require an actual
-                // change to the vtable.
-                let valty = ValTy {
-                    value: src,
-                    ty: dest_ty,
-                };
-                self.write_value(valty, dest)
-            }
-            (_, &ty::TyDynamic(ref data, _)) => {
-                let trait_ref = data.principal().unwrap().with_self_ty(
-                    *self.tcx,
-                    src_pointee_ty,
-                );
-                let trait_ref = self.tcx.erase_regions(&trait_ref);
-                let vtable = self.get_vtable(src_pointee_ty, trait_ref)?;
-                let ptr = self.into_ptr(src)?;
-                let valty = ValTy {
-                    value: ptr.to_value_with_vtable(vtable),
-                    ty: dest_ty,
-                };
-                self.write_value(valty, dest)
-            }
-
-            _ => bug!("invalid unsizing {:?} -> {:?}", src_ty, dest_ty),
-        }
-    }
-
-    crate fn unsize_into(
-        &mut self,
-        src: Value,
-        src_layout: TyLayout<'tcx>,
-        dst: Place,
-        dst_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx> {
-        match (&src_layout.ty.sty, &dst_layout.ty.sty) {
-            (&ty::TyRef(_, s, _), &ty::TyRef(_, d, _)) |
-            (&ty::TyRef(_, s, _), &ty::TyRawPtr(TypeAndMut { ty: d, .. })) |
-            (&ty::TyRawPtr(TypeAndMut { ty: s, .. }),
-             &ty::TyRawPtr(TypeAndMut { ty: d, .. })) => {
-                self.unsize_into_ptr(src, src_layout.ty, dst, dst_layout.ty, s, d)
-            }
-            (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => {
-                assert_eq!(def_a, def_b);
-                if def_a.is_box() || def_b.is_box() {
-                    if !def_a.is_box() || !def_b.is_box() {
-                        bug!("invalid unsizing between {:?} -> {:?}", src_layout, dst_layout);
-                    }
-                    return self.unsize_into_ptr(
-                        src,
-                        src_layout.ty,
-                        dst,
-                        dst_layout.ty,
-                        src_layout.ty.boxed_ty(),
-                        dst_layout.ty.boxed_ty(),
-                    );
-                }
-
-                // unsizing of generic struct with pointer fields
-                // Example: `Arc<T>` -> `Arc<Trait>`
-                // here we need to increase the size of every &T thin ptr field to a fat ptr
-                for i in 0..src_layout.fields.count() {
-                    let (dst_f_place, dst_field) =
-                        self.place_field(dst, mir::Field::new(i), dst_layout)?;
-                    if dst_field.is_zst() {
-                        continue;
-                    }
-                    let (src_f_value, src_field) = match src {
-                        Value::ByRef(ptr, align) => {
-                            let src_place = Place::from_scalar_ptr(ptr.into(), align);
-                            let (src_f_place, src_field) =
-                                self.place_field(src_place, mir::Field::new(i), src_layout)?;
-                            (self.read_place(src_f_place)?, src_field)
-                        }
-                        Value::Scalar(_) | Value::ScalarPair(..) => {
-                            let src_field = src_layout.field(&self, i)?;
-                            assert_eq!(src_layout.fields.offset(i).bytes(), 0);
-                            assert_eq!(src_field.size, src_layout.size);
-                            (src, src_field)
-                        }
-                    };
-                    if src_field.ty == dst_field.ty {
-                        self.write_value(ValTy {
-                            value: src_f_value,
-                            ty: src_field.ty,
-                        }, dst_f_place)?;
-                    } else {
-                        self.unsize_into(src_f_value, src_field, dst_f_place, dst_field)?;
-                    }
-                }
-                Ok(())
-            }
-            _ => {
-                bug!(
-                    "unsize_into: invalid conversion: {:?} -> {:?}",
-                    src_layout,
-                    dst_layout
-                )
-            }
-        }
-    }
-
-    pub fn dump_local(&self, place: Place) {
+    pub fn dump_place(&self, place: Place) {
         // Debug output
         if !log_enabled!(::log::Level::Trace) {
             return;
@@ -1716,22 +717,23 @@ pub fn dump_local(&self, place: Place) {
                             panic!("Failed to access local: {:?}", err);
                         }
                     }
-                    Ok(Value::ByRef(ptr, align)) => {
+                    Ok(Operand::Indirect(mplace)) => {
+                        let (ptr, align) = mplace.to_scalar_ptr_align();
                         match ptr {
                             Scalar::Ptr(ptr) => {
                                 write!(msg, " by align({}) ref:", align.abi()).unwrap();
                                 allocs.push(ptr.alloc_id);
                             }
-                            ptr => write!(msg, " integral by ref: {:?}", ptr).unwrap(),
+                            ptr => write!(msg, " by integral ref: {:?}", ptr).unwrap(),
                         }
                     }
-                    Ok(Value::Scalar(val)) => {
+                    Ok(Operand::Immediate(Value::Scalar(val))) => {
                         write!(msg, " {:?}", val).unwrap();
                         if let ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) = val {
                             allocs.push(ptr.alloc_id);
                         }
                     }
-                    Ok(Value::ScalarPair(val1, val2)) => {
+                    Ok(Operand::Immediate(Value::ScalarPair(val1, val2))) => {
                         write!(msg, " ({:?}, {:?})", val1, val2).unwrap();
                         if let ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) = val1 {
                             allocs.push(ptr.alloc_id);
@@ -1745,10 +747,10 @@ pub fn dump_local(&self, place: Place) {
                 trace!("{}", msg);
                 self.memory.dump_allocs(allocs);
             }
-            Place::Ptr { ptr, align, .. } => {
-                match ptr {
-                    ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) => {
-                        trace!("by align({}) ref:", align.abi());
+            Place::Ptr(mplace) => {
+                match mplace.ptr {
+                    Scalar::Ptr(ptr) => {
+                        trace!("by align({}) ref:", mplace.align.abi());
                         self.memory.dump_alloc(ptr.alloc_id);
                     }
                     ptr => trace!(" integral by ref: {:?}", ptr),
@@ -1774,7 +776,9 @@ pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> (Vec<FrameInfo
             } else {
                 last_span = Some(span);
             }
-            let location = if self.tcx.def_key(instance.def_id()).disambiguated_data.data == DefPathData::ClosureExpr {
+            let location = if self.tcx.def_key(instance.def_id()).disambiguated_data.data
+                == DefPathData::ClosureExpr
+            {
                 "closure".to_owned()
             } else {
                 instance.to_string()
@@ -1795,119 +799,15 @@ pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> (Vec<FrameInfo
         (frames, self.tcx.span)
     }
 
+    #[inline(always)]
     pub fn sign_extend(&self, value: u128, ty: TyLayout<'_>) -> u128 {
-        super::sign_extend(value, ty)
+        assert!(ty.abi.is_signed());
+        sign_extend(value, ty.size)
     }
 
+    #[inline(always)]
     pub fn truncate(&self, value: u128, ty: TyLayout<'_>) -> u128 {
-        super::truncate(value, ty)
-    }
-
-    fn write_field_name(&self, s: &mut String, ty: Ty<'tcx>, i: usize, variant: usize) -> ::std::fmt::Result {
-        match ty.sty {
-            ty::TyBool |
-            ty::TyChar |
-            ty::TyInt(_) |
-            ty::TyUint(_) |
-            ty::TyFloat(_) |
-            ty::TyFnPtr(_) |
-            ty::TyNever |
-            ty::TyFnDef(..) |
-            ty::TyGeneratorWitness(..) |
-            ty::TyForeign(..) |
-            ty::TyDynamic(..) => {
-                bug!("field_name({:?}): not applicable", ty)
-            }
-
-            // Potentially-fat pointers.
-            ty::TyRef(_, pointee, _) |
-            ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
-                assert!(i < 2);
-
-                // Reuse the fat *T type as its own thin pointer data field.
-                // This provides information about e.g. DST struct pointees
-                // (which may have no non-DST form), and will work as long
-                // as the `Abi` or `FieldPlacement` is checked by users.
-                if i == 0 {
-                    return write!(s, ".data_ptr");
-                }
-
-                match self.tcx.struct_tail(pointee).sty {
-                    ty::TySlice(_) |
-                    ty::TyStr => write!(s, ".len"),
-                    ty::TyDynamic(..) => write!(s, ".vtable_ptr"),
-                    _ => bug!("field_name({:?}): not applicable", ty)
-                }
-            }
-
-            // Arrays and slices.
-            ty::TyArray(_, _) |
-            ty::TySlice(_) |
-            ty::TyStr => write!(s, "[{}]", i),
-
-            // generators and closures.
-            ty::TyClosure(def_id, _) | ty::TyGenerator(def_id, _, _) => {
-                let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
-                let freevar = self.tcx.with_freevars(node_id, |fv| fv[i]);
-                write!(s, ".upvar({})", self.tcx.hir.name(freevar.var_id()))
-            }
-
-            ty::TyTuple(_) => write!(s, ".{}", i),
-
-            // enums
-            ty::TyAdt(def, ..) if def.is_enum() => {
-                let variant = &def.variants[variant];
-                write!(s, ".{}::{}", variant.name, variant.fields[i].ident)
-            }
-
-            // other ADTs.
-            ty::TyAdt(def, _) => write!(s, ".{}", def.non_enum_variant().fields[i].ident),
-
-            ty::TyProjection(_) | ty::TyAnon(..) | ty::TyParam(_) |
-            ty::TyInfer(_) | ty::TyError => {
-                bug!("write_field_name: unexpected type `{}`", ty)
-            }
-        }
-    }
-
-    pub fn storage_live(&mut self, local: mir::Local) -> EvalResult<'tcx, LocalValue> {
-        trace!("{:?} is now live", local);
-
-        let ty = self.frame().mir.local_decls[local].ty;
-        let init = self.init_value(ty)?;
-        // StorageLive *always* kills the value that's currently stored
-        Ok(mem::replace(&mut self.frame_mut().locals[local], LocalValue::Live(init)))
-    }
-
-    fn init_value(&mut self, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
-        let ty = self.monomorphize(ty, self.substs());
-        let layout = self.layout_of(ty)?;
-        Ok(match layout.abi {
-            layout::Abi::Scalar(..) => Value::Scalar(ScalarMaybeUndef::Undef),
-            layout::Abi::ScalarPair(..) => Value::ScalarPair(
-                ScalarMaybeUndef::Undef,
-                ScalarMaybeUndef::Undef,
-            ),
-            _ => Value::ByRef(self.alloc_ptr(layout)?.into(), layout.align),
-        })
+        truncate(value, ty.size)
     }
 }
 
-impl<'mir, 'tcx> Frame<'mir, 'tcx> {
-    fn set_local(&mut self, local: mir::Local, value: Value) -> EvalResult<'tcx> {
-        match self.locals[local] {
-            LocalValue::Dead => err!(DeadLocal),
-            LocalValue::Live(ref mut local) => {
-                *local = value;
-                Ok(())
-            }
-        }
-    }
-
-    /// Returns the old value of the local
-    pub fn storage_dead(&mut self, local: mir::Local) -> LocalValue {
-        trace!("{:?} is now dead", local);
-
-        mem::replace(&mut self.locals[local], LocalValue::Dead)
-    }
-}
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
new file mode 100644 (file)
index 0000000..e8fd43a
--- /dev/null
@@ -0,0 +1,173 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Intrinsics and other functions that the miri engine executes without
+//! looking at their MIR.  Intrinsics/functions supported here are shared by CTFE
+//! and miri.
+
+use syntax::symbol::Symbol;
+use rustc::ty;
+use rustc::ty::layout::{LayoutOf, Primitive};
+use rustc::mir::interpret::{
+    EvalResult, EvalErrorKind, Scalar,
+};
+
+use super::{
+    Machine, PlaceTy, OpTy, EvalContext,
+};
+
+
+fn numeric_intrinsic<'tcx>(
+    name: &str,
+    bits: u128,
+    kind: Primitive,
+) -> EvalResult<'tcx, Scalar> {
+    let size = match kind {
+        Primitive::Int(integer, _) => integer.size(),
+        _ => bug!("invalid `{}` argument: {:?}", name, bits),
+    };
+    let extra = 128 - size.bits() as u128;
+    let bits_out = match name {
+        "ctpop" => bits.count_ones() as u128,
+        "ctlz" => bits.leading_zeros() as u128 - extra,
+        "cttz" => (bits << extra).trailing_zeros() as u128 - extra,
+        "bswap" => (bits << extra).swap_bytes(),
+        _ => bug!("not a numeric intrinsic: {}", name),
+    };
+    Ok(Scalar::from_uint(bits_out, size))
+}
+
+impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+    /// Returns whether emulation happened.
+    pub fn emulate_intrinsic(
+        &mut self,
+        instance: ty::Instance<'tcx>,
+        args: &[OpTy<'tcx>],
+        dest: PlaceTy<'tcx>,
+    ) -> EvalResult<'tcx, bool> {
+        let substs = instance.substs;
+
+        let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
+        match intrinsic_name {
+            "min_align_of" => {
+                let elem_ty = substs.type_at(0);
+                let elem_align = self.layout_of(elem_ty)?.align.abi();
+                let align_val = Scalar::from_uint(elem_align, dest.layout.size);
+                self.write_scalar(align_val, dest)?;
+            }
+
+            "size_of" => {
+                let ty = substs.type_at(0);
+                let size = self.layout_of(ty)?.size.bytes() as u128;
+                let size_val = Scalar::from_uint(size, dest.layout.size);
+                self.write_scalar(size_val, dest)?;
+            }
+
+            "type_id" => {
+                let ty = substs.type_at(0);
+                let type_id = self.tcx.type_id_hash(ty) as u128;
+                let id_val = Scalar::from_uint(type_id, dest.layout.size);
+                self.write_scalar(id_val, dest)?;
+            }
+            "ctpop" | "cttz" | "cttz_nonzero" | "ctlz" | "ctlz_nonzero" | "bswap" => {
+                let ty = substs.type_at(0);
+                let layout_of = self.layout_of(ty)?;
+                let bits = self.read_scalar(args[0])?.to_bits(layout_of.size)?;
+                let kind = match layout_of.abi {
+                    ty::layout::Abi::Scalar(ref scalar) => scalar.value,
+                    _ => Err(::rustc::mir::interpret::EvalErrorKind::TypeNotPrimitive(ty))?,
+                };
+                let out_val = if intrinsic_name.ends_with("_nonzero") {
+                    if bits == 0 {
+                        return err!(Intrinsic(format!("{} called on 0", intrinsic_name)));
+                    }
+                    numeric_intrinsic(intrinsic_name.trim_right_matches("_nonzero"), bits, kind)?
+                } else {
+                    numeric_intrinsic(intrinsic_name, bits, kind)?
+                };
+                self.write_scalar(out_val, dest)?;
+            }
+            "transmute" => {
+                // Go through an allocation, to make sure the completely different layouts
+                // do not pose a problem.  (When the user transmutes through a union,
+                // there will not be a layout mismatch.)
+                let dest = self.force_allocation(dest)?;
+                self.copy_op(args[0], dest.into())?;
+            }
+
+            _ => return Ok(false),
+        }
+
+        Ok(true)
+    }
+
+    /// "Intercept" a function call because we have something special to do for it.
+    /// Returns whether an intercept happened.
+    pub fn hook_fn(
+        &mut self,
+        instance: ty::Instance<'tcx>,
+        args: &[OpTy<'tcx>],
+        dest: Option<PlaceTy<'tcx>>,
+    ) -> EvalResult<'tcx, bool> {
+        let def_id = instance.def_id();
+        // Some fn calls are actually BinOp intrinsics
+        if let Some((op, oflo)) = self.tcx.is_binop_lang_item(def_id) {
+            let dest = dest.expect("128 lowerings can't diverge");
+            let l = self.read_value(args[0])?;
+            let r = self.read_value(args[1])?;
+            if oflo {
+                self.binop_with_overflow(op, l, r, dest)?;
+            } else {
+                self.binop_ignore_overflow(op, l, r, dest)?;
+            }
+            return Ok(true);
+        } else if Some(def_id) == self.tcx.lang_items().panic_fn() {
+            assert!(args.len() == 1);
+            // &(&'static str, &'static str, u32, u32)
+            let ptr = self.read_value(args[0])?;
+            let place = self.ref_to_mplace(ptr)?;
+            let (msg, file, line, col) = (
+                self.mplace_field(place, 0)?,
+                self.mplace_field(place, 1)?,
+                self.mplace_field(place, 2)?,
+                self.mplace_field(place, 3)?,
+            );
+
+            let msg_place = self.ref_to_mplace(self.read_value(msg.into())?)?;
+            let msg = Symbol::intern(self.read_str(msg_place)?);
+            let file_place = self.ref_to_mplace(self.read_value(file.into())?)?;
+            let file = Symbol::intern(self.read_str(file_place)?);
+            let line = self.read_scalar(line.into())?.to_u32()?;
+            let col = self.read_scalar(col.into())?.to_u32()?;
+            return Err(EvalErrorKind::Panic { msg, file, line, col }.into());
+        } else if Some(def_id) == self.tcx.lang_items().begin_panic_fn() {
+            assert!(args.len() == 2);
+            // &'static str, &(&'static str, u32, u32)
+            let msg = args[0];
+            let ptr = self.read_value(args[1])?;
+            let place = self.ref_to_mplace(ptr)?;
+            let (file, line, col) = (
+                self.mplace_field(place, 0)?,
+                self.mplace_field(place, 1)?,
+                self.mplace_field(place, 2)?,
+            );
+
+            let msg_place = self.ref_to_mplace(self.read_value(msg.into())?)?;
+            let msg = Symbol::intern(self.read_str(msg_place)?);
+            let file_place = self.ref_to_mplace(self.read_value(file.into())?)?;
+            let file = Symbol::intern(self.read_str(file_place)?);
+            let line = self.read_scalar(line.into())?.to_u32()?;
+            let col = self.read_scalar(col.into())?.to_u32()?;
+            return Err(EvalErrorKind::Panic { msg, file, line, col }.into());
+        } else {
+            return Ok(false);
+        }
+    }
+}
index 112d8759c6832b1b48f979829b109a9b400884d7..57af63d63d9c47d074d9572b4c642b588c97345d 100644 (file)
@@ -1,17 +1,25 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
 //! This module contains everything needed to instantiate an interpreter.
 //! This separation exists to ensure that no fancy miri features like
 //! interpreting common C functions leak into CTFE.
 
 use std::hash::Hash;
 
-use rustc::mir::interpret::{AllocId, EvalResult, Scalar, Pointer, AccessKind, GlobalId};
-use super::{EvalContext, Place, ValTy, Memory};
-
+use rustc::hir::def_id::DefId;
+use rustc::mir::interpret::{Allocation, EvalResult, Scalar};
 use rustc::mir;
-use rustc::ty::{self, Ty};
-use rustc::ty::layout::Size;
-use syntax::source_map::Span;
-use syntax::ast::Mutability;
+use rustc::ty::{self, layout::TyLayout, query::TyCtxtAt};
+
+use super::{EvalContext, PlaceTy, OpTy};
 
 /// Methods of this trait signifies a point where CTFE evaluation would fail
 /// and some use case dependent behaviour can instead be applied
@@ -20,107 +28,69 @@ pub trait Machine<'mir, 'tcx>: Clone + Eq + Hash {
     type MemoryData: Clone + Eq + Hash;
 
     /// Additional memory kinds a machine wishes to distinguish from the builtin ones
-    type MemoryKinds: ::std::fmt::Debug + PartialEq + Copy + Clone;
+    type MemoryKinds: ::std::fmt::Debug + Copy + Clone + Eq + Hash;
+
+    /// The memory kind to use for mutated statics -- or None if those are not supported.
+    const MUT_STATIC_KIND: Option<Self::MemoryKinds>;
 
     /// Entry point to all function calls.
     ///
-    /// Returns Ok(true) when the function was handled completely
-    /// e.g. due to missing mir
-    ///
-    /// Returns Ok(false) if a new stack frame was pushed
-    fn eval_fn_call<'a>(
+    /// Returns either the mir to use for the call, or `None` if execution should
+    /// just proceed (which usually means this hook did all the work that the
+    /// called function should usually have done).  In the latter case, it is
+    /// this hook's responsibility to call `goto_block(ret)` to advance the instruction pointer!
+    /// (This is to support functions like `__rust_maybe_catch_panic` that neither find a MIR
+    /// nor just jump to `ret`, but instead push their own stack frame.)
+    /// Passing `dest`and `ret` in the same `Option` proved very annoying when only one of them
+    /// was used.
+    fn find_fn<'a>(
         ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
-        destination: Option<(Place, mir::BasicBlock)>,
-        args: &[ValTy<'tcx>],
-        span: Span,
-        sig: ty::FnSig<'tcx>,
-    ) -> EvalResult<'tcx, bool>;
+        args: &[OpTy<'tcx>],
+        dest: Option<PlaceTy<'tcx>>,
+        ret: Option<mir::BasicBlock>,
+    ) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>>;
 
-    /// directly process an intrinsic without pushing a stack frame.
+    /// Directly process an intrinsic without pushing a stack frame.
+    /// If this returns successfully, the engine will take care of jumping to the next block.
     fn call_intrinsic<'a>(
         ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
-        args: &[ValTy<'tcx>],
-        dest: Place,
-        dest_layout: ty::layout::TyLayout<'tcx>,
-        target: mir::BasicBlock,
+        args: &[OpTy<'tcx>],
+        dest: PlaceTy<'tcx>,
     ) -> EvalResult<'tcx>;
 
-    /// Called for all binary operations except on float types.
-    ///
-    /// Returns `None` if the operation should be handled by the integer
-    /// op code in order to share more code between machines
+    /// Called for read access to a foreign static item.
+    /// This can be called multiple times for the same static item and should return consistent
+    /// results.  Once the item is *written* the first time, as usual for statics a copy is
+    /// made and this function is not called again.
+    fn find_foreign_static<'a>(
+        tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
+        def_id: DefId,
+    ) -> EvalResult<'tcx, &'tcx Allocation>;
+
+    /// Called for all binary operations on integer(-like) types when one operand is a pointer
+    /// value, and for the `Offset` operation that is inherently about pointers.
     ///
     /// Returns a (value, overflowed) pair if the operation succeeded
-    fn try_ptr_op<'a>(
+    fn ptr_op<'a>(
         ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
         bin_op: mir::BinOp,
         left: Scalar,
-        left_ty: Ty<'tcx>,
+        left_layout: TyLayout<'tcx>,
         right: Scalar,
-        right_ty: Ty<'tcx>,
-    ) -> EvalResult<'tcx, Option<(Scalar, bool)>>;
-
-    /// Called when trying to mark machine defined `MemoryKinds` as static
-    fn mark_static_initialized<'a>(
-        _mem: &mut Memory<'a, 'mir, 'tcx, Self>,
-        _id: AllocId,
-        _mutability: Mutability,
-    ) -> EvalResult<'tcx, bool>;
-
-    /// Called when requiring a pointer to a static. Non const eval can
-    /// create a mutable memory location for `static mut`
-    fn init_static<'a>(
-        ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
-        cid: GlobalId<'tcx>,
-    ) -> EvalResult<'tcx, AllocId>;
+        right_layout: TyLayout<'tcx>,
+    ) -> EvalResult<'tcx, (Scalar, bool)>;
 
     /// Heap allocations via the `box` keyword
     ///
     /// Returns a pointer to the allocated memory
     fn box_alloc<'a>(
         ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
-        ty: Ty<'tcx>,
-        dest: Place,
+        dest: PlaceTy<'tcx>,
     ) -> EvalResult<'tcx>;
 
-    /// Called when trying to access a global declared with a `linkage` attribute
-    fn global_item_with_linkage<'a>(
-        ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
-        instance: ty::Instance<'tcx>,
-        mutability: Mutability,
-    ) -> EvalResult<'tcx>;
-
-    fn check_locks<'a>(
-        _mem: &Memory<'a, 'mir, 'tcx, Self>,
-        _ptr: Pointer,
-        _size: Size,
-        _access: AccessKind,
-    ) -> EvalResult<'tcx> {
-        Ok(())
-    }
-
-    fn add_lock<'a>(
-        _mem: &mut Memory<'a, 'mir, 'tcx, Self>,
-        _id: AllocId,
-    ) {}
-
-    fn free_lock<'a>(
-        _mem: &mut Memory<'a, 'mir, 'tcx, Self>,
-        _id: AllocId,
-        _len: u64,
-    ) -> EvalResult<'tcx> {
-        Ok(())
-    }
-
-    fn end_region<'a>(
-        _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
-        _reg: Option<::rustc::middle::region::Scope>,
-    ) -> EvalResult<'tcx> {
-        Ok(())
-    }
-
+    /// Execute a validation operation
     fn validation_op<'a>(
         _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
         _op: ::rustc::mir::ValidationOp,
index b62add8a559b41b3d9dc152f5327416e1190ae7e..59bebbb87a7755289ffd46041ffdce433251a61d 100644 (file)
@@ -1,26 +1,38 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! The memory subsystem.
+//!
+//! Generally, we use `Pointer` to denote memory addresses. However, some operations
+//! have a "size"-like parameter, and they take `Scalar` for the address because
+//! if the size is 0, then the pointer can also be a (properly aligned, non-NULL)
+//! integer.  It is crucial that these operations call `check_align` *before*
+//! short-circuiting the empty case!
+
 use std::collections::VecDeque;
 use std::hash::{Hash, Hasher};
 use std::ptr;
 
-use rustc::hir::def_id::DefId;
-use rustc::ty::Instance;
-use rustc::ty::ParamEnv;
-use rustc::ty::query::TyCtxtAt;
-use rustc::ty::layout::{self, Align, TargetDataLayout, Size};
-use rustc::mir::interpret::{Pointer, AllocId, Allocation, AccessKind, Value, ScalarMaybeUndef,
-                            EvalResult, Scalar, EvalErrorKind, GlobalId, AllocType};
-pub use rustc::mir::interpret::{write_target_uint, write_target_int, read_target_uint};
+use rustc::ty::{self, Instance, query::TyCtxtAt};
+use rustc::ty::layout::{self, Align, TargetDataLayout, Size, HasDataLayout};
+use rustc::mir::interpret::{Pointer, AllocId, Allocation, ConstValue, ScalarMaybeUndef, GlobalId,
+                            EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic,
+                            truncate};
+pub use rustc::mir::interpret::{write_target_uint, read_target_uint};
 use rustc_data_structures::fx::{FxHashSet, FxHashMap, FxHasher};
 
 use syntax::ast::Mutability;
 
-use super::{EvalContext, Machine};
-
-////////////////////////////////////////////////////////////////////////////////
-// Allocations and pointers
-////////////////////////////////////////////////////////////////////////////////
+use super::Machine;
 
-#[derive(Debug, PartialEq, Eq, Copy, Clone)]
+#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
 pub enum MemoryKind<T> {
     /// Error if deallocated except during a stack pop
     Stack,
@@ -28,27 +40,36 @@ pub enum MemoryKind<T> {
     Machine(T),
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// Top-level interpreter memory
-////////////////////////////////////////////////////////////////////////////////
-
 #[derive(Clone)]
 pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
     /// Additional data required by the Machine
     pub data: M::MemoryData,
 
-    /// Helps guarantee that stack allocations aren't deallocated via `rust_deallocate`
-    alloc_kind: FxHashMap<AllocId, MemoryKind<M::MemoryKinds>>,
-
-    /// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations).
-    alloc_map: FxHashMap<AllocId, Allocation>,
-
-    /// The current stack frame.  Used to check accesses against locks.
-    pub cur_frame: usize,
+    /// Allocations local to this instance of the miri engine.  The kind
+    /// helps ensure that the same mechanism is used for allocation and
+    /// deallocation.  When an allocation is not found here, it is a
+    /// static and looked up in the `tcx` for read access.  Writing to
+    /// a static creates a copy here, in the machine.
+    alloc_map: FxHashMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation)>,
 
     pub tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
 }
 
+impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for &'a Memory<'a, 'mir, 'tcx, M> {
+    #[inline]
+    fn data_layout(&self) -> &TargetDataLayout {
+        &self.tcx.data_layout
+    }
+}
+impl<'a, 'b, 'c, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout
+    for &'b &'c mut Memory<'a, 'mir, 'tcx, M>
+{
+    #[inline]
+    fn data_layout(&self) -> &TargetDataLayout {
+        &self.tcx.data_layout
+    }
+}
+
 impl<'a, 'mir, 'tcx, M> Eq for Memory<'a, 'mir, 'tcx, M>
     where M: Machine<'mir, 'tcx>,
           'tcx: 'a + 'mir,
@@ -61,16 +82,12 @@ impl<'a, 'mir, 'tcx, M> PartialEq for Memory<'a, 'mir, 'tcx, M>
     fn eq(&self, other: &Self) -> bool {
         let Memory {
             data,
-            alloc_kind,
             alloc_map,
-            cur_frame,
             tcx: _,
         } = self;
 
         *data == other.data
-            && *alloc_kind == other.alloc_kind
             && *alloc_map == other.alloc_map
-            && *cur_frame == other.cur_frame
     }
 }
 
@@ -81,14 +98,11 @@ impl<'a, 'mir, 'tcx, M> Hash for Memory<'a, 'mir, 'tcx, M>
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Memory {
             data,
-            alloc_kind: _,
             alloc_map: _,
-            cur_frame,
             tcx: _,
         } = self;
 
         data.hash(state);
-        cur_frame.hash(state);
 
         // We ignore some fields which don't change between evaluation steps.
 
@@ -96,10 +110,11 @@ fn hash<H: Hasher>(&self, state: &mut H) {
         // iteration orders, we use a commutative operation (in this case
         // addition, but XOR would also work), to combine the hash of each
         // `Allocation`.
-        self.allocations()
-            .map(|allocs| {
+        self.alloc_map.iter()
+            .map(|(&id, alloc)| {
                 let mut h = FxHasher::default();
-                allocs.hash(&mut h);
+                id.hash(&mut h);
+                alloc.hash(&mut h);
                 h.finish()
             })
             .fold(0u64, |hash, x| hash.wrapping_add(x))
@@ -111,48 +126,36 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
     pub fn new(tcx: TyCtxtAt<'a, 'tcx, 'tcx>, data: M::MemoryData) -> Self {
         Memory {
             data,
-            alloc_kind: FxHashMap::default(),
             alloc_map: FxHashMap::default(),
             tcx,
-            cur_frame: usize::max_value(),
         }
     }
 
-    pub fn allocations<'x>(
-        &'x self,
-    ) -> impl Iterator<Item = (AllocId, &'x Allocation)> {
-        self.alloc_map.iter().map(|(&id, alloc)| (id, alloc))
-    }
-
     pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> Pointer {
         self.tcx.alloc_map.lock().create_fn_alloc(instance).into()
     }
 
-    pub fn allocate_bytes(&mut self, bytes: &[u8]) -> Pointer {
+    pub fn allocate_static_bytes(&mut self, bytes: &[u8]) -> Pointer {
         self.tcx.allocate_bytes(bytes).into()
     }
 
-    /// kind is `None` for statics
-    pub fn allocate_value(
+    pub fn allocate_with(
         &mut self,
         alloc: Allocation,
         kind: MemoryKind<M::MemoryKinds>,
     ) -> EvalResult<'tcx, AllocId> {
         let id = self.tcx.alloc_map.lock().reserve();
-        M::add_lock(self, id);
-        self.alloc_map.insert(id, alloc);
-        self.alloc_kind.insert(id, kind);
+        self.alloc_map.insert(id, (kind, alloc));
         Ok(id)
     }
 
-    /// kind is `None` for statics
     pub fn allocate(
         &mut self,
         size: Size,
         align: Align,
         kind: MemoryKind<M::MemoryKinds>,
     ) -> EvalResult<'tcx, Pointer> {
-        self.allocate_value(Allocation::undef(size, align), kind).map(Pointer::from)
+        self.allocate_with(Allocation::undef(size, align), kind).map(Pointer::from)
     }
 
     pub fn reallocate(
@@ -167,15 +170,6 @@ pub fn reallocate(
         if ptr.offset.bytes() != 0 {
             return err!(ReallocateNonBasePtr);
         }
-        if self.alloc_map.contains_key(&ptr.alloc_id) {
-            let alloc_kind = self.alloc_kind[&ptr.alloc_id];
-            if alloc_kind != kind {
-                return err!(ReallocatedWrongMemoryKind(
-                    format!("{:?}", alloc_kind),
-                    format!("{:?}", kind),
-                ));
-            }
-        }
 
         // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc"
         let new_ptr = self.allocate(new_size, new_align, kind)?;
@@ -185,20 +179,21 @@ pub fn reallocate(
             new_ptr.into(),
             new_align,
             old_size.min(new_size),
-            /*nonoverlapping*/
-            true,
+            /*nonoverlapping*/ true,
         )?;
         self.deallocate(ptr, Some((old_size, old_align)), kind)?;
 
         Ok(new_ptr)
     }
 
+    /// Deallocate a local, or do nothing if that local has been made into a static
     pub fn deallocate_local(&mut self, ptr: Pointer) -> EvalResult<'tcx> {
-        match self.alloc_kind.get(&ptr.alloc_id).cloned() {
-            Some(MemoryKind::Stack) => self.deallocate(ptr, None, MemoryKind::Stack),
-            // Happens if the memory was interned into immutable memory
-            None => Ok(()),
-            other => bug!("local contained non-stack memory: {:?}", other),
+        // The allocation might be already removed by static interning.
+        // This can only really happen in the CTFE instance, not in miri.
+        if self.alloc_map.contains_key(&ptr.alloc_id) {
+            self.deallocate(ptr, None, MemoryKind::Stack)
+        } else {
+            Ok(())
         }
     }
 
@@ -212,9 +207,10 @@ pub fn deallocate(
             return err!(DeallocateNonBasePtr);
         }
 
-        let alloc = match self.alloc_map.remove(&ptr.alloc_id) {
+        let (alloc_kind, alloc) = match self.alloc_map.remove(&ptr.alloc_id) {
             Some(alloc) => alloc,
             None => {
+                // Deallocating static memory -- always an error
                 return match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
                     Some(AllocType::Function(..)) => err!(DeallocatedWrongMemoryKind(
                         "function".to_string(),
@@ -230,15 +226,6 @@ pub fn deallocate(
             }
         };
 
-        let alloc_kind = self.alloc_kind.remove(&ptr.alloc_id).expect("alloc_map out of sync with alloc_kind");
-
-        // It is okay for us to still holds locks on deallocation -- for example, we could store data we own
-        // in a local, and the local could be deallocated (from StorageDead) before the function returns.
-        // However, we should check *something*.  For now, we make sure that there is no conflicting write
-        // lock by another frame.  We *have* to permit deallocation if we hold a read lock.
-        // TODO: Figure out the exact rules here.
-        M::free_lock(self, ptr.alloc_id, alloc.bytes.len() as u64)?;
-
         if alloc_kind != kind {
             return err!(DeallocatedWrongMemoryKind(
                 format!("{:?}", alloc_kind),
@@ -247,7 +234,11 @@ pub fn deallocate(
         }
         if let Some((size, align)) = size_and_align {
             if size.bytes() != alloc.bytes.len() as u64 || align != alloc.align {
-                return err!(IncorrectAllocationInformation(size, Size::from_bytes(alloc.bytes.len() as u64), align, alloc.align));
+                let bytes = Size::from_bytes(alloc.bytes.len() as u64);
+                return err!(IncorrectAllocationInformation(size,
+                                                           bytes,
+                                                           align,
+                                                           alloc.align));
             }
         }
 
@@ -256,15 +247,8 @@ pub fn deallocate(
         Ok(())
     }
 
-    pub fn pointer_size(&self) -> Size {
-        self.tcx.data_layout.pointer_size
-    }
-
-    pub fn endianness(&self) -> layout::Endian {
-        self.tcx.data_layout.endian
-    }
-
-    /// Check that the pointer is aligned AND non-NULL.
+    /// Check that the pointer is aligned AND non-NULL. This supports scalars
+    /// for the benefit of other parts of miri that need to check alignment even for ZST.
     pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx> {
         // Check non-NULL/Undef, extract offset
         let (offset, alloc_align) = match ptr {
@@ -274,13 +258,12 @@ pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx
             }
             Scalar::Bits { bits, size } => {
                 assert_eq!(size as u64, self.pointer_size().bytes());
-                // FIXME: what on earth does this line do? docs or fix needed!
-                let v = ((bits as u128) % (1 << self.pointer_size().bytes())) as u64;
-                if v == 0 {
+                assert!(bits < (1u128 << self.pointer_size().bits()));
+                if bits == 0 {
                     return err!(InvalidNullPointerUsage);
                 }
-                // the base address if the "integer allocation" is 0 and hence always aligned
-                (v, required_align)
+                // the "base address" is 0 and hence always aligned
+                (bits as u64, required_align)
             }
         };
         // Check alignment
@@ -301,6 +284,13 @@ pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx
         }
     }
 
+    /// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end
+    /// of an allocation (i.e., at the first *inaccessible* location) *is* considered
+    /// in-bounds!  This follows C's/LLVM's rules.  The `access` boolean is just used
+    /// for the error message.
+    /// If you want to check bounds before doing a memory access, be sure to
+    /// check the pointer one past the end of your access, then everything will
+    /// work out exactly.
     pub fn check_bounds(&self, ptr: Pointer, access: bool) -> EvalResult<'tcx> {
         let alloc = self.get(ptr.alloc_id)?;
         let allocation_size = alloc.bytes.len() as u64;
@@ -317,63 +307,79 @@ pub fn check_bounds(&self, ptr: Pointer, access: bool) -> EvalResult<'tcx> {
 
 /// Allocation accessors
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
-    fn const_eval_static(&self, def_id: DefId) -> EvalResult<'tcx, &'tcx Allocation> {
-        if self.tcx.is_foreign_item(def_id) {
-            return err!(ReadForeignStatic);
+    /// Helper function to obtain the global (tcx) allocation for a static
+    fn get_static_alloc(
+        tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
+        id: AllocId,
+    ) -> EvalResult<'tcx, &'tcx Allocation> {
+        let alloc = tcx.alloc_map.lock().get(id);
+        let def_id = match alloc {
+            Some(AllocType::Memory(mem)) => {
+                return Ok(mem)
+            }
+            Some(AllocType::Function(..)) => {
+                return err!(DerefFunctionPointer)
+            }
+            Some(AllocType::Static(did)) => {
+                did
+            }
+            None =>
+                return err!(DanglingPointerDeref),
+        };
+        // We got a "lazy" static that has not been computed yet, do some work
+        trace!("static_alloc: Need to compute {:?}", def_id);
+        if tcx.is_foreign_item(def_id) {
+            return M::find_foreign_static(tcx, def_id);
         }
-        let instance = Instance::mono(self.tcx.tcx, def_id);
+        let instance = Instance::mono(tcx.tcx, def_id);
         let gid = GlobalId {
             instance,
             promoted: None,
         };
-        self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|err| {
+        tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| {
             // no need to report anything, the const_eval call takes care of that for statics
-            assert!(self.tcx.is_static(def_id).is_some());
+            assert!(tcx.is_static(def_id).is_some());
             EvalErrorKind::ReferencedConstant(err).into()
-        }).map(|val| {
-            self.tcx.const_value_to_allocation(val)
+        }).map(|const_val| {
+            if let ConstValue::ByRef(_, allocation, _) = const_val.val {
+                allocation
+            } else {
+                bug!("Matching on non-ByRef static")
+            }
         })
     }
 
     pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> {
-        // normal alloc?
         match self.alloc_map.get(&id) {
-            Some(alloc) => Ok(alloc),
-            // uninitialized static alloc?
-            None => {
-                // static alloc?
-                let alloc = self.tcx.alloc_map.lock().get(id);
-                match alloc {
-                    Some(AllocType::Memory(mem)) => Ok(mem),
-                    Some(AllocType::Function(..)) => {
-                        Err(EvalErrorKind::DerefFunctionPointer.into())
-                    }
-                    Some(AllocType::Static(did)) => {
-                        self.const_eval_static(did)
-                    }
-                    None => Err(EvalErrorKind::DanglingPointerDeref.into()),
-                }
-            },
+            // Normal alloc?
+            Some(alloc) => Ok(&alloc.1),
+            // Static. No need to make any copies, just provide read access to the global static
+            // memory in tcx.
+            None => Self::get_static_alloc(self.tcx, id),
         }
     }
 
-    fn get_mut(
+    pub fn get_mut(
         &mut self,
         id: AllocId,
     ) -> EvalResult<'tcx, &mut Allocation> {
-        // normal alloc?
-        match self.alloc_map.get_mut(&id) {
-            Some(alloc) => Ok(alloc),
-            // uninitialized static alloc?
-            None => {
-                // no alloc or immutable alloc? produce an error
-                match self.tcx.alloc_map.lock().get(id) {
-                    Some(AllocType::Memory(..)) |
-                    Some(AllocType::Static(..)) => err!(ModifiedConstantMemory),
-                    Some(AllocType::Function(..)) => err!(DerefFunctionPointer),
-                    None => err!(DanglingPointerDeref),
-                }
-            },
+        // Static?
+        if !self.alloc_map.contains_key(&id) {
+            // Ask the machine for what to do
+            if let Some(kind) = M::MUT_STATIC_KIND {
+                // The machine supports mutating statics.  Make a copy, use that.
+                self.deep_copy_static(id, MemoryKind::Machine(kind))?;
+            } else {
+                return err!(ModifiedConstantMemory)
+            }
+        }
+        // If we come here, we know the allocation is in our map
+        let alloc = &mut self.alloc_map.get_mut(&id).unwrap().1;
+        // See if we are allowed to mutate this
+        if alloc.mutability == Mutability::Immutable {
+            err!(ModifiedConstantMemory)
+        } else {
+            Ok(alloc)
         }
     }
 
@@ -381,17 +387,13 @@ pub fn get_fn(&self, ptr: Pointer) -> EvalResult<'tcx, Instance<'tcx>> {
         if ptr.offset.bytes() != 0 {
             return err!(InvalidFunctionPointer);
         }
-        debug!("reading fn ptr: {}", ptr.alloc_id);
+        trace!("reading fn ptr: {}", ptr.alloc_id);
         match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
             Some(AllocType::Function(instance)) => Ok(instance),
             _ => Err(EvalErrorKind::ExecuteMemory.into()),
         }
     }
 
-    pub fn get_alloc_kind(&self, id: AllocId) -> Option<MemoryKind<M::MemoryKinds>> {
-        self.alloc_kind.get(&id).cloned()
-    }
-
     /// For debugging, print an allocation and all allocations it points to, recursively.
     pub fn dump_alloc(&self, id: AllocId) {
         if !log_enabled!(::log::Level::Trace) {
@@ -419,14 +421,14 @@ pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
             let (alloc, immutable) =
                 // normal alloc?
                 match self.alloc_map.get(&id) {
-                    Some(a) => (a, match self.alloc_kind[&id] {
+                    Some((kind, alloc)) => (alloc, match kind {
                         MemoryKind::Stack => " (stack)".to_owned(),
                         MemoryKind::Machine(m) => format!(" ({:?})", m),
                     }),
                     None => {
                         // static alloc?
                         match self.tcx.alloc_map.lock().get(id) {
-                            Some(AllocType::Memory(a)) => (a, "(immutable)".to_owned()),
+                            Some(AllocType::Memory(a)) => (a, " (immutable)".to_owned()),
                             Some(AllocType::Function(func)) => {
                                 trace!("{} {}", msg, func);
                                 continue;
@@ -487,9 +489,12 @@ pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
 
     pub fn leak_report(&self) -> usize {
         trace!("### LEAK REPORT ###");
+        let mut_static_kind = M::MUT_STATIC_KIND.map(|k| MemoryKind::Machine(k));
         let leaks: Vec<_> = self.alloc_map
-            .keys()
-            .cloned()
+            .iter()
+            .filter_map(|(&id, &(kind, _))|
+                // exclude mutable statics
+                if Some(kind) == mut_static_kind { None } else { Some(id) } )
             .collect();
         let n = leaks.len();
         self.dump_allocs(leaks);
@@ -499,19 +504,29 @@ pub fn leak_report(&self) -> usize {
 
 /// Byte accessors
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
-    fn get_bytes_unchecked(
+    /// The last argument controls whether we error out when there are undefined
+    /// or pointer bytes.  You should never call this, call `get_bytes` or
+    /// `get_bytes_with_undef_and_ptr` instead,
+    fn get_bytes_internal(
         &self,
         ptr: Pointer,
         size: Size,
         align: Align,
+        check_defined_and_ptr: bool,
     ) -> EvalResult<'tcx, &[u8]> {
-        // Zero-sized accesses can use dangling pointers, but they still have to be aligned and non-NULL
+        assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`");
         self.check_align(ptr.into(), align)?;
-        if size.bytes() == 0 {
-            return Ok(&[]);
+        // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
+        self.check_bounds(ptr.offset(size, &*self)?, true)?;
+
+        if check_defined_and_ptr {
+            self.check_defined(ptr, size)?;
+            self.check_relocations(ptr, size)?;
+        } else {
+            // We still don't want relocations on the *edges*
+            self.check_relocation_edges(ptr, size)?;
         }
-        M::check_locks(self, ptr, size, AccessKind::Read)?;
-        self.check_bounds(ptr.offset(size, self)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
+
         let alloc = self.get(ptr.alloc_id)?;
         assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
         assert_eq!(size.bytes() as usize as u64, size.bytes());
@@ -519,66 +534,51 @@ fn get_bytes_unchecked(
         Ok(&alloc.bytes[offset..offset + size.bytes() as usize])
     }
 
-    fn get_bytes_unchecked_mut(
-        &mut self,
-        ptr: Pointer,
-        size: Size,
-        align: Align,
-    ) -> EvalResult<'tcx, &mut [u8]> {
-        // Zero-sized accesses can use dangling pointers, but they still have to be aligned and non-NULL
-        self.check_align(ptr.into(), align)?;
-        if size.bytes() == 0 {
-            return Ok(&mut []);
-        }
-        M::check_locks(self, ptr, size, AccessKind::Write)?;
-        self.check_bounds(ptr.offset(size, &*self)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
-        let alloc = self.get_mut(ptr.alloc_id)?;
-        assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
-        assert_eq!(size.bytes() as usize as u64, size.bytes());
-        let offset = ptr.offset.bytes() as usize;
-        Ok(&mut alloc.bytes[offset..offset + size.bytes() as usize])
+    #[inline]
+    fn get_bytes(&self, ptr: Pointer, size: Size, align: Align) -> EvalResult<'tcx, &[u8]> {
+        self.get_bytes_internal(ptr, size, align, true)
     }
 
-    fn get_bytes(&self, ptr: Pointer, size: Size, align: Align) -> EvalResult<'tcx, &[u8]> {
-        assert_ne!(size.bytes(), 0);
-        if self.relocations(ptr, size)?.len() != 0 {
-            return err!(ReadPointerAsBytes);
-        }
-        self.check_defined(ptr, size)?;
-        self.get_bytes_unchecked(ptr, size, align)
+    /// It is the caller's responsibility to handle undefined and pointer bytes.
+    /// However, this still checks that there are no relocations on the egdes.
+    #[inline]
+    fn get_bytes_with_undef_and_ptr(
+        &self,
+        ptr: Pointer,
+        size: Size,
+        align: Align
+    ) -> EvalResult<'tcx, &[u8]> {
+        self.get_bytes_internal(ptr, size, align, false)
     }
 
+    /// Just calling this already marks everything as defined and removes relocations,
+    /// so be sure to actually put data there!
     fn get_bytes_mut(
         &mut self,
         ptr: Pointer,
         size: Size,
         align: Align,
     ) -> EvalResult<'tcx, &mut [u8]> {
-        assert_ne!(size.bytes(), 0);
+        assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`");
+        self.check_align(ptr.into(), align)?;
+        // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
+        self.check_bounds(ptr.offset(size, &self)?, true)?;
+
+        self.mark_definedness(ptr, size, true)?;
         self.clear_relocations(ptr, size)?;
-        self.mark_definedness(ptr.into(), size, true)?;
-        self.get_bytes_unchecked_mut(ptr, size, align)
+
+        let alloc = self.get_mut(ptr.alloc_id)?;
+        assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
+        assert_eq!(size.bytes() as usize as u64, size.bytes());
+        let offset = ptr.offset.bytes() as usize;
+        Ok(&mut alloc.bytes[offset..offset + size.bytes() as usize])
     }
 }
 
 /// Reading and writing
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
-    /// mark an allocation pointed to by a static as static and initialized
-    fn mark_inner_allocation_initialized(
-        &mut self,
-        alloc: AllocId,
-        mutability: Mutability,
-    ) -> EvalResult<'tcx> {
-        match self.alloc_kind.get(&alloc) {
-            // do not go into statics
-            None => Ok(()),
-            // just locals and machine allocs
-            Some(_) => self.mark_static_initialized(alloc, mutability),
-        }
-    }
-
     /// mark an allocation as static and initialized, either mutable or not
-    pub fn mark_static_initialized(
+    pub fn intern_static(
         &mut self,
         alloc_id: AllocId,
         mutability: Mutability,
@@ -588,31 +588,48 @@ pub fn mark_static_initialized(
             alloc_id,
             mutability
         );
-        // The machine handled it
-        if M::mark_static_initialized(self, alloc_id, mutability)? {
-            return Ok(())
-        }
-        let alloc = self.alloc_map.remove(&alloc_id);
-        match self.alloc_kind.remove(&alloc_id) {
-            None => {},
-            Some(MemoryKind::Machine(_)) => bug!("machine didn't handle machine alloc"),
-            Some(MemoryKind::Stack) => {},
+        // remove allocation
+        let (kind, mut alloc) = self.alloc_map.remove(&alloc_id).unwrap();
+        match kind {
+            MemoryKind::Machine(_) => bug!("Static cannot refer to machine memory"),
+            MemoryKind::Stack => {},
         }
-        if let Some(mut alloc) = alloc {
-            // ensure llvm knows not to put this into immutable memroy
-            alloc.runtime_mutability = mutability;
-            let alloc = self.tcx.intern_const_alloc(alloc);
-            self.tcx.alloc_map.lock().set_id_memory(alloc_id, alloc);
-            // recurse into inner allocations
-            for &alloc in alloc.relocations.values() {
-                self.mark_inner_allocation_initialized(alloc, mutability)?;
+        // ensure llvm knows not to put this into immutable memory
+        alloc.mutability = mutability;
+        let alloc = self.tcx.intern_const_alloc(alloc);
+        self.tcx.alloc_map.lock().set_id_memory(alloc_id, alloc);
+        // recurse into inner allocations
+        for &alloc in alloc.relocations.values() {
+            // FIXME: Reusing the mutability here is likely incorrect.  It is originally
+            // determined via `is_freeze`, and data is considered frozen if there is no
+            // `UnsafeCell` *immediately* in that data -- however, this search stops
+            // at references.  So whenever we follow a reference, we should likely
+            // assume immutability -- and we should make sure that the compiler
+            // does not permit code that would break this!
+            if self.alloc_map.contains_key(&alloc) {
+                // Not yet interned, so proceed recursively
+                self.intern_static(alloc, mutability)?;
             }
-        } else {
-            bug!("no allocation found for {:?}", alloc_id);
         }
         Ok(())
     }
 
+    /// The alloc_id must refer to a (mutable) static; a deep copy of that
+    /// static is made into this memory.
+    fn deep_copy_static(
+        &mut self,
+        id: AllocId,
+        kind: MemoryKind<M::MemoryKinds>,
+    ) -> EvalResult<'tcx> {
+        let alloc = Self::get_static_alloc(self.tcx, id)?;
+        if alloc.mutability == Mutability::Immutable {
+            return err!(ModifiedConstantMemory);
+        }
+        let old = self.alloc_map.insert(id, (kind, alloc.clone()));
+        assert!(old.is_none(), "deep_copy_static: must not overwrite existing memory");
+        Ok(())
+    }
+
     pub fn copy(
         &mut self,
         src: Scalar,
@@ -635,19 +652,20 @@ pub fn copy_repeatedly(
         length: u64,
         nonoverlapping: bool,
     ) -> EvalResult<'tcx> {
-        // Empty accesses don't need to be valid pointers, but they should still be aligned
-        self.check_align(src, src_align)?;
-        self.check_align(dest, dest_align)?;
         if size.bytes() == 0 {
+            // Nothing to do for ZST, other than checking alignment and non-NULLness.
+            self.check_align(src, src_align)?;
+            self.check_align(dest, dest_align)?;
             return Ok(());
         }
         let src = src.to_ptr()?;
         let dest = dest.to_ptr()?;
-        self.check_relocation_edges(src, size)?;
 
         // first copy the relocations to a temporary buffer, because
         // `get_bytes_mut` will clear the relocations, which is correct,
         // since we don't want to keep any relocations at the target.
+        // (`get_bytes_with_undef_and_ptr` below checks that there are no
+        // relocations overlapping the edges; those would not be handled correctly).
         let relocations = {
             let relocations = self.relocations(src, size)?;
             let mut new_relocations = Vec::with_capacity(relocations.len() * (length as usize));
@@ -656,7 +674,8 @@ pub fn copy_repeatedly(
                     relocations
                     .iter()
                     .map(|&(offset, alloc_id)| {
-                    (offset + dest.offset - src.offset + (i * size * relocations.len() as u64), alloc_id)
+                    (offset + dest.offset - src.offset + (i * size * relocations.len() as u64),
+                    alloc_id)
                     })
                 );
             }
@@ -664,7 +683,8 @@ pub fn copy_repeatedly(
             new_relocations
         };
 
-        let src_bytes = self.get_bytes_unchecked(src, size, src_align)?.as_ptr();
+        // This also checks alignment, and relocation edges on the src.
+        let src_bytes = self.get_bytes_with_undef_and_ptr(src, size, src_align)?.as_ptr();
         let dest_bytes = self.get_bytes_mut(dest, size * length, dest_align)?.as_mut_ptr();
 
         // SAFE: The above indexing would have panicked if there weren't at least `size` bytes
@@ -684,17 +704,22 @@ pub fn copy_repeatedly(
                 }
 
                 for i in 0..length {
-                    ptr::copy(src_bytes, dest_bytes.offset((size.bytes() * i) as isize), size.bytes() as usize);
+                    ptr::copy(src_bytes,
+                              dest_bytes.offset((size.bytes() * i) as isize),
+                              size.bytes() as usize);
                 }
             } else {
                 for i in 0..length {
-                    ptr::copy_nonoverlapping(src_bytes, dest_bytes.offset((size.bytes() * i) as isize), size.bytes() as usize);
+                    ptr::copy_nonoverlapping(src_bytes,
+                                             dest_bytes.offset((size.bytes() * i) as isize),
+                                             size.bytes() as usize);
                 }
             }
         }
 
+        // copy definedness to the destination
         self.copy_undef_mask(src, dest, size, length)?;
-        // copy back the relocations
+        // copy the relocations to the destination
         self.get_mut(dest.alloc_id)?.relocations.insert_presorted(relocations);
 
         Ok(())
@@ -707,11 +732,8 @@ pub fn read_c_str(&self, ptr: Pointer) -> EvalResult<'tcx, &[u8]> {
         match alloc.bytes[offset..].iter().position(|&c| c == 0) {
             Some(size) => {
                 let p1 = Size::from_bytes((size + 1) as u64);
-                if self.relocations(ptr, p1)?.len() != 0 {
-                    return err!(ReadPointerAsBytes);
-                }
+                self.check_relocations(ptr, p1)?;
                 self.check_defined(ptr, p1)?;
-                M::check_locks(self, ptr, p1, AccessKind::Read)?;
                 Ok(&alloc.bytes[offset..offset + size])
             }
             None => err!(UnterminatedCString(ptr)),
@@ -721,8 +743,8 @@ pub fn read_c_str(&self, ptr: Pointer) -> EvalResult<'tcx, &[u8]> {
     pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> {
         // Empty accesses don't need to be valid pointers, but they should still be non-NULL
         let align = Align::from_bytes(1, 1).unwrap();
-        self.check_align(ptr, align)?;
         if size.bytes() == 0 {
+            self.check_align(ptr, align)?;
             return Ok(&[]);
         }
         self.get_bytes(ptr.to_ptr()?, size, align)
@@ -731,8 +753,8 @@ pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> {
     pub fn write_bytes(&mut self, ptr: Scalar, src: &[u8]) -> EvalResult<'tcx> {
         // Empty accesses don't need to be valid pointers, but they should still be non-NULL
         let align = Align::from_bytes(1, 1).unwrap();
-        self.check_align(ptr, align)?;
         if src.is_empty() {
+            self.check_align(ptr, align)?;
             return Ok(());
         }
         let bytes = self.get_bytes_mut(ptr.to_ptr()?, Size::from_bytes(src.len() as u64), align)?;
@@ -743,8 +765,8 @@ pub fn write_bytes(&mut self, ptr: Scalar, src: &[u8]) -> EvalResult<'tcx> {
     pub fn write_repeat(&mut self, ptr: Scalar, val: u8, count: Size) -> EvalResult<'tcx> {
         // Empty accesses don't need to be valid pointers, but they should still be non-NULL
         let align = Align::from_bytes(1, 1).unwrap();
-        self.check_align(ptr, align)?;
         if count.bytes() == 0 {
+            self.check_align(ptr, align)?;
             return Ok(());
         }
         let bytes = self.get_bytes_mut(ptr.to_ptr()?, count, align)?;
@@ -754,53 +776,57 @@ pub fn write_repeat(&mut self, ptr: Scalar, val: u8, count: Size) -> EvalResult<
         Ok(())
     }
 
-    pub fn read_scalar(&self, ptr: Pointer, ptr_align: Align, size: Size) -> EvalResult<'tcx, ScalarMaybeUndef> {
-        self.check_relocation_edges(ptr, size)?; // Make sure we don't read part of a pointer as a pointer
-        let endianness = self.endianness();
-        let bytes = self.get_bytes_unchecked(ptr, size, ptr_align.min(self.int_align(size)))?;
+    /// Read a *non-ZST* scalar
+    pub fn read_scalar(
+        &self,
+        ptr: Pointer,
+        ptr_align: Align,
+        size: Size
+    ) -> EvalResult<'tcx, ScalarMaybeUndef> {
+        // get_bytes_unchecked tests alignment and relocation edges
+        let bytes = self.get_bytes_with_undef_and_ptr(
+            ptr, size, ptr_align.min(self.int_align(size))
+        )?;
         // Undef check happens *after* we established that the alignment is correct.
         // We must not return Ok() for unaligned pointers!
-        if self.check_defined(ptr, size).is_err() {
-            // this inflates undefined bytes to the entire scalar, even if only a few bytes are undefined
+        if !self.is_defined(ptr, size)? {
+            // this inflates undefined bytes to the entire scalar, even if only a few
+            // bytes are undefined
             return Ok(ScalarMaybeUndef::Undef);
         }
         // Now we do the actual reading
-        let bits = read_target_uint(endianness, bytes).unwrap();
+        let bits = read_target_uint(self.tcx.data_layout.endian, bytes).unwrap();
         // See if we got a pointer
         if size != self.pointer_size() {
-            if self.relocations(ptr, size)?.len() != 0 {
-                return err!(ReadPointerAsBytes);
-            }
+            // *Now* better make sure that the inside also is free of relocations.
+            self.check_relocations(ptr, size)?;
         } else {
             let alloc = self.get(ptr.alloc_id)?;
             match alloc.relocations.get(&ptr.offset) {
-                Some(&alloc_id) => return Ok(ScalarMaybeUndef::Scalar(Pointer::new(alloc_id, Size::from_bytes(bits as u64)).into())),
+                Some(&alloc_id) => {
+                    let ptr = Pointer::new(alloc_id, Size::from_bytes(bits as u64));
+                    return Ok(ScalarMaybeUndef::Scalar(ptr.into()))
+                }
                 None => {},
             }
         }
         // We don't. Just return the bits.
-        Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
-            bits,
-            size: size.bytes() as u8,
-        }))
+        Ok(ScalarMaybeUndef::Scalar(Scalar::from_uint(bits, size)))
     }
 
-    pub fn read_ptr_sized(&self, ptr: Pointer, ptr_align: Align) -> EvalResult<'tcx, ScalarMaybeUndef> {
+    pub fn read_ptr_sized(&self, ptr: Pointer, ptr_align: Align)
+        -> EvalResult<'tcx, ScalarMaybeUndef> {
         self.read_scalar(ptr, ptr_align, self.pointer_size())
     }
 
+    /// Write a *non-ZST* scalar
     pub fn write_scalar(
         &mut self,
-        ptr: Scalar,
+        ptr: Pointer,
         ptr_align: Align,
         val: ScalarMaybeUndef,
         type_size: Size,
-        type_align: Align,
-        signed: bool,
     ) -> EvalResult<'tcx> {
-        let endianness = self.endianness();
-        self.check_align(ptr, ptr_align)?;
-
         let val = match val {
             ScalarMaybeUndef::Scalar(scalar) => scalar,
             ScalarMaybeUndef::Undef => return self.mark_definedness(ptr, type_size, false),
@@ -812,27 +838,19 @@ pub fn write_scalar(
                 val.offset.bytes() as u128
             }
 
-            Scalar::Bits { size: 0, .. } => {
-                // nothing to do for ZSTs
-                assert_eq!(type_size.bytes(), 0);
-                return Ok(());
-            }
-
             Scalar::Bits { bits, size } => {
                 assert_eq!(size as u64, type_size.bytes());
+                debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
+                    "Unexpected value of size {} when writing to memory", size);
                 bits
             },
         };
 
-        let ptr = ptr.to_ptr()?;
-
         {
-            let dst = self.get_bytes_mut(ptr, type_size, ptr_align.min(type_align))?;
-            if signed {
-                write_target_int(endianness, dst, bytes as i128).unwrap();
-            } else {
-                write_target_uint(endianness, dst, bytes).unwrap();
-            }
+            // get_bytes_mut checks alignment
+            let endian = self.tcx.data_layout.endian;
+            let dst = self.get_bytes_mut(ptr, type_size, ptr_align)?;
+            write_target_uint(endian, dst, bytes).unwrap();
         }
 
         // See if we have to also write a relocation
@@ -849,9 +867,10 @@ pub fn write_scalar(
         Ok(())
     }
 
-    pub fn write_ptr_sized_unsigned(&mut self, ptr: Pointer, ptr_align: Align, val: ScalarMaybeUndef) -> EvalResult<'tcx> {
+    pub fn write_ptr_sized(&mut self, ptr: Pointer, ptr_align: Align, val: ScalarMaybeUndef)
+        -> EvalResult<'tcx> {
         let ptr_size = self.pointer_size();
-        self.write_scalar(ptr.into(), ptr_align, val, ptr_size, ptr_align, false)
+        self.write_scalar(ptr.into(), ptr_align, val, ptr_size)
     }
 
     fn int_align(&self, size: Size) -> Align {
@@ -871,16 +890,35 @@ fn int_align(&self, size: Size) -> Align {
 
 /// Relocations
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
+    /// Return all relocations overlapping with the given ptr-offset pair.
     fn relocations(
         &self,
         ptr: Pointer,
         size: Size,
     ) -> EvalResult<'tcx, &[(Size, AllocId)]> {
+        // We have to go back `pointer_size - 1` bytes, as that one would still overlap with
+        // the beginning of this range.
         let start = ptr.offset.bytes().saturating_sub(self.pointer_size().bytes() - 1);
-        let end = ptr.offset + size;
+        let end = ptr.offset + size; // this does overflow checking
         Ok(self.get(ptr.alloc_id)?.relocations.range(Size::from_bytes(start)..end))
     }
 
+    /// Check that there ar eno relocations overlapping with the given range.
+    #[inline(always)]
+    fn check_relocations(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
+        if self.relocations(ptr, size)?.len() != 0 {
+            err!(ReadPointerAsBytes)
+        } else {
+            Ok(())
+        }
+    }
+
+    /// Remove all relocations inside the given range.
+    /// If there are relocations overlapping with the edges, they
+    /// are removed as well *and* the bytes they cover are marked as
+    /// uninitialized.  This is a somewhat odd "spooky action at a distance",
+    /// but it allows strictly more code to run than if we would just error
+    /// immediately in that case.
     fn clear_relocations(&mut self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
         // Find the start and end of the given range and its outermost relocations.
         let (first, last) = {
@@ -913,12 +951,12 @@ fn clear_relocations(&mut self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
         Ok(())
     }
 
+    /// Error if there are relocations overlapping with the egdes of the
+    /// given memory range.
+    #[inline]
     fn check_relocation_edges(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
-        let overlapping_start = self.relocations(ptr, Size::ZERO)?.len();
-        let overlapping_end = self.relocations(ptr.offset(size, self)?, Size::ZERO)?.len();
-        if overlapping_start + overlapping_end != 0 {
-            return err!(ReadPointerAsBytes);
-        }
+        self.check_relocations(ptr, Size::ZERO)?;
+        self.check_relocations(ptr.offset(size, self)?, Size::ZERO)?;
         Ok(())
     }
 }
@@ -953,28 +991,32 @@ fn copy_undef_mask(
         Ok(())
     }
 
-    fn check_defined(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
+    fn is_defined(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx, bool> {
         let alloc = self.get(ptr.alloc_id)?;
-        if !alloc.undef_mask.is_range_defined(
+        Ok(alloc.undef_mask.is_range_defined(
             ptr.offset,
             ptr.offset + size,
-        )
-        {
-            return err!(ReadUndefBytes);
+        ))
+    }
+
+    #[inline]
+    fn check_defined(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
+        if self.is_defined(ptr, size)? {
+            Ok(())
+        } else {
+            err!(ReadUndefBytes)
         }
-        Ok(())
     }
 
     pub fn mark_definedness(
         &mut self,
-        ptr: Scalar,
+        ptr: Pointer,
         size: Size,
         new_state: bool,
     ) -> EvalResult<'tcx> {
         if size.bytes() == 0 {
             return Ok(());
         }
-        let ptr = ptr.to_ptr()?;
         let alloc = self.get_mut(ptr.alloc_id)?;
         alloc.undef_mask.set_range(
             ptr.offset,
@@ -984,100 +1026,3 @@ pub fn mark_definedness(
         Ok(())
     }
 }
-
-////////////////////////////////////////////////////////////////////////////////
-// Unaligned accesses
-////////////////////////////////////////////////////////////////////////////////
-
-pub trait HasMemory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
-    fn memory_mut(&mut self) -> &mut Memory<'a, 'mir, 'tcx, M>;
-    fn memory(&self) -> &Memory<'a, 'mir, 'tcx, M>;
-
-    /// Convert the value into a pointer (or a pointer-sized integer).  If the value is a ByRef,
-    /// this may have to perform a load.
-    fn into_ptr(
-        &self,
-        value: Value,
-    ) -> EvalResult<'tcx, ScalarMaybeUndef> {
-        Ok(match value {
-            Value::ByRef(ptr, align) => {
-                self.memory().read_ptr_sized(ptr.to_ptr()?, align)?
-            }
-            Value::Scalar(ptr) |
-            Value::ScalarPair(ptr, _) => ptr,
-        }.into())
-    }
-
-    fn into_ptr_vtable_pair(
-        &self,
-        value: Value,
-    ) -> EvalResult<'tcx, (ScalarMaybeUndef, Pointer)> {
-        match value {
-            Value::ByRef(ref_ptr, align) => {
-                let mem = self.memory();
-                let ptr = mem.read_ptr_sized(ref_ptr.to_ptr()?, align)?.into();
-                let vtable = mem.read_ptr_sized(
-                    ref_ptr.ptr_offset(mem.pointer_size(), &mem.tcx.data_layout)?.to_ptr()?,
-                    align
-                )?.unwrap_or_err()?.to_ptr()?;
-                Ok((ptr, vtable))
-            }
-
-            Value::ScalarPair(ptr, vtable) => Ok((ptr, vtable.unwrap_or_err()?.to_ptr()?)),
-            _ => bug!("expected ptr and vtable, got {:?}", value),
-        }
-    }
-
-    fn into_slice(
-        &self,
-        value: Value,
-    ) -> EvalResult<'tcx, (ScalarMaybeUndef, u64)> {
-        match value {
-            Value::ByRef(ref_ptr, align) => {
-                let mem = self.memory();
-                let ptr = mem.read_ptr_sized(ref_ptr.to_ptr()?, align)?.into();
-                let len = mem.read_ptr_sized(
-                    ref_ptr.ptr_offset(mem.pointer_size(), &mem.tcx.data_layout)?.to_ptr()?,
-                    align
-                )?.unwrap_or_err()?.to_bits(mem.pointer_size())? as u64;
-                Ok((ptr, len))
-            }
-            Value::ScalarPair(ptr, val) => {
-                let len = val.unwrap_or_err()?.to_bits(self.memory().pointer_size())?;
-                Ok((ptr, len as u64))
-            }
-            Value::Scalar(_) => bug!("expected ptr and length, got {:?}", value),
-        }
-    }
-}
-
-impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasMemory<'a, 'mir, 'tcx, M> for Memory<'a, 'mir, 'tcx, M> {
-    #[inline]
-    fn memory_mut(&mut self) -> &mut Memory<'a, 'mir, 'tcx, M> {
-        self
-    }
-
-    #[inline]
-    fn memory(&self) -> &Memory<'a, 'mir, 'tcx, M> {
-        self
-    }
-}
-
-impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasMemory<'a, 'mir, 'tcx, M> for EvalContext<'a, 'mir, 'tcx, M> {
-    #[inline]
-    fn memory_mut(&mut self) -> &mut Memory<'a, 'mir, 'tcx, M> {
-        &mut self.memory
-    }
-
-    #[inline]
-    fn memory(&self) -> &Memory<'a, 'mir, 'tcx, M> {
-        &self.memory
-    }
-}
-
-impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> layout::HasDataLayout for &'a Memory<'a, 'mir, 'tcx, M> {
-    #[inline]
-    fn data_layout(&self) -> &TargetDataLayout {
-        &self.tcx.data_layout
-    }
-}
index bc77f6e29d271dd61d7b21585f9c7b3ce75466da..462c4b8889dd1977dc06c8154a388ac92fe56c6e 100644 (file)
@@ -1,56 +1,49 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
 //! An interpreter for MIR used in CTFE and by miri
 
 mod cast;
-mod const_eval;
 mod eval_context;
 mod place;
+mod operand;
 mod machine;
 mod memory;
 mod operator;
 mod step;
 mod terminator;
 mod traits;
+mod validity;
+mod intrinsics;
 
 pub use self::eval_context::{
-    EvalContext, Frame, StackPopCleanup,
-    TyAndPacked, ValTy,
+    EvalContext, Frame, StackPopCleanup, LocalValue,
 };
 
-pub use self::place::{Place, PlaceExtra};
+pub use self::place::{Place, PlaceTy, MemPlace, MPlaceTy};
+
+pub use self::memory::{Memory, MemoryKind};
+
+pub use self::machine::Machine;
 
-pub use self::memory::{Memory, MemoryKind, HasMemory};
+pub use self::operand::{Value, ValTy, Operand, OpTy};
 
-pub use self::const_eval::{
+// reexports for compatibility
+pub use const_eval::{
     eval_promoted,
     mk_borrowck_eval_cx,
     mk_eval_cx,
     CompileTimeEvaluator,
-    const_value_to_allocation_provider,
+    const_to_allocation_provider,
     const_eval_provider,
-    const_val_field,
+    const_field,
     const_variant_index,
-    value_to_const_value,
+    op_to_const,
 };
-
-pub use self::machine::Machine;
-
-pub use self::memory::{write_target_uint, write_target_int, read_target_uint};
-
-use rustc::ty::layout::TyLayout;
-
-pub fn sign_extend(value: u128, layout: TyLayout<'_>) -> u128 {
-    let size = layout.size.bits();
-    assert!(layout.abi.is_signed());
-    // sign extend
-    let shift = 128 - size;
-    // shift the unsigned value to the left
-    // and back to the right as signed (essentially fills with FF on the left)
-    (((value << shift) as i128) >> shift) as u128
-}
-
-pub fn truncate(value: u128, layout: TyLayout<'_>) -> u128 {
-    let size = layout.size.bits();
-    let shift = 128 - size;
-    // truncate (shift left to drop out leftover values, shift right to fill with zeroes)
-    (value << shift) >> shift
-}
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
new file mode 100644 (file)
index 0000000..6f9e0cf
--- /dev/null
@@ -0,0 +1,597 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Functions concerning immediate values and operands, and reading from operands.
+//! All high-level functions to read from memory work on operands as sources.
+
+use std::hash::{Hash, Hasher};
+use std::convert::TryInto;
+
+use rustc::{mir, ty};
+use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt};
+use rustc_data_structures::indexed_vec::Idx;
+
+use rustc::mir::interpret::{
+    GlobalId, ConstValue, Scalar, EvalResult, Pointer, ScalarMaybeUndef, EvalErrorKind
+};
+use super::{EvalContext, Machine, MemPlace, MPlaceTy, MemoryKind};
+
+/// A `Value` represents a single immediate self-contained Rust value.
+///
+/// For optimization of a few very common cases, there is also a representation for a pair of
+/// primitive values (`ScalarPair`). It allows Miri to avoid making allocations for checked binary
+/// operations and fat pointers. This idea was taken from rustc's codegen.
+/// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely
+/// defined on `Value`, and do not have to work with a `Place`.
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub enum Value {
+    Scalar(ScalarMaybeUndef),
+    ScalarPair(ScalarMaybeUndef, ScalarMaybeUndef),
+}
+
+impl<'tcx> Value {
+    pub fn new_slice(
+        val: Scalar,
+        len: u64,
+        cx: impl HasDataLayout
+    ) -> Self {
+        Value::ScalarPair(val.into(), Scalar::from_uint(len, cx.data_layout().pointer_size).into())
+    }
+
+    pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self {
+        Value::ScalarPair(val.into(), Scalar::Ptr(vtable).into())
+    }
+
+    #[inline]
+    pub fn to_scalar_or_undef(self) -> ScalarMaybeUndef {
+        match self {
+            Value::Scalar(val) => val,
+            Value::ScalarPair(..) => bug!("Got a fat pointer where a scalar was expected"),
+        }
+    }
+
+    #[inline]
+    pub fn to_scalar(self) -> EvalResult<'tcx, Scalar> {
+        self.to_scalar_or_undef().not_undef()
+    }
+
+    #[inline]
+    pub fn to_scalar_pair(self) -> EvalResult<'tcx, (Scalar, Scalar)> {
+        match self {
+            Value::Scalar(..) => bug!("Got a thin pointer where a scalar pair was expected"),
+            Value::ScalarPair(a, b) => Ok((a.not_undef()?, b.not_undef()?))
+        }
+    }
+
+    /// Convert the value into a pointer (or a pointer-sized integer).
+    /// Throws away the second half of a ScalarPair!
+    #[inline]
+    pub fn to_scalar_ptr(self) -> EvalResult<'tcx, Scalar> {
+        match self {
+            Value::Scalar(ptr) |
+            Value::ScalarPair(ptr, _) => ptr.not_undef(),
+        }
+    }
+}
+
+// ScalarPair needs a type to interpret, so we often have a value and a type together
+// as input for binary and cast operations.
+#[derive(Copy, Clone, Debug)]
+pub struct ValTy<'tcx> {
+    value: Value,
+    pub layout: TyLayout<'tcx>,
+}
+
+impl<'tcx> ::std::ops::Deref for ValTy<'tcx> {
+    type Target = Value;
+    #[inline(always)]
+    fn deref(&self) -> &Value {
+        &self.value
+    }
+}
+
+/// An `Operand` is the result of computing a `mir::Operand`. It can be immediate,
+/// or still in memory.  The latter is an optimization, to delay reading that chunk of
+/// memory and to avoid having to store arbitrary-sized data here.
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub enum Operand {
+    Immediate(Value),
+    Indirect(MemPlace),
+}
+
+impl Operand {
+    #[inline]
+    pub fn to_mem_place(self) -> MemPlace {
+        match self {
+            Operand::Indirect(mplace) => mplace,
+            _ => bug!("to_mem_place: expected Operand::Indirect, got {:?}", self),
+
+        }
+    }
+
+    #[inline]
+    pub fn to_immediate(self) -> Value {
+        match self {
+            Operand::Immediate(val) => val,
+            _ => bug!("to_immediate: expected Operand::Immediate, got {:?}", self),
+
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug)]
+pub struct OpTy<'tcx> {
+    crate op: Operand, // ideally we'd make this private, but const_prop needs this
+    pub layout: TyLayout<'tcx>,
+}
+
+impl<'tcx> ::std::ops::Deref for OpTy<'tcx> {
+    type Target = Operand;
+    #[inline(always)]
+    fn deref(&self) -> &Operand {
+        &self.op
+    }
+}
+
+impl<'tcx> From<MPlaceTy<'tcx>> for OpTy<'tcx> {
+    #[inline(always)]
+    fn from(mplace: MPlaceTy<'tcx>) -> Self {
+        OpTy {
+            op: Operand::Indirect(*mplace),
+            layout: mplace.layout
+        }
+    }
+}
+
+impl<'tcx> From<ValTy<'tcx>> for OpTy<'tcx> {
+    #[inline(always)]
+    fn from(val: ValTy<'tcx>) -> Self {
+        OpTy {
+            op: Operand::Immediate(val.value),
+            layout: val.layout
+        }
+    }
+}
+
+// Validation needs to hash OpTy, but we cannot hash Layout -- so we just hash the type
+impl<'tcx> Hash for OpTy<'tcx> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.op.hash(state);
+        self.layout.ty.hash(state);
+    }
+}
+impl<'tcx> PartialEq for OpTy<'tcx> {
+    fn eq(&self, other: &Self) -> bool {
+        self.op == other.op && self.layout.ty == other.layout.ty
+    }
+}
+impl<'tcx> Eq for OpTy<'tcx> {}
+
+// Use the existing layout if given (but sanity check in debug mode),
+// or compute the layout.
+#[inline(always)]
+fn from_known_layout<'tcx>(
+    layout: Option<TyLayout<'tcx>>,
+    compute: impl FnOnce() -> EvalResult<'tcx, TyLayout<'tcx>>
+) -> EvalResult<'tcx, TyLayout<'tcx>> {
+    match layout {
+        None => compute(),
+        Some(layout) => {
+            if cfg!(debug_assertions) {
+                let layout2 = compute()?;
+                assert_eq!(layout.details, layout2.details,
+                    "Mismatch in layout of supposedly equal-layout types {:?} and {:?}",
+                    layout.ty, layout2.ty);
+            }
+            Ok(layout)
+        }
+    }
+}
+
+impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+    /// Try reading a value in memory; this is interesting particularily for ScalarPair.
+    /// Return None if the layout does not permit loading this as a value.
+    pub(super) fn try_read_value_from_mplace(
+        &self,
+        mplace: MPlaceTy<'tcx>,
+    ) -> EvalResult<'tcx, Option<Value>> {
+        if mplace.layout.is_unsized() {
+            // Dont touch unsized
+            return Ok(None);
+        }
+        let (ptr, ptr_align) = mplace.to_scalar_ptr_align();
+
+        if mplace.layout.size.bytes() == 0 {
+            // Not all ZSTs have a layout we would handle below, so just short-circuit them
+            // all here.
+            self.memory.check_align(ptr, ptr_align)?;
+            return Ok(Some(Value::Scalar(Scalar::zst().into())));
+        }
+
+        let ptr = ptr.to_ptr()?;
+        match mplace.layout.abi {
+            layout::Abi::Scalar(..) => {
+                let scalar = self.memory.read_scalar(ptr, ptr_align, mplace.layout.size)?;
+                Ok(Some(Value::Scalar(scalar)))
+            }
+            layout::Abi::ScalarPair(ref a, ref b) => {
+                let (a, b) = (&a.value, &b.value);
+                let (a_size, b_size) = (a.size(self), b.size(self));
+                let a_ptr = ptr;
+                let b_offset = a_size.abi_align(b.align(self));
+                assert!(b_offset.bytes() > 0); // we later use the offset to test which field to use
+                let b_ptr = ptr.offset(b_offset, self)?.into();
+                let a_val = self.memory.read_scalar(a_ptr, ptr_align, a_size)?;
+                let b_val = self.memory.read_scalar(b_ptr, ptr_align, b_size)?;
+                Ok(Some(Value::ScalarPair(a_val, b_val)))
+            }
+            _ => Ok(None),
+        }
+    }
+
+    /// Try returning an immediate value for the operand.
+    /// If the layout does not permit loading this as a value, return where in memory
+    /// we can find the data.
+    /// Note that for a given layout, this operation will either always fail or always
+    /// succeed!  Whether it succeeds depends on whether the layout can be represented
+    /// in a `Value`, not on which data is stored there currently.
+    pub(crate) fn try_read_value(
+        &self,
+        src: OpTy<'tcx>,
+    ) -> EvalResult<'tcx, Result<Value, MemPlace>> {
+        Ok(match src.try_as_mplace() {
+            Ok(mplace) => {
+                if let Some(val) = self.try_read_value_from_mplace(mplace)? {
+                    Ok(val)
+                } else {
+                    Err(*mplace)
+                }
+            },
+            Err(val) => Ok(val),
+        })
+    }
+
+    /// Read a value from a place, asserting that that is possible with the given layout.
+    #[inline(always)]
+    pub fn read_value(&self, op: OpTy<'tcx>) -> EvalResult<'tcx, ValTy<'tcx>> {
+        if let Ok(value) = self.try_read_value(op)? {
+            Ok(ValTy { value, layout: op.layout })
+        } else {
+            bug!("primitive read failed for type: {:?}", op.layout.ty);
+        }
+    }
+
+    /// Read a scalar from a place
+    pub fn read_scalar(&self, op: OpTy<'tcx>) -> EvalResult<'tcx, ScalarMaybeUndef> {
+        match *self.read_value(op)? {
+            Value::ScalarPair(..) => bug!("got ScalarPair for type: {:?}", op.layout.ty),
+            Value::Scalar(val) => Ok(val),
+        }
+    }
+
+    // Turn the MPlace into a string (must already be dereferenced!)
+    pub fn read_str(
+        &self,
+        mplace: MPlaceTy<'tcx>,
+    ) -> EvalResult<'tcx, &str> {
+        let len = mplace.len(self)?;
+        let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len as u64))?;
+        let str = ::std::str::from_utf8(bytes)
+            .map_err(|err| EvalErrorKind::ValidationFailure(err.to_string()))?;
+        Ok(str)
+    }
+
+    pub fn uninit_operand(&mut self, layout: TyLayout<'tcx>) -> EvalResult<'tcx, Operand> {
+        // This decides which types we will use the Immediate optimization for, and hence should
+        // match what `try_read_value` and `eval_place_to_op` support.
+        if layout.is_zst() {
+            return Ok(Operand::Immediate(Value::Scalar(Scalar::zst().into())));
+        }
+
+        Ok(match layout.abi {
+            layout::Abi::Scalar(..) =>
+                Operand::Immediate(Value::Scalar(ScalarMaybeUndef::Undef)),
+            layout::Abi::ScalarPair(..) =>
+                Operand::Immediate(Value::ScalarPair(
+                    ScalarMaybeUndef::Undef,
+                    ScalarMaybeUndef::Undef,
+                )),
+            _ => {
+                trace!("Forcing allocation for local of type {:?}", layout.ty);
+                Operand::Indirect(
+                    *self.allocate(layout, MemoryKind::Stack)?
+                )
+            }
+        })
+    }
+
+    /// Projection functions
+    pub fn operand_field(
+        &self,
+        op: OpTy<'tcx>,
+        field: u64,
+    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+        let base = match op.try_as_mplace() {
+            Ok(mplace) => {
+                // The easy case
+                let field = self.mplace_field(mplace, field)?;
+                return Ok(field.into());
+            },
+            Err(value) => value
+        };
+
+        let field = field.try_into().unwrap();
+        let field_layout = op.layout.field(self, field)?;
+        if field_layout.size.bytes() == 0 {
+            let val = Value::Scalar(Scalar::zst().into());
+            return Ok(OpTy { op: Operand::Immediate(val), layout: field_layout });
+        }
+        let offset = op.layout.fields.offset(field);
+        let value = match base {
+            // the field covers the entire type
+            _ if offset.bytes() == 0 && field_layout.size == op.layout.size => base,
+            // extract fields from types with `ScalarPair` ABI
+            Value::ScalarPair(a, b) => {
+                let val = if offset.bytes() == 0 { a } else { b };
+                Value::Scalar(val)
+            },
+            Value::Scalar(val) =>
+                bug!("field access on non aggregate {:#?}, {:#?}", val, op.layout),
+        };
+        Ok(OpTy { op: Operand::Immediate(value), layout: field_layout })
+    }
+
+    pub fn operand_downcast(
+        &self,
+        op: OpTy<'tcx>,
+        variant: usize,
+    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+        // Downcasts only change the layout
+        Ok(match op.try_as_mplace() {
+            Ok(mplace) => {
+                self.mplace_downcast(mplace, variant)?.into()
+            },
+            Err(..) => {
+                let layout = op.layout.for_variant(self, variant);
+                OpTy { layout, ..op }
+            }
+        })
+    }
+
+    // Take an operand, representing a pointer, and dereference it -- that
+    // will always be a MemPlace.
+    pub(super) fn deref_operand(
+        &self,
+        src: OpTy<'tcx>,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+        let val = self.read_value(src)?;
+        trace!("deref to {} on {:?}", val.layout.ty, val);
+        Ok(self.ref_to_mplace(val)?)
+    }
+
+    pub fn operand_projection(
+        &self,
+        base: OpTy<'tcx>,
+        proj_elem: &mir::PlaceElem<'tcx>,
+    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+        use rustc::mir::ProjectionElem::*;
+        Ok(match *proj_elem {
+            Field(field, _) => self.operand_field(base, field.index() as u64)?,
+            Downcast(_, variant) => self.operand_downcast(base, variant)?,
+            Deref => self.deref_operand(base)?.into(),
+            // The rest should only occur as mplace, we do not use Immediates for types
+            // allowing such operations.  This matches place_projection forcing an allocation.
+            Subslice { .. } | ConstantIndex { .. } | Index(_) => {
+                let mplace = base.to_mem_place();
+                self.mplace_projection(mplace, proj_elem)?.into()
+            }
+        })
+    }
+
+    // Evaluate a place with the goal of reading from it.  This lets us sometimes
+    // avoid allocations.  If you already know the layout, you can pass it in
+    // to avoid looking it up again.
+    fn eval_place_to_op(
+        &self,
+        mir_place: &mir::Place<'tcx>,
+        layout: Option<TyLayout<'tcx>>,
+    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+        use rustc::mir::Place::*;
+        let op = match *mir_place {
+            Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
+            Local(local) => {
+                let op = *self.frame().locals[local].access()?;
+                let layout = from_known_layout(layout,
+                    || self.layout_of_local(self.cur_frame(), local))?;
+                OpTy { op, layout }
+            },
+
+            Projection(ref proj) => {
+                let op = self.eval_place_to_op(&proj.base, None)?;
+                self.operand_projection(op, &proj.elem)?
+            }
+
+            _ => self.eval_place_to_mplace(mir_place)?.into(),
+        };
+
+        trace!("eval_place_to_op: got {:?}", *op);
+        Ok(op)
+    }
+
+    /// Evaluate the operand, returning a place where you can then find the data.
+    /// if you already know the layout, you can save two some table lookups
+    /// by passing it in here.
+    pub fn eval_operand(
+        &self,
+        mir_op: &mir::Operand<'tcx>,
+        layout: Option<TyLayout<'tcx>>,
+    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+        use rustc::mir::Operand::*;
+        let op = match *mir_op {
+            // FIXME: do some more logic on `move` to invalidate the old location
+            Copy(ref place) |
+            Move(ref place) =>
+                self.eval_place_to_op(place, layout)?,
+
+            Constant(ref constant) => {
+                let layout = from_known_layout(layout, || {
+                    let ty = self.monomorphize(mir_op.ty(self.mir(), *self.tcx), self.substs());
+                    self.layout_of(ty)
+                })?;
+                let op = self.const_value_to_op(constant.literal.val)?;
+                OpTy { op, layout }
+            }
+        };
+        trace!("{:?}: {:?}", mir_op, *op);
+        Ok(op)
+    }
+
+    /// Evaluate a bunch of operands at once
+    pub(super) fn eval_operands(
+        &self,
+        ops: &[mir::Operand<'tcx>],
+    ) -> EvalResult<'tcx, Vec<OpTy<'tcx>>> {
+        ops.into_iter()
+            .map(|op| self.eval_operand(op, None))
+            .collect()
+    }
+
+    // Also used e.g. when miri runs into a constant.
+    pub(super) fn const_value_to_op(
+        &self,
+        val: ConstValue<'tcx>,
+    ) -> EvalResult<'tcx, Operand> {
+        trace!("const_value_to_op: {:?}", val);
+        match val {
+            ConstValue::Unevaluated(def_id, substs) => {
+                let instance = self.resolve(def_id, substs)?;
+                self.global_to_op(GlobalId {
+                    instance,
+                    promoted: None,
+                })
+            }
+            ConstValue::ByRef(id, alloc, offset) => {
+                // We rely on mutability being set correctly in that allocation to prevent writes
+                // where none should happen -- and for `static mut`, we copy on demand anyway.
+                Ok(Operand::Indirect(MemPlace::from_ptr(Pointer::new(id, offset), alloc.align)))
+            },
+            ConstValue::ScalarPair(a, b) =>
+                Ok(Operand::Immediate(Value::ScalarPair(a.into(), b))),
+            ConstValue::Scalar(x) =>
+                Ok(Operand::Immediate(Value::Scalar(x.into()))),
+        }
+    }
+    pub fn const_to_op(
+        &self,
+        cnst: &ty::Const<'tcx>,
+    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+        let op = self.const_value_to_op(cnst.val)?;
+        Ok(OpTy { op, layout: self.layout_of(cnst.ty)? })
+    }
+
+    pub(super) fn global_to_op(&self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, Operand> {
+        let cv = self.const_eval(gid)?;
+        self.const_value_to_op(cv.val)
+    }
+
+    /// Read discriminant, return the runtime value as well as the variant index.
+    pub fn read_discriminant(
+        &self,
+        rval: OpTy<'tcx>,
+    ) -> EvalResult<'tcx, (u128, usize)> {
+        trace!("read_discriminant_value {:#?}", rval.layout);
+        if rval.layout.abi == layout::Abi::Uninhabited {
+            return err!(Unreachable);
+        }
+
+        match rval.layout.variants {
+            layout::Variants::Single { index } => {
+                let discr_val = rval.layout.ty.ty_adt_def().map_or(
+                    index as u128,
+                    |def| def.discriminant_for_variant(*self.tcx, index).val);
+                return Ok((discr_val, index));
+            }
+            layout::Variants::Tagged { .. } |
+            layout::Variants::NicheFilling { .. } => {},
+        }
+        // read raw discriminant value
+        let discr_op = self.operand_field(rval, 0)?;
+        let discr_val = self.read_value(discr_op)?;
+        let raw_discr = discr_val.to_scalar()?;
+        trace!("discr value: {:?}", raw_discr);
+        // post-process
+        Ok(match rval.layout.variants {
+            layout::Variants::Single { .. } => bug!(),
+            layout::Variants::Tagged { .. } => {
+                let real_discr = if discr_val.layout.ty.is_signed() {
+                    let i = raw_discr.to_bits(discr_val.layout.size)? as i128;
+                    // going from layout tag type to typeck discriminant type
+                    // requires first sign extending with the layout discriminant
+                    let shift = 128 - discr_val.layout.size.bits();
+                    let sexted = (i << shift) >> shift;
+                    // and then zeroing with the typeck discriminant type
+                    let discr_ty = rval.layout.ty
+                        .ty_adt_def().expect("tagged layout corresponds to adt")
+                        .repr
+                        .discr_type();
+                    let discr_ty = layout::Integer::from_attr(self.tcx.tcx, discr_ty);
+                    let shift = 128 - discr_ty.size().bits();
+                    let truncatee = sexted as u128;
+                    (truncatee << shift) >> shift
+                } else {
+                    raw_discr.to_bits(discr_val.layout.size)?
+                };
+                // Make sure we catch invalid discriminants
+                let index = rval.layout.ty
+                    .ty_adt_def()
+                    .expect("tagged layout for non adt")
+                    .discriminants(self.tcx.tcx)
+                    .position(|var| var.val == real_discr)
+                    .ok_or_else(|| EvalErrorKind::InvalidDiscriminant(real_discr))?;
+                (real_discr, index)
+            },
+            layout::Variants::NicheFilling {
+                dataful_variant,
+                ref niche_variants,
+                niche_start,
+                ..
+            } => {
+                let variants_start = *niche_variants.start() as u128;
+                let variants_end = *niche_variants.end() as u128;
+                let real_discr = match raw_discr {
+                    Scalar::Ptr(_) => {
+                        // The niche must be just 0 (which a pointer value never is)
+                        assert!(niche_start == 0);
+                        assert!(variants_start == variants_end);
+                        dataful_variant as u128
+                    },
+                    Scalar::Bits { bits: raw_discr, size } => {
+                        assert_eq!(size as u64, discr_val.layout.size.bytes());
+                        let discr = raw_discr.wrapping_sub(niche_start)
+                            .wrapping_add(variants_start);
+                        if variants_start <= discr && discr <= variants_end {
+                            discr
+                        } else {
+                            dataful_variant as u128
+                        }
+                    },
+                };
+                let index = real_discr as usize;
+                assert_eq!(index as u128, real_discr);
+                assert!(index < rval.layout.ty
+                    .ty_adt_def()
+                    .expect("tagged layout for non adt")
+                    .variants.len());
+                (real_discr, index)
+            }
+        })
+    }
+
+}
index 732c85bd0147a18ab56342c2bef097a5c10d8999..d07d37d43b13e64a7eaa958bacae83018b10e185 100644 (file)
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
 use rustc::mir;
-use rustc::ty::{self, Ty, layout};
+use rustc::ty::{self, layout::{Size, TyLayout}};
 use syntax::ast::FloatTy;
-use rustc::ty::layout::{LayoutOf, TyLayout};
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
+use rustc::mir::interpret::{EvalResult, Scalar};
 
-use super::{EvalContext, Place, Machine, ValTy};
+use super::{EvalContext, PlaceTy, Value, Machine, ValTy};
 
-use rustc::mir::interpret::{EvalResult, Scalar, Value};
 
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
-    fn binop_with_overflow(
-        &self,
-        op: mir::BinOp,
-        left: ValTy<'tcx>,
-        right: ValTy<'tcx>,
-    ) -> EvalResult<'tcx, (Scalar, bool)> {
-        let left_val = self.value_to_scalar(left)?;
-        let right_val = self.value_to_scalar(right)?;
-        self.binary_op(op, left_val, left.ty, right_val, right.ty)
-    }
-
     /// Applies the binary operation `op` to the two operands and writes a tuple of the result
     /// and a boolean signifying the potential overflow to the destination.
-    pub fn intrinsic_with_overflow(
+    pub fn binop_with_overflow(
         &mut self,
         op: mir::BinOp,
         left: ValTy<'tcx>,
         right: ValTy<'tcx>,
-        dest: Place,
-        dest_ty: Ty<'tcx>,
+        dest: PlaceTy<'tcx>,
     ) -> EvalResult<'tcx> {
-        let (val, overflowed) = self.binop_with_overflow(op, left, right)?;
+        let (val, overflowed) = self.binary_op_val(op, left, right)?;
         let val = Value::ScalarPair(val.into(), Scalar::from_bool(overflowed).into());
-        let valty = ValTy {
-            value: val,
-            ty: dest_ty,
-        };
-        self.write_value(valty, dest)
+        self.write_value(val, dest)
     }
 
     /// Applies the binary operation `op` to the arguments and writes the result to the
-    /// destination. Returns `true` if the operation overflowed.
-    pub fn intrinsic_overflowing(
+    /// destination.
+    pub fn binop_ignore_overflow(
         &mut self,
         op: mir::BinOp,
         left: ValTy<'tcx>,
         right: ValTy<'tcx>,
-        dest: Place,
-        dest_ty: Ty<'tcx>,
-    ) -> EvalResult<'tcx, bool> {
-        let (val, overflowed) = self.binop_with_overflow(op, left, right)?;
-        self.write_scalar(dest, val, dest_ty)?;
-        Ok(overflowed)
+        dest: PlaceTy<'tcx>,
+    ) -> EvalResult<'tcx> {
+        let (val, _overflowed) = self.binary_op_val(op, left, right)?;
+        self.write_scalar(val, dest)
     }
 }
 
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
-    /// Returns the result of the specified operation and whether it overflowed.
-    pub fn binary_op(
+    fn binary_char_op(
         &self,
         bin_op: mir::BinOp,
-        left: Scalar,
-        left_ty: Ty<'tcx>,
-        right: Scalar,
-        right_ty: Ty<'tcx>,
+        l: char,
+        r: char,
     ) -> EvalResult<'tcx, (Scalar, bool)> {
         use rustc::mir::BinOp::*;
 
-        let left_layout = self.layout_of(left_ty)?;
-        let right_layout = self.layout_of(right_ty)?;
-
-        let left_kind = match left_layout.abi {
-            layout::Abi::Scalar(ref scalar) => scalar.value,
-            _ => return err!(TypeNotPrimitive(left_ty)),
+        let res = match bin_op {
+            Eq => l == r,
+            Ne => l != r,
+            Lt => l < r,
+            Le => l <= r,
+            Gt => l > r,
+            Ge => l >= r,
+            _ => bug!("Invalid operation on char: {:?}", bin_op),
         };
-        let right_kind = match right_layout.abi {
-            layout::Abi::Scalar(ref scalar) => scalar.value,
-            _ => return err!(TypeNotPrimitive(right_ty)),
+        return Ok((Scalar::from_bool(res), false));
+    }
+
+    fn binary_bool_op(
+        &self,
+        bin_op: mir::BinOp,
+        l: bool,
+        r: bool,
+    ) -> EvalResult<'tcx, (Scalar, bool)> {
+        use rustc::mir::BinOp::*;
+
+        let res = match bin_op {
+            Eq => l == r,
+            Ne => l != r,
+            Lt => l < r,
+            Le => l <= r,
+            Gt => l > r,
+            Ge => l >= r,
+            BitAnd => l & r,
+            BitOr => l | r,
+            BitXor => l ^ r,
+            _ => bug!("Invalid operation on bool: {:?}", bin_op),
         };
-        trace!("Running binary op {:?}: {:?} ({:?}), {:?} ({:?})", bin_op, left, left_kind, right, right_kind);
+        return Ok((Scalar::from_bool(res), false));
+    }
 
-        // I: Handle operations that support pointers
-        if !left_kind.is_float() && !right_kind.is_float() {
-            if let Some(handled) = M::try_ptr_op(self, bin_op, left, left_ty, right, right_ty)? {
-                return Ok(handled);
-            }
+    fn binary_float_op(
+        &self,
+        bin_op: mir::BinOp,
+        fty: FloatTy,
+        // passing in raw bits
+        l: u128,
+        r: u128,
+    ) -> EvalResult<'tcx, (Scalar, bool)> {
+        use rustc::mir::BinOp::*;
+
+        macro_rules! float_math {
+            ($ty:path, $size:expr) => {{
+                let l = <$ty>::from_bits(l);
+                let r = <$ty>::from_bits(r);
+                let bitify = |res: ::rustc_apfloat::StatusAnd<$ty>|
+                    Scalar::from_uint(res.value.to_bits(), Size::from_bytes($size));
+                let val = match bin_op {
+                    Eq => Scalar::from_bool(l == r),
+                    Ne => Scalar::from_bool(l != r),
+                    Lt => Scalar::from_bool(l < r),
+                    Le => Scalar::from_bool(l <= r),
+                    Gt => Scalar::from_bool(l > r),
+                    Ge => Scalar::from_bool(l >= r),
+                    Add => bitify(l + r),
+                    Sub => bitify(l - r),
+                    Mul => bitify(l * r),
+                    Div => bitify(l / r),
+                    Rem => bitify(l % r),
+                    _ => bug!("invalid float op: `{:?}`", bin_op),
+                };
+                return Ok((val, false));
+            }};
         }
+        match fty {
+            FloatTy::F32 => float_math!(Single, 4),
+            FloatTy::F64 => float_math!(Double, 8),
+        }
+    }
 
-        // II: From now on, everything must be bytes, no pointers
-        let l = left.to_bits(left_layout.size)?;
-        let r = right.to_bits(right_layout.size)?;
+    fn binary_int_op(
+        &self,
+        bin_op: mir::BinOp,
+        // passing in raw bits
+        l: u128,
+        left_layout: TyLayout<'tcx>,
+        r: u128,
+        right_layout: TyLayout<'tcx>,
+    ) -> EvalResult<'tcx, (Scalar, bool)> {
+        use rustc::mir::BinOp::*;
 
-        // These ops can have an RHS with a different numeric type.
-        if right_kind.is_int() && (bin_op == Shl || bin_op == Shr) {
+        // Shift ops can have an RHS with a different numeric type.
+        if bin_op == Shl || bin_op == Shr {
             let signed = left_layout.abi.is_signed();
             let mut oflo = (r as u32 as u128) != r;
             let mut r = r as u32;
@@ -118,24 +167,23 @@ pub fn binary_op(
                 }
             };
             let truncated = self.truncate(result, left_layout);
-            return Ok((Scalar::Bits {
-                bits: truncated,
-                size: size.bytes() as u8,
-            }, oflo));
+            return Ok((Scalar::from_uint(truncated, size), oflo));
         }
 
-        if left_kind != right_kind {
+        // For the remaining ops, the types must be the same on both sides
+        if left_layout.ty != right_layout.ty {
             let msg = format!(
-                "unimplemented binary op {:?}: {:?} ({:?}), {:?} ({:?})",
+                "unimplemented asymmetric binary op {:?}: {:?} ({:?}), {:?} ({:?})",
                 bin_op,
-                left,
-                left_kind,
-                right,
-                right_kind
+                l,
+                left_layout.ty,
+                r,
+                right_layout.ty
             );
             return err!(Unimplemented(msg));
         }
 
+        // Operations that need special treatment for signed integers
         if left_layout.abi.is_signed() {
             let op: Option<fn(&i128, &i128) -> bool> = match bin_op {
                 Lt => Some(i128::lt),
@@ -167,7 +215,7 @@ pub fn binary_op(
                     Rem | Div => {
                         // int_min / -1
                         if r == -1 && l == (1 << (size.bits() - 1)) {
-                            return Ok((Scalar::Bits { bits: l, size: size.bytes() as u8 }, true));
+                            return Ok((Scalar::from_uint(l, size), true));
                         }
                     },
                     _ => {},
@@ -179,48 +227,14 @@ pub fn binary_op(
                     let max = 1 << (size.bits() - 1);
                     oflo = result >= max || result < -max;
                 }
+                // this may be out-of-bounds for the result type, so we have to truncate ourselves
                 let result = result as u128;
                 let truncated = self.truncate(result, left_layout);
-                return Ok((Scalar::Bits {
-                    bits: truncated,
-                    size: size.bytes() as u8,
-                }, oflo));
-            }
-        }
-
-        if let ty::TyFloat(fty) = left_ty.sty {
-            macro_rules! float_math {
-                ($ty:path, $size:expr) => {{
-                    let l = <$ty>::from_bits(l);
-                    let r = <$ty>::from_bits(r);
-                    let bitify = |res: ::rustc_apfloat::StatusAnd<$ty>| Scalar::Bits {
-                        bits: res.value.to_bits(),
-                        size: $size,
-                    };
-                    let val = match bin_op {
-                        Eq => Scalar::from_bool(l == r),
-                        Ne => Scalar::from_bool(l != r),
-                        Lt => Scalar::from_bool(l < r),
-                        Le => Scalar::from_bool(l <= r),
-                        Gt => Scalar::from_bool(l > r),
-                        Ge => Scalar::from_bool(l >= r),
-                        Add => bitify(l + r),
-                        Sub => bitify(l - r),
-                        Mul => bitify(l * r),
-                        Div => bitify(l / r),
-                        Rem => bitify(l % r),
-                        _ => bug!("invalid float op: `{:?}`", bin_op),
-                    };
-                    return Ok((val, false));
-                }};
-            }
-            match fty {
-                FloatTy::F32 => float_math!(Single, 4),
-                FloatTy::F64 => float_math!(Double, 8),
+                return Ok((Scalar::from_uint(truncated, size), oflo));
             }
         }
 
-        let size = self.layout_of(left_ty).unwrap().size.bytes() as u8;
+        let size = left_layout.size;
 
         // only ints left
         let val = match bin_op {
@@ -232,11 +246,12 @@ macro_rules! float_math {
             Gt => Scalar::from_bool(l > r),
             Ge => Scalar::from_bool(l >= r),
 
-            BitOr => Scalar::Bits { bits: l | r, size },
-            BitAnd => Scalar::Bits { bits: l & r, size },
-            BitXor => Scalar::Bits { bits: l ^ r, size },
+            BitOr => Scalar::from_uint(l | r, size),
+            BitAnd => Scalar::from_uint(l & r, size),
+            BitXor => Scalar::from_uint(l ^ r, size),
 
             Add | Sub | Mul | Rem | Div => {
+                debug_assert!(!left_layout.abi.is_signed());
                 let op: fn(u128, u128) -> (u128, bool) = match bin_op {
                     Add => u128::overflowing_add,
                     Sub => u128::overflowing_sub,
@@ -249,20 +264,16 @@ macro_rules! float_math {
                 };
                 let (result, oflo) = op(l, r);
                 let truncated = self.truncate(result, left_layout);
-                return Ok((Scalar::Bits {
-                    bits: truncated,
-                    size,
-                }, oflo || truncated != result));
+                return Ok((Scalar::from_uint(truncated, size), oflo || truncated != result));
             }
 
             _ => {
                 let msg = format!(
-                    "unimplemented binary op {:?}: {:?} ({:?}), {:?} ({:?})",
+                    "unimplemented binary op {:?}: {:?}, {:?} (both {:?})",
                     bin_op,
-                    left,
-                    left_ty,
-                    right,
-                    right_ty,
+                    l,
+                    r,
+                    right_layout.ty,
                 );
                 return err!(Unimplemented(msg));
             }
@@ -271,6 +282,73 @@ macro_rules! float_math {
         Ok((val, false))
     }
 
+    /// Convenience wrapper that's useful when keeping the layout together with the
+    /// value.
+    #[inline]
+    pub fn binary_op_val(
+        &self,
+        bin_op: mir::BinOp,
+        left: ValTy<'tcx>,
+        right: ValTy<'tcx>,
+    ) -> EvalResult<'tcx, (Scalar, bool)> {
+        self.binary_op(
+            bin_op,
+            left.to_scalar()?, left.layout,
+            right.to_scalar()?, right.layout,
+        )
+    }
+
+    /// Returns the result of the specified operation and whether it overflowed.
+    pub fn binary_op(
+        &self,
+        bin_op: mir::BinOp,
+        left: Scalar,
+        left_layout: TyLayout<'tcx>,
+        right: Scalar,
+        right_layout: TyLayout<'tcx>,
+    ) -> EvalResult<'tcx, (Scalar, bool)> {
+        trace!("Running binary op {:?}: {:?} ({:?}), {:?} ({:?})",
+            bin_op, left, left_layout.ty, right, right_layout.ty);
+
+        match left_layout.ty.sty {
+            ty::Char => {
+                assert_eq!(left_layout.ty, right_layout.ty);
+                let left = left.to_char()?;
+                let right = right.to_char()?;
+                self.binary_char_op(bin_op, left, right)
+            }
+            ty::Bool => {
+                assert_eq!(left_layout.ty, right_layout.ty);
+                let left = left.to_bool()?;
+                let right = right.to_bool()?;
+                self.binary_bool_op(bin_op, left, right)
+            }
+            ty::Float(fty) => {
+                assert_eq!(left_layout.ty, right_layout.ty);
+                let left = left.to_bits(left_layout.size)?;
+                let right = right.to_bits(right_layout.size)?;
+                self.binary_float_op(bin_op, fty, left, right)
+            }
+            _ => {
+                // Must be integer(-like) types.  Don't forget about == on fn pointers.
+                assert!(left_layout.ty.is_integral() || left_layout.ty.is_unsafe_ptr() ||
+                    left_layout.ty.is_fn());
+                assert!(right_layout.ty.is_integral() || right_layout.ty.is_unsafe_ptr() ||
+                    right_layout.ty.is_fn());
+
+                // Handle operations that support pointer values
+                if left.is_ptr() || right.is_ptr() || bin_op == mir::BinOp::Offset {
+                    return M::ptr_op(self, bin_op, left, left_layout, right, right_layout);
+                }
+
+                // Everything else only works with "proper" bits
+                let left = left.to_bits(left_layout.size).expect("we checked is_ptr");
+                let right = right.to_bits(right_layout.size).expect("we checked is_ptr");
+                self.binary_int_op(bin_op, left, left_layout, right, right_layout)
+            }
+        }
+    }
+
     pub fn unary_op(
         &self,
         un_op: mir::UnOp,
@@ -281,25 +359,39 @@ pub fn unary_op(
         use rustc_apfloat::ieee::{Single, Double};
         use rustc_apfloat::Float;
 
-        let size = layout.size;
-        let bytes = val.to_bits(size)?;
-
-        let result_bytes = match (un_op, &layout.ty.sty) {
-
-            (Not, ty::TyBool) => !val.to_bool()? as u128,
-
-            (Not, _) => !bytes,
-
-            (Neg, ty::TyFloat(FloatTy::F32)) => Single::to_bits(-Single::from_bits(bytes)),
-            (Neg, ty::TyFloat(FloatTy::F64)) => Double::to_bits(-Double::from_bits(bytes)),
+        trace!("Running unary op {:?}: {:?} ({:?})", un_op, val, layout.ty.sty);
 
-            (Neg, _) if bytes == (1 << (size.bits() - 1)) => return err!(OverflowNeg),
-            (Neg, _) => (-(bytes as i128)) as u128,
-        };
-
-        Ok(Scalar::Bits {
-            bits: self.truncate(result_bytes, layout),
-            size: size.bytes() as u8,
-        })
+        match layout.ty.sty {
+            ty::Bool => {
+                let val = val.to_bool()?;
+                let res = match un_op {
+                    Not => !val,
+                    _ => bug!("Invalid bool op {:?}", un_op)
+                };
+                Ok(Scalar::from_bool(res))
+            }
+            ty::Float(fty) => {
+                let val = val.to_bits(layout.size)?;
+                let res = match (un_op, fty) {
+                    (Neg, FloatTy::F32) => Single::to_bits(-Single::from_bits(val)),
+                    (Neg, FloatTy::F64) => Double::to_bits(-Double::from_bits(val)),
+                    _ => bug!("Invalid float op {:?}", un_op)
+                };
+                Ok(Scalar::from_uint(res, layout.size))
+            }
+            _ => {
+                assert!(layout.ty.is_integral());
+                let val = val.to_bits(layout.size)?;
+                let res = match un_op {
+                    Not => !val,
+                    Neg => {
+                        assert!(layout.abi.is_signed());
+                        (-(val as i128)) as u128
+                    }
+                };
+                // res needs tuncating
+                Ok(Scalar::from_uint(self.truncate(res, layout), layout.size))
+            }
+        }
     }
 }
index 91c2519230695a08c8b621c53b387029312a417e..5bf6b2b46b7a6f6975be33a88d4145925d20ccbf 100644 (file)
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Computations on places -- field projections, going from mir::Place, and writing
+//! into a place.
+//! All high-level functions to write to memory work on places as destinations.
+
+use std::convert::TryFrom;
+
 use rustc::mir;
-use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
+use rustc::ty::{self, Ty};
+use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout};
 use rustc_data_structures::indexed_vec::Idx;
 
-use rustc::mir::interpret::{GlobalId, Value, Scalar, EvalResult, Pointer, ScalarMaybeUndef};
-use super::{EvalContext, Machine, ValTy};
-use interpret::memory::HasMemory;
+use rustc::mir::interpret::{
+    GlobalId, Scalar, EvalResult, Pointer, ScalarMaybeUndef, PointerArithmetic
+};
+use super::{EvalContext, Machine, Value, ValTy, Operand, OpTy, MemoryKind};
+
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct MemPlace {
+    /// A place may have an integral pointer for ZSTs, and since it might
+    /// be turned back into a reference before ever being dereferenced.
+    /// However, it may never be undef.
+    pub ptr: Scalar,
+    pub align: Align,
+    /// Metadata for unsized places.  Interpretation is up to the type.
+    /// Must not be present for sized types, but can be missing for unsized types
+    /// (e.g. `extern type`).
+    pub extra: Option<Scalar>,
+}
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
 pub enum Place {
     /// A place referring to a value allocated in the `Memory` system.
-    Ptr {
-        /// A place may have an invalid (integral or undef) pointer,
-        /// since it might be turned back into a reference
-        /// before ever being dereferenced.
-        ptr: ScalarMaybeUndef,
-        align: Align,
-        extra: PlaceExtra,
+    Ptr(MemPlace),
+
+    /// To support alloc-free locals, we are able to write directly to a local.
+    /// (Without that optimization, we'd just always be a `MemPlace`.)
+    Local {
+        frame: usize,
+        local: mir::Local,
     },
+}
 
-    /// A place referring to a value on the stack. Represented by a stack frame index paired with
-    /// a Mir local index.
-    Local { frame: usize, local: mir::Local },
+#[derive(Copy, Clone, Debug)]
+pub struct PlaceTy<'tcx> {
+    place: Place,
+    pub layout: TyLayout<'tcx>,
 }
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub enum PlaceExtra {
-    None,
-    Length(u64),
-    Vtable(Pointer),
-    DowncastVariant(usize),
+impl<'tcx> ::std::ops::Deref for PlaceTy<'tcx> {
+    type Target = Place;
+    #[inline(always)]
+    fn deref(&self) -> &Place {
+        &self.place
+    }
 }
 
-impl<'tcx> Place {
-    /// Produces a Place that will error if attempted to be read from
-    pub fn undef() -> Self {
-        Self::from_scalar_ptr(ScalarMaybeUndef::Undef, Align::from_bytes(1, 1).unwrap())
+/// A MemPlace with its layout. Constructing it is only possible in this module.
+#[derive(Copy, Clone, Debug)]
+pub struct MPlaceTy<'tcx> {
+    mplace: MemPlace,
+    pub layout: TyLayout<'tcx>,
+}
+
+impl<'tcx> ::std::ops::Deref for MPlaceTy<'tcx> {
+    type Target = MemPlace;
+    #[inline(always)]
+    fn deref(&self) -> &MemPlace {
+        &self.mplace
+    }
+}
+
+impl<'tcx> From<MPlaceTy<'tcx>> for PlaceTy<'tcx> {
+    #[inline(always)]
+    fn from(mplace: MPlaceTy<'tcx>) -> Self {
+        PlaceTy {
+            place: Place::Ptr(mplace.mplace),
+            layout: mplace.layout
+        }
     }
+}
 
-    pub fn from_scalar_ptr(ptr: ScalarMaybeUndef, align: Align) -> Self {
-        Place::Ptr {
+impl MemPlace {
+    #[inline(always)]
+    pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self {
+        MemPlace {
             ptr,
             align,
-            extra: PlaceExtra::None,
+            extra: None,
         }
     }
 
+    #[inline(always)]
     pub fn from_ptr(ptr: Pointer, align: Align) -> Self {
-        Self::from_scalar_ptr(ScalarMaybeUndef::Scalar(ptr.into()), align)
+        Self::from_scalar_ptr(ptr.into(), align)
     }
 
-    pub fn to_ptr_align_extra(self) -> (ScalarMaybeUndef, Align, PlaceExtra) {
-        match self {
-            Place::Ptr { ptr, align, extra } => (ptr, align, extra),
-            _ => bug!("to_ptr_and_extra: expected Place::Ptr, got {:?}", self),
+    #[inline(always)]
+    pub fn to_scalar_ptr_align(self) -> (Scalar, Align) {
+        assert_eq!(self.extra, None);
+        (self.ptr, self.align)
+    }
+
+    /// Extract the ptr part of the mplace
+    #[inline(always)]
+    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
+        // At this point, we forget about the alignment information --
+        // the place has been turned into a reference, and no matter where it came from,
+        // it now must be aligned.
+        self.to_scalar_ptr_align().0.to_ptr()
+    }
 
+    /// Turn a mplace into a (thin or fat) pointer, as a reference, pointing to the same space.
+    /// This is the inverse of `ref_to_mplace`.
+    pub fn to_ref(self) -> Value {
+        // We ignore the alignment of the place here -- special handling for packed structs ends
+        // at the `&` operator.
+        match self.extra {
+            None => Value::Scalar(self.ptr.into()),
+            Some(extra) => Value::ScalarPair(self.ptr.into(), extra.into()),
         }
     }
+}
 
-    pub fn to_ptr_align(self) -> (ScalarMaybeUndef, Align) {
-        let (ptr, align, _extra) = self.to_ptr_align_extra();
-        (ptr, align)
+impl<'tcx> MPlaceTy<'tcx> {
+    #[inline]
+    fn from_aligned_ptr(ptr: Pointer, layout: TyLayout<'tcx>) -> Self {
+        MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align), layout }
     }
 
-    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
-        // At this point, we forget about the alignment information -- the place has been turned into a reference,
-        // and no matter where it came from, it now must be aligned.
-        self.to_ptr_align().0.unwrap_or_err()?.to_ptr()
-    }
-
-    pub(super) fn elem_ty_and_len(
-        self,
-        ty: Ty<'tcx>,
-        tcx: TyCtxt<'_, 'tcx, '_>
-    ) -> (Ty<'tcx>, u64) {
-        match ty.sty {
-            ty::TyArray(elem, n) => (elem, n.unwrap_usize(tcx)),
-
-            ty::TySlice(elem) => {
-                match self {
-                    Place::Ptr { extra: PlaceExtra::Length(len), .. } => (elem, len),
-                    _ => {
-                        bug!(
-                            "elem_ty_and_len of a TySlice given non-slice place: {:?}",
-                            self
-                        )
-                    }
-                }
+    #[inline]
+    pub(super) fn len(self, cx: impl HasDataLayout) -> EvalResult<'tcx, u64> {
+        if self.layout.is_unsized() {
+            // We need to consult `extra` metadata
+            match self.layout.ty.sty {
+                ty::Slice(..) | ty::Str =>
+                    return self.extra.unwrap().to_usize(cx),
+                _ => bug!("len not supported on unsized type {:?}", self.layout.ty),
             }
+        } else {
+            // Go through the layout.  There are lots of types that support a length,
+            // e.g. SIMD types.
+            match self.layout.fields {
+                layout::FieldPlacement::Array { count, .. } => Ok(count),
+                _ => bug!("len not supported on sized type {:?}", self.layout.ty),
+            }
+        }
+    }
 
-            _ => bug!("elem_ty_and_len expected array or slice, got {:?}", ty),
+    #[inline]
+    pub(super) fn vtable(self) -> EvalResult<'tcx, Pointer> {
+        match self.layout.ty.sty {
+            ty::Dynamic(..) => self.extra.unwrap().to_ptr(),
+            _ => bug!("vtable not supported on type {:?}", self.layout.ty),
         }
     }
 }
 
+impl<'tcx> OpTy<'tcx> {
+    #[inline(always)]
+    pub fn try_as_mplace(self) -> Result<MPlaceTy<'tcx>, Value> {
+        match *self {
+            Operand::Indirect(mplace) => Ok(MPlaceTy { mplace, layout: self.layout }),
+            Operand::Immediate(value) => Err(value),
+        }
+    }
+
+    #[inline(always)]
+    pub fn to_mem_place(self) -> MPlaceTy<'tcx> {
+        self.try_as_mplace().unwrap()
+    }
+}
+
+impl<'tcx> Place {
+    /// Produces a Place that will error if attempted to be read from or written to
+    #[inline]
+    pub fn null(cx: impl HasDataLayout) -> Self {
+        Self::from_scalar_ptr(Scalar::ptr_null(cx), Align::from_bytes(1, 1).unwrap())
+    }
+
+    #[inline]
+    pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self {
+        Place::Ptr(MemPlace::from_scalar_ptr(ptr, align))
+    }
+
+    #[inline]
+    pub fn from_ptr(ptr: Pointer, align: Align) -> Self {
+        Place::Ptr(MemPlace::from_ptr(ptr, align))
+    }
+
+    #[inline]
+    pub fn to_mem_place(self) -> MemPlace {
+        match self {
+            Place::Ptr(mplace) => mplace,
+            _ => bug!("to_mem_place: expected Place::Ptr, got {:?}", self),
+
+        }
+    }
+
+    #[inline]
+    pub fn to_scalar_ptr_align(self) -> (Scalar, Align) {
+        self.to_mem_place().to_scalar_ptr_align()
+    }
+
+    #[inline]
+    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
+        self.to_mem_place().to_ptr()
+    }
+}
+
+impl<'tcx> PlaceTy<'tcx> {
+    /// Produces a Place that will error if attempted to be read from or written to
+    #[inline]
+    pub fn null(cx: impl HasDataLayout, layout: TyLayout<'tcx>) -> Self {
+        PlaceTy { place: Place::from_scalar_ptr(Scalar::ptr_null(cx), layout.align), layout }
+    }
+
+    #[inline]
+    pub fn to_mem_place(self) -> MPlaceTy<'tcx> {
+        MPlaceTy { mplace: self.place.to_mem_place(), layout: self.layout }
+    }
+}
+
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
-    /// Reads a value from the place without going through the intermediate step of obtaining
-    /// a `miri::Place`
-    pub fn try_read_place(
+    /// Take a value, which represents a (thin or fat) reference, and make it a place.
+    /// Alignment is just based on the type.  This is the inverse of `MemPlace::to_ref`.
+    pub fn ref_to_mplace(
+        &self, val: ValTy<'tcx>
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+        let pointee_type = val.layout.ty.builtin_deref(true).unwrap().ty;
+        let layout = self.layout_of(pointee_type)?;
+        let align = layout.align;
+        let mplace = match *val {
+            Value::Scalar(ptr) =>
+                MemPlace { ptr: ptr.not_undef()?, align, extra: None },
+            Value::ScalarPair(ptr, extra) =>
+                MemPlace { ptr: ptr.not_undef()?, align, extra: Some(extra.not_undef()?) },
+        };
+        Ok(MPlaceTy { mplace, layout })
+    }
+
+    /// Offset a pointer to project to a field. Unlike place_field, this is always
+    /// possible without allocating, so it can take &self. Also return the field's layout.
+    /// This supports both struct and array fields.
+    #[inline(always)]
+    pub fn mplace_field(
         &self,
-        place: &mir::Place<'tcx>,
-    ) -> EvalResult<'tcx, Option<Value>> {
-        use rustc::mir::Place::*;
-        match *place {
-            // Might allow this in the future, right now there's no way to do this from Rust code anyway
-            Local(mir::RETURN_PLACE) => err!(ReadFromReturnPointer),
-            // Directly reading a local will always succeed
-            Local(local) => self.frame().locals[local].access().map(Some),
-            // No fast path for statics. Reading from statics is rare and would require another
-            // Machine function to handle differently in miri.
-            Promoted(_) |
-            Static(_) => Ok(None),
-            Projection(ref proj) => self.try_read_place_projection(proj),
-        }
+        base: MPlaceTy<'tcx>,
+        field: u64,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+        // Not using the layout method because we want to compute on u64
+        let offset = match base.layout.fields {
+            layout::FieldPlacement::Arbitrary { ref offsets, .. } =>
+                offsets[usize::try_from(field).unwrap()],
+            layout::FieldPlacement::Array { stride, .. } => {
+                let len = base.len(self)?;
+                assert!(field < len, "Tried to access element {} of array/slice with length {}",
+                    field, len);
+                stride * field
+            }
+            layout::FieldPlacement::Union(count) => {
+                assert!(field < count as u64,
+                        "Tried to access field {} of union with {} fields", field, count);
+                // Offset is always 0
+                Size::from_bytes(0)
+            }
+        };
+        // the only way conversion can fail if is this is an array (otherwise we already panicked
+        // above). In that case, all fields are equal.
+        let field_layout = base.layout.field(self, usize::try_from(field).unwrap_or(0))?;
+
+        // Offset may need adjustment for unsized fields
+        let (extra, offset) = if field_layout.is_unsized() {
+            // re-use parent metadata to determine dynamic field layout
+            let (_, align) = self.size_and_align_of(base.extra, field_layout)?;
+            (base.extra, offset.abi_align(align))
+
+        } else {
+            // base.extra could be present; we might be accessing a sized field of an unsized
+            // struct.
+            (None, offset)
+        };
+
+        let ptr = base.ptr.ptr_offset(offset, self)?;
+        let align = base.align.min(field_layout.align); // only use static information
+
+        Ok(MPlaceTy { mplace: MemPlace { ptr, align, extra }, layout: field_layout })
     }
 
-    pub fn read_field(
+    // Iterates over all fields of an array. Much more efficient than doing the
+    // same by repeatedly calling `mplace_array`.
+    pub fn mplace_array_fields(
         &self,
-        base: Value,
-        variant: Option<usize>,
-        field: mir::Field,
-        mut base_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, (Value, TyLayout<'tcx>)> {
-        if let Some(variant_index) = variant {
-            base_layout = base_layout.for_variant(self, variant_index);
-        }
-        let field_index = field.index();
-        let field = base_layout.field(self, field_index)?;
-        if field.size.bytes() == 0 {
-            return Ok((
-                Value::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits { bits: 0, size: 0 })),
-                field,
-            ));
-        }
-        let offset = base_layout.fields.offset(field_index);
-        let value = match base {
-            // the field covers the entire type
-            Value::ScalarPair(..) |
-            Value::Scalar(_) if offset.bytes() == 0 && field.size == base_layout.size => base,
-            // extract fields from types with `ScalarPair` ABI
-            Value::ScalarPair(a, b) => {
-                let val = if offset.bytes() == 0 { a } else { b };
-                Value::Scalar(val)
-            },
-            Value::ByRef(base_ptr, align) => {
-                let offset = base_layout.fields.offset(field_index);
-                let ptr = base_ptr.ptr_offset(offset, self)?;
-                let align = align.min(base_layout.align).min(field.align);
-                assert!(!field.is_unsized());
-                Value::ByRef(ptr, align)
-            },
-            Value::Scalar(val) => bug!("field access on non aggregate {:#?}, {:#?}", val, base_layout),
+        base: MPlaceTy<'tcx>,
+    ) -> EvalResult<'tcx, impl Iterator<Item=EvalResult<'tcx, MPlaceTy<'tcx>>> + 'a> {
+        let len = base.len(self)?; // also asserts that we have a type where this makes sense
+        let stride = match base.layout.fields {
+            layout::FieldPlacement::Array { stride, .. } => stride,
+            _ => bug!("mplace_array_fields: expected an array layout"),
         };
-        Ok((value, field))
+        let layout = base.layout.field(self, 0)?;
+        let dl = &self.tcx.data_layout;
+        Ok((0..len).map(move |i| {
+            let ptr = base.ptr.ptr_offset(i * stride, dl)?;
+            Ok(MPlaceTy {
+                mplace: MemPlace { ptr, align: base.align, extra: None },
+                layout
+            })
+        }))
     }
 
-    fn try_read_place_projection(
+    pub fn mplace_subslice(
         &self,
-        proj: &mir::PlaceProjection<'tcx>,
-    ) -> EvalResult<'tcx, Option<Value>> {
-        use rustc::mir::ProjectionElem::*;
-        let base = match self.try_read_place(&proj.base)? {
-            Some(base) => base,
-            None => return Ok(None),
+        base: MPlaceTy<'tcx>,
+        from: u64,
+        to: u64,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+        let len = base.len(self)?; // also asserts that we have a type where this makes sense
+        assert!(from <= len - to);
+
+        // Not using layout method because that works with usize, and does not work with slices
+        // (that have count 0 in their layout).
+        let from_offset = match base.layout.fields {
+            layout::FieldPlacement::Array { stride, .. } =>
+                stride * from,
+            _ => bug!("Unexpected layout of index access: {:#?}", base.layout),
         };
-        let base_ty = self.place_ty(&proj.base);
-        let base_layout = self.layout_of(base_ty)?;
-        match proj.elem {
-            Field(field, _) => Ok(Some(self.read_field(base, None, field, base_layout)?.0)),
-            // The NullablePointer cases should work fine, need to take care for normal enums
-            Downcast(..) |
-            Subslice { .. } |
-            // reading index 0 or index 1 from a ByVal or ByVal pair could be optimized
-            ConstantIndex { .. } | Index(_) |
-            // No way to optimize this projection any better than the normal place path
-            Deref => Ok(None),
-        }
+        let ptr = base.ptr.ptr_offset(from_offset, self)?;
+
+        // Compute extra and new layout
+        let inner_len = len - to - from;
+        let (extra, ty) = match base.layout.ty.sty {
+            // It is not nice to match on the type, but that seems to be the only way to
+            // implement this.
+            ty::Array(inner, _) =>
+                (None, self.tcx.mk_array(inner, inner_len)),
+            ty::Slice(..) => {
+                let len = Scalar::from_uint(inner_len, self.pointer_size());
+                (Some(len), base.layout.ty)
+            }
+            _ =>
+                bug!("cannot subslice non-array type: `{:?}`", base.layout.ty),
+        };
+        let layout = self.layout_of(ty)?;
+
+        Ok(MPlaceTy {
+            mplace: MemPlace { ptr, align: base.align, extra },
+            layout
+        })
     }
 
-    /// Returns a value and (in case of a ByRef) if we are supposed to use aligned accesses.
-    pub(super) fn eval_and_read_place(
+    pub fn mplace_downcast(
+        &self,
+        base: MPlaceTy<'tcx>,
+        variant: usize,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+        // Downcasts only change the layout
+        assert_eq!(base.extra, None);
+        Ok(MPlaceTy { layout: base.layout.for_variant(self, variant), ..base })
+    }
+
+    /// Project into an mplace
+    pub fn mplace_projection(
+        &self,
+        base: MPlaceTy<'tcx>,
+        proj_elem: &mir::PlaceElem<'tcx>,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+        use rustc::mir::ProjectionElem::*;
+        Ok(match *proj_elem {
+            Field(field, _) => self.mplace_field(base, field.index() as u64)?,
+            Downcast(_, variant) => self.mplace_downcast(base, variant)?,
+            Deref => self.deref_operand(base.into())?,
+
+            Index(local) => {
+                let n = *self.frame().locals[local].access()?;
+                let n_layout = self.layout_of(self.tcx.types.usize)?;
+                let n = self.read_scalar(OpTy { op: n, layout: n_layout })?;
+                let n = n.to_bits(self.tcx.data_layout.pointer_size)?;
+                self.mplace_field(base, u64::try_from(n).unwrap())?
+            }
+
+            ConstantIndex {
+                offset,
+                min_length,
+                from_end,
+            } => {
+                let n = base.len(self)?;
+                assert!(n >= min_length as u64);
+
+                let index = if from_end {
+                    n - u64::from(offset)
+                } else {
+                    u64::from(offset)
+                };
+
+                self.mplace_field(base, index)?
+            }
+
+            Subslice { from, to } =>
+                self.mplace_subslice(base, u64::from(from), u64::from(to))?,
+        })
+    }
+
+    /// Get the place of a field inside the place, and also the field's type.
+    /// Just a convenience function, but used quite a bit.
+    pub fn place_field(
         &mut self,
-        place: &mir::Place<'tcx>,
-    ) -> EvalResult<'tcx, Value> {
-        // Shortcut for things like accessing a fat pointer's field,
-        // which would otherwise (in the `eval_place` path) require moving a `ScalarPair` to memory
-        // and returning an `Place::Ptr` to it
-        if let Some(val) = self.try_read_place(place)? {
-            return Ok(val);
-        }
-        let place = self.eval_place(place)?;
-        self.read_place(place)
+        base: PlaceTy<'tcx>,
+        field: u64,
+    ) -> EvalResult<'tcx, PlaceTy<'tcx>> {
+        // FIXME: We could try to be smarter and avoid allocation for fields that span the
+        // entire place.
+        let mplace = self.force_allocation(base)?;
+        Ok(self.mplace_field(mplace, field)?.into())
     }
 
-    pub fn read_place(&self, place: Place) -> EvalResult<'tcx, Value> {
-        match place {
-            Place::Ptr { ptr, align, extra } => {
-                assert_eq!(extra, PlaceExtra::None);
-                Ok(Value::ByRef(ptr.unwrap_or_err()?, align))
+    pub fn place_downcast(
+        &mut self,
+        base: PlaceTy<'tcx>,
+        variant: usize,
+    ) -> EvalResult<'tcx, PlaceTy<'tcx>> {
+        // Downcast just changes the layout
+        Ok(match base.place {
+            Place::Ptr(mplace) =>
+                self.mplace_downcast(MPlaceTy { mplace, layout: base.layout }, variant)?.into(),
+            Place::Local { .. } => {
+                let layout = base.layout.for_variant(&self, variant);
+                PlaceTy { layout, ..base }
             }
-            Place::Local { frame, local } => self.stack[frame].locals[local].access(),
-        }
+        })
     }
 
-    pub fn eval_place(&mut self, mir_place: &mir::Place<'tcx>) -> EvalResult<'tcx, Place> {
-        use rustc::mir::Place::*;
-        let place = match *mir_place {
-            Local(mir::RETURN_PLACE) => self.frame().return_place,
-            Local(local) => Place::Local {
-                frame: self.cur_frame(),
-                local,
-            },
+    /// Project into a place
+    pub fn place_projection(
+        &mut self,
+        base: PlaceTy<'tcx>,
+        proj_elem: &mir::ProjectionElem<'tcx, mir::Local, Ty<'tcx>>,
+    ) -> EvalResult<'tcx, PlaceTy<'tcx>> {
+        use rustc::mir::ProjectionElem::*;
+        Ok(match *proj_elem {
+            Field(field, _) =>  self.place_field(base, field.index() as u64)?,
+            Downcast(_, variant) => self.place_downcast(base, variant)?,
+            Deref => self.deref_operand(self.place_to_op(base)?)?.into(),
+            // For the other variants, we have to force an allocation.
+            // This matches `operand_projection`.
+            Subslice { .. } | ConstantIndex { .. } | Index(_) => {
+                let mplace = self.force_allocation(base)?;
+                self.mplace_projection(mplace, proj_elem)?.into()
+            }
+        })
+    }
 
+    /// Evaluate statics and promoteds to an `MPlace`.  Used to share some code between
+    /// `eval_place` and `eval_place_to_op`.
+    pub(super) fn eval_place_to_mplace(
+        &self,
+        mir_place: &mir::Place<'tcx>
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+        use rustc::mir::Place::*;
+        Ok(match *mir_place {
             Promoted(ref promoted) => {
                 let instance = self.frame().instance;
-                let val = self.read_global_as_value(GlobalId {
+                let op = self.global_to_op(GlobalId {
                     instance,
                     promoted: Some(promoted.0),
                 })?;
-                if let Value::ByRef(ptr, align) = val {
-                    Place::Ptr {
-                        ptr: ptr.into(),
-                        align,
-                        extra: PlaceExtra::None,
-                    }
-                } else {
-                    bug!("evaluated promoted and got {:#?}", val);
+                let mplace = op.to_mem_place(); // these are always in memory
+                let ty = self.monomorphize(promoted.1, self.substs());
+                MPlaceTy {
+                    mplace,
+                    layout: self.layout_of(ty)?,
                 }
             }
 
             Static(ref static_) => {
-                let layout = self.layout_of(self.place_ty(mir_place))?;
+                let ty = self.monomorphize(static_.ty, self.substs());
+                let layout = self.layout_of(ty)?;
                 let instance = ty::Instance::mono(*self.tcx, static_.def_id);
                 let cid = GlobalId {
                     instance,
                     promoted: None
                 };
-                let alloc = Machine::init_static(self, cid)?;
-                Place::Ptr {
-                    ptr: ScalarMaybeUndef::Scalar(Scalar::Ptr(alloc.into())),
-                    align: layout.align,
-                    extra: PlaceExtra::None,
-                }
+                // Just create a lazy reference, so we can support recursive statics.
+                // tcx takes are of assigning every static one and only one unique AllocId.
+                // When the data here is ever actually used, memory will notice,
+                // and it knows how to deal with alloc_id that are present in the
+                // global table but not in its local memory: It calls back into tcx through
+                // a query, triggering the CTFE machinery to actually turn this lazy reference
+                // into a bunch of bytes.  IOW, statics are evaluated with CTFE even when
+                // this EvalContext uses another Machine (e.g., in miri).  This is what we
+                // want!  This way, computing statics works concistently between codegen
+                // and miri: They use the same query to eventually obtain a `ty::Const`
+                // and use that for further computation.
+                let alloc = self.tcx.alloc_map.lock().intern_static(cid.instance.def_id());
+                MPlaceTy::from_aligned_ptr(alloc.into(), layout)
             }
 
+            _ => bug!("eval_place_to_mplace called on {:?}", mir_place),
+        })
+    }
+
+    /// Compute a place.  You should only use this if you intend to write into this
+    /// place; for reading, a more efficient alternative is `eval_place_for_read`.
+    pub fn eval_place(&mut self, mir_place: &mir::Place<'tcx>) -> EvalResult<'tcx, PlaceTy<'tcx>> {
+        use rustc::mir::Place::*;
+        let place = match *mir_place {
+            Local(mir::RETURN_PLACE) => PlaceTy {
+                place: self.frame().return_place,
+                layout: self.layout_of_local(self.cur_frame(), mir::RETURN_PLACE)?,
+            },
+            Local(local) => PlaceTy {
+                place: Place::Local {
+                    frame: self.cur_frame(),
+                    local,
+                },
+                layout: self.layout_of_local(self.cur_frame(), local)?,
+            },
+
             Projection(ref proj) => {
-                let ty = self.place_ty(&proj.base);
                 let place = self.eval_place(&proj.base)?;
-                return self.eval_place_projection(place, ty, &proj.elem);
+                self.place_projection(place, &proj.elem)?
             }
-        };
 
-        self.dump_local(place);
+            _ => self.eval_place_to_mplace(mir_place)?.into(),
+        };
 
+        self.dump_place(place.place);
         Ok(place)
     }
 
-    pub fn place_field(
+    /// Write a scalar to a place
+    pub fn write_scalar(
         &mut self,
-        base: Place,
-        field: mir::Field,
-        mut base_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, (Place, TyLayout<'tcx>)> {
-        match base {
-            Place::Ptr { extra: PlaceExtra::DowncastVariant(variant_index), .. } => {
-                base_layout = base_layout.for_variant(&self, variant_index);
-            }
-            _ => {}
-        }
-        let field_index = field.index();
-        let field = base_layout.field(&self, field_index)?;
-        let offset = base_layout.fields.offset(field_index);
+        val: impl Into<ScalarMaybeUndef>,
+        dest: PlaceTy<'tcx>,
+    ) -> EvalResult<'tcx> {
+        self.write_value(Value::Scalar(val.into()), dest)
+    }
 
-        // Do not allocate in trivial cases
-        let (base_ptr, base_align, base_extra) = match base {
-            Place::Ptr { ptr, align, extra } => (ptr, align, extra),
+    /// Write a value to a place
+    pub fn write_value(
+        &mut self,
+        src_val: Value,
+        dest: PlaceTy<'tcx>,
+    ) -> EvalResult<'tcx> {
+        trace!("write_value: {:?} <- {:?}", *dest, src_val);
+        // See if we can avoid an allocation. This is the counterpart to `try_read_value`,
+        // but not factored as a separate function.
+        let mplace = match dest.place {
             Place::Local { frame, local } => {
-                match (self.stack[frame].locals[local].access()?, &base_layout.abi) {
-                    // in case the field covers the entire type, just return the value
-                    (Value::Scalar(_), &layout::Abi::Scalar(_)) |
-                    (Value::ScalarPair(..), &layout::Abi::ScalarPair(..))
-                    if offset.bytes() == 0 && field.size == base_layout.size => {
-                        return Ok((base, field))
+                match *self.stack[frame].locals[local].access_mut()? {
+                    Operand::Immediate(ref mut dest_val) => {
+                        // Yay, we can just change the local directly.
+                        *dest_val = src_val;
+                        return Ok(());
                     },
-                    _ => self.force_allocation(base)?.to_ptr_align_extra(),
+                    Operand::Indirect(mplace) => mplace, // already in memory
                 }
-            }
-        };
-
-        let offset = match base_extra {
-            PlaceExtra::Vtable(tab) => {
-                let (_, align) = self.size_and_align_of_dst(
-                    base_layout.ty,
-                    base_ptr.to_value_with_vtable(tab),
-                )?;
-                offset.abi_align(align)
-            }
-            _ => offset,
-        };
-
-        let ptr = base_ptr.ptr_offset(offset, &self)?;
-        let align = base_align.min(base_layout.align).min(field.align);
-        let extra = if !field.is_unsized() {
-            PlaceExtra::None
-        } else {
-            match base_extra {
-                PlaceExtra::None => bug!("expected fat pointer"),
-                PlaceExtra::DowncastVariant(..) => {
-                    bug!("Rust doesn't support unsized fields in enum variants")
-                }
-                PlaceExtra::Vtable(_) |
-                PlaceExtra::Length(_) => {}
-            }
-            base_extra
+            },
+            Place::Ptr(mplace) => mplace, // already in memory
         };
 
-        Ok((Place::Ptr { ptr, align, extra }, field))
+        // This is already in memory, write there.
+        let dest = MPlaceTy { mplace, layout: dest.layout };
+        self.write_value_to_mplace(src_val, dest)
     }
 
-    pub fn val_to_place(&self, val: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, Place> {
-        let layout = self.layout_of(ty)?;
-        Ok(match self.tcx.struct_tail(ty).sty {
-            ty::TyDynamic(..) => {
-                let (ptr, vtable) = self.into_ptr_vtable_pair(val)?;
-                Place::Ptr {
-                    ptr,
-                    align: layout.align,
-                    extra: PlaceExtra::Vtable(vtable),
-                }
+    /// Write a value to memory
+    fn write_value_to_mplace(
+        &mut self,
+        value: Value,
+        dest: MPlaceTy<'tcx>,
+    ) -> EvalResult<'tcx> {
+        let (ptr, ptr_align) = dest.to_scalar_ptr_align();
+        // Note that it is really important that the type here is the right one, and matches the
+        // type things are read at. In case `src_val` is a `ScalarPair`, we don't do any magic here
+        // to handle padding properly, which is only correct if we never look at this data with the
+        // wrong type.
+
+        // Nothing to do for ZSTs, other than checking alignment
+        if dest.layout.size.bytes() == 0 {
+            self.memory.check_align(ptr, ptr_align)?;
+            return Ok(());
+        }
+
+        let ptr = ptr.to_ptr()?;
+        match value {
+            Value::Scalar(scalar) => {
+                self.memory.write_scalar(
+                    ptr, ptr_align.min(dest.layout.align), scalar, dest.layout.size
+                )
             }
-            ty::TyStr | ty::TySlice(_) => {
-                let (ptr, len) = self.into_slice(val)?;
-                Place::Ptr {
-                    ptr,
-                    align: layout.align,
-                    extra: PlaceExtra::Length(len),
-                }
+            Value::ScalarPair(a_val, b_val) => {
+                let (a, b) = match dest.layout.abi {
+                    layout::Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value),
+                    _ => bug!("write_value_to_mplace: invalid ScalarPair layout: {:#?}",
+                              dest.layout)
+                };
+                let (a_size, b_size) = (a.size(&self), b.size(&self));
+                let (a_align, b_align) = (a.align(&self), b.align(&self));
+                let b_offset = a_size.abi_align(b_align);
+                let b_ptr = ptr.offset(b_offset, &self)?.into();
+
+                self.memory.write_scalar(ptr, ptr_align.min(a_align), a_val, a_size)?;
+                self.memory.write_scalar(b_ptr, ptr_align.min(b_align), b_val, b_size)
             }
-            _ => Place::from_scalar_ptr(self.into_ptr(val)?, layout.align),
-        })
+        }
     }
 
-    pub fn place_index(
+    /// Copy the data from an operand to a place
+    pub fn copy_op(
         &mut self,
-        base: Place,
-        outer_ty: Ty<'tcx>,
-        n: u64,
-    ) -> EvalResult<'tcx, Place> {
-        // Taking the outer type here may seem odd; it's needed because for array types, the outer type gives away the length.
-        let base = self.force_allocation(base)?;
-        let (base_ptr, align) = base.to_ptr_align();
-
-        let (elem_ty, len) = base.elem_ty_and_len(outer_ty, self.tcx.tcx);
-        let elem_size = self.layout_of(elem_ty)?.size;
-        assert!(
-            n < len,
-            "Tried to access element {} of array/slice with length {}",
-            n,
-            len
-        );
-        let ptr = base_ptr.ptr_offset(elem_size * n, &*self)?;
-        Ok(Place::Ptr {
-            ptr,
-            align,
-            extra: PlaceExtra::None,
-        })
+        src: OpTy<'tcx>,
+        dest: PlaceTy<'tcx>,
+    ) -> EvalResult<'tcx> {
+        assert_eq!(src.layout.size, dest.layout.size,
+            "Size mismatch when copying!\nsrc: {:#?}\ndest: {:#?}", src, dest);
+
+        // Let us see if the layout is simple so we take a shortcut, avoid force_allocation.
+        let (src_ptr, src_align) = match self.try_read_value(src)? {
+            Ok(src_val) =>
+                // Yay, we got a value that we can write directly.  We write with the
+                // *source layout*, because that was used to load, and if they do not match
+                // this is a transmute we want to support.
+                return self.write_value(src_val, PlaceTy { place: *dest, layout: src.layout }),
+            Err(mplace) => mplace.to_scalar_ptr_align(),
+        };
+        // Slow path, this does not fit into an immediate. Just memcpy.
+        trace!("copy_op: {:?} <- {:?}", *dest, *src);
+        let (dest_ptr, dest_align) = self.force_allocation(dest)?.to_scalar_ptr_align();
+        self.memory.copy(
+            src_ptr, src_align,
+            dest_ptr, dest_align,
+            src.layout.size, false
+        )
     }
 
-    pub(super) fn place_downcast(
+    /// Make sure that a place is in memory, and return where it is.
+    /// This is essentially `force_to_memplace`.
+    pub fn force_allocation(
         &mut self,
-        base: Place,
-        variant: usize,
-    ) -> EvalResult<'tcx, Place> {
-        // FIXME(solson)
-        let base = self.force_allocation(base)?;
-        let (ptr, align) = base.to_ptr_align();
-        let extra = PlaceExtra::DowncastVariant(variant);
-        Ok(Place::Ptr { ptr, align, extra })
+        place: PlaceTy<'tcx>,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+        let mplace = match place.place {
+            Place::Local { frame, local } => {
+                match *self.stack[frame].locals[local].access()? {
+                    Operand::Indirect(mplace) => mplace,
+                    Operand::Immediate(value) => {
+                        // We need to make an allocation.
+                        // FIXME: Consider not doing anything for a ZST, and just returning
+                        // a fake pointer?  Are we even called for ZST?
+
+                        // We need the layout of the local.  We can NOT use the layout we got,
+                        // that might e.g. be an inner field of a struct with `Scalar` layout,
+                        // that has different alignment than the outer field.
+                        let local_layout = self.layout_of_local(frame, local)?;
+                        let ptr = self.allocate(local_layout, MemoryKind::Stack)?;
+                        self.write_value_to_mplace(value, ptr)?;
+                        let mplace = ptr.mplace;
+                        // Update the local
+                        *self.stack[frame].locals[local].access_mut()? =
+                            Operand::Indirect(mplace);
+                        mplace
+                    }
+                }
+            }
+            Place::Ptr(mplace) => mplace
+        };
+        // Return with the original layout, so that the caller can go on
+        Ok(MPlaceTy { mplace, layout: place.layout })
     }
 
-    pub fn eval_place_projection(
+    pub fn allocate(
         &mut self,
-        base: Place,
-        base_ty: Ty<'tcx>,
-        proj_elem: &mir::ProjectionElem<'tcx, mir::Local, Ty<'tcx>>,
-    ) -> EvalResult<'tcx, Place> {
-        use rustc::mir::ProjectionElem::*;
-        match *proj_elem {
-            Field(field, _) => {
-                let layout = self.layout_of(base_ty)?;
-                Ok(self.place_field(base, field, layout)?.0)
-            }
-
-            Downcast(_, variant) => {
-                self.place_downcast(base, variant)
-            }
-
-            Deref => {
-                let val = self.read_place(base)?;
-
-                let pointee_type = match base_ty.sty {
-                    ty::TyRawPtr(ref tam) => tam.ty,
-                    ty::TyRef(_, ty, _) => ty,
-                    ty::TyAdt(def, _) if def.is_box() => base_ty.boxed_ty(),
-                    _ => bug!("can only deref pointer types"),
-                };
-
-                trace!("deref to {} on {:?}", pointee_type, val);
+        layout: TyLayout<'tcx>,
+        kind: MemoryKind<M::MemoryKinds>,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+        assert!(!layout.is_unsized(), "cannot alloc memory for unsized type");
+        let ptr = self.memory.allocate(layout.size, layout.align, kind)?;
+        Ok(MPlaceTy::from_aligned_ptr(ptr, layout))
+    }
 
-                self.val_to_place(val, pointee_type)
+    pub fn write_discriminant_index(
+        &mut self,
+        variant_index: usize,
+        dest: PlaceTy<'tcx>,
+    ) -> EvalResult<'tcx> {
+        match dest.layout.variants {
+            layout::Variants::Single { index } => {
+                assert_eq!(index, variant_index);
             }
-
-            Index(local) => {
-                let value = self.frame().locals[local].access()?;
-                let ty = self.tcx.types.usize;
-                let n = self
-                    .value_to_scalar(ValTy { value, ty })?
-                    .to_bits(self.tcx.data_layout.pointer_size)?;
-                self.place_index(base, base_ty, n as u64)
+            layout::Variants::Tagged { ref tag, .. } => {
+                let adt_def = dest.layout.ty.ty_adt_def().unwrap();
+                assert!(variant_index < adt_def.variants.len());
+                let discr_val = adt_def
+                    .discriminant_for_variant(*self.tcx, variant_index)
+                    .val;
+
+                // raw discriminants for enums are isize or bigger during
+                // their computation, but the in-memory tag is the smallest possible
+                // representation
+                let size = tag.value.size(self.tcx.tcx);
+                let shift = 128 - size.bits();
+                let discr_val = (discr_val << shift) >> shift;
+
+                let discr_dest = self.place_field(dest, 0)?;
+                self.write_scalar(Scalar::from_uint(discr_val, size), discr_dest)?;
             }
-
-            ConstantIndex {
-                offset,
-                min_length,
-                from_end,
+            layout::Variants::NicheFilling {
+                dataful_variant,
+                ref niche_variants,
+                niche_start,
+                ..
             } => {
-                // FIXME(solson)
-                let base = self.force_allocation(base)?;
-                let (base_ptr, align) = base.to_ptr_align();
-
-                let (elem_ty, n) = base.elem_ty_and_len(base_ty, self.tcx.tcx);
-                let elem_size = self.layout_of(elem_ty)?.size;
-                assert!(n >= min_length as u64);
+                assert!(variant_index < dest.layout.ty.ty_adt_def().unwrap().variants.len());
+                if variant_index != dataful_variant {
+                    let niche_dest =
+                        self.place_field(dest, 0)?;
+                    let niche_value = ((variant_index - niche_variants.start()) as u128)
+                        .wrapping_add(niche_start);
+                    self.write_scalar(
+                        Scalar::from_uint(niche_value, niche_dest.layout.size),
+                        niche_dest
+                    )?;
+                }
+            }
+        }
 
-                let index = if from_end {
-                    n - u64::from(offset)
-                } else {
-                    u64::from(offset)
-                };
+        Ok(())
+    }
 
-                let ptr = base_ptr.ptr_offset(elem_size * index, &self)?;
-                Ok(Place::Ptr { ptr, align, extra: PlaceExtra::None })
+    /// Every place can be read from, so we can turm them into an operand
+    #[inline(always)]
+    pub fn place_to_op(&self, place: PlaceTy<'tcx>) -> EvalResult<'tcx, OpTy<'tcx>> {
+        let op = match place.place {
+            Place::Ptr(mplace) => {
+                Operand::Indirect(mplace)
             }
+            Place::Local { frame, local } =>
+                *self.stack[frame].locals[local].access()?
+        };
+        Ok(OpTy { op, layout: place.layout })
+    }
 
-            Subslice { from, to } => {
-                // FIXME(solson)
-                let base = self.force_allocation(base)?;
-                let (base_ptr, align) = base.to_ptr_align();
-
-                let (elem_ty, n) = base.elem_ty_and_len(base_ty, self.tcx.tcx);
-                let elem_size = self.layout_of(elem_ty)?.size;
-                assert!(u64::from(from) <= n - u64::from(to));
-                let ptr = base_ptr.ptr_offset(elem_size * u64::from(from), &self)?;
-                // sublicing arrays produces arrays
-                let extra = if self.type_is_sized(base_ty) {
-                    PlaceExtra::None
-                } else {
-                    PlaceExtra::Length(n - u64::from(to) - u64::from(from))
-                };
-                Ok(Place::Ptr { ptr, align, extra })
-            }
+    /// Turn a place with a `dyn Trait` type into a place with the actual dynamic type.
+    /// Also return some more information so drop doesn't have to run the same code twice.
+    pub(super) fn unpack_dyn_trait(&self, mplace: MPlaceTy<'tcx>)
+    -> EvalResult<'tcx, (ty::Instance<'tcx>, MPlaceTy<'tcx>)> {
+        let vtable = mplace.vtable()?; // also sanity checks the type
+        let (instance, ty) = self.read_drop_type_from_vtable(vtable)?;
+        let layout = self.layout_of(ty)?;
+
+        // More sanity checks
+        if cfg!(debug_assertions) {
+            let (size, align) = self.read_size_and_align_from_vtable(vtable)?;
+            assert_eq!(size, layout.size);
+            assert_eq!(align.abi(), layout.align.abi()); // only ABI alignment is preserved
         }
-    }
 
-    pub fn place_ty(&self, place: &mir::Place<'tcx>) -> Ty<'tcx> {
-        self.monomorphize(
-            place.ty(self.mir(), *self.tcx).to_ty(*self.tcx),
-            self.substs(),
-        )
+        let mplace = MPlaceTy {
+            mplace: MemPlace { extra: None, ..*mplace },
+            layout
+        };
+        Ok((instance, mplace))
     }
 }
index 57b56db14bb4b719e00a19560a35120108d78211..114ef093ec2fddd90327a2cfcbfe9326b36ad91c 100644 (file)
@@ -1,12 +1,50 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
 //! This module contains the `EvalContext` methods for executing a single step of the interpreter.
 //!
 //! The main entry point is the `step` method.
 
 use rustc::mir;
+use rustc::ty::layout::LayoutOf;
+use rustc::mir::interpret::{EvalResult, Scalar, PointerArithmetic};
 
-use rustc::mir::interpret::EvalResult;
 use super::{EvalContext, Machine};
 
+/// Classify whether an operator is "left-homogeneous", i.e. the LHS has the
+/// same type as the result.
+#[inline]
+fn binop_left_homogeneous(op: mir::BinOp) -> bool {
+    use rustc::mir::BinOp::*;
+    match op {
+        Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr |
+        Offset | Shl | Shr =>
+            true,
+        Eq | Ne | Lt | Le | Gt | Ge =>
+            false,
+    }
+}
+/// Classify whether an operator is "right-homogeneous", i.e. the RHS has the
+/// same type as the LHS.
+#[inline]
+fn binop_right_homogeneous(op: mir::BinOp) -> bool {
+    use rustc::mir::BinOp::*;
+    match op {
+        Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr |
+        Eq | Ne | Lt | Le | Gt | Ge =>
+            true,
+        Offset | Shl | Shr =>
+            false,
+    }
+}
+
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
     pub fn inc_step_counter_and_detect_loops(&mut self) -> EvalResult<'tcx, ()> {
         /// The number of steps between loop detector snapshots.
@@ -38,8 +76,13 @@ pub fn inc_step_counter_and_detect_loops(&mut self) -> EvalResult<'tcx, ()> {
         self.loop_detector.observe_and_analyze(&self.machine, &self.stack, &self.memory)
     }
 
+    pub fn run(&mut self) -> EvalResult<'tcx> {
+        while self.step()? {}
+        Ok(())
+    }
+
     /// Returns true as long as there are more things to do.
-    pub fn step(&mut self) -> EvalResult<'tcx, bool> {
+    fn step(&mut self) -> EvalResult<'tcx, bool> {
         if self.stack.is_empty() {
             return Ok(false);
         }
@@ -66,12 +109,12 @@ pub fn step(&mut self) -> EvalResult<'tcx, bool> {
     }
 
     fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx> {
-        trace!("{:?}", stmt);
+        debug!("{:?}", stmt);
 
         use rustc::mir::StatementKind::*;
 
-        // Some statements (e.g. box) push new stack frames.  We have to record the stack frame number
-        // *before* executing the statement.
+        // Some statements (e.g. box) push new stack frames.
+        // We have to record the stack frame number *before* executing the statement.
         let frame_idx = self.cur_frame();
         self.tcx.span = stmt.source_info.span;
         self.memory.tcx.span = stmt.source_info.span;
@@ -84,8 +127,7 @@ fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx> {
                 variant_index,
             } => {
                 let dest = self.eval_place(place)?;
-                let dest_ty = self.place_ty(place);
-                self.write_discriminant_value(dest_ty, dest, variant_index)?;
+                self.write_discriminant_index(variant_index, dest)?;
             }
 
             // Mark locals as alive
@@ -96,7 +138,7 @@ fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx> {
 
             // Mark locals as dead
             StorageDead(local) => {
-                let old_val = self.frame_mut().storage_dead(local);
+                let old_val = self.storage_dead(local);
                 self.deallocate_local(old_val)?;
             }
 
@@ -110,10 +152,8 @@ fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx> {
                     M::validation_op(self, op, operand)?;
                 }
             }
-            EndRegion(ce) => {
-                M::end_region(self, Some(ce))?;
-            }
 
+            EndRegion(..) => {}
             UserAssertTy(..) => {}
 
             // Defined to do nothing. These are added by optimization passes, to avoid changing the
@@ -127,13 +167,168 @@ fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx> {
         Ok(())
     }
 
+    /// Evaluate an assignment statement.
+    ///
+    /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
+    /// type writes its results directly into the memory specified by the place.
+    fn eval_rvalue_into_place(
+        &mut self,
+        rvalue: &mir::Rvalue<'tcx>,
+        place: &mir::Place<'tcx>,
+    ) -> EvalResult<'tcx> {
+        let dest = self.eval_place(place)?;
+
+        use rustc::mir::Rvalue::*;
+        match *rvalue {
+            Use(ref operand) => {
+                // Avoid recomputing the layout
+                let op = self.eval_operand(operand, Some(dest.layout))?;
+                self.copy_op(op, dest)?;
+            }
+
+            BinaryOp(bin_op, ref left, ref right) => {
+                let layout = if binop_left_homogeneous(bin_op) { Some(dest.layout) } else { None };
+                let left = self.read_value(self.eval_operand(left, layout)?)?;
+                let layout = if binop_right_homogeneous(bin_op) { Some(left.layout) } else { None };
+                let right = self.read_value(self.eval_operand(right, layout)?)?;
+                self.binop_ignore_overflow(
+                    bin_op,
+                    left,
+                    right,
+                    dest,
+                )?;
+            }
+
+            CheckedBinaryOp(bin_op, ref left, ref right) => {
+                // Due to the extra boolean in the result, we can never reuse the `dest.layout`.
+                let left = self.read_value(self.eval_operand(left, None)?)?;
+                let layout = if binop_right_homogeneous(bin_op) { Some(left.layout) } else { None };
+                let right = self.read_value(self.eval_operand(right, layout)?)?;
+                self.binop_with_overflow(
+                    bin_op,
+                    left,
+                    right,
+                    dest,
+                )?;
+            }
+
+            UnaryOp(un_op, ref operand) => {
+                // The operand always has the same type as the result.
+                let val = self.read_value(self.eval_operand(operand, Some(dest.layout))?)?;
+                let val = self.unary_op(un_op, val.to_scalar()?, dest.layout)?;
+                self.write_scalar(val, dest)?;
+            }
+
+            Aggregate(ref kind, ref operands) => {
+                let (dest, active_field_index) = match **kind {
+                    mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
+                        self.write_discriminant_index(variant_index, dest)?;
+                        if adt_def.is_enum() {
+                            (self.place_downcast(dest, variant_index)?, active_field_index)
+                        } else {
+                            (dest, active_field_index)
+                        }
+                    }
+                    _ => (dest, None)
+                };
+
+                for (i, operand) in operands.iter().enumerate() {
+                    let op = self.eval_operand(operand, None)?;
+                    // Ignore zero-sized fields.
+                    if !op.layout.is_zst() {
+                        let field_index = active_field_index.unwrap_or(i);
+                        let field_dest = self.place_field(dest, field_index as u64)?;
+                        self.copy_op(op, field_dest)?;
+                    }
+                }
+            }
+
+            Repeat(ref operand, _) => {
+                let op = self.eval_operand(operand, None)?;
+                let dest = self.force_allocation(dest)?;
+                let length = dest.len(&self)?;
+
+                if length > 0 {
+                    // write the first
+                    let first = self.mplace_field(dest, 0)?;
+                    self.copy_op(op, first.into())?;
+
+                    if length > 1 {
+                        // copy the rest
+                        let (dest, dest_align) = first.to_scalar_ptr_align();
+                        let rest = dest.ptr_offset(first.layout.size, &self)?;
+                        self.memory.copy_repeatedly(
+                            dest, dest_align, rest, dest_align, first.layout.size, length - 1, true
+                        )?;
+                    }
+                }
+            }
+
+            Len(ref place) => {
+                // FIXME(CTFE): don't allow computing the length of arrays in const eval
+                let src = self.eval_place(place)?;
+                let mplace = self.force_allocation(src)?;
+                let len = mplace.len(&self)?;
+                let size = self.pointer_size();
+                self.write_scalar(
+                    Scalar::from_uint(len, size),
+                    dest,
+                )?;
+            }
+
+            Ref(_, _, ref place) => {
+                let src = self.eval_place(place)?;
+                let val = self.force_allocation(src)?.to_ref();
+                self.write_value(val, dest)?;
+            }
+
+            NullaryOp(mir::NullOp::Box, _) => {
+                M::box_alloc(self, dest)?;
+            }
+
+            NullaryOp(mir::NullOp::SizeOf, ty) => {
+                let ty = self.monomorphize(ty, self.substs());
+                let layout = self.layout_of(ty)?;
+                assert!(!layout.is_unsized(),
+                        "SizeOf nullary MIR operator called for unsized type");
+                let size = self.pointer_size();
+                self.write_scalar(
+                    Scalar::from_uint(layout.size.bytes(), size),
+                    dest,
+                )?;
+            }
+
+            Cast(kind, ref operand, cast_ty) => {
+                debug_assert_eq!(self.monomorphize(cast_ty, self.substs()), dest.layout.ty);
+                let src = self.eval_operand(operand, None)?;
+                self.cast(src, kind, dest)?;
+            }
+
+            Discriminant(ref place) => {
+                let place = self.eval_place(place)?;
+                let discr_val = self.read_discriminant(self.place_to_op(place)?)?.0;
+                let size = dest.layout.size;
+                self.write_scalar(Scalar::from_uint(discr_val, size), dest)?;
+            }
+        }
+
+        self.dump_place(*dest);
+
+        Ok(())
+    }
+
     fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<'tcx> {
-        trace!("{:?}", terminator.kind);
+        debug!("{:?}", terminator.kind);
         self.tcx.span = terminator.source_info.span;
         self.memory.tcx.span = terminator.source_info.span;
+
+        let old_stack = self.cur_frame();
+        let old_bb = self.frame().block;
         self.eval_terminator(terminator)?;
         if !self.stack.is_empty() {
-            trace!("// {:?}", self.frame().block);
+            // This should change *something*
+            debug_assert!(self.cur_frame() != old_stack || self.frame().block != old_bb);
+            debug!("// {:?}", self.frame().block);
         }
         Ok(())
     }
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
new file mode 100644 (file)
index 0000000..de86810
--- /dev/null
@@ -0,0 +1,451 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::borrow::Cow;
+
+use rustc::{mir, ty};
+use rustc::ty::layout::{self, TyLayout, LayoutOf};
+use syntax::source_map::Span;
+use rustc_target::spec::abi::Abi;
+
+use rustc::mir::interpret::{EvalResult, PointerArithmetic, EvalErrorKind, Scalar};
+use super::{
+    EvalContext, Machine, Value, OpTy, Place, PlaceTy, Operand, StackPopCleanup
+};
+
+impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+    #[inline]
+    pub fn goto_block(&mut self, target: Option<mir::BasicBlock>) -> EvalResult<'tcx> {
+        if let Some(target) = target {
+            self.frame_mut().block = target;
+            self.frame_mut().stmt = 0;
+            Ok(())
+        } else {
+            err!(Unreachable)
+        }
+    }
+
+    pub(super) fn eval_terminator(
+        &mut self,
+        terminator: &mir::Terminator<'tcx>,
+    ) -> EvalResult<'tcx> {
+        use rustc::mir::TerminatorKind::*;
+        match terminator.kind {
+            Return => {
+                self.dump_place(self.frame().return_place);
+                self.pop_stack_frame()?
+            }
+
+            Goto { target } => self.goto_block(Some(target))?,
+
+            SwitchInt {
+                ref discr,
+                ref values,
+                ref targets,
+                ..
+            } => {
+                let discr = self.read_value(self.eval_operand(discr, None)?)?;
+                trace!("SwitchInt({:?})", *discr);
+
+                // Branch to the `otherwise` case by default, if no match is found.
+                let mut target_block = targets[targets.len() - 1];
+
+                for (index, &const_int) in values.iter().enumerate() {
+                    // Compare using binary_op, to also support pointer values
+                    let const_int = Scalar::from_uint(const_int, discr.layout.size);
+                    let (res, _) = self.binary_op(mir::BinOp::Eq,
+                        discr.to_scalar()?, discr.layout,
+                        const_int, discr.layout,
+                    )?;
+                    if res.to_bool()? {
+                        target_block = targets[index];
+                        break;
+                    }
+                }
+
+                self.goto_block(Some(target_block))?;
+            }
+
+            Call {
+                ref func,
+                ref args,
+                ref destination,
+                ..
+            } => {
+                let (dest, ret) = match *destination {
+                    Some((ref lv, target)) => (Some(self.eval_place(lv)?), Some(target)),
+                    None => (None, None),
+                };
+
+                let func = self.eval_operand(func, None)?;
+                let (fn_def, abi) = match func.layout.ty.sty {
+                    ty::FnPtr(sig) => {
+                        let caller_abi = sig.abi();
+                        let fn_ptr = self.read_scalar(func)?.to_ptr()?;
+                        let instance = self.memory.get_fn(fn_ptr)?;
+                        (instance, caller_abi)
+                    }
+                    ty::FnDef(def_id, substs) => {
+                        let sig = func.layout.ty.fn_sig(*self.tcx);
+                        (self.resolve(def_id, substs)?, sig.abi())
+                    },
+                    _ => {
+                        let msg = format!("can't handle callee of type {:?}", func.layout.ty);
+                        return err!(Unimplemented(msg));
+                    }
+                };
+                let args = self.eval_operands(args)?;
+                self.eval_fn_call(
+                    fn_def,
+                    terminator.source_info.span,
+                    abi,
+                    &args[..],
+                    dest,
+                    ret,
+                )?;
+            }
+
+            Drop {
+                ref location,
+                target,
+                ..
+            } => {
+                // FIXME(CTFE): forbid drop in const eval
+                let place = self.eval_place(location)?;
+                let ty = place.layout.ty;
+                trace!("TerminatorKind::drop: {:?}, type {}", location, ty);
+
+                let instance = ::monomorphize::resolve_drop_in_place(*self.tcx, ty);
+                self.drop_in_place(
+                    place,
+                    instance,
+                    terminator.source_info.span,
+                    target,
+                )?;
+            }
+
+            Assert {
+                ref cond,
+                expected,
+                ref msg,
+                target,
+                ..
+            } => {
+                let cond_val = self.read_value(self.eval_operand(cond, None)?)?
+                    .to_scalar()?.to_bool()?;
+                if expected == cond_val {
+                    self.goto_block(Some(target))?;
+                } else {
+                    // Compute error message
+                    use rustc::mir::interpret::EvalErrorKind::*;
+                    return match *msg {
+                        BoundsCheck { ref len, ref index } => {
+                            let len = self.read_value(self.eval_operand(len, None)?)
+                                .expect("can't eval len").to_scalar()?
+                                .to_bits(self.memory().pointer_size())? as u64;
+                            let index = self.read_value(self.eval_operand(index, None)?)
+                                .expect("can't eval index").to_scalar()?
+                                .to_bits(self.memory().pointer_size())? as u64;
+                            err!(BoundsCheck { len, index })
+                        }
+                        Overflow(op) => Err(Overflow(op).into()),
+                        OverflowNeg => Err(OverflowNeg.into()),
+                        DivisionByZero => Err(DivisionByZero.into()),
+                        RemainderByZero => Err(RemainderByZero.into()),
+                        GeneratorResumedAfterReturn |
+                        GeneratorResumedAfterPanic => unimplemented!(),
+                        _ => bug!(),
+                    };
+                }
+            }
+
+            Yield { .. } |
+            GeneratorDrop |
+            DropAndReplace { .. } |
+            Resume |
+            Abort => unimplemented!("{:#?}", terminator.kind),
+            FalseEdges { .. } => bug!("should have been eliminated by\
+                                      `simplify_branches` mir pass"),
+            FalseUnwind { .. } => bug!("should have been eliminated by\
+                                       `simplify_branches` mir pass"),
+            Unreachable => return err!(Unreachable),
+        }
+
+        Ok(())
+    }
+
+    fn check_argument_compat(
+        caller: TyLayout<'tcx>,
+        callee: TyLayout<'tcx>,
+    ) -> bool {
+        if caller.ty == callee.ty {
+            // No question
+            return true;
+        }
+        // Compare layout
+        match (&caller.abi, &callee.abi) {
+            (layout::Abi::Scalar(ref caller), layout::Abi::Scalar(ref callee)) =>
+                // Different valid ranges are okay (once we enforce validity,
+                // that will take care to make it UB to leave the range, just
+                // like for transmute).
+                caller.value == callee.value,
+            // Be conservative
+            _ => false
+        }
+    }
+
+    /// Pass a single argument, checking the types for compatibility.
+    fn pass_argument(
+        &mut self,
+        skip_zst: bool,
+        caller_arg: &mut impl Iterator<Item=OpTy<'tcx>>,
+        callee_arg: PlaceTy<'tcx>,
+    ) -> EvalResult<'tcx> {
+        if skip_zst && callee_arg.layout.is_zst() {
+            // Nothing to do.
+            trace!("Skipping callee ZST");
+            return Ok(());
+        }
+        let caller_arg = caller_arg.next()
+            .ok_or_else(|| EvalErrorKind::FunctionArgCountMismatch)?;
+        if skip_zst {
+            debug_assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out");
+        }
+        // Now, check
+        if !Self::check_argument_compat(caller_arg.layout, callee_arg.layout) {
+            return err!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty));
+        }
+        self.copy_op(caller_arg, callee_arg)
+    }
+
+    /// Call this function -- pushing the stack frame and initializing the arguments.
+    fn eval_fn_call(
+        &mut self,
+        instance: ty::Instance<'tcx>,
+        span: Span,
+        caller_abi: Abi,
+        args: &[OpTy<'tcx>],
+        dest: Option<PlaceTy<'tcx>>,
+        ret: Option<mir::BasicBlock>,
+    ) -> EvalResult<'tcx> {
+        trace!("eval_fn_call: {:#?}", instance);
+
+        match instance.def {
+            ty::InstanceDef::Intrinsic(..) => {
+                if caller_abi != Abi::RustIntrinsic {
+                    return err!(FunctionAbiMismatch(caller_abi, Abi::RustIntrinsic));
+                }
+                // The intrinsic itself cannot diverge, so if we got here without a return
+                // place... (can happen e.g. for transmute returning `!`)
+                let dest = match dest {
+                    Some(dest) => dest,
+                    None => return err!(Unreachable)
+                };
+                M::call_intrinsic(self, instance, args, dest)?;
+                // No stack frame gets pushed, the main loop will just act as if the
+                // call completed.
+                self.goto_block(ret)?;
+                self.dump_place(*dest);
+                Ok(())
+            }
+            ty::InstanceDef::ClosureOnceShim { .. } |
+            ty::InstanceDef::FnPtrShim(..) |
+            ty::InstanceDef::DropGlue(..) |
+            ty::InstanceDef::CloneShim(..) |
+            ty::InstanceDef::Item(_) => {
+                // ABI check
+                {
+                    let callee_abi = {
+                        let instance_ty = instance.ty(*self.tcx);
+                        match instance_ty.sty {
+                            ty::FnDef(..) =>
+                                instance_ty.fn_sig(*self.tcx).abi(),
+                            ty::Closure(..) => Abi::RustCall,
+                            ty::Generator(..) => Abi::Rust,
+                            _ => bug!("unexpected callee ty: {:?}", instance_ty),
+                        }
+                    };
+                    // Rust and RustCall are compatible
+                    let normalize_abi = |abi| if abi == Abi::RustCall { Abi::Rust } else { abi };
+                    if normalize_abi(caller_abi) != normalize_abi(callee_abi) {
+                        return err!(FunctionAbiMismatch(caller_abi, callee_abi));
+                    }
+                }
+
+                // We need MIR for this fn
+                let mir = match M::find_fn(self, instance, args, dest, ret)? {
+                    Some(mir) => mir,
+                    None => return Ok(()),
+                };
+
+                let return_place = match dest {
+                    Some(place) => *place,
+                    None => Place::null(&self),
+                };
+                self.push_stack_frame(
+                    instance,
+                    span,
+                    mir,
+                    return_place,
+                    StackPopCleanup::Goto(ret),
+                )?;
+
+                // We want to pop this frame again in case there was an error, to put
+                // the blame in the right location.  Until the 2018 edition is used in
+                // the compiler, we have to do this with an immediately invoked function.
+                let res = (||{
+                    trace!(
+                        "caller ABI: {:?}, args: {:#?}",
+                        caller_abi,
+                        args.iter()
+                            .map(|arg| (arg.layout.ty, format!("{:?}", **arg)))
+                            .collect::<Vec<_>>()
+                    );
+                    trace!(
+                        "spread_arg: {:?}, locals: {:#?}",
+                        mir.spread_arg,
+                        mir.args_iter()
+                            .map(|local|
+                                (local, self.layout_of_local(self.cur_frame(), local).unwrap().ty)
+                            )
+                            .collect::<Vec<_>>()
+                    );
+
+                    // Figure out how to pass which arguments.
+                    // We have two iterators: Where the arguments come from,
+                    // and where they go to.
+                    let skip_zst = match caller_abi {
+                        Abi::Rust | Abi::RustCall => true,
+                        _ => false
+                    };
+
+                    // For where they come from: If the ABI is RustCall, we untuple the
+                    // last incoming argument.  These two iterators do not have the same type,
+                    // so to keep the code paths uniform we accept an allocation
+                    // (for RustCall ABI only).
+                    let caller_args : Cow<[OpTy<'tcx>]> =
+                        if caller_abi == Abi::RustCall && !args.is_empty() {
+                            // Untuple
+                            let (&untuple_arg, args) = args.split_last().unwrap();
+                            trace!("eval_fn_call: Will pass last argument by untupling");
+                            Cow::from(args.iter().map(|&a| Ok(a))
+                                .chain((0..untuple_arg.layout.fields.count()).into_iter()
+                                    .map(|i| self.operand_field(untuple_arg, i as u64))
+                                )
+                                .collect::<EvalResult<Vec<OpTy<'tcx>>>>()?)
+                        } else {
+                            // Plain arg passing
+                            Cow::from(args)
+                        };
+                    // Skip ZSTs
+                    let mut caller_iter = caller_args.iter()
+                        .filter(|op| !skip_zst || !op.layout.is_zst())
+                        .map(|op| *op);
+
+                    // Now we have to spread them out across the callee's locals,
+                    // taking into account the `spread_arg`.  If we could write
+                    // this is a single iterator (that handles `spread_arg`), then
+                    // `pass_argument` would be the loop body. It takes care to
+                    // not advance `caller_iter` for ZSTs.
+                    let mut locals_iter = mir.args_iter();
+                    while let Some(local) = locals_iter.next() {
+                        let dest = self.eval_place(&mir::Place::Local(local))?;
+                        if Some(local) == mir.spread_arg {
+                            // Must be a tuple
+                            for i in 0..dest.layout.fields.count() {
+                                let dest = self.place_field(dest, i as u64)?;
+                                self.pass_argument(skip_zst, &mut caller_iter, dest)?;
+                            }
+                        } else {
+                            // Normal argument
+                            self.pass_argument(skip_zst, &mut caller_iter, dest)?;
+                        }
+                    }
+                    // Now we should have no more caller args
+                    if caller_iter.next().is_some() {
+                        trace!("Caller has too many args over");
+                        return err!(FunctionArgCountMismatch);
+                    }
+                    Ok(())
+                })();
+                match res {
+                    Err(err) => {
+                        self.stack.pop();
+                        Err(err)
+                    }
+                    Ok(v) => Ok(v)
+                }
+            }
+            // cannot use the shim here, because that will only result in infinite recursion
+            ty::InstanceDef::Virtual(_, idx) => {
+                let ptr_size = self.pointer_size();
+                let ptr_align = self.tcx.data_layout.pointer_align;
+                let ptr = self.ref_to_mplace(self.read_value(args[0])?)?;
+                let vtable = ptr.vtable()?;
+                let fn_ptr = self.memory.read_ptr_sized(
+                    vtable.offset(ptr_size * (idx as u64 + 3), &self)?,
+                    ptr_align
+                )?.to_ptr()?;
+                let instance = self.memory.get_fn(fn_ptr)?;
+
+                // We have to patch the self argument, in particular get the layout
+                // expected by the actual function. Cannot just use "field 0" due to
+                // Box<self>.
+                let mut args = args.to_vec();
+                let pointee = args[0].layout.ty.builtin_deref(true).unwrap().ty;
+                let fake_fat_ptr_ty = self.tcx.mk_mut_ptr(pointee);
+                args[0].layout = self.layout_of(fake_fat_ptr_ty)?.field(&self, 0)?;
+                args[0].op = Operand::Immediate(Value::Scalar(ptr.ptr.into())); // strip vtable
+                trace!("Patched self operand to {:#?}", args[0]);
+                // recurse with concrete function
+                self.eval_fn_call(instance, span, caller_abi, &args, dest, ret)
+            }
+        }
+    }
+
+    fn drop_in_place(
+        &mut self,
+        place: PlaceTy<'tcx>,
+        instance: ty::Instance<'tcx>,
+        span: Span,
+        target: mir::BasicBlock,
+    ) -> EvalResult<'tcx> {
+        trace!("drop_in_place: {:?},\n  {:?}, {:?}", *place, place.layout.ty, instance);
+        // We take the address of the object.  This may well be unaligned, which is fine
+        // for us here.  However, unaligned accesses will probably make the actual drop
+        // implementation fail -- a problem shared by rustc.
+        let place = self.force_allocation(place)?;
+
+        let (instance, place) = match place.layout.ty.sty {
+            ty::Dynamic(..) => {
+                // Dropping a trait object.
+                self.unpack_dyn_trait(place)?
+            }
+            _ => (instance, place),
+        };
+
+        let arg = OpTy {
+            op: Operand::Immediate(place.to_ref()),
+            layout: self.layout_of(self.tcx.mk_mut_ptr(place.layout.ty))?,
+        };
+
+        let ty = self.tcx.mk_nil(); // return type is ()
+        let dest = PlaceTy::null(&self, self.layout_of(ty)?);
+
+        self.eval_fn_call(
+            instance,
+            span,
+            Abi::Rust,
+            &[arg],
+            Some(dest),
+            Some(target),
+        )
+    }
+}
diff --git a/src/librustc_mir/interpret/terminator/drop.rs b/src/librustc_mir/interpret/terminator/drop.rs
deleted file mode 100644 (file)
index f86c0e8..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-use rustc::mir::BasicBlock;
-use rustc::ty::{self, Ty};
-use syntax::source_map::Span;
-
-use rustc::mir::interpret::{EvalResult, Value};
-use interpret::{Machine, ValTy, EvalContext, Place, PlaceExtra};
-
-impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
-    pub(crate) fn drop_place(
-        &mut self,
-        place: Place,
-        instance: ty::Instance<'tcx>,
-        ty: Ty<'tcx>,
-        span: Span,
-        target: BasicBlock,
-    ) -> EvalResult<'tcx> {
-        trace!("drop_place: {:#?}", place);
-        // We take the address of the object.  This may well be unaligned, which is fine for us here.
-        // However, unaligned accesses will probably make the actual drop implementation fail -- a problem shared
-        // by rustc.
-        let val = match self.force_allocation(place)? {
-            Place::Ptr {
-                ptr,
-                align: _,
-                extra: PlaceExtra::Vtable(vtable),
-            } => ptr.to_value_with_vtable(vtable),
-            Place::Ptr {
-                ptr,
-                align: _,
-                extra: PlaceExtra::Length(len),
-            } => ptr.to_value_with_len(len, self.tcx.tcx),
-            Place::Ptr {
-                ptr,
-                align: _,
-                extra: PlaceExtra::None,
-            } => Value::Scalar(ptr),
-            _ => bug!("force_allocation broken"),
-        };
-        self.drop(val, instance, ty, span, target)
-    }
-
-    fn drop(
-        &mut self,
-        arg: Value,
-        instance: ty::Instance<'tcx>,
-        ty: Ty<'tcx>,
-        span: Span,
-        target: BasicBlock,
-    ) -> EvalResult<'tcx> {
-        trace!("drop: {:#?}, {:?}, {:?}", arg, ty.sty, instance.def);
-
-        let instance = match ty.sty {
-            ty::TyDynamic(..) => {
-                if let Value::ScalarPair(_, vtable) = arg {
-                    self.read_drop_type_from_vtable(vtable.unwrap_or_err()?.to_ptr()?)?
-                } else {
-                    bug!("expected fat ptr, got {:?}", arg);
-                }
-            }
-            _ => instance,
-        };
-
-        // the drop function expects a reference to the value
-        let valty = ValTy {
-            value: arg,
-            ty: self.tcx.mk_mut_ptr(ty),
-        };
-
-        let fn_sig = self.tcx.fn_sig(instance.def_id()).skip_binder().clone();
-
-        self.eval_fn_call(
-            instance,
-            Some((Place::undef(), target)),
-            &[valty],
-            span,
-            fn_sig,
-        )
-    }
-}
diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs
deleted file mode 100644 (file)
index 3a77255..0000000
+++ /dev/null
@@ -1,406 +0,0 @@
-use rustc::mir;
-use rustc::ty::{self, Ty};
-use rustc::ty::layout::{LayoutOf, Size};
-use syntax::source_map::Span;
-use rustc_target::spec::abi::Abi;
-
-use rustc::mir::interpret::{EvalResult, Scalar, Value};
-use super::{EvalContext, Place, Machine, ValTy};
-
-use rustc_data_structures::indexed_vec::Idx;
-use interpret::memory::HasMemory;
-
-mod drop;
-
-impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
-    pub fn goto_block(&mut self, target: mir::BasicBlock) {
-        self.frame_mut().block = target;
-        self.frame_mut().stmt = 0;
-    }
-
-    pub(super) fn eval_terminator(
-        &mut self,
-        terminator: &mir::Terminator<'tcx>,
-    ) -> EvalResult<'tcx> {
-        use rustc::mir::TerminatorKind::*;
-        match terminator.kind {
-            Return => {
-                self.dump_local(self.frame().return_place);
-                self.pop_stack_frame()?
-            }
-
-            Goto { target } => self.goto_block(target),
-
-            SwitchInt {
-                ref discr,
-                ref values,
-                ref targets,
-                ..
-            } => {
-                let discr_val = self.eval_operand(discr)?;
-                let discr_prim = self.value_to_scalar(discr_val)?;
-                let discr_layout = self.layout_of(discr_val.ty).unwrap();
-                trace!("SwitchInt({:?}, {:#?})", discr_prim, discr_layout);
-
-                // Branch to the `otherwise` case by default, if no match is found.
-                let mut target_block = targets[targets.len() - 1];
-
-                for (index, &const_int) in values.iter().enumerate() {
-                    // Compare using binary_op
-                    let const_int = Scalar::Bits { bits: const_int, size: discr_layout.size.bytes() as u8 };
-                    let res = self.binary_op(mir::BinOp::Eq,
-                        discr_prim, discr_val.ty,
-                        const_int, discr_val.ty
-                    )?;
-                    if res.0.to_bits(Size::from_bytes(1))? != 0 {
-                        target_block = targets[index];
-                        break;
-                    }
-                }
-
-                self.goto_block(target_block);
-            }
-
-            Call {
-                ref func,
-                ref args,
-                ref destination,
-                ..
-            } => {
-                let destination = match *destination {
-                    Some((ref lv, target)) => Some((self.eval_place(lv)?, target)),
-                    None => None,
-                };
-
-                let func = self.eval_operand(func)?;
-                let (fn_def, sig) = match func.ty.sty {
-                    ty::TyFnPtr(sig) => {
-                        let fn_ptr = self.value_to_scalar(func)?.to_ptr()?;
-                        let instance = self.memory.get_fn(fn_ptr)?;
-                        let instance_ty = instance.ty(*self.tcx);
-                        match instance_ty.sty {
-                            ty::TyFnDef(..) => {
-                                let real_sig = instance_ty.fn_sig(*self.tcx);
-                                let sig = self.tcx.normalize_erasing_late_bound_regions(
-                                    ty::ParamEnv::reveal_all(),
-                                    &sig,
-                                );
-                                let real_sig = self.tcx.normalize_erasing_late_bound_regions(
-                                    ty::ParamEnv::reveal_all(),
-                                    &real_sig,
-                                );
-                                if !self.check_sig_compat(sig, real_sig)? {
-                                    return err!(FunctionPointerTyMismatch(real_sig, sig));
-                                }
-                            }
-                            ref other => bug!("instance def ty: {:?}", other),
-                        }
-                        (instance, sig)
-                    }
-                    ty::TyFnDef(def_id, substs) => (
-                        self.resolve(def_id, substs)?,
-                        func.ty.fn_sig(*self.tcx),
-                    ),
-                    _ => {
-                        let msg = format!("can't handle callee of type {:?}", func.ty);
-                        return err!(Unimplemented(msg));
-                    }
-                };
-                let args = self.operands_to_args(args)?;
-                let sig = self.tcx.normalize_erasing_late_bound_regions(
-                    ty::ParamEnv::reveal_all(),
-                    &sig,
-                );
-                self.eval_fn_call(
-                    fn_def,
-                    destination,
-                    &args,
-                    terminator.source_info.span,
-                    sig,
-                )?;
-            }
-
-            Drop {
-                ref location,
-                target,
-                ..
-            } => {
-                // FIXME(CTFE): forbid drop in const eval
-                let place = self.eval_place(location)?;
-                let ty = self.place_ty(location);
-                let ty = self.tcx.subst_and_normalize_erasing_regions(
-                    self.substs(),
-                    ty::ParamEnv::reveal_all(),
-                    &ty,
-                );
-                trace!("TerminatorKind::drop: {:?}, type {}", location, ty);
-
-                let instance = ::monomorphize::resolve_drop_in_place(*self.tcx, ty);
-                self.drop_place(
-                    place,
-                    instance,
-                    ty,
-                    terminator.source_info.span,
-                    target,
-                )?;
-            }
-
-            Assert {
-                ref cond,
-                expected,
-                ref msg,
-                target,
-                ..
-            } => {
-                let cond_val = self.eval_operand_to_scalar(cond)?.to_bool()?;
-                if expected == cond_val {
-                    self.goto_block(target);
-                } else {
-                    use rustc::mir::interpret::EvalErrorKind::*;
-                    return match *msg {
-                        BoundsCheck { ref len, ref index } => {
-                            let len = self.eval_operand_to_scalar(len)
-                                .expect("can't eval len")
-                                .to_bits(self.memory().pointer_size())? as u64;
-                            let index = self.eval_operand_to_scalar(index)
-                                .expect("can't eval index")
-                                .to_bits(self.memory().pointer_size())? as u64;
-                            err!(BoundsCheck { len, index })
-                        }
-                        Overflow(op) => Err(Overflow(op).into()),
-                        OverflowNeg => Err(OverflowNeg.into()),
-                        DivisionByZero => Err(DivisionByZero.into()),
-                        RemainderByZero => Err(RemainderByZero.into()),
-                        GeneratorResumedAfterReturn |
-                        GeneratorResumedAfterPanic => unimplemented!(),
-                        _ => bug!(),
-                    };
-                }
-            }
-
-            Yield { .. } => unimplemented!("{:#?}", terminator.kind),
-            GeneratorDrop => unimplemented!(),
-            DropAndReplace { .. } => unimplemented!(),
-            Resume => unimplemented!(),
-            Abort => unimplemented!(),
-            FalseEdges { .. } => bug!("should have been eliminated by `simplify_branches` mir pass"),
-            FalseUnwind { .. } => bug!("should have been eliminated by `simplify_branches` mir pass"),
-            Unreachable => return err!(Unreachable),
-        }
-
-        Ok(())
-    }
-
-    /// Decides whether it is okay to call the method with signature `real_sig` using signature `sig`.
-    /// FIXME: This should take into account the platform-dependent ABI description.
-    fn check_sig_compat(
-        &mut self,
-        sig: ty::FnSig<'tcx>,
-        real_sig: ty::FnSig<'tcx>,
-    ) -> EvalResult<'tcx, bool> {
-        fn check_ty_compat<'tcx>(ty: Ty<'tcx>, real_ty: Ty<'tcx>) -> bool {
-            if ty == real_ty {
-                return true;
-            } // This is actually a fast pointer comparison
-            return match (&ty.sty, &real_ty.sty) {
-                // Permit changing the pointer type of raw pointers and references as well as
-                // mutability of raw pointers.
-                // TODO: Should not be allowed when fat pointers are involved.
-                (&ty::TyRawPtr(_), &ty::TyRawPtr(_)) => true,
-                (&ty::TyRef(_, _, _), &ty::TyRef(_, _, _)) => {
-                    ty.is_mutable_pointer() == real_ty.is_mutable_pointer()
-                }
-                // rule out everything else
-                _ => false,
-            };
-        }
-
-        if sig.abi == real_sig.abi && sig.variadic == real_sig.variadic &&
-            sig.inputs_and_output.len() == real_sig.inputs_and_output.len() &&
-            sig.inputs_and_output
-                .iter()
-                .zip(real_sig.inputs_and_output)
-                .all(|(ty, real_ty)| check_ty_compat(ty, real_ty))
-        {
-            // Definitely good.
-            return Ok(true);
-        }
-
-        if sig.variadic || real_sig.variadic {
-            // We're not touching this
-            return Ok(false);
-        }
-
-        // We need to allow what comes up when a non-capturing closure is cast to a fn().
-        match (sig.abi, real_sig.abi) {
-            (Abi::Rust, Abi::RustCall) // check the ABIs.  This makes the test here non-symmetric.
-                if check_ty_compat(sig.output(), real_sig.output()) && real_sig.inputs_and_output.len() == 3 => {
-                // First argument of real_sig must be a ZST
-                let fst_ty = real_sig.inputs_and_output[0];
-                if self.layout_of(fst_ty)?.is_zst() {
-                    // Second argument must be a tuple matching the argument list of sig
-                    let snd_ty = real_sig.inputs_and_output[1];
-                    match snd_ty.sty {
-                        ty::TyTuple(tys) if sig.inputs().len() == tys.len() =>
-                            if sig.inputs().iter().zip(tys).all(|(ty, real_ty)| check_ty_compat(ty, real_ty)) {
-                                return Ok(true)
-                            },
-                        _ => {}
-                    }
-                }
-            }
-            _ => {}
-        };
-
-        // Nope, this doesn't work.
-        return Ok(false);
-    }
-
-    fn eval_fn_call(
-        &mut self,
-        instance: ty::Instance<'tcx>,
-        destination: Option<(Place, mir::BasicBlock)>,
-        args: &[ValTy<'tcx>],
-        span: Span,
-        sig: ty::FnSig<'tcx>,
-    ) -> EvalResult<'tcx> {
-        trace!("eval_fn_call: {:#?}", instance);
-        match instance.def {
-            ty::InstanceDef::Intrinsic(..) => {
-                let (ret, target) = match destination {
-                    Some(dest) => dest,
-                    _ => return err!(Unreachable),
-                };
-                let ty = sig.output();
-                let layout = self.layout_of(ty)?;
-                M::call_intrinsic(self, instance, args, ret, layout, target)?;
-                self.dump_local(ret);
-                Ok(())
-            }
-            // FIXME: figure out why we can't just go through the shim
-            ty::InstanceDef::ClosureOnceShim { .. } => {
-                if M::eval_fn_call(self, instance, destination, args, span, sig)? {
-                    return Ok(());
-                }
-                let mut arg_locals = self.frame().mir.args_iter();
-                match sig.abi {
-                    // closure as closure once
-                    Abi::RustCall => {
-                        for (arg_local, &valty) in arg_locals.zip(args) {
-                            let dest = self.eval_place(&mir::Place::Local(arg_local))?;
-                            self.write_value(valty, dest)?;
-                        }
-                    }
-                    // non capture closure as fn ptr
-                    // need to inject zst ptr for closure object (aka do nothing)
-                    // and need to pack arguments
-                    Abi::Rust => {
-                        trace!(
-                            "arg_locals: {:#?}",
-                            self.frame().mir.args_iter().collect::<Vec<_>>()
-                        );
-                        trace!("args: {:#?}", args);
-                        let local = arg_locals.nth(1).unwrap();
-                        for (i, &valty) in args.into_iter().enumerate() {
-                            let dest = self.eval_place(&mir::Place::Local(local).field(
-                                mir::Field::new(i),
-                                valty.ty,
-                            ))?;
-                            self.write_value(valty, dest)?;
-                        }
-                    }
-                    _ => bug!("bad ABI for ClosureOnceShim: {:?}", sig.abi),
-                }
-                Ok(())
-            }
-            ty::InstanceDef::FnPtrShim(..) |
-            ty::InstanceDef::DropGlue(..) |
-            ty::InstanceDef::CloneShim(..) |
-            ty::InstanceDef::Item(_) => {
-                // Push the stack frame, and potentially be entirely done if the call got hooked
-                if M::eval_fn_call(self, instance, destination, args, span, sig)? {
-                    return Ok(());
-                }
-
-                // Pass the arguments
-                let mut arg_locals = self.frame().mir.args_iter();
-                trace!("ABI: {:?}", sig.abi);
-                trace!(
-                    "arg_locals: {:#?}",
-                    self.frame().mir.args_iter().collect::<Vec<_>>()
-                );
-                trace!("args: {:#?}", args);
-                match sig.abi {
-                    Abi::RustCall => {
-                        assert_eq!(args.len(), 2);
-
-                        {
-                            // write first argument
-                            let first_local = arg_locals.next().unwrap();
-                            let dest = self.eval_place(&mir::Place::Local(first_local))?;
-                            self.write_value(args[0], dest)?;
-                        }
-
-                        // unpack and write all other args
-                        let layout = self.layout_of(args[1].ty)?;
-                        if let ty::TyTuple(_) = args[1].ty.sty {
-                            if layout.is_zst() {
-                                // Nothing to do, no need to unpack zsts
-                                return Ok(());
-                            }
-                            if self.frame().mir.args_iter().count() == layout.fields.count() + 1 {
-                                for (i, arg_local) in arg_locals.enumerate() {
-                                    let field = mir::Field::new(i);
-                                    let (value, layout) = self.read_field(args[1].value, None, field, layout)?;
-                                    let dest = self.eval_place(&mir::Place::Local(arg_local))?;
-                                    let valty = ValTy {
-                                        value,
-                                        ty: layout.ty,
-                                    };
-                                    self.write_value(valty, dest)?;
-                                }
-                            } else {
-                                trace!("manual impl of rust-call ABI");
-                                // called a manual impl of a rust-call function
-                                let dest = self.eval_place(
-                                    &mir::Place::Local(arg_locals.next().unwrap()),
-                                )?;
-                                self.write_value(args[1], dest)?;
-                            }
-                        } else {
-                            bug!(
-                                "rust-call ABI tuple argument was {:#?}, {:#?}",
-                                args[1].ty,
-                                layout
-                            );
-                        }
-                    }
-                    _ => {
-                        for (arg_local, &valty) in arg_locals.zip(args) {
-                            let dest = self.eval_place(&mir::Place::Local(arg_local))?;
-                            self.write_value(valty, dest)?;
-                        }
-                    }
-                }
-                Ok(())
-            }
-            // cannot use the shim here, because that will only result in infinite recursion
-            ty::InstanceDef::Virtual(_, idx) => {
-                let ptr_size = self.memory.pointer_size();
-                let ptr_align = self.tcx.data_layout.pointer_align;
-                let (ptr, vtable) = self.into_ptr_vtable_pair(args[0].value)?;
-                let fn_ptr = self.memory.read_ptr_sized(
-                    vtable.offset(ptr_size * (idx as u64 + 3), &self)?,
-                    ptr_align
-                )?.unwrap_or_err()?.to_ptr()?;
-                let instance = self.memory.get_fn(fn_ptr)?;
-                let mut args = args.to_vec();
-                let ty = self.layout_of(args[0].ty)?.field(&self, 0)?.ty;
-                args[0].ty = ty;
-                args[0].value = Value::Scalar(ptr);
-                // recurse with concrete function
-                self.eval_fn_call(instance, destination, &args, span, sig)
-            }
-        }
-    }
-}
index 84583680988b7c093c368eeb93cfd8d3c2aad59e..0e09f65f0a8eaba3b4f370b13cfbfa582401ed7f 100644 (file)
@@ -1,6 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{Size, Align, LayoutOf};
-use rustc::mir::interpret::{Scalar, Pointer, EvalResult};
+use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic};
 
 use syntax::ast::Mutability;
 
@@ -25,7 +35,7 @@ pub fn get_vtable(
         let size = layout.size.bytes();
         let align = layout.align.abi();
 
-        let ptr_size = self.memory.pointer_size();
+        let ptr_size = self.pointer_size();
         let ptr_align = self.tcx.data_layout.pointer_align;
         let methods = self.tcx.vtable_methods(trait_ref);
         let vtable = self.memory.allocate(
@@ -36,29 +46,24 @@ pub fn get_vtable(
 
         let drop = ::monomorphize::resolve_drop_in_place(*self.tcx, ty);
         let drop = self.memory.create_fn_alloc(drop);
-        self.memory.write_ptr_sized_unsigned(vtable, ptr_align, Scalar::Ptr(drop).into())?;
+        self.memory.write_ptr_sized(vtable, ptr_align, Scalar::Ptr(drop).into())?;
 
         let size_ptr = vtable.offset(ptr_size, &self)?;
-        self.memory.write_ptr_sized_unsigned(size_ptr, ptr_align, Scalar::Bits {
-            bits: size as u128,
-            size: ptr_size.bytes() as u8,
-        }.into())?;
+        self.memory.write_ptr_sized(size_ptr, ptr_align, Scalar::from_uint(size, ptr_size).into())?;
         let align_ptr = vtable.offset(ptr_size * 2, &self)?;
-        self.memory.write_ptr_sized_unsigned(align_ptr, ptr_align, Scalar::Bits {
-            bits: align as u128,
-            size: ptr_size.bytes() as u8,
-        }.into())?;
+        self.memory.write_ptr_sized(align_ptr, ptr_align,
+            Scalar::from_uint(align, ptr_size).into())?;
 
         for (i, method) in methods.iter().enumerate() {
             if let Some((def_id, substs)) = *method {
                 let instance = self.resolve(def_id, substs)?;
                 let fn_ptr = self.memory.create_fn_alloc(instance);
                 let method_ptr = vtable.offset(ptr_size * (3 + i as u64), &self)?;
-                self.memory.write_ptr_sized_unsigned(method_ptr, ptr_align, Scalar::Ptr(fn_ptr).into())?;
+                self.memory.write_ptr_sized(method_ptr, ptr_align, Scalar::Ptr(fn_ptr).into())?;
             }
         }
 
-        self.memory.mark_static_initialized(
+        self.memory.intern_static(
             vtable.alloc_id,
             Mutability::Immutable,
         )?;
@@ -66,27 +71,35 @@ pub fn get_vtable(
         Ok(vtable)
     }
 
+    /// Return the drop fn instance as well as the actual dynamic type
     pub fn read_drop_type_from_vtable(
         &self,
         vtable: Pointer,
-    ) -> EvalResult<'tcx, ty::Instance<'tcx>> {
+    ) -> EvalResult<'tcx, (ty::Instance<'tcx>, ty::Ty<'tcx>)> {
         // we don't care about the pointee type, we just want a pointer
         let pointer_align = self.tcx.data_layout.pointer_align;
-        let drop_fn = self.memory.read_ptr_sized(vtable, pointer_align)?.unwrap_or_err()?.to_ptr()?;
-        self.memory.get_fn(drop_fn)
+        let drop_fn = self.memory.read_ptr_sized(vtable, pointer_align)?.to_ptr()?;
+        let drop_instance = self.memory.get_fn(drop_fn)?;
+        trace!("Found drop fn: {:?}", drop_instance);
+        let fn_sig = drop_instance.ty(*self.tcx).fn_sig(*self.tcx);
+        let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, &fn_sig);
+        // the drop function takes *mut T where T is the type being dropped, so get that
+        let ty = fn_sig.inputs()[0].builtin_deref(true).unwrap().ty;
+        Ok((drop_instance, ty))
     }
 
     pub fn read_size_and_align_from_vtable(
         &self,
         vtable: Pointer,
     ) -> EvalResult<'tcx, (Size, Align)> {
-        let pointer_size = self.memory.pointer_size();
+        let pointer_size = self.pointer_size();
         let pointer_align = self.tcx.data_layout.pointer_align;
-        let size = self.memory.read_ptr_sized(vtable.offset(pointer_size, self)?, pointer_align)?.unwrap_or_err()?.to_bits(pointer_size)? as u64;
+        let size = self.memory.read_ptr_sized(vtable.offset(pointer_size, self)?,pointer_align)?
+            .to_bits(pointer_size)? as u64;
         let align = self.memory.read_ptr_sized(
             vtable.offset(pointer_size * 2, self)?,
             pointer_align
-        )?.unwrap_or_err()?.to_bits(pointer_size)? as u64;
+        )?.to_bits(pointer_size)? as u64;
         Ok((Size::from_bytes(size), Align::from_bytes(align, align).unwrap()))
     }
 }
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
new file mode 100644 (file)
index 0000000..ef2ae8f
--- /dev/null
@@ -0,0 +1,442 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt::Write;
+
+use syntax_pos::symbol::Symbol;
+use rustc::ty::layout::{self, Size, Primitive};
+use rustc::ty::{self, Ty};
+use rustc_data_structures::fx::FxHashSet;
+use rustc::mir::interpret::{
+    Scalar, AllocType, EvalResult, ScalarMaybeUndef, EvalErrorKind, PointerArithmetic
+};
+
+use super::{
+    OpTy, Machine, EvalContext
+};
+
+macro_rules! validation_failure{
+    ($what:expr, $where:expr, $details:expr) => {{
+        let where_ = path_format($where);
+        let where_ = if where_.is_empty() {
+            String::new()
+        } else {
+            format!(" at {}", where_)
+        };
+        err!(ValidationFailure(format!(
+            "encountered {}{}, but expected {}",
+            $what, where_, $details,
+        )))
+    }};
+    ($what:expr, $where:expr) => {{
+        let where_ = path_format($where);
+        let where_ = if where_.is_empty() {
+            String::new()
+        } else {
+            format!(" at {}", where_)
+        };
+        err!(ValidationFailure(format!(
+            "encountered {}{}",
+            $what, where_,
+        )))
+    }};
+}
+
+/// We want to show a nice path to the invalid field for diagnotsics,
+/// but avoid string operations in the happy case where no error happens.
+/// So we track a `Vec<PathElem>` where `PathElem` contains all the data we
+/// need to later print something for the user.
+#[derive(Copy, Clone, Debug)]
+pub enum PathElem {
+    Field(Symbol),
+    ClosureVar(Symbol),
+    ArrayElem(usize),
+    TupleElem(usize),
+    Deref,
+    Tag,
+}
+
+// Adding a Deref and making a copy of the path to be put into the queue
+// always go together.  This one does it with only new allocation.
+fn path_clone_and_deref(path: &Vec<PathElem>) -> Vec<PathElem> {
+    let mut new_path = Vec::with_capacity(path.len()+1);
+    new_path.clone_from(path);
+    new_path.push(PathElem::Deref);
+    new_path
+}
+
+/// Format a path
+fn path_format(path: &Vec<PathElem>) -> String {
+    use self::PathElem::*;
+
+    let mut out = String::new();
+    for elem in path.iter() {
+        match elem {
+            Field(name) => write!(out, ".{}", name).unwrap(),
+            ClosureVar(name) => write!(out, ".<closure-var({})>", name).unwrap(),
+            TupleElem(idx) => write!(out, ".{}", idx).unwrap(),
+            ArrayElem(idx) => write!(out, "[{}]", idx).unwrap(),
+            Deref =>
+                // This does not match Rust syntax, but it is more readable for long paths -- and
+                // some of the other items here also are not Rust syntax.  Actually we can't
+                // even use the usual syntax because we are just showing the projections,
+                // not the root.
+                write!(out, ".<deref>").unwrap(),
+            Tag => write!(out, ".<enum-tag>").unwrap(),
+        }
+    }
+    out
+}
+
+impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+    fn validate_scalar(
+        &self,
+        value: ScalarMaybeUndef,
+        size: Size,
+        scalar: &layout::Scalar,
+        path: &Vec<PathElem>,
+        ty: Ty,
+    ) -> EvalResult<'tcx> {
+        trace!("validate scalar: {:#?}, {:#?}, {:#?}, {}", value, size, scalar, ty);
+        let (lo, hi) = scalar.valid_range.clone().into_inner();
+
+        let value = match value {
+            ScalarMaybeUndef::Scalar(scalar) => scalar,
+            ScalarMaybeUndef::Undef => return validation_failure!("undefined bytes", path),
+        };
+
+        let bits = match value {
+            Scalar::Bits { bits, size: value_size } => {
+                assert_eq!(value_size as u64, size.bytes());
+                bits
+            },
+            Scalar::Ptr(_) => {
+                let ptr_size = self.pointer_size();
+                let ptr_max = u128::max_value() >> (128 - ptr_size.bits());
+                return if lo > hi {
+                    if lo - hi == 1 {
+                        // no gap, all values are ok
+                        Ok(())
+                    } else if hi < ptr_max || lo > 1 {
+                        let max = u128::max_value() >> (128 - size.bits());
+                        validation_failure!(
+                            "pointer",
+                            path,
+                            format!("something in the range {:?} or {:?}", 0..=lo, hi..=max)
+                        )
+                    } else {
+                        Ok(())
+                    }
+                } else if hi < ptr_max || lo > 1 {
+                    validation_failure!(
+                        "pointer",
+                        path,
+                        format!("something in the range {:?}", scalar.valid_range)
+                    )
+                } else {
+                    Ok(())
+                };
+            },
+        };
+
+        // char gets a special treatment, because its number space is not contiguous so `TyLayout`
+        // has no special checks for chars
+        match ty.sty {
+            ty::Char => {
+                debug_assert_eq!(size.bytes(), 4);
+                if ::std::char::from_u32(bits as u32).is_none() {
+                    return validation_failure!(
+                        "character",
+                        path,
+                        "a valid unicode codepoint"
+                    );
+                }
+            }
+            _ => {},
+        }
+
+        use std::ops::RangeInclusive;
+        let in_range = |bound: RangeInclusive<u128>| bound.contains(&bits);
+        if lo > hi {
+            if in_range(0..=hi) || in_range(lo..=u128::max_value()) {
+                Ok(())
+            } else {
+                validation_failure!(
+                    bits,
+                    path,
+                    format!("something in the range {:?} or {:?}", ..=hi, lo..)
+                )
+            }
+        } else {
+            if in_range(scalar.valid_range.clone()) {
+                Ok(())
+            } else {
+                validation_failure!(
+                    bits,
+                    path,
+                    format!("something in the range {:?}", scalar.valid_range)
+                )
+            }
+        }
+    }
+
+    /// This function checks the data at `op`.
+    /// It will error if the bits at the destination do not match the ones described by the layout.
+    /// The `path` may be pushed to, but the part that is present when the function
+    /// starts must not be changed!
+    pub fn validate_operand(
+        &self,
+        dest: OpTy<'tcx>,
+        path: &mut Vec<PathElem>,
+        seen: &mut FxHashSet<(OpTy<'tcx>)>,
+        todo: &mut Vec<(OpTy<'tcx>, Vec<PathElem>)>,
+    ) -> EvalResult<'tcx> {
+        trace!("validate_operand: {:?}, {:#?}", *dest, dest.layout);
+
+        // Find the right variant.  We have to handle this as a prelude, not via
+        // proper recursion with the new inner layout, to be able to later nicely
+        // print the field names of the enum field that is being accessed.
+        let (variant, dest) = match dest.layout.variants {
+            layout::Variants::NicheFilling { .. } |
+            layout::Variants::Tagged { .. } => {
+                let variant = match self.read_discriminant(dest) {
+                    Ok(res) => res.1,
+                    Err(err) => match err.kind {
+                        EvalErrorKind::InvalidDiscriminant(val) =>
+                            return validation_failure!(
+                                format!("invalid enum discriminant {}", val), path
+                            ),
+                        _ =>
+                            return validation_failure!(
+                                format!("non-integer enum discriminant"), path
+                            ),
+                    }
+                };
+                let inner_dest = self.operand_downcast(dest, variant)?;
+                // Put the variant projection onto the path, as a field
+                path.push(PathElem::Field(dest.layout.ty
+                                          .ty_adt_def()
+                                          .unwrap()
+                                          .variants[variant].name));
+                trace!("variant layout: {:#?}", dest.layout);
+                (variant, inner_dest)
+            },
+            layout::Variants::Single { index } => {
+                // Pre-processing for trait objects: Treat them at their real type.
+                // (We do not do this for slices and strings: For slices it is not needed,
+                // `mplace_array_fields` does the right thing, and for strings there is no
+                // real type that would show the actual length.)
+                let dest = match dest.layout.ty.sty {
+                    ty::Dynamic(..) => {
+                        let dest = dest.to_mem_place(); // immediate trait objects are not a thing
+                        match self.unpack_dyn_trait(dest) {
+                            Ok(res) => res.1.into(),
+                            Err(_) =>
+                                return validation_failure!(
+                                    "invalid vtable in fat pointer", path
+                                ),
+                        }
+                    }
+                    _ => dest
+                };
+                (index, dest)
+            }
+        };
+
+        // Remember the length, in case we need to truncate
+        let path_len = path.len();
+
+        // Validate all fields
+        match dest.layout.fields {
+            // primitives are unions with zero fields
+            // We still check `layout.fields`, not `layout.abi`, because `layout.abi`
+            // is `Scalar` for newtypes around scalars, but we want to descend through the
+            // fields to get a proper `path`.
+            layout::FieldPlacement::Union(0) => {
+                match dest.layout.abi {
+                    // nothing to do, whatever the pointer points to, it is never going to be read
+                    layout::Abi::Uninhabited =>
+                        return validation_failure!("a value of an uninhabited type", path),
+                    // check that the scalar is a valid pointer or that its bit range matches the
+                    // expectation.
+                    layout::Abi::Scalar(ref scalar_layout) => {
+                        let size = scalar_layout.value.size(self);
+                        let value = match self.read_value(dest) {
+                            Ok(val) => val,
+                            Err(err) => match err.kind {
+                                EvalErrorKind::PointerOutOfBounds { .. } |
+                                EvalErrorKind::ReadUndefBytes =>
+                                    return validation_failure!(
+                                        "uninitialized or out-of-bounds memory", path
+                                    ),
+                                _ =>
+                                    return validation_failure!(
+                                        "unrepresentable data", path
+                                    ),
+                            }
+                        };
+                        let scalar = value.to_scalar_or_undef();
+                        self.validate_scalar(scalar, size, scalar_layout, &path, dest.layout.ty)?;
+                        if scalar_layout.value == Primitive::Pointer {
+                            // ignore integer pointers, we can't reason about the final hardware
+                            if let Scalar::Ptr(ptr) = scalar.not_undef()? {
+                                let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id);
+                                if let Some(AllocType::Static(did)) = alloc_kind {
+                                    // statics from other crates are already checked.
+                                    // extern statics cannot be validated as they have no body.
+                                    if !did.is_local() || self.tcx.is_foreign_item(did) {
+                                        return Ok(());
+                                    }
+                                }
+                                if value.layout.ty.builtin_deref(false).is_some() {
+                                    let ptr_op = self.ref_to_mplace(value)?.into();
+                                    // we have not encountered this pointer+layout combination
+                                    // before.
+                                    if seen.insert(ptr_op) {
+                                        trace!("Recursing below ptr {:#?}", *value);
+                                        todo.push((ptr_op, path_clone_and_deref(path)));
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    _ => bug!("bad abi for FieldPlacement::Union(0): {:#?}", dest.layout.abi),
+                }
+            }
+            layout::FieldPlacement::Union(_) => {
+                // We can't check unions, their bits are allowed to be anything.
+                // The fields don't need to correspond to any bit pattern of the union's fields.
+                // See https://github.com/rust-lang/rust/issues/32836#issuecomment-406875389
+            },
+            layout::FieldPlacement::Array { .. } if !dest.layout.is_zst() => {
+                let dest = dest.to_mem_place(); // non-ZST array/slice/str cannot be immediate
+                // Special handling for strings to verify UTF-8
+                match dest.layout.ty.sty {
+                    ty::Str => {
+                        match self.read_str(dest) {
+                            Ok(_) => {},
+                            Err(err) => match err.kind {
+                                EvalErrorKind::PointerOutOfBounds { .. } |
+                                EvalErrorKind::ReadUndefBytes =>
+                                    // The error here looks slightly different than it does
+                                    // for slices, because we do not report the index into the
+                                    // str at which we are OOB.
+                                    return validation_failure!(
+                                        "uninitialized or out-of-bounds memory", path
+                                    ),
+                                _ =>
+                                    return validation_failure!(
+                                        "non-UTF-8 data in str", path
+                                    ),
+                            }
+                        }
+                    }
+                    _ => {
+                        // This handles the unsized case correctly as well, as well as
+                        // SIMD an all sorts of other array-like types.
+                        for (i, field) in self.mplace_array_fields(dest)?.enumerate() {
+                            let field = field?;
+                            path.push(PathElem::ArrayElem(i));
+                            self.validate_operand(field.into(), path, seen, todo)?;
+                            path.truncate(path_len);
+                        }
+                    }
+                }
+            },
+            layout::FieldPlacement::Array { .. } => {
+                // An empty array.  Nothing to do.
+            }
+            layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
+                // Fat pointers are treated like pointers, not aggregates.
+                if dest.layout.ty.builtin_deref(true).is_some() {
+                    // This is a fat pointer.
+                    let ptr = match self.read_value(dest.into())
+                        .and_then(|val| self.ref_to_mplace(val))
+                    {
+                        Ok(ptr) => ptr,
+                        Err(_) =>
+                            return validation_failure!(
+                                "undefined location or metadata in fat pointer", path
+                            ),
+                    };
+                    // check metadata early, for better diagnostics
+                    match self.tcx.struct_tail(ptr.layout.ty).sty {
+                        ty::Dynamic(..) => {
+                            match ptr.extra.unwrap().to_ptr() {
+                                Ok(_) => {},
+                                Err(_) =>
+                                    return validation_failure!(
+                                        "non-pointer vtable in fat pointer", path
+                                    ),
+                            }
+                            // FIXME: More checks for the vtable.
+                        }
+                        ty::Slice(..) | ty::Str => {
+                            match ptr.extra.unwrap().to_usize(self) {
+                                Ok(_) => {},
+                                Err(_) =>
+                                    return validation_failure!(
+                                        "non-integer slice length in fat pointer", path
+                                    ),
+                            }
+                        }
+                        _ =>
+                            bug!("Unexpected unsized type tail: {:?}",
+                                self.tcx.struct_tail(ptr.layout.ty)
+                            ),
+                    }
+                    // for safe ptrs, recursively check it
+                    if !dest.layout.ty.is_unsafe_ptr() {
+                        let ptr = ptr.into();
+                        if seen.insert(ptr) {
+                            trace!("Recursing below fat ptr {:?}", ptr);
+                            todo.push((ptr, path_clone_and_deref(path)));
+                        }
+                    }
+                } else {
+                    // Not a pointer, perform regular aggregate handling below
+                    for i in 0..offsets.len() {
+                        let field = self.operand_field(dest, i as u64)?;
+                        path.push(self.aggregate_field_path_elem(dest.layout.ty, variant, i));
+                        self.validate_operand(field, path, seen, todo)?;
+                        path.truncate(path_len);
+                    }
+                }
+            }
+        }
+        Ok(())
+    }
+
+    fn aggregate_field_path_elem(&self, ty: Ty<'tcx>, variant: usize, field: usize) -> PathElem {
+        match ty.sty {
+            // generators and closures.
+            ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
+                let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
+                let freevar = self.tcx.with_freevars(node_id, |fv| fv[field]);
+                PathElem::ClosureVar(self.tcx.hir.name(freevar.var_id()))
+            }
+
+            // tuples
+            ty::Tuple(_) => PathElem::TupleElem(field),
+
+            // enums
+            ty::Adt(def, ..) if def.is_enum() => {
+                let variant = &def.variants[variant];
+                PathElem::Field(variant.fields[field].ident.name)
+            }
+
+            // other ADTs
+            ty::Adt(def, _) => PathElem::Field(def.non_enum_variant().fields[field].ident.name),
+
+            // nothing else has an aggregate layout
+            _ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", ty),
+        }
+    }
+}
index bda80ff562c75ede8ef6cbacc79b5982d36de066..a55f0496c2dee487f9d155c5dfbca18f0e8e0e37 100644 (file)
 */
 
 #![cfg_attr(not(stage0), feature(nll))]
-#![feature(infer_outlives_requirements)]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(in_band_lifetimes)]
+#![feature(impl_header_lifetime_elision)]
 #![feature(slice_patterns)]
 #![feature(slice_sort_by_cached_key)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(catch_expr)]
 #![feature(crate_visibility_modifier)]
-#![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(decl_macro)]
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 #![feature(exhaustive_patterns)]
 #![feature(range_contains)]
 #![feature(rustc_diagnostic_macros)]
@@ -36,6 +35,8 @@
 #![feature(unicode_internals)]
 #![feature(step_trait)]
 #![feature(slice_concat_ext)]
+#![feature(if_while_or_patterns)]
+#![feature(try_from)]
 
 #![recursion_limit="256"]
 
 extern crate rustc_apfloat;
 extern crate byteorder;
 extern crate core;
+extern crate smallvec;
+
+// Once we can use edition 2018 in the compiler,
+// replace this with real try blocks.
+macro_rules! try_block {
+    ($($inside:tt)*) => (
+        (||{ ::std::ops::Try::from_ok({ $($inside)* }) })()
+    )
+}
 
 mod diagnostics;
 
@@ -72,6 +82,7 @@
 pub mod util;
 pub mod interpret;
 pub mod monomorphize;
+pub mod const_eval;
 
 pub use hair::pattern::check_crate as matchck_crate;
 use rustc::ty::query::Providers;
@@ -81,7 +92,6 @@ pub fn provide(providers: &mut Providers) {
     shim::provide(providers);
     transform::provide(providers);
     providers.const_eval = interpret::const_eval_provider;
-    providers.const_value_to_allocation = interpret::const_value_to_allocation_provider;
     providers.check_match = hair::pattern::check_match;
 }
 
index 230d6f0472edde6f538b447f779b1adbdc057275..52bbffa7519df069a687358e9f75b1aee345a58b 100644 (file)
 use rustc::hir::{self, CodegenFnAttrFlags};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 
-use rustc::hir::map as hir_map;
+use rustc::hir::Node;
 use rustc::hir::def_id::DefId;
 use rustc::mir::interpret::{AllocId, ConstValue, ScalarMaybeUndef};
 use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
@@ -571,7 +571,7 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
                     &source_ty,
                 );
                 match source_ty.sty {
-                    ty::TyClosure(def_id, substs) => {
+                    ty::Closure(def_id, substs) => {
                         let instance = monomorphize::resolve_closure(
                             self.tcx, def_id, substs, ty::ClosureKind::FnOnce);
                         if should_monomorphize_locally(self.tcx, &instance) {
@@ -680,7 +680,7 @@ fn visit_fn_use<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           is_direct_call: bool,
                           output: &mut Vec<MonoItem<'tcx>>)
 {
-    if let ty::TyFnDef(def_id, substs) = ty.sty {
+    if let ty::FnDef(def_id, substs) = ty.sty {
         let instance = ty::Instance::resolve(tcx,
                                              ty::ParamEnv::reveal_all(),
                                              def_id,
@@ -740,7 +740,7 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance:
     };
 
     return match tcx.hir.get_if_local(def_id) {
-        Some(hir_map::NodeForeignItem(..)) => {
+        Some(Node::ForeignItem(..)) => {
             false // foreign items are linked against, not codegened.
         }
         Some(_) => true,
@@ -838,8 +838,8 @@ fn find_vtable_types_for_unsizing<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
             let tail = tcx.struct_tail(ty);
             match tail.sty {
-                ty::TyForeign(..) => false,
-                ty::TyStr | ty::TySlice(..) | ty::TyDynamic(..) => true,
+                ty::Foreign(..) => false,
+                ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
                 _ => bug!("unexpected unsized tail: {:?}", tail.sty),
             }
         };
@@ -851,20 +851,20 @@ fn find_vtable_types_for_unsizing<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     };
 
     match (&source_ty.sty, &target_ty.sty) {
-        (&ty::TyRef(_, a, _),
-         &ty::TyRef(_, b, _)) |
-        (&ty::TyRef(_, a, _),
-         &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) |
-        (&ty::TyRawPtr(ty::TypeAndMut { ty: a, .. }),
-         &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) => {
+        (&ty::Ref(_, a, _),
+         &ty::Ref(_, b, _)) |
+        (&ty::Ref(_, a, _),
+         &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) |
+        (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }),
+         &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
             ptr_vtable(a, b)
         }
-        (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
+        (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
             ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty())
         }
 
-        (&ty::TyAdt(source_adt_def, source_substs),
-         &ty::TyAdt(target_adt_def, target_substs)) => {
+        (&ty::Adt(source_adt_def, source_substs),
+         &ty::Adt(target_adt_def, target_substs)) => {
             assert_eq!(source_adt_def, target_adt_def);
 
             let kind =
@@ -906,7 +906,7 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_regions() &&
             !impl_ty.needs_subst() && !impl_ty.has_escaping_regions());
 
-    if let ty::TyDynamic(ref trait_ty, ..) = trait_ty.sty {
+    if let ty::Dynamic(ref trait_ty, ..) = trait_ty.sty {
         if let Some(principal) = trait_ty.principal() {
             let poly_trait_ref = principal.with_self_ty(tcx, impl_ty);
             assert!(!poly_trait_ref.has_escaping_regions());
@@ -1023,7 +1023,6 @@ fn is_root(&self, def_id: DefId) -> bool {
             MonoItemCollectionMode::Lazy => {
                 self.entry_fn == Some(def_id) ||
                 self.tcx.is_reachable_non_generic(def_id) ||
-                self.tcx.is_weak_lang_item(def_id) ||
                 self.tcx.codegen_fn_attrs(def_id).flags.contains(
                     CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
             }
@@ -1272,7 +1271,7 @@ fn collect_const<'a, 'tcx>(
         ConstValue::ScalarPair(Scalar::Ptr(ptr), _) |
         ConstValue::Scalar(Scalar::Ptr(ptr)) =>
             collect_miri(tcx, ptr.alloc_id, output),
-        ConstValue::ByRef(alloc, _offset) => {
+        ConstValue::ByRef(_id, alloc, _offset) => {
             for &id in alloc.relocations.values() {
                 collect_miri(tcx, id, output);
             }
index f73c9d43699fcf86aa41e183fc82fc9c03340d7b..3187a91e225970d8edaecfa20b51d3d96ba7dfb9 100644 (file)
@@ -257,29 +257,29 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
         match t.sty {
-            ty::TyBool              => output.push_str("bool"),
-            ty::TyChar              => output.push_str("char"),
-            ty::TyStr               => output.push_str("str"),
-            ty::TyNever             => output.push_str("!"),
-            ty::TyInt(ast::IntTy::Isize)    => output.push_str("isize"),
-            ty::TyInt(ast::IntTy::I8)    => output.push_str("i8"),
-            ty::TyInt(ast::IntTy::I16)   => output.push_str("i16"),
-            ty::TyInt(ast::IntTy::I32)   => output.push_str("i32"),
-            ty::TyInt(ast::IntTy::I64)   => output.push_str("i64"),
-            ty::TyInt(ast::IntTy::I128)   => output.push_str("i128"),
-            ty::TyUint(ast::UintTy::Usize)   => output.push_str("usize"),
-            ty::TyUint(ast::UintTy::U8)   => output.push_str("u8"),
-            ty::TyUint(ast::UintTy::U16)  => output.push_str("u16"),
-            ty::TyUint(ast::UintTy::U32)  => output.push_str("u32"),
-            ty::TyUint(ast::UintTy::U64)  => output.push_str("u64"),
-            ty::TyUint(ast::UintTy::U128)  => output.push_str("u128"),
-            ty::TyFloat(ast::FloatTy::F32) => output.push_str("f32"),
-            ty::TyFloat(ast::FloatTy::F64) => output.push_str("f64"),
-            ty::TyAdt(adt_def, substs) => {
+            ty::Bool              => output.push_str("bool"),
+            ty::Char              => output.push_str("char"),
+            ty::Str               => output.push_str("str"),
+            ty::Never             => output.push_str("!"),
+            ty::Int(ast::IntTy::Isize)    => output.push_str("isize"),
+            ty::Int(ast::IntTy::I8)    => output.push_str("i8"),
+            ty::Int(ast::IntTy::I16)   => output.push_str("i16"),
+            ty::Int(ast::IntTy::I32)   => output.push_str("i32"),
+            ty::Int(ast::IntTy::I64)   => output.push_str("i64"),
+            ty::Int(ast::IntTy::I128)   => output.push_str("i128"),
+            ty::Uint(ast::UintTy::Usize)   => output.push_str("usize"),
+            ty::Uint(ast::UintTy::U8)   => output.push_str("u8"),
+            ty::Uint(ast::UintTy::U16)  => output.push_str("u16"),
+            ty::Uint(ast::UintTy::U32)  => output.push_str("u32"),
+            ty::Uint(ast::UintTy::U64)  => output.push_str("u64"),
+            ty::Uint(ast::UintTy::U128)  => output.push_str("u128"),
+            ty::Float(ast::FloatTy::F32) => output.push_str("f32"),
+            ty::Float(ast::FloatTy::F64) => output.push_str("f64"),
+            ty::Adt(adt_def, substs) => {
                 self.push_def_path(adt_def.did, output);
                 self.push_type_params(substs, iter::empty(), output);
             },
-            ty::TyTuple(component_types) => {
+            ty::Tuple(component_types) => {
                 output.push('(');
                 for &component_type in component_types {
                     self.push_type_name(component_type, output);
@@ -291,7 +291,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
                 }
                 output.push(')');
             },
-            ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
+            ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
                 output.push('*');
                 match mutbl {
                     hir::MutImmutable => output.push_str("const "),
@@ -300,7 +300,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
 
                 self.push_type_name(inner_type, output);
             },
-            ty::TyRef(_, inner_type, mutbl) => {
+            ty::Ref(_, inner_type, mutbl) => {
                 output.push('&');
                 if mutbl == hir::MutMutable {
                     output.push_str("mut ");
@@ -308,18 +308,18 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
 
                 self.push_type_name(inner_type, output);
             },
-            ty::TyArray(inner_type, len) => {
+            ty::Array(inner_type, len) => {
                 output.push('[');
                 self.push_type_name(inner_type, output);
                 write!(output, "; {}", len.unwrap_usize(self.tcx)).unwrap();
                 output.push(']');
             },
-            ty::TySlice(inner_type) => {
+            ty::Slice(inner_type) => {
                 output.push('[');
                 self.push_type_name(inner_type, output);
                 output.push(']');
             },
-            ty::TyDynamic(ref trait_data, ..) => {
+            ty::Dynamic(ref trait_data, ..) => {
                 if let Some(principal) = trait_data.principal() {
                     self.push_def_path(principal.def_id(), output);
                     self.push_type_params(principal.skip_binder().substs,
@@ -327,9 +327,9 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
                         output);
                 }
             },
-            ty::TyForeign(did) => self.push_def_path(did, output),
-            ty::TyFnDef(..) |
-            ty::TyFnPtr(_) => {
+            ty::Foreign(did) => self.push_def_path(did, output),
+            ty::FnDef(..) |
+            ty::FnPtr(_) => {
                 let sig = t.fn_sig(self.tcx);
                 if sig.unsafety() == hir::Unsafety::Unsafe {
                     output.push_str("unsafe ");
@@ -373,19 +373,19 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
                     self.push_type_name(sig.output(), output);
                 }
             },
-            ty::TyGenerator(def_id, GeneratorSubsts { ref substs }, _) |
-            ty::TyClosure(def_id, ClosureSubsts { ref substs }) => {
+            ty::Generator(def_id, GeneratorSubsts { ref substs }, _) |
+            ty::Closure(def_id, ClosureSubsts { ref substs }) => {
                 self.push_def_path(def_id, output);
                 let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id));
                 let substs = substs.truncate_to(self.tcx, generics);
                 self.push_type_params(substs, iter::empty(), output);
             }
-            ty::TyError |
-            ty::TyInfer(_) |
-            ty::TyProjection(..) |
-            ty::TyParam(_) |
-            ty::TyGeneratorWitness(_) |
-            ty::TyAnon(..) => {
+            ty::Error |
+            ty::Infer(_) |
+            ty::Projection(..) |
+            ty::Param(_) |
+            ty::GeneratorWitness(_) |
+            ty::Anon(..) => {
                 bug!("DefPathBasedNames: Trying to create type name for \
                                          unexpected type: {:?}", t);
             }
index 7d7be69b35559915fe3456df1978a181e3ff3f51..c480fa4124665763d516c763247c327b70b1b449 100644 (file)
@@ -516,10 +516,8 @@ fn mono_item_visibility(
         //   visibility below. Like the weak lang items, though, we can't let
         //   LLVM internalize them as this decision is left up to the linker to
         //   omit them, so prevent them from being internalized.
-        let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
-        let std_internal_symbol = codegen_fn_attrs.flags
-            .contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
-        if tcx.is_weak_lang_item(def_id) || std_internal_symbol {
+        let attrs = tcx.codegen_fn_attrs(def_id);
+        if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
             *can_be_internalized = false;
         }
 
index 7bfbda8b786e3ee1f54e74da840f6adbe91b802c..7e7e7cfade6238f2e12100e6e06b4c7ddfdb0db6 100644 (file)
@@ -165,7 +165,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
 
     // Check if this is a generator, if so, return the drop glue for it
-    if let Some(&ty::TyS { sty: ty::TyGenerator(gen_def_id, substs, _), .. }) = ty {
+    if let Some(&ty::TyS { sty: ty::Generator(gen_def_id, substs, _), .. }) = ty {
         let mir = &**tcx.optimized_mir(gen_def_id).generator_drop.as_ref().unwrap();
         return mir.subst(tcx, substs.substs);
     }
@@ -301,17 +301,17 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     match self_ty.sty {
         _ if is_copy => builder.copy_shim(),
-        ty::TyArray(ty, len) => {
+        ty::Array(ty, len) => {
             let len = len.unwrap_usize(tcx);
             builder.array_shim(dest, src, ty, len)
         }
-        ty::TyClosure(def_id, substs) => {
+        ty::Closure(def_id, substs) => {
             builder.tuple_like_shim(
                 dest, src,
                 substs.upvar_tys(def_id, tcx)
             )
         }
-        ty::TyTuple(tys) => builder.tuple_like_shim(dest, src, tys.iter().cloned()),
+        ty::Tuple(tys) => builder.tuple_like_shim(dest, src, tys.iter().cloned()),
         _ => {
             bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty)
         }
@@ -440,6 +440,7 @@ fn make_clone_call(
         let func = Operand::Constant(box Constant {
             span: self.span,
             ty: func_ty,
+            user_ty: None,
             literal: ty::Const::zero_sized(self.tcx, func_ty),
         });
 
@@ -498,6 +499,7 @@ fn make_usize(&self, value: u64) -> Box<Constant<'tcx>> {
         box Constant {
             span: self.span,
             ty: self.tcx.types.usize,
+            user_ty: None,
             literal: ty::Const::from_usize(self.tcx, value),
         }
     }
@@ -725,6 +727,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             (Operand::Constant(box Constant {
                 span,
                 ty,
+                user_ty: None,
                 literal: ty::Const::zero_sized(tcx, ty),
              }),
              vec![rcvr])
@@ -821,7 +824,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
     let sig = gcx.normalize_erasing_regions(param_env, sig);
 
     let (adt_def, substs) = match sig.output().sty {
-        ty::TyAdt(adt_def, substs) => (adt_def, substs),
+        ty::Adt(adt_def, substs) => (adt_def, substs),
         _ => bug!("unexpected type for ADT ctor {:?}", sig.output())
     };
 
@@ -847,7 +850,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
             kind: StatementKind::Assign(
                 Place::Local(RETURN_PLACE),
                 Rvalue::Aggregate(
-                    box AggregateKind::Adt(adt_def, variant_no, substs, None),
+                    box AggregateKind::Adt(adt_def, variant_no, substs, None, None),
                     (1..sig.inputs().len()+1).map(|i| {
                         Operand::Move(Place::Local(Local::new(i)))
                     }).collect()
index 4f7f45f173f73c6ec216da2f69f26889e2978e3e..6efefdaa004008e66e52d9e3daad3b5b3efcbf4a 100644 (file)
@@ -45,7 +45,7 @@ fn place_context<'a, 'tcx, D>(
                     // A Deref projection may restrict the context, this depends on the type
                     // being deref'd.
                     let context = match ty.sty {
-                        ty::TyRef(re, _, mutbl) => {
+                        ty::Ref(re, _, mutbl) => {
                             let re = match re {
                                 &RegionKind::ReScope(ce) => Some(ce),
                                 &RegionKind::ReErased =>
@@ -54,12 +54,12 @@ fn place_context<'a, 'tcx, D>(
                             };
                             (re, mutbl)
                         }
-                        ty::TyRawPtr(_) =>
+                        ty::RawPtr(_) =>
                             // There is no guarantee behind even a mutable raw pointer,
                             // no write locks are acquired there, so we also don't want to
                             // release any.
                             (None, hir::MutImmutable),
-                        ty::TyAdt(adt, _) if adt.is_box() => (None, hir::MutMutable),
+                        ty::Adt(adt, _) if adt.is_box() => (None, hir::MutMutable),
                         _ => bug!("Deref on a non-pointer type {:?}", ty),
                     };
                     // "Intersect" this restriction with proj.base.
@@ -85,7 +85,7 @@ fn place_context<'a, 'tcx, D>(
 fn fn_contains_unsafe<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource) -> bool {
     use rustc::hir::intravisit::{self, Visitor, FnKind};
     use rustc::hir::map::blocks::FnLikeNode;
-    use rustc::hir::map::Node;
+    use rustc::hir::Node;
 
     /// Decide if this is an unsafe block
     fn block_is_unsafe(block: &hir::Block) -> bool {
@@ -142,13 +142,13 @@ fn fn_is_closure<'a>(fn_like: FnLikeNode<'a>) -> bool {
             }
             // Check if this is an unsafe block, or an item
             match node {
-                Node::NodeExpr(&hir::Expr { node: hir::ExprKind::Block(ref block, _), ..}) => {
+                Node::Expr(&hir::Expr { node: hir::ExprKind::Block(ref block, _), ..}) => {
                     if block_is_unsafe(&*block) {
                         // Found an unsafe block, we can bail out here.
                         return true;
                     }
                 }
-                Node::NodeItem(..) => {
+                Node::Item(..) => {
                     // No walking up beyond items.  This makes sure the loop always terminates.
                     break;
                 }
index 80e484d5957140e2d311e256d03e0516f84487b3..ec7fd371a442bb8ca406751b2953587379eb3173 100644 (file)
@@ -15,6 +15,7 @@
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt};
 use rustc::hir;
+use rustc::hir::Node;
 use rustc::hir::def_id::DefId;
 use rustc::lint::builtin::{SAFE_EXTERN_STATICS, SAFE_PACKED_BORROWS, UNUSED_UNSAFE};
 use rustc::mir::*;
@@ -27,6 +28,7 @@
 
 pub struct UnsafetyChecker<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
+    min_const_fn: bool,
     source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
     violations: Vec<UnsafetyViolation>,
     source_info: SourceInfo,
@@ -37,12 +39,16 @@ pub struct UnsafetyChecker<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'gcx, 'tcx> UnsafetyChecker<'a, 'tcx> {
-    fn new(mir: &'a Mir<'tcx>,
-           source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
-           tcx: TyCtxt<'a, 'tcx, 'tcx>,
-           param_env: ty::ParamEnv<'tcx>) -> Self {
+    fn new(
+        min_const_fn: bool,
+        mir: &'a Mir<'tcx>,
+        source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Self {
         Self {
             mir,
+            min_const_fn,
             source_scope_local_data,
             violations: vec![],
             source_info: SourceInfo {
@@ -179,13 +185,13 @@ fn visit_place(&mut self,
                 }
                 let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx);
                 match base_ty.sty {
-                    ty::TyRawPtr(..) => {
+                    ty::RawPtr(..) => {
                         self.require_unsafe("dereference of raw pointer",
                             "raw pointers may be NULL, dangling or unaligned; they can violate \
                              aliasing rules and cause data races: all of these are undefined \
                              behavior")
                     }
-                    ty::TyAdt(adt, _) => {
+                    ty::Adt(adt, _) => {
                         if adt.is_union() {
                             if context == PlaceContext::Store ||
                                 context == PlaceContext::AsmOutput ||
@@ -268,6 +274,15 @@ fn require_unsafe(&mut self,
     fn register_violations(&mut self,
                            violations: &[UnsafetyViolation],
                            unsafe_blocks: &[(ast::NodeId, bool)]) {
+        if self.min_const_fn {
+            for violation in violations {
+                let mut violation = violation.clone();
+                violation.kind = UnsafetyViolationKind::MinConstFn;
+                if !self.violations.contains(&violation) {
+                    self.violations.push(violation)
+                }
+            }
+        }
         let within_unsafe = match self.source_scope_local_data[self.source_info.scope].safety {
             Safety::Safe => {
                 for violation in violations {
@@ -275,7 +290,6 @@ fn register_violations(&mut self,
                         self.violations.push(violation.clone())
                     }
                 }
-
                 false
             }
             Safety::BuiltinUnsafe | Safety::FnUnsafe => true,
@@ -368,6 +382,7 @@ fn unsafety_check_result<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
 
     let param_env = tcx.param_env(def_id);
     let mut checker = UnsafetyChecker::new(
+        tcx.is_const_fn(def_id) && tcx.is_min_const_fn(def_id),
         mir, source_scope_local_data, tcx, param_env);
     checker.visit_mir(mir);
 
@@ -407,7 +422,7 @@ fn is_enclosed(tcx: TyCtxt,
     if parent_id != id {
         if used_unsafe.contains(&parent_id) {
             Some(("block".to_string(), parent_id))
-        } else if let Some(hir::map::NodeItem(&hir::Item {
+        } else if let Some(Node::Item(&hir::Item {
             node: hir::ItemKind::Fn(_, header, _, _),
             ..
         })) = tcx.hir.find(parent_id) {
@@ -477,6 +492,15 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
                     .note(&details.as_str()[..])
                     .emit();
             }
+            UnsafetyViolationKind::MinConstFn => {
+                tcx.sess.struct_span_err(
+                    source_info.span,
+                    &format!("{} is unsafe and unsafe operations \
+                            are not allowed in const fn", description))
+                    .span_label(source_info.span, &description.as_str()[..])
+                    .note(&details.as_str()[..])
+                    .emit();
+            }
             UnsafetyViolationKind::ExternStatic(lint_node_id) => {
                 tcx.lint_node_note(SAFE_EXTERN_STATICS,
                               lint_node_id,
index 47c45adb85f5af9e969bad255a0839bed0f7b55e..e2b1a255eaca29fba90b48c664c84f5b27b2e5c0 100644 (file)
 
 use rustc::hir::def::Def;
 use rustc::mir::{Constant, Location, Place, Mir, Operand, Rvalue, Local};
-use rustc::mir::{NullOp, StatementKind, Statement, BasicBlock, LocalKind};
+use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind};
 use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
 use rustc::mir::visit::{Visitor, PlaceContext};
-use rustc::mir::interpret::{ConstEvalErr, EvalErrorKind, ScalarMaybeUndef};
+use rustc::mir::interpret::{
+    ConstEvalErr, EvalErrorKind, ScalarMaybeUndef, Scalar, GlobalId, EvalResult
+};
 use rustc::ty::{TyCtxt, self, Instance};
-use rustc::mir::interpret::{Value, Scalar, GlobalId, EvalResult};
-use interpret::EvalContext;
-use interpret::CompileTimeEvaluator;
-use interpret::{eval_promoted, mk_borrowck_eval_cx, ValTy};
+use interpret::{EvalContext, CompileTimeEvaluator, eval_promoted, mk_borrowck_eval_cx};
+use interpret::{self, Value, OpTy, MemoryKind};
 use transform::{MirPass, MirSource};
 use syntax::source_map::{Span, DUMMY_SP};
 use rustc::ty::subst::Substs;
-use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use rustc::ty::ParamEnv;
 use rustc::ty::layout::{
     LayoutOf, TyLayout, LayoutError,
@@ -65,7 +65,7 @@ fn run_pass<'a, 'tcx>(&self,
     }
 }
 
-type Const<'tcx> = (Value, TyLayout<'tcx>, Span);
+type Const<'tcx> = (OpTy<'tcx>, Span);
 
 /// Finds optimization opportunities on the MIR.
 struct ConstPropagator<'b, 'a, 'tcx:'a+'b> {
@@ -153,7 +153,9 @@ fn use_ecx<F, T>(
                     | MachineError(_)
                     // at runtime these transformations might make sense
                     // FIXME: figure out the rules and start linting
-                    | FunctionPointerTyMismatch(..)
+                    | FunctionAbiMismatch(..)
+                    | FunctionArgMismatch(..)
+                    | FunctionArgCountMismatch
                     // fine at runtime, might be a register address or sth
                     | ReadBytesAsPointer
                     // fine at runtime
@@ -170,7 +172,7 @@ fn use_ecx<F, T>(
                     | DoubleFree
                     | InvalidFunctionPointer
                     | InvalidBool
-                    | InvalidDiscriminant
+                    | InvalidDiscriminant(..)
                     | PointerOutOfBounds { .. }
                     | InvalidNullPointerUsage
                     | MemoryLockViolation { .. }
@@ -230,7 +232,7 @@ fn use_ecx<F, T>(
                     // FIXME: implement
                     => {},
 
-                    | Panic
+                    | Panic { .. }
                     | BoundsCheck{..}
                     | Overflow(_)
                     | OverflowNeg
@@ -257,10 +259,9 @@ fn eval_constant(
         source_info: SourceInfo,
     ) -> Option<Const<'tcx>> {
         self.ecx.tcx.span = source_info.span;
-        match self.ecx.const_to_value(c.literal.val) {
-            Ok(val) => {
-                let layout = self.tcx.layout_of(self.param_env.and(c.literal.ty)).ok()?;
-                Some((val, layout, c.span))
+        match self.ecx.const_to_op(c.literal) {
+            Ok(op) => {
+                Some((op, c.span))
             },
             Err(error) => {
                 let (stacktrace, span) = self.ecx.generate_stacktrace(None);
@@ -284,12 +285,15 @@ fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option
             Place::Projection(ref proj) => match proj.elem {
                 ProjectionElem::Field(field, _) => {
                     trace!("field proj on {:?}", proj.base);
-                    let (base, layout, span) = self.eval_place(&proj.base, source_info)?;
-                    let valty = self.use_ecx(source_info, |this| {
-                        this.ecx.read_field(base, None, field, layout)
+                    let (base, span) = self.eval_place(&proj.base, source_info)?;
+                    let res = self.use_ecx(source_info, |this| {
+                        this.ecx.operand_field(base, field.index() as u64)
                     })?;
-                    Some((valty.0, valty.1, span))
+                    Some((res, span))
                 },
+                // We could get more projections by using e.g. `operand_projection`,
+                // but we do not even have the stack frame set up properly so
+                // an `Index` projection would throw us off-track.
                 _ => None,
             },
             Place::Promoted(ref promoted) => {
@@ -306,12 +310,11 @@ fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option
                 };
                 // cannot use `const_eval` here, because that would require having the MIR
                 // for the current function available, but we're producing said MIR right now
-                let (value, _, ty) = self.use_ecx(source_info, |this| {
+                let res = self.use_ecx(source_info, |this| {
                     eval_promoted(&mut this.ecx, cid, this.mir, this.param_env)
                 })?;
-                let val = (value, ty, source_info.span);
-                trace!("evaluated promoted {:?} to {:?}", promoted, val);
-                Some(val)
+                trace!("evaluated promoted {:?} to {:?}", promoted, res);
+                Some((res, source_info.span))
             },
             _ => None,
         }
@@ -343,17 +346,11 @@ fn const_prop(
             Rvalue::Discriminant(..) => None,
 
             Rvalue::Cast(kind, ref operand, _) => {
-                let (value, layout, span) = self.eval_operand(operand, source_info)?;
+                let (op, span) = self.eval_operand(operand, source_info)?;
                 self.use_ecx(source_info, |this| {
-                    let dest_ptr = this.ecx.alloc_ptr(place_layout)?;
-                    let place_align = place_layout.align;
-                    let dest = ::interpret::Place::from_ptr(dest_ptr, place_align);
-                    this.ecx.cast(ValTy { value, ty: layout.ty }, kind, place_layout.ty, dest)?;
-                    Ok((
-                        Value::ByRef(dest_ptr.into(), place_align),
-                        place_layout,
-                        span,
-                    ))
+                    let dest = this.ecx.allocate(place_layout, MemoryKind::Stack)?;
+                    this.ecx.cast(op, kind, dest.into())?;
+                    Ok((dest.into(), span))
                 })
             }
 
@@ -361,11 +358,15 @@ fn const_prop(
             Rvalue::Len(_) => None,
             Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
                 type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some((
-                    Value::Scalar(Scalar::Bits {
-                        bits: n as u128,
-                        size: self.tcx.data_layout.pointer_size.bytes() as u8,
-                    }.into()),
-                    self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
+                    OpTy {
+                        op: interpret::Operand::Immediate(Value::Scalar(
+                            Scalar::Bits {
+                                bits: n as u128,
+                                size: self.tcx.data_layout.pointer_size.bytes() as u8,
+                            }.into()
+                        )),
+                        layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
+                    },
                     span,
                 )))
             }
@@ -381,12 +382,30 @@ fn const_prop(
                     return None;
                 }
 
-                let val = self.eval_operand(arg, source_info)?;
-                let prim = self.use_ecx(source_info, |this| {
-                    this.ecx.value_to_scalar(ValTy { value: val.0, ty: val.1.ty })
+                let (arg, _) = self.eval_operand(arg, source_info)?;
+                let val = self.use_ecx(source_info, |this| {
+                    let prim = this.ecx.read_scalar(arg)?.not_undef()?;
+                    match op {
+                        UnOp::Neg => {
+                            // Need to do overflow check here: For actual CTFE, MIR
+                            // generation emits code that does this before calling the op.
+                            let size = arg.layout.size;
+                            if prim.to_bits(size)? == (1 << (size.bits() - 1)) {
+                                return err!(OverflowNeg);
+                            }
+                        }
+                        UnOp::Not => {
+                            // Cannot overflow
+                        }
+                    }
+                    // Now run the actual operation.
+                    this.ecx.unary_op(op, prim, arg.layout)
                 })?;
-                let val = self.use_ecx(source_info, |this| this.ecx.unary_op(op, prim, val.1))?;
-                Some((Value::Scalar(val.into()), place_layout, span))
+                let res = OpTy {
+                    op: interpret::Operand::Immediate(Value::Scalar(val.into())),
+                    layout: place_layout,
+                };
+                Some((res, span))
             }
             Rvalue::CheckedBinaryOp(op, ref left, ref right) |
             Rvalue::BinaryOp(op, ref left, ref right) => {
@@ -404,7 +423,7 @@ fn const_prop(
                 }
 
                 let r = self.use_ecx(source_info, |this| {
-                    this.ecx.value_to_scalar(ValTy { value: right.0, ty: right.1.ty })
+                    this.ecx.read_value(right.0)
                 })?;
                 if op == BinOp::Shr || op == BinOp::Shl {
                     let left_ty = left.ty(self.mir, self.tcx);
@@ -414,8 +433,9 @@ fn const_prop(
                         .unwrap()
                         .size
                         .bits();
-                    let right_size = right.1.size;
-                    if r.to_bits(right_size).ok().map_or(false, |b| b >= left_bits as u128) {
+                    let right_size = right.0.layout.size;
+                    let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
+                    if r_bits.ok().map_or(false, |b| b >= left_bits as u128) {
                         let source_scope_local_data = match self.mir.source_scope_local_data {
                             ClearCrossCrate::Set(ref data) => data,
                             ClearCrossCrate::Clear => return None,
@@ -436,11 +456,11 @@ fn const_prop(
                 }
                 let left = self.eval_operand(left, source_info)?;
                 let l = self.use_ecx(source_info, |this| {
-                    this.ecx.value_to_scalar(ValTy { value: left.0, ty: left.1.ty })
+                    this.ecx.read_value(left.0)
                 })?;
                 trace!("const evaluating {:?} for {:?} and {:?}", op, left, right);
                 let (val, overflow) = self.use_ecx(source_info, |this| {
-                    this.ecx.binary_op(op, l, left.1.ty, r, right.1.ty)
+                    this.ecx.binary_op_val(op, l, r)
                 })?;
                 let val = if let Rvalue::CheckedBinaryOp(..) = *rvalue {
                     Value::ScalarPair(
@@ -455,7 +475,11 @@ fn const_prop(
                     }
                     Value::Scalar(val.into())
                 };
-                Some((val, place_layout, span))
+                let res = OpTy {
+                    op: interpret::Operand::Immediate(val),
+                    layout: place_layout,
+                };
+                Some((res, span))
             },
         }
     }
@@ -571,7 +595,8 @@ fn visit_terminator_kind(
         if let TerminatorKind::Assert { expected, msg, cond, .. } = kind {
             if let Some(value) = self.eval_operand(cond, source_info) {
                 trace!("assertion on {:?} should be {:?}", value, expected);
-                if Value::Scalar(Scalar::from_bool(*expected).into()) != value.0 {
+                let expected = Value::Scalar(Scalar::from_bool(*expected).into());
+                if expected != value.0.to_immediate() {
                     // poison all places this operand references so that further code
                     // doesn't use the invalid value
                     match cond {
@@ -607,7 +632,7 @@ fn visit_terminator_kind(
                             let len = self
                                 .eval_operand(len, source_info)
                                 .expect("len must be const");
-                            let len = match len.0 {
+                            let len = match len.0.to_immediate() {
                                 Value::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits {
                                     bits, ..
                                 })) => bits,
@@ -616,7 +641,7 @@ fn visit_terminator_kind(
                             let index = self
                                 .eval_operand(index, source_info)
                                 .expect("index must be const");
-                            let index = match index.0 {
+                            let index = match index.0.to_immediate() {
                                 Value::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits {
                                     bits, ..
                                 })) => bits,
index 8b2b9ef7e814d3c3ecb1381f6117b0d7edf5c89a..cff098c7b73d594e6a8dd9f1e2dc5e9fc83a1ad1 100644 (file)
@@ -48,7 +48,7 @@ fn run_pass<'a, 'tcx>(&self,
 
                 let mut set_discriminant = None;
                 let active_field_index = match *kind {
-                    AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
+                    AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
                         if adt_def.is_enum() {
                             set_discriminant = Some(Statement {
                                 kind: StatementKind::SetDiscriminant {
index 937d01a0c5e883e6fa890abdc68f051802ed13cb..225de03a329651d252e4bc7ee32aeaf2479bbc78 100644 (file)
@@ -18,7 +18,7 @@
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
 use rustc::util::nodemap::FxHashMap;
-use rustc_data_structures::indexed_set::IdxSetBuf;
+use rustc_data_structures::indexed_set::IdxSet;
 use rustc_data_structures::indexed_vec::Idx;
 use transform::{MirPass, MirSource};
 use util::patch::MirPatch;
@@ -93,12 +93,12 @@ fn find_dead_unwinds<'a, 'tcx>(
     mir: &Mir<'tcx>,
     id: ast::NodeId,
     env: &MoveDataParamEnv<'tcx, 'tcx>)
-    -> IdxSetBuf<BasicBlock>
+    -> IdxSet<BasicBlock>
 {
     debug!("find_dead_unwinds({:?})", mir.span);
     // We only need to do this pass once, because unwind edges can only
     // reach cleanup blocks, which can't have unwind edges themselves.
-    let mut dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
+    let mut dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len());
     let flow_inits =
         do_dataflow(tcx, mir, id, &[], &dead_unwinds,
                     MaybeInitializedPlaces::new(tcx, mir, &env),
@@ -112,7 +112,7 @@ fn find_dead_unwinds<'a, 'tcx>(
 
         let mut init_data = InitializationData {
             live: flow_inits.sets().on_entry_set_for(bb.index()).to_owned(),
-            dead: IdxSetBuf::new_empty(env.move_data.move_paths.len()),
+            dead: IdxSet::new_empty(env.move_data.move_paths.len()),
         };
         debug!("find_dead_unwinds @ {:?}: {:?}; init_data={:?}",
                bb, bb_data, init_data.live);
@@ -147,8 +147,8 @@ fn find_dead_unwinds<'a, 'tcx>(
 }
 
 struct InitializationData {
-    live: IdxSetBuf<MovePathIndex>,
-    dead: IdxSetBuf<MovePathIndex>
+    live: IdxSet<MovePathIndex>,
+    dead: IdxSet<MovePathIndex>
 }
 
 impl InitializationData {
@@ -543,6 +543,7 @@ fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
         Rvalue::Use(Operand::Constant(Box::new(Constant {
             span,
             ty: self.tcx.types.bool,
+            user_ty: None,
             literal: ty::Const::from_bool(self.tcx, val),
         })))
     }
index a3647edd155d3d71b105891b4e16b16d7400a683..dcbf92b57b13a2a895a0ee897fd44b1b20eb4aad 100644 (file)
 use rustc::ty::{self, TyCtxt, AdtDef, Ty};
 use rustc::ty::subst::Substs;
 use util::dump_mir;
-use util::liveness::{self, IdentityMap, LivenessMode};
+use util::liveness::{self, IdentityMap};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
-use rustc_data_structures::indexed_set::IdxSetBuf;
-use std::collections::HashMap;
+use rustc_data_structures::indexed_set::IdxSet;
 use std::borrow::Cow;
 use std::iter::once;
 use std::mem;
@@ -142,10 +142,12 @@ struct TransformVisitor<'a, 'tcx: 'a> {
     state_field: usize,
 
     // Mapping from Local to (type of local, generator struct index)
-    remap: HashMap<Local, (Ty<'tcx>, usize)>,
+    // FIXME(eddyb) This should use `IndexVec<Local, Option<_>>`.
+    remap: FxHashMap<Local, (Ty<'tcx>, usize)>,
 
     // A map from a suspension point in a block to the locals which have live storage at that point
-    storage_liveness: HashMap<BasicBlock, liveness::LiveVarSet<Local>>,
+    // FIXME(eddyb) This should use `IndexVec<BasicBlock, Option<_>>`.
+    storage_liveness: FxHashMap<BasicBlock, liveness::LiveVarSet<Local>>,
 
     // A list of suspension points, generated during the transform
     suspension_points: Vec<SuspensionPoint>,
@@ -157,7 +159,7 @@ struct TransformVisitor<'a, 'tcx: 'a> {
 impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
     // Make a GeneratorState rvalue
     fn make_state(&self, idx: usize, val: Operand<'tcx>) -> Rvalue<'tcx> {
-        let adt = AggregateKind::Adt(self.state_adt_ref, idx, self.state_substs, None);
+        let adt = AggregateKind::Adt(self.state_adt_ref, idx, self.state_substs, None, None);
         Rvalue::Aggregate(box adt, vec![val])
     }
 
@@ -177,6 +179,7 @@ fn set_state(&self, state_disc: u32, source_info: SourceInfo) -> Statement<'tcx>
         let val = Operand::Constant(box Constant {
             span: source_info.span,
             ty: self.tcx.types.u32,
+            user_ty: None,
             literal: ty::Const::from_bits(
                 self.tcx,
                 state_disc.into(),
@@ -363,13 +366,16 @@ fn visit_rvalue(&mut self,
     }
 }
 
-fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                               mir: &Mir<'tcx>,
-                                               source: MirSource,
-                                               movable: bool) ->
-                                               (liveness::LiveVarSet<Local>,
-                                                HashMap<BasicBlock, liveness::LiveVarSet<Local>>) {
-    let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
+fn locals_live_across_suspend_points(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &Mir<'tcx>,
+    source: MirSource,
+    movable: bool,
+) -> (
+    liveness::LiveVarSet<Local>,
+    FxHashMap<BasicBlock, liveness::LiveVarSet<Local>>,
+) {
+    let dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len());
     let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap();
 
     // Calculate when MIR locals have live storage. This gives us an upper bound of their
@@ -381,7 +387,7 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     // Find the MIR locals which do not use StorageLive/StorageDead statements.
     // The storage of these locals are always live.
-    let mut ignored = StorageIgnored(IdxSetBuf::new_filled(mir.local_decls.len()));
+    let mut ignored = StorageIgnored(IdxSet::new_filled(mir.local_decls.len()));
     ignored.visit_mir(mir);
 
     // Calculate the MIR locals which have been previously
@@ -401,10 +407,6 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut set = liveness::LiveVarSet::new_empty(mir.local_decls.len());
     let mut liveness = liveness::liveness_of_locals(
         mir,
-        LivenessMode {
-            include_regular_use: true,
-            include_drops: true,
-        },
         &IdentityMap::new(mir),
     );
     liveness::dump_mir(
@@ -416,7 +418,7 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         &liveness,
     );
 
-    let mut storage_liveness_map = HashMap::new();
+    let mut storage_liveness_map = FxHashMap::default();
 
     for (block, data) in mir.basic_blocks().iter_enumerated() {
         if let TerminatorKind::Yield { .. } = data.terminator().kind {
@@ -480,9 +482,9 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             interior: Ty<'tcx>,
                             movable: bool,
                             mir: &mut Mir<'tcx>)
-    -> (HashMap<Local, (Ty<'tcx>, usize)>,
+    -> (FxHashMap<Local, (Ty<'tcx>, usize)>,
         GeneratorLayout<'tcx>,
-        HashMap<BasicBlock, liveness::LiveVarSet<Local>>)
+        FxHashMap<BasicBlock, liveness::LiveVarSet<Local>>)
 {
     // Use a liveness analysis to compute locals which are live across a suspension point
     let (live_locals, storage_liveness) = locals_live_across_suspend_points(tcx,
@@ -493,7 +495,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // MIR types
     let allowed_upvars = tcx.erase_regions(&upvars);
     let allowed = match interior.sty {
-        ty::TyGeneratorWitness(s) => tcx.erase_late_bound_regions(&s),
+        ty::GeneratorWitness(s) => tcx.erase_late_bound_regions(&s),
         _ => bug!(),
     };
 
@@ -710,6 +712,7 @@ fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         cond: Operand::Constant(box Constant {
             span: mir.span,
             ty: tcx.types.bool,
+            user_ty: None,
             literal: ty::Const::from_bool(tcx, false),
         }),
         expected: true,
@@ -863,7 +866,7 @@ fn run_pass<'a, 'tcx>(&self,
 
         // Get the interior types and substs which typeck computed
         let (upvars, interior, movable) = match gen_ty.sty {
-            ty::TyGenerator(_, substs, movability) => {
+            ty::Generator(_, substs, movability) => {
                 (substs.upvar_tys(def_id, tcx).collect(),
                  substs.witness(def_id, tcx),
                  movability == hir::GeneratorMovability::Movable)
index 85115427edae9dc00d0cfd7bf8e4f90f3ad79eb5..31e437ce2281acb9b1dc6556f8b336cca8374091 100644 (file)
@@ -95,7 +95,7 @@ fn run_pass(&self, caller_mir: &mut Mir<'tcx>) {
                 let terminator = bb_data.terminator();
                 if let TerminatorKind::Call {
                     func: Operand::Constant(ref f), .. } = terminator.kind {
-                        if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty {
+                        if let ty::FnDef(callee_def_id, substs) = f.ty.sty {
                             if let Some(instance) = Instance::resolve(self.tcx,
                                                                       param_env,
                                                                       callee_def_id,
@@ -158,7 +158,7 @@ fn run_pass(&self, caller_mir: &mut Mir<'tcx>) {
                     let terminator = bb_data.terminator();
                     if let TerminatorKind::Call {
                         func: Operand::Constant(ref f), .. } = terminator.kind {
-                        if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty {
+                        if let ty::FnDef(callee_def_id, substs) = f.ty.sty {
                             // Don't inline the same function multiple times.
                             if callsite.callee != callee_def_id {
                                 callsites.push_back(CallSite {
@@ -314,7 +314,7 @@ fn should_inline(&self,
                 }
 
                 TerminatorKind::Call {func: Operand::Constant(ref f), .. } => {
-                    if let ty::TyFnDef(def_id, _) = f.ty.sty {
+                    if let ty::FnDef(def_id, _) = f.ty.sty {
                         // Don't give intrinsics the extra penalty for calls
                         let f = tcx.fn_sig(def_id);
                         if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic {
@@ -538,7 +538,7 @@ fn make_call_args(
             assert!(args.next().is_none());
 
             let tuple = Place::Local(tuple);
-            let tuple_tys = if let ty::TyTuple(s) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty {
+            let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty {
                 s
             } else {
                 bug!("Closure arguments are not passed as a tuple");
@@ -704,7 +704,7 @@ fn visit_terminator_kind(&mut self, block: BasicBlock,
                     *unwind = Some(self.update_target(tgt));
                 } else if !self.in_cleanup_block {
                     // Unless this drop is in a cleanup block, add an unwind edge to
-                    // the orignal call's cleanup block
+                    // the original call's cleanup block
                     *unwind = self.cleanup_block;
                 }
             }
@@ -716,7 +716,7 @@ fn visit_terminator_kind(&mut self, block: BasicBlock,
                     *cleanup = Some(self.update_target(tgt));
                 } else if !self.in_cleanup_block {
                     // Unless this call is in a cleanup block, add an unwind edge to
-                    // the orignal call's cleanup block
+                    // the original call's cleanup block
                     *cleanup = self.cleanup_block;
                 }
             }
@@ -726,7 +726,7 @@ fn visit_terminator_kind(&mut self, block: BasicBlock,
                     *cleanup = Some(self.update_target(tgt));
                 } else if !self.in_cleanup_block {
                     // Unless this assert is in a cleanup block, add an unwind edge to
-                    // the orignal call's cleanup block
+                    // the original call's cleanup block
                     *cleanup = self.cleanup_block;
                 }
             }
index 6e06beb30419d12e6e7f764d44e4bfd06c8d37bf..12780ef8be945483416abc4cce8611c3df56ec7c 100644 (file)
@@ -12,7 +12,7 @@
 
 use rustc::mir::{Constant, Location, Place, Mir, Operand, ProjectionElem, Rvalue, Local};
 use rustc::mir::visit::{MutVisitor, Visitor};
-use rustc::ty::{TyCtxt, TypeVariants};
+use rustc::ty::{TyCtxt, TyKind};
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::Idx;
 use std::mem;
@@ -100,10 +100,10 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
 
         if let Rvalue::Len(ref place) = *rvalue {
             let place_ty = place.ty(&self.mir.local_decls, self.tcx).to_ty(self.tcx);
-            if let TypeVariants::TyArray(_, len) = place_ty.sty {
+            if let TyKind::Array(_, len) = place_ty.sty {
                 let span = self.mir.source_info(location).span;
                 let ty = self.tcx.types.usize;
-                let constant = Constant { span, ty, literal: len };
+                let constant = Constant { span, ty, literal: len, user_ty: None };
                 self.optimizations.arrays_lengths.insert(location, constant);
             }
         }
index 83cd7bf549d5536904e82bdc31cd01c16dcc3a53..8ed5600400b516e09f2abf3ef66cbdc2cf36b7b5 100644 (file)
@@ -13,7 +13,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::middle::lang_items::LangItem;
 use rustc::mir::*;
-use rustc::ty::{Slice, Ty, TyCtxt, TypeVariants};
+use rustc::ty::{List, Ty, TyCtxt, TyKind};
 use rustc_data_structures::indexed_vec::{Idx};
 use transform::{MirPass, MirSource};
 use syntax;
@@ -114,7 +114,7 @@ fn lower_128bit_ops<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<
                         source_info,
                         kind: TerminatorKind::Call {
                             func: Operand::function_handle(tcx, call_did,
-                                Slice::empty(), source_info.span),
+                                List::empty(), source_info.span),
                             args: vec![lhs, rhs],
                             destination: Some((place, bb)),
                             cleanup: None,
@@ -190,8 +190,8 @@ fn ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Ty<'tcx>> {
 
 fn sign_of_128bit(ty: Ty) -> Option<bool> {
     match ty.sty {
-        TypeVariants::TyInt(syntax::ast::IntTy::I128) => Some(true),
-        TypeVariants::TyUint(syntax::ast::UintTy::U128) => Some(false),
+        TyKind::Int(syntax::ast::IntTy::I128) => Some(true),
+        TyKind::Uint(syntax::ast::UintTy::U128) => Some(false),
         _ => None,
     }
 }
index 90dfebeef1b0ca7b0bb194b1bc46d3808e2ca251..1e05b07030ef898436f6740b9ebce4076a11d749 100644 (file)
@@ -36,6 +36,7 @@
 pub mod add_call_guards;
 pub mod promote_consts;
 pub mod qualify_consts;
+mod qualify_min_const_fn;
 pub mod remove_noop_landing_pads;
 pub mod dump_mir;
 pub mod deaggregator;
index b3ae65f5325925b855570e5e607e0ee276b8df3b..bb66b9ed6ece8759e6900e3e04f1cd8f45c1e8c4 100644 (file)
@@ -302,7 +302,7 @@ fn promote_candidate(mut self, candidate: Candidate) {
                     let ref mut statement = blocks[loc.block].statements[loc.statement_index];
                     match statement.kind {
                         StatementKind::Assign(_, Rvalue::Ref(_, _, ref mut place)) => {
-                            // Find the underlying local for this (necessarilly interior) borrow.
+                            // Find the underlying local for this (necessarily interior) borrow.
                             // HACK(eddyb) using a recursive function because of mutable borrows.
                             fn interior_base<'a, 'tcx>(place: &'a mut Place<'tcx>)
                                                        -> &'a mut Place<'tcx> {
index d876ee77e76cf7ccbdf5c0a20d0e778a05895bbb..0d24286869e6fb3b274b85ca968cc561312a14c1 100644 (file)
@@ -15,7 +15,7 @@
 //! diagnostics as to why a constant rvalue wasn't promoted.
 
 use rustc_data_structures::bitvec::BitArray;
-use rustc_data_structures::indexed_set::IdxSetBuf;
+use rustc_data_structures::indexed_set::IdxSet;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use rustc_data_structures::fx::FxHashSet;
 use rustc::hir;
@@ -127,6 +127,7 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            mir: &'a Mir<'tcx>,
            mode: Mode)
            -> Qualifier<'a, 'tcx, 'tcx> {
+        assert!(def_id.is_local());
         let mut rpo = traversal::reverse_postorder(mir);
         let temps = promote_consts::collect_temps(mir, &mut rpo);
         rpo.reset();
@@ -279,7 +280,7 @@ fn assign(&mut self, dest: &Place<'tcx>, location: Location) {
     }
 
     /// Qualify a whole const, static initializer or const fn.
-    fn qualify_const(&mut self) -> (Qualif, Lrc<IdxSetBuf<Local>>) {
+    fn qualify_const(&mut self) -> (Qualif, Lrc<IdxSet<Local>>) {
         debug!("qualifying {} {:?}", self.mode, self.def_id);
 
         let mir = self.mir;
@@ -382,7 +383,7 @@ fn qualify_const(&mut self) -> (Qualif, Lrc<IdxSetBuf<Local>>) {
 
 
         // Collect all the temps we need to promote.
-        let mut promoted_temps = IdxSetBuf::new_empty(self.temp_promotion_state.len());
+        let mut promoted_temps = IdxSet::new_empty(self.temp_promotion_state.len());
 
         for candidate in &self.promotion_candidates {
             match *candidate {
@@ -400,6 +401,11 @@ fn qualify_const(&mut self) -> (Qualif, Lrc<IdxSetBuf<Local>>) {
 
         (self.qualif, Lrc::new(promoted_temps))
     }
+
+    fn is_const_panic_fn(&self, def_id: DefId) -> bool {
+        Some(def_id) == self.tcx.lang_items().panic_fn() ||
+        Some(def_id) == self.tcx.lang_items().begin_panic_fn()
+    }
 }
 
 /// Accumulates an Rvalue or Call's effects in self.qualif.
@@ -495,7 +501,7 @@ fn visit_place(&mut self,
                                 this.add(Qualif::NOT_CONST);
                             } else {
                                 let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
-                                if let ty::TyRawPtr(_) = base_ty.sty {
+                                if let ty::RawPtr(_) = base_ty.sty {
                                     if !this.tcx.sess.features_untracked().const_raw_ptr_deref {
                                         emit_feature_err(
                                             &this.tcx.sess.parse_sess, "const_raw_ptr_deref",
@@ -591,7 +597,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
             if let Place::Projection(ref proj) = *place {
                 if let ProjectionElem::Deref = proj.elem {
                     let base_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
-                    if let ty::TyRef(..) = base_ty.sty {
+                    if let ty::Ref(..) = base_ty.sty {
                         is_reborrow = true;
                     }
                 }
@@ -638,10 +644,10 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                     if self.mode == Mode::StaticMut {
                         // Inside a `static mut`, &mut [...] is also allowed.
                         match ty.sty {
-                            ty::TyArray(..) | ty::TySlice(_) => forbidden_mut = false,
+                            ty::Array(..) | ty::Slice(_) => forbidden_mut = false,
                             _ => {}
                         }
-                    } else if let ty::TyArray(_, len) = ty.sty {
+                    } else if let ty::Array(_, len) = ty.sty {
                         // FIXME(eddyb) the `self.mode == Mode::Fn` condition
                         // seems unnecessary, given that this is merely a ZST.
                         if len.unwrap_usize(self.tcx) == 0 && self.mode == Mode::Fn {
@@ -745,7 +751,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
             }
 
             Rvalue::BinaryOp(op, ref lhs, _) => {
-                if let ty::TyRawPtr(_) = lhs.ty(self.mir, self.tcx).sty {
+                if let ty::RawPtr(_) = lhs.ty(self.mir, self.tcx).sty {
                     assert!(op == BinOp::Eq || op == BinOp::Ne ||
                             op == BinOp::Le || op == BinOp::Lt ||
                             op == BinOp::Ge || op == BinOp::Gt ||
@@ -809,7 +815,7 @@ fn visit_terminator_kind(&mut self,
             let fn_ty = func.ty(self.mir, self.tcx);
             let mut callee_def_id = None;
             let (mut is_shuffle, mut is_const_fn) = (false, None);
-            if let ty::TyFnDef(def_id, _) = fn_ty.sty {
+            if let ty::FnDef(def_id, _) = fn_ty.sty {
                 callee_def_id = Some(def_id);
                 match self.tcx.fn_sig(def_id).abi() {
                     Abi::RustIntrinsic |
@@ -825,6 +831,18 @@ fn visit_terminator_kind(&mut self,
                             | "cttz_nonzero"
                             | "ctlz"
                             | "ctlz_nonzero" => is_const_fn = Some(def_id),
+                            "transmute" => {
+                                if self.mode != Mode::Fn {
+                                    is_const_fn = Some(def_id);
+                                    if !self.tcx.sess.features_untracked().const_transmute {
+                                        emit_feature_err(
+                                            &self.tcx.sess.parse_sess, "const_transmute",
+                                            self.span, GateIssue::Language,
+                                            &format!("The use of std::mem::transmute() \
+                                            is gated in {}s", self.mode));
+                                    }
+                                }
+                            }
 
                             name if name.starts_with("simd_shuffle") => {
                                 is_shuffle = true;
@@ -834,7 +852,7 @@ fn visit_terminator_kind(&mut self,
                         }
                     }
                     _ => {
-                        if self.tcx.is_const_fn(def_id) {
+                        if self.tcx.is_const_fn(def_id) || self.is_const_panic_fn(def_id) {
                             is_const_fn = Some(def_id);
                         }
                     }
@@ -880,11 +898,26 @@ fn visit_terminator_kind(&mut self,
 
             // Const fn calls.
             if let Some(def_id) = is_const_fn {
+                // check the const_panic feature gate or
                 // find corresponding rustc_const_unstable feature
-                if let Some(&attr::Stability {
-                    rustc_const_unstable: Some(attr::RustcConstUnstable {
-                        feature: ref feature_name
-                    }),
+                // FIXME: cannot allow this inside `allow_internal_unstable` because that would make
+                // `panic!` insta stable in constants, since the macro is marked with the attr
+                if self.is_const_panic_fn(def_id) {
+                    if self.mode == Mode::Fn {
+                        // never promote panics
+                        self.qualif = Qualif::NOT_CONST;
+                    } else if !self.tcx.sess.features_untracked().const_panic {
+                        // don't allow panics in constants without the feature gate
+                        emit_feature_err(
+                            &self.tcx.sess.parse_sess,
+                            "const_panic",
+                            self.span,
+                            GateIssue::Language,
+                            &format!("panicking in {}s is unstable", self.mode),
+                        );
+                    }
+                } else if let Some(&attr::Stability {
+                    const_stability: Some(ref feature_name),
                 .. }) = self.tcx.lookup_stability(def_id) {
                     if
                         // feature-gate is not enabled,
@@ -893,9 +926,6 @@ fn visit_terminator_kind(&mut self,
                             .iter()
                             .any(|&(ref sym, _)| sym == feature_name) &&
 
-                        // this doesn't come from a crate with the feature-gate enabled,
-                        self.def_id.is_local() &&
-
                         // this doesn't come from a macro that has #[allow_internal_unstable]
                         !self.span.allows_unstable()
                     {
@@ -1082,7 +1112,7 @@ pub fn provide(providers: &mut Providers) {
 
 fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               def_id: DefId)
-                              -> (u8, Lrc<IdxSetBuf<Local>>) {
+                              -> (u8, Lrc<IdxSet<Local>>) {
     // NB: This `borrow()` is guaranteed to be valid (i.e., the value
     // cannot yet be stolen), because `mir_validated()`, which steals
     // from `mir_const(), forces this query to execute before
@@ -1091,7 +1121,7 @@ fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     if mir.return_ty().references_error() {
         tcx.sess.delay_span_bug(mir.span, "mir_const_qualif: Mir had errors");
-        return (Qualif::NOT_CONST.bits(), Lrc::new(IdxSetBuf::new_empty(0)));
+        return (Qualif::NOT_CONST.bits(), Lrc::new(IdxSet::new_empty(0)));
     }
 
     let mut qualifier = Qualifier::new(tcx, def_id, mir, Mode::Const);
@@ -1141,8 +1171,20 @@ fn run_pass<'a, 'tcx>(&self,
             let (temps, candidates) = {
                 let mut qualifier = Qualifier::new(tcx, def_id, mir, mode);
                 if mode == Mode::ConstFn {
-                    // Enforce a constant-like CFG for `const fn`.
-                    qualifier.qualify_const();
+                    if tcx.is_min_const_fn(def_id) {
+                        // enforce `min_const_fn` for stable const fns
+                        use super::qualify_min_const_fn::is_min_const_fn;
+                        if let Err((span, err)) = is_min_const_fn(tcx, def_id, mir) {
+                            tcx.sess.span_err(span, &err);
+                        } else {
+                            // this should not produce any errors, but better safe than sorry
+                            // FIXME(#53819)
+                            qualifier.qualify_const();
+                        }
+                    } else {
+                        // Enforce a constant-like CFG for `const fn`.
+                        qualifier.qualify_const();
+                    }
                 } else {
                     while let Some((bb, data)) = qualifier.rpo.next() {
                         qualifier.visit_basic_block_data(bb, data);
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
new file mode 100644 (file)
index 0000000..56e32ea
--- /dev/null
@@ -0,0 +1,358 @@
+use rustc::hir::def_id::DefId;
+use rustc::hir;
+use rustc::mir::*;
+use rustc::ty::{self, Predicate, TyCtxt};
+use std::borrow::Cow;
+use syntax_pos::Span;
+
+type McfResult = Result<(), (Span, Cow<'static, str>)>;
+
+pub fn is_min_const_fn(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId,
+    mir: &'a Mir<'tcx>,
+) -> McfResult {
+    let mut current = def_id;
+    loop {
+        let predicates = tcx.predicates_of(current);
+        for predicate in &predicates.predicates {
+            match predicate {
+                | Predicate::RegionOutlives(_)
+                | Predicate::TypeOutlives(_)
+                | Predicate::WellFormed(_)
+                | Predicate::ConstEvaluatable(..) => continue,
+                | Predicate::ObjectSafe(_) => {
+                    bug!("object safe predicate on function: {:#?}", predicate)
+                }
+                Predicate::ClosureKind(..) => {
+                    bug!("closure kind predicate on function: {:#?}", predicate)
+                }
+                Predicate::Subtype(_) => bug!("subtype predicate on function: {:#?}", predicate),
+                Predicate::Projection(_) => {
+                    let span = tcx.def_span(current);
+                    // we'll hit a `Predicate::Trait` later which will report an error
+                    tcx.sess
+                        .delay_span_bug(span, "projection without trait bound");
+                    continue;
+                }
+                Predicate::Trait(pred) => {
+                    if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
+                        continue;
+                    }
+                    match pred.skip_binder().self_ty().sty {
+                        ty::Param(ref p) => {
+                            let generics = tcx.generics_of(current);
+                            let def = generics.type_param(p, tcx);
+                            let span = tcx.def_span(def.def_id);
+                            return Err((
+                                span,
+                                "trait bounds other than `Sized` \
+                                 on const fn parameters are unstable"
+                                    .into(),
+                            ));
+                        }
+                        // other kinds of bounds are either tautologies
+                        // or cause errors in other passes
+                        _ => continue,
+                    }
+                }
+            }
+        }
+        match predicates.parent {
+            Some(parent) => current = parent,
+            None => break,
+        }
+    }
+
+    for local in mir.vars_iter() {
+        return Err((
+            mir.local_decls[local].source_info.span,
+            "local variables in const fn are unstable".into(),
+        ));
+    }
+    for local in &mir.local_decls {
+        check_ty(tcx, local.ty, local.source_info.span)?;
+    }
+    // impl trait is gone in MIR, so check the return type manually
+    check_ty(
+        tcx,
+        tcx.fn_sig(def_id).output().skip_binder(),
+        mir.local_decls.iter().next().unwrap().source_info.span,
+    )?;
+
+    for bb in mir.basic_blocks() {
+        check_terminator(tcx, mir, bb.terminator())?;
+        for stmt in &bb.statements {
+            check_statement(tcx, mir, stmt)?;
+        }
+    }
+    Ok(())
+}
+
+fn check_ty(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    ty: ty::Ty<'tcx>,
+    span: Span,
+) -> McfResult {
+    for ty in ty.walk() {
+        match ty.sty {
+            ty::Ref(_, _, hir::Mutability::MutMutable) => return Err((
+                span,
+                "mutable references in const fn are unstable".into(),
+            )),
+            ty::Anon(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
+            ty::FnPtr(..) => {
+                return Err((span, "function pointers in const fn are unstable".into()))
+            }
+            ty::Dynamic(preds, _) => {
+                for pred in preds.iter() {
+                    match pred.skip_binder() {
+                        | ty::ExistentialPredicate::AutoTrait(_)
+                        | ty::ExistentialPredicate::Projection(_) => {
+                            return Err((
+                                span,
+                                "trait bounds other than `Sized` \
+                                 on const fn parameters are unstable"
+                                    .into(),
+                            ))
+                        }
+                        ty::ExistentialPredicate::Trait(trait_ref) => {
+                            if Some(trait_ref.def_id) != tcx.lang_items().sized_trait() {
+                                return Err((
+                                    span,
+                                    "trait bounds other than `Sized` \
+                                     on const fn parameters are unstable"
+                                        .into(),
+                                ));
+                            }
+                        }
+                    }
+                }
+            }
+            _ => {}
+        }
+    }
+    Ok(())
+}
+
+fn check_rvalue(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+    rvalue: &Rvalue<'tcx>,
+    span: Span,
+) -> McfResult {
+    match rvalue {
+        Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => {
+            check_operand(tcx, mir, operand, span)
+        }
+        Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => {
+            check_place(tcx, mir, place, span, PlaceMode::Read)
+        }
+        Rvalue::Cast(_, operand, cast_ty) => {
+            use rustc::ty::cast::CastTy;
+            let cast_in = CastTy::from_ty(operand.ty(mir, tcx)).expect("bad input type for cast");
+            let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
+            match (cast_in, cast_out) {
+                (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => Err((
+                    span,
+                    "casting pointers to ints is unstable in const fn".into(),
+                )),
+                (CastTy::RPtr(_), CastTy::Float) => bug!(),
+                (CastTy::RPtr(_), CastTy::Int(_)) => bug!(),
+                (CastTy::Ptr(_), CastTy::RPtr(_)) => bug!(),
+                _ => check_operand(tcx, mir, operand, span),
+            }
+        }
+        // binops are fine on integers
+        Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
+            check_operand(tcx, mir, lhs, span)?;
+            check_operand(tcx, mir, rhs, span)?;
+            let ty = lhs.ty(mir, tcx);
+            if ty.is_integral() || ty.is_bool() || ty.is_char() {
+                Ok(())
+            } else {
+                Err((
+                    span,
+                    "only int, `bool` and `char` operations are stable in const fn".into(),
+                ))
+            }
+        }
+        // checked by regular const fn checks
+        Rvalue::NullaryOp(..) => Ok(()),
+        Rvalue::UnaryOp(_, operand) => {
+            let ty = operand.ty(mir, tcx);
+            if ty.is_integral() || ty.is_bool() {
+                check_operand(tcx, mir, operand, span)
+            } else {
+                Err((
+                    span,
+                    "only int and `bool` operations are stable in const fn".into(),
+                ))
+            }
+        }
+        Rvalue::Aggregate(_, operands) => {
+            for operand in operands {
+                check_operand(tcx, mir, operand, span)?;
+            }
+            Ok(())
+        }
+    }
+}
+
+enum PlaceMode {
+    Assign,
+    Read,
+}
+
+fn check_statement(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+    statement: &Statement<'tcx>,
+) -> McfResult {
+    let span = statement.source_info.span;
+    match &statement.kind {
+        StatementKind::Assign(place, rval) => {
+            check_place(tcx, mir, place, span, PlaceMode::Assign)?;
+            check_rvalue(tcx, mir, rval, span)
+        }
+
+        StatementKind::ReadForMatch(_) => Err((span, "match in const fn is unstable".into())),
+
+        // just an assignment
+        StatementKind::SetDiscriminant { .. } => Ok(()),
+
+        | StatementKind::InlineAsm { .. } => {
+            Err((span, "cannot use inline assembly in const fn".into()))
+        }
+
+        // These are all NOPs
+        | StatementKind::StorageLive(_)
+        | StatementKind::StorageDead(_)
+        | StatementKind::Validate(..)
+        | StatementKind::EndRegion(_)
+        | StatementKind::UserAssertTy(..)
+        | StatementKind::Nop => Ok(()),
+    }
+}
+
+fn check_operand(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+    operand: &Operand<'tcx>,
+    span: Span,
+) -> McfResult {
+    match operand {
+        Operand::Move(place) | Operand::Copy(place) => {
+            check_place(tcx, mir, place, span, PlaceMode::Read)
+        }
+        Operand::Constant(_) => Ok(()),
+    }
+}
+
+fn check_place(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+    place: &Place<'tcx>,
+    span: Span,
+    mode: PlaceMode,
+) -> McfResult {
+    match place {
+        Place::Local(l) => match mode {
+            PlaceMode::Assign => match mir.local_kind(*l) {
+                LocalKind::Temp | LocalKind::ReturnPointer => Ok(()),
+                LocalKind::Arg | LocalKind::Var => {
+                    Err((span, "assignments in const fn are unstable".into()))
+                }
+            },
+            PlaceMode::Read => Ok(()),
+        },
+        // promoteds are always fine, they are essentially constants
+        Place::Promoted(_) => Ok(()),
+        Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())),
+        Place::Projection(proj) => {
+            match proj.elem {
+                | ProjectionElem::Deref | ProjectionElem::Field(..) | ProjectionElem::Index(_) => {
+                    check_place(tcx, mir, &proj.base, span, mode)
+                }
+                // slice patterns are unstable
+                | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
+                    return Err((span, "slice patterns in const fn are unstable".into()))
+                }
+                | ProjectionElem::Downcast(..) => {
+                    Err((span, "`match` or `if let` in `const fn` is unstable".into()))
+                }
+            }
+        }
+    }
+}
+
+fn check_terminator(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+    terminator: &Terminator<'tcx>,
+) -> McfResult {
+    let span = terminator.source_info.span;
+    match &terminator.kind {
+        | TerminatorKind::Goto { .. }
+        | TerminatorKind::Return
+        | TerminatorKind::Resume => Ok(()),
+
+        TerminatorKind::Drop { location, .. } => {
+            check_place(tcx, mir, location, span, PlaceMode::Read)
+        }
+        TerminatorKind::DropAndReplace { location, value, .. } => {
+            check_place(tcx, mir, location, span, PlaceMode::Read)?;
+            check_operand(tcx, mir, value, span)
+        },
+        TerminatorKind::SwitchInt { .. } => Err((
+            span,
+            "`if`, `match`, `&&` and `||` are not stable in const fn".into(),
+        )),
+        | TerminatorKind::Abort | TerminatorKind::Unreachable => {
+            Err((span, "const fn with unreachable code is not stable".into()))
+        }
+        | TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
+            Err((span, "const fn generators are unstable".into()))
+        }
+
+        TerminatorKind::Call {
+            func,
+            args,
+            destination: _,
+            cleanup: _,
+        } => {
+            let fn_ty = func.ty(mir, tcx);
+            if let ty::FnDef(def_id, _) = fn_ty.sty {
+                if tcx.is_min_const_fn(def_id) {
+                    check_operand(tcx, mir, func, span)?;
+
+                    for arg in args {
+                        check_operand(tcx, mir, arg, span)?;
+                    }
+                    Ok(())
+                } else {
+                    Err((
+                        span,
+                        "can only call other `min_const_fn` within a `min_const_fn`".into(),
+                    ))
+                }
+            } else {
+                Err((span, "can only call other const fns within const fn".into()))
+            }
+        }
+
+        TerminatorKind::Assert {
+            cond,
+            expected: _,
+            msg: _,
+            target: _,
+            cleanup: _,
+        } => check_operand(tcx, mir, cond, span),
+
+        | TerminatorKind::FalseEdges { .. } | TerminatorKind::FalseUnwind { .. } => span_bug!(
+            terminator.source_info.span,
+            "min_const_fn encountered `{:#?}`",
+            terminator
+        ),
+    }
+}
index 776d7888459f78a7d862dc0ac151f46ff589dede..eda7de0fd79d48da9ade13918219acb914d4af23 100644 (file)
@@ -14,7 +14,7 @@
 
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::{self, Mir, Location};
-use rustc_data_structures::indexed_set::IdxSetBuf;
+use rustc_data_structures::indexed_set::IdxSet;
 use rustc_data_structures::indexed_vec::Idx;
 use transform::{MirPass, MirSource};
 
@@ -47,7 +47,7 @@ fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let param_env = tcx.param_env(def_id);
         let move_data = MoveData::gather_moves(mir, tcx).unwrap();
         let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
-        let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
+        let dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len());
         let flow_inits =
             do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
                         MaybeInitializedPlaces::new(tcx, mir, &mdpe),
@@ -209,8 +209,8 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             &mut sets, Location { block: bb, statement_index: j });
         results.0.operator.statement_effect(
             &mut sets, Location { block: bb, statement_index: j });
-        sets.on_entry.union_hybrid(sets.gen_set);
-        sets.on_entry.subtract_hybrid(sets.kill_set);
+        sets.on_entry.union(sets.gen_set);
+        sets.on_entry.subtract(sets.kill_set);
     }
 
     results.0.operator.before_terminator_effect(
@@ -229,7 +229,7 @@ fn is_rustc_peek<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     if let Some(mir::Terminator { ref kind, source_info, .. }) = *terminator {
         if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind {
             if let mir::Operand::Constant(ref func) = *oper {
-                if let ty::TyFnDef(def_id, _) = func.ty.sty {
+                if let ty::FnDef(def_id, _) = func.ty.sty {
                     let abi = tcx.fn_sig(def_id).abi();
                     let name = tcx.item_name(def_id);
                     if abi == Abi::RustIntrinsic &&  name == "rustc_peek" {
index 7a8c35e7b96f5fec18117b675fa9ed8075fc5b6e..78464b2a104ec301501e6d14d7f482ec8c47b619 100644 (file)
@@ -80,7 +80,7 @@ fn visit_assign(&mut self,
                     // no need to transformation
                 } else {
                     let place_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
-                    if let ty::TyArray(item_ty, const_size) = place_ty.sty {
+                    if let ty::Array(item_ty, const_size) = place_ty.sty {
                         if let Some(size) = const_size.assert_usize(self.tcx) {
                             assert!(size <= u32::max_value() as u64,
                                     "uniform array move out doesn't supported
@@ -190,7 +190,7 @@ fn run_pass<'a, 'tcx>(&self,
                                 let local_use = &visitor.locals_use[*local];
                                 let opt_index_and_place = Self::try_get_item_source(local_use, mir);
                                 // each local should be used twice:
-                                //  in assign and in aggregate statments
+                                //  in assign and in aggregate statements
                                 if local_use.use_count == 2 && opt_index_and_place.is_some() {
                                     let (index, src_place) = opt_index_and_place.unwrap();
                                     return Some((local_use, index, src_place));
@@ -202,7 +202,7 @@ fn run_pass<'a, 'tcx>(&self,
                         let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2);
                         let opt_size = opt_src_place.and_then(|src_place| {
                             let src_ty = src_place.ty(mir, tcx).to_ty(tcx);
-                            if let ty::TyArray(_, ref size_o) = src_ty.sty {
+                            if let ty::Array(_, ref size_o) = src_ty.sty {
                                 size_o.assert_usize(tcx)
                             } else {
                                 None
@@ -231,15 +231,15 @@ fn check_and_patch<'tcx>(candidate: Location,
         if opt_size.is_some() && items.iter().all(
             |l| l.is_some() && l.unwrap().2 == opt_src_place.unwrap()) {
 
-            let indicies: Vec<_> = items.iter().map(|x| x.unwrap().1).collect();
-            for i in 1..indicies.len() {
-                if indicies[i - 1] + 1 != indicies[i] {
+            let indices: Vec<_> = items.iter().map(|x| x.unwrap().1).collect();
+            for i in 1..indices.len() {
+                if indices[i - 1] + 1 != indices[i] {
                     return;
                 }
             }
 
-            let min = *indicies.first().unwrap();
-            let max = *indicies.last().unwrap();
+            let min = *indices.first().unwrap();
+            let max = *indices.last().unwrap();
 
             for item in items {
                 let locals_use = item.unwrap().0;
index d1410210bda96e8653e7e09a1ec53397a8223daa..8717bd08ae4a5ba90c39340e3ecdf61649e4e687 100644 (file)
@@ -59,7 +59,7 @@ fn is_within_packed<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             ProjectionElem::Field(..) => {
                 let ty = base.ty(local_decls, tcx).to_ty(tcx);
                 match ty.sty {
-                    ty::TyAdt(def, _) if def.repr.packed() => {
+                    ty::Adt(def, _) if def.repr.packed() => {
                         return true
                     }
                     _ => {}
index 7be6241b3f91e153b386bde27727dbefdb0f8e24..b67780ccdbc10282d2cb654ff884e3bba319fc34 100644 (file)
@@ -425,8 +425,8 @@ fn cannot_move_out_of_interior_noncopy(
         o: Origin,
     ) -> DiagnosticBuilder<'cx> {
         let type_name = match (&ty.sty, is_index) {
-            (&ty::TyArray(_, _), Some(true)) | (&ty::TyArray(_, _), None) => "array",
-            (&ty::TySlice(_), _) => "slice",
+            (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array",
+            (&ty::Slice(_), _) => "slice",
             _ => span_bug!(move_from_span, "this path should not cause illegal move"),
         };
         let mut err = struct_span_err!(
@@ -474,7 +474,7 @@ fn cannot_act_on_moved_value(
     ) -> DiagnosticBuilder<'cx> {
         let moved_path = moved_path
             .map(|mp| format!(": `{}`", mp))
-            .unwrap_or("".to_owned());
+            .unwrap_or(String::new());
 
         let err = struct_span_err!(
             self,
index bbffeec631abd3c72dab7bf96765798d712aa461..1c0c98d621c83325a97b53ded27c6d31d9cb5afa 100644 (file)
@@ -562,7 +562,7 @@ fn destructor_call_block<'a>(&mut self, (succ, unwind): (BasicBlock, Unwind))
     ///    if can_go then succ else drop-block
     /// drop-block:
     ///    if ptr_based {
-    ///        ptr = cur
+    ///        ptr = &mut *cur
     ///        cur = cur.offset(1)
     ///    } else {
     ///        ptr = &mut P[cur]
@@ -591,7 +591,14 @@ fn drop_loop(&mut self,
 
         let one = self.constant_usize(1);
         let (ptr_next, cur_next) = if ptr_based {
-            (Rvalue::Use(copy(&Place::Local(cur))),
+            (Rvalue::Ref(
+                tcx.types.re_erased,
+                BorrowKind::Mut { allow_two_phase_borrow: false },
+                Place::Projection(Box::new(Projection {
+                    base: Place::Local(cur),
+                    elem: ProjectionElem::Deref,
+                }))
+             ),
              Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Local(cur)), one))
         } else {
             (Rvalue::Ref(
@@ -736,7 +743,7 @@ fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock {
         if ptr_based {
             let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place));
             let tmp = Place::Local(self.new_temp(tmp_ty));
-            // tmp = &P;
+            // tmp = &mut P;
             // cur = tmp as *mut T;
             // end = Offset(cur, len);
             drop_block_stmts.push(self.assign(&tmp, Rvalue::Ref(
@@ -780,7 +787,7 @@ fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock {
     fn open_drop<'a>(&mut self) -> BasicBlock {
         let ty = self.place_ty(self.place);
         match ty.sty {
-            ty::TyClosure(def_id, substs) => {
+            ty::Closure(def_id, substs) => {
                 let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect();
                 self.open_drop_for_tuple(&tys)
             }
@@ -790,30 +797,30 @@ fn open_drop<'a>(&mut self) -> BasicBlock {
             // This should only happen for the self argument on the resume function.
             // It effetively only contains upvars until the generator transformation runs.
             // See librustc_mir/transform/generator.rs for more details.
-            ty::TyGenerator(def_id, substs, _) => {
+            ty::Generator(def_id, substs, _) => {
                 let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect();
                 self.open_drop_for_tuple(&tys)
             }
-            ty::TyTuple(tys) => {
+            ty::Tuple(tys) => {
                 self.open_drop_for_tuple(tys)
             }
-            ty::TyAdt(def, substs) => {
+            ty::Adt(def, substs) => {
                 if def.is_box() {
                     self.open_drop_for_box(def, substs)
                 } else {
                     self.open_drop_for_adt(def, substs)
                 }
             }
-            ty::TyDynamic(..) => {
+            ty::Dynamic(..) => {
                 let unwind = self.unwind; // FIXME(#43234)
                 let succ = self.succ;
                 self.complete_drop(Some(DropFlagMode::Deep), succ, unwind)
             }
-            ty::TyArray(ety, size) => {
+            ty::Array(ety, size) => {
                 let size = size.assert_usize(self.tcx());
                 self.open_drop_for_array(ety, size)
             },
-            ty::TySlice(ety) => self.open_drop_for_array(ety, None),
+            ty::Slice(ety) => self.open_drop_for_array(ety, None),
 
             _ => bug!("open drop from non-ADT `{:?}`", ty)
         }
@@ -962,6 +969,7 @@ fn constant_usize(&self, val: u16) -> Operand<'tcx> {
         Operand::Constant(box Constant {
             span: self.source_info.span,
             ty: self.tcx().types.usize,
+            user_ty: None,
             literal: ty::Const::from_usize(self.tcx(), val.into()),
         })
     }
index 6c5b38a806e57b1a9ec8426297741fb0b34cbd3f..3ae470e1d4bbd113f00d04297b60629c352804aa 100644 (file)
 //! generator yield points, all pre-existing references are invalidated, so this
 //! doesn't matter).
 
-use rustc::mir::visit::MirVisitable;
 use rustc::mir::visit::{PlaceContext, Visitor};
 use rustc::mir::Local;
 use rustc::mir::*;
 use rustc::ty::{item_path, TyCtxt};
-use rustc_data_structures::indexed_set::IdxSetBuf;
+use rustc_data_structures::indexed_set::IdxSet;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::work_queue::WorkQueue;
 use std::fs;
 use transform::MirSource;
 use util::pretty::{dump_enabled, write_basic_block, write_mir_intro};
 
-pub type LiveVarSet<V> = IdxSetBuf<V>;
+pub type LiveVarSet<V> = IdxSet<V>;
 
 /// This gives the result of the liveness analysis at the boundary of
-/// basic blocks. You can use `simulate_block` to obtain the
-/// intra-block results.
+/// basic blocks.
 ///
 /// The `V` type defines the set of variables that we computed
 /// liveness for. This is often `Local`, in which case we computed
 /// liveness for all variables -- but it can also be some other type,
 /// which indicates a subset of the variables within the graph.
 pub struct LivenessResult<V: Idx> {
-    /// Liveness mode in use when these results were computed.
-    pub mode: LivenessMode,
-
     /// Live variables on exit to each basic block. This is equal to
     /// the union of the `ins` for each successor.
     pub outs: IndexVec<BasicBlock, LiveVarSet<V>>,
@@ -104,68 +99,11 @@ fn num_variables(&self) -> usize {
     }
 }
 
-#[derive(Copy, Clone, Debug)]
-pub struct LivenessMode {
-    /// If true, then we will consider "regular uses" of a variable to be live.
-    /// For example, if the user writes `foo(x)`, then this is a regular use of
-    /// the variable `x`.
-    pub include_regular_use: bool,
-
-    /// If true, then we will consider (implicit) drops of a variable
-    /// to be live.  For example, if the user writes `{ let x =
-    /// vec![...]; .. }`, then the drop at the end of the block is an
-    /// implicit drop.
-    ///
-    /// NB. Despite its name, a call like `::std::mem::drop(x)` is
-    /// **not** considered a drop for this purposes, but rather a
-    /// regular use.
-    pub include_drops: bool,
-}
-
-/// A combination of liveness results, used in NLL.
-pub struct LivenessResults<V: Idx> {
-    /// Liveness results where a regular use makes a variable X live,
-    /// but not a drop.
-    pub regular: LivenessResult<V>,
-
-    /// Liveness results where a drop makes a variable X live,
-    /// but not a regular use.
-    pub drop: LivenessResult<V>,
-}
-
-impl<V: Idx> LivenessResults<V> {
-    pub fn compute<'tcx>(
-        mir: &Mir<'tcx>,
-        map: &impl LiveVariableMap<LiveVar = V>,
-    ) -> LivenessResults<V> {
-        LivenessResults {
-            regular: liveness_of_locals(
-                &mir,
-                LivenessMode {
-                    include_regular_use: true,
-                    include_drops: false,
-                },
-                map,
-            ),
-
-            drop: liveness_of_locals(
-                &mir,
-                LivenessMode {
-                    include_regular_use: false,
-                    include_drops: true,
-                },
-                map,
-            ),
-        }
-    }
-}
-
 /// Compute which local variables are live within the given function
 /// `mir`. The liveness mode `mode` determines what sorts of uses are
 /// considered to make a variable live (e.g., do drops count?).
 pub fn liveness_of_locals<'tcx, V: Idx>(
     mir: &Mir<'tcx>,
-    mode: LivenessMode,
     map: &impl LiveVariableMap<LiveVar = V>,
 ) -> LivenessResult<V> {
     let num_live_vars = map.num_variables();
@@ -173,7 +111,7 @@ pub fn liveness_of_locals<'tcx, V: Idx>(
     let def_use: IndexVec<_, DefsUses<V>> = mir
         .basic_blocks()
         .iter()
-        .map(|b| block(mode, map, b, num_live_vars))
+        .map(|b| block(map, b, num_live_vars))
         .collect();
 
     let mut outs: IndexVec<_, LiveVarSet<V>> = mir
@@ -208,80 +146,17 @@ pub fn liveness_of_locals<'tcx, V: Idx>(
         }
     }
 
-    LivenessResult { mode, outs }
-}
-
-impl<V: Idx> LivenessResult<V> {
-    /// Walks backwards through the statements/terminator in the given
-    /// basic block `block`.  At each point within `block`, invokes
-    /// the callback `op` with the current location and the set of
-    /// variables that are live on entry to that location.
-    pub fn simulate_block<'tcx, OP>(
-        &self,
-        mir: &Mir<'tcx>,
-        block: BasicBlock,
-        map: &impl LiveVariableMap<LiveVar = V>,
-        mut callback: OP,
-    ) where
-        OP: FnMut(Location, &LiveVarSet<V>),
-    {
-        let data = &mir[block];
-
-        // Get a copy of the bits on exit from the block.
-        let mut bits = self.outs[block].clone();
-
-        // Start with the maximal statement index -- i.e., right before
-        // the terminator executes.
-        let mut statement_index = data.statements.len();
-
-        // Compute liveness right before terminator and invoke callback.
-        let terminator_location = Location {
-            block,
-            statement_index,
-        };
-        let num_live_vars = map.num_variables();
-        let mut visitor = DefsUsesVisitor {
-            mode: self.mode,
-            map,
-            defs_uses: DefsUses {
-                defs: LiveVarSet::new_empty(num_live_vars),
-                uses: LiveVarSet::new_empty(num_live_vars),
-            },
-        };
-        // Visit the various parts of the basic block in reverse. If we go
-        // forward, the logic in `add_def` and `add_use` would be wrong.
-        visitor.update_bits_and_do_callback(
-            terminator_location,
-            &data.terminator,
-            &mut bits,
-            &mut callback,
-        );
-
-        // Compute liveness before each statement (in rev order) and invoke callback.
-        for statement in data.statements.iter().rev() {
-            statement_index -= 1;
-            let statement_location = Location {
-                block,
-                statement_index,
-            };
-            visitor.defs_uses.clear();
-            visitor.update_bits_and_do_callback(
-                statement_location,
-                statement,
-                &mut bits,
-                &mut callback,
-            );
-        }
-    }
+    LivenessResult { outs }
 }
 
 #[derive(Eq, PartialEq, Clone)]
 pub enum DefUse {
     Def,
     Use,
+    Drop,
 }
 
-pub fn categorize<'tcx>(context: PlaceContext<'tcx>, mode: LivenessMode) -> Option<DefUse> {
+pub fn categorize<'tcx>(context: PlaceContext<'tcx>) -> Option<DefUse> {
     match context {
         ///////////////////////////////////////////////////////////////////////////
         // DEFS
@@ -322,13 +197,8 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>, mode: LivenessMode) -> Opti
         PlaceContext::Inspect |
         PlaceContext::Copy |
         PlaceContext::Move |
-        PlaceContext::Validate => {
-            if mode.include_regular_use {
-                Some(DefUse::Use)
-            } else {
-                None
-            }
-        }
+        PlaceContext::Validate =>
+            Some(DefUse::Use),
 
         ///////////////////////////////////////////////////////////////////////////
         // DROP USES
@@ -338,13 +208,8 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>, mode: LivenessMode) -> Opti
         // uses in drop are special because `#[may_dangle]`
         // attributes can affect whether lifetimes must be live.
 
-        PlaceContext::Drop => {
-            if mode.include_drops {
-                Some(DefUse::Use)
-            } else {
-                None
-            }
-        }
+        PlaceContext::Drop =>
+            Some(DefUse::Drop),
     }
 }
 
@@ -353,7 +218,6 @@ struct DefsUsesVisitor<'lv, V, M>
     V: Idx,
     M: LiveVariableMap<LiveVar = V> + 'lv,
 {
-    mode: LivenessMode,
     map: &'lv M,
     defs_uses: DefsUses<V>,
 }
@@ -365,11 +229,6 @@ struct DefsUses<V: Idx> {
 }
 
 impl<V: Idx> DefsUses<V> {
-    fn clear(&mut self) {
-        self.uses.clear();
-        self.defs.clear();
-    }
-
     fn apply(&self, bits: &mut LiveVarSet<V>) -> bool {
         bits.subtract(&self.defs) | bits.union(&self.uses)
     }
@@ -404,29 +263,6 @@ fn add_use(&mut self, index: V) {
     }
 }
 
-impl<'lv, V, M> DefsUsesVisitor<'lv, V, M>
-where
-    V: Idx,
-    M: LiveVariableMap<LiveVar = V>,
-{
-    /// Update `bits` with the effects of `value` and call `callback`. We
-    /// should always visit in reverse order. This method assumes that we have
-    /// not visited anything before; if you have, clear `bits` first.
-    fn update_bits_and_do_callback<'tcx, OP>(
-        &mut self,
-        location: Location,
-        value: &impl MirVisitable<'tcx>,
-        bits: &mut LiveVarSet<V>,
-        callback: &mut OP,
-    ) where
-        OP: FnMut(Location, &LiveVarSet<V>),
-    {
-        value.apply(location, self);
-        self.defs_uses.apply(bits);
-        callback(location, bits);
-    }
-}
-
 impl<'tcx, 'lv, V, M> Visitor<'tcx> for DefsUsesVisitor<'lv, V, M>
 where
     V: Idx,
@@ -434,23 +270,21 @@ impl<'tcx, 'lv, V, M> Visitor<'tcx> for DefsUsesVisitor<'lv, V, M>
 {
     fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) {
         if let Some(v_index) = self.map.from_local(local) {
-            match categorize(context, self.mode) {
+            match categorize(context) {
                 Some(DefUse::Def) => self.defs_uses.add_def(v_index),
-                Some(DefUse::Use) => self.defs_uses.add_use(v_index),
-                None => (),
+                Some(DefUse::Use) | Some(DefUse::Drop) => self.defs_uses.add_use(v_index),
+                _ => (),
             }
         }
     }
 }
 
 fn block<'tcx, V: Idx>(
-    mode: LivenessMode,
     map: &impl LiveVariableMap<LiveVar = V>,
     b: &BasicBlockData<'tcx>,
     locals: usize,
 ) -> DefsUses<V> {
     let mut visitor = DefsUsesVisitor {
-        mode,
         map,
         defs_uses: DefsUses {
             defs: LiveVarSet::new_empty(locals),
@@ -526,7 +360,8 @@ pub fn write_mir_fn<'a, 'tcx, V: Idx>(
     write_mir_intro(tcx, src, mir, w)?;
     for block in mir.basic_blocks().indices() {
         let print = |w: &mut dyn Write, prefix, result: &IndexVec<BasicBlock, LiveVarSet<V>>| {
-            let live: Vec<String> = result[block].iter()
+            let live: Vec<String> = result[block]
+                .iter()
                 .map(|v| map.from_live_var(v))
                 .map(|local| format!("{:?}", local))
                 .collect();
index df975998edcf8f6b400e898d3e1be8b377d0bc15..e0643d8f978103a1a3a91dc707e6011ca44bc3ab 100644 (file)
@@ -140,7 +140,7 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(
 ) where
     F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
 {
-    let _: io::Result<()> = do catch {
+    let _: io::Result<()> = try_block! {
         let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?;
         writeln!(file, "// MIR for `{}`", node_path)?;
         writeln!(file, "// source = {:?}", source)?;
@@ -156,7 +156,7 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(
     };
 
     if tcx.sess.opts.debugging_opts.dump_mir_graphviz {
-        let _: io::Result<()> = do catch {
+        let _: io::Result<()> = try_block! {
             let mut file =
                 create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, source)?;
             write_mir_fn_graphviz(tcx, source.def_id, mir, &mut file)?;
@@ -397,10 +397,13 @@ fn push(&mut self, lines: &str) {
 impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ExtraComments<'cx, 'gcx, 'tcx> {
     fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
         self.super_constant(constant, location);
-        let Constant { span, ty, literal } = constant;
+        let Constant { span, ty, user_ty, literal } = constant;
         self.push("mir::Constant");
         self.push(&format!("+ span: {:?}", span));
         self.push(&format!("+ ty: {:?}", ty));
+        if let Some(user_ty) = user_ty {
+            self.push(&format!("+ user_ty: {:?}", user_ty));
+        }
         self.push(&format!("+ literal: {:?}", literal));
     }
 
@@ -429,6 +432,11 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                     self.push(&format!("+ movability: {:?}", movability));
                 }
 
+                AggregateKind::Adt(_, _, _, Some(user_ty), _) => {
+                    self.push("adt");
+                    self.push(&format!("+ user_ty: {:?}", user_ty));
+                }
+
                 _ => {}
             },
 
@@ -459,7 +467,7 @@ fn write_scope_tree(
     let indent = depth * INDENT.len();
 
     let children = match scope_tree.get(&parent) {
-        Some(childs) => childs,
+        Some(children) => children,
         None => return Ok(()),
     };
 
index b3ba86ad8a4b32af8f7f6629cca53f8891221b8f..ed8fd305977e5e9b7a71359411211774d4d81420 100644 (file)
@@ -11,6 +11,7 @@
 #![sanitizer_runtime]
 #![feature(alloc_system)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(sanitizer_runtime)]
 #![feature(staged_api)]
 #![no_std]
index 11d1d85c97d394a2d7bd44cd7aa933d1f02de0ba..bca119660aa2a4e93a9dd14768fa1d64b0dd2032 100644 (file)
@@ -25,6 +25,7 @@
 use syntax::visit::{self, Visitor};
 use syntax_pos::Span;
 use errors;
+use errors::Applicability;
 
 struct AstValidator<'a> {
     session: &'a Session,
@@ -185,11 +186,12 @@ fn visit_expr(&mut self, expr: &'a Expr) {
                 );
                 match val.node {
                     ExprKind::Lit(ref v) if v.node.is_numeric() => {
-                        err.span_suggestion(
+                        err.span_suggestion_with_applicability(
                             place.span.between(val.span),
                             "if you meant to write a comparison against a negative value, add a \
                              space in between `<` and `-`",
                             "< -".to_string(),
+                            Applicability::MaybeIncorrect
                         );
                     }
                     _ => {}
index d62cb00923f7047411ff3a17d5da3886d33d6ea9..94ea229cbd91ba03f01697adc3057d2f81322390 100644 (file)
@@ -19,6 +19,7 @@
        html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(rustc_diagnostic_macros)]
 
 #[macro_use]
index 8ef20126e035fdb48dc88d3584f0e18598d13600..44030c284fd812227b8d550e7e8a4aafd60ae62b 100644 (file)
@@ -13,7 +13,7 @@
 
 use rustc::hir::map::Map;
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
-use rustc::hir::{self, Destination};
+use rustc::hir::{self, Node, Destination};
 use syntax::ast;
 use syntax_pos::Span;
 
@@ -115,7 +115,7 @@ fn visit_expr(&mut self, e: &'hir hir::Expr) {
 
                 if loop_id != ast::DUMMY_NODE_ID {
                     match self.hir_map.find(loop_id).unwrap() {
-                        hir::map::NodeBlock(_) => return,
+                        Node::Block(_) => return,
                         _=> (),
                     }
                 }
@@ -158,7 +158,7 @@ fn visit_expr(&mut self, e: &'hir hir::Expr) {
 
                 match label.target_id {
                     Ok(loop_id) => {
-                        if let hir::map::NodeBlock(block) = self.hir_map.find(loop_id).unwrap() {
+                        if let Node::Block(block) = self.hir_map.find(loop_id).unwrap() {
                             struct_span_err!(self.sess, e.span, E0696,
                                             "`continue` pointing to a labeled block")
                                 .span_label(e.span,
index 864d9e1a16f069adcf1c3ccde9ebc6a93fc2db86..ea4fba3e1248182af89e6b6b99149195c9045e0e 100644 (file)
@@ -178,9 +178,7 @@ fn handle_const_fn_call(&mut self, def_id: DefId,
         }
 
         if let Some(&attr::Stability {
-            rustc_const_unstable: Some(attr::RustcConstUnstable {
-                                           feature: ref feature_name
-                                       }),
+            const_stability: Some(ref feature_name),
             .. }) = self.tcx.lookup_stability(def_id) {
             let stable_check =
                 // feature-gate is enabled,
@@ -189,9 +187,6 @@ fn handle_const_fn_call(&mut self, def_id: DefId,
                     .iter()
                     .any(|&(ref sym, _)| sym == feature_name) ||
 
-                    // this comes from a crate with the feature-gate enabled,
-                    !def_id.is_local() ||
-
                     // this comes from a macro that has #[allow_internal_unstable]
                     span.allows_unstable();
             if !stable_check {
@@ -328,7 +323,7 @@ fn check_expr_kind<'a, 'tcx>(
     e: &'tcx hir::Expr, node_ty: Ty<'tcx>) -> Promotability {
 
     let ty_result = match node_ty.sty {
-        ty::TyAdt(def, _) if def.has_dtor(v.tcx) => {
+        ty::Adt(def, _) if def.has_dtor(v.tcx) => {
             NotPromotable
         }
         _ => Promotable
@@ -356,7 +351,7 @@ fn check_expr_kind<'a, 'tcx>(
                 return NotPromotable;
             }
             match v.tables.node_id_to_type(lhs.hir_id).sty {
-                ty::TyRawPtr(_) => {
+                ty::RawPtr(_) => {
                     assert!(op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne ||
                         op.node == hir::BinOpKind::Le || op.node == hir::BinOpKind::Lt ||
                         op.node == hir::BinOpKind::Ge || op.node == hir::BinOpKind::Gt);
@@ -494,7 +489,7 @@ fn check_expr_kind<'a, 'tcx>(
                 Some(ref expr) => { struct_result = struct_result & v.check_expr(&expr); },
                 None => {},
             }
-            if let ty::TyAdt(adt, ..) = v.tables.expr_ty(e).sty {
+            if let ty::Adt(adt, ..) = v.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() {
                     return NotPromotable;
index d41f4cd61f763a5e95da78c570ab07690d55b7b0..f093d672498ad4b2483ad71133cb43b4a38cd852 100644 (file)
@@ -8,9 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(bad_style)]
+#![allow(nonstandard_style)]
 
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 
 pub struct Intrinsic {
     pub inputs: &'static [&'static Type],
index 67f53a67313f798f1f9d2979d9f57e0a949095af..5b56266638552490473463f22f13505052b0fdab 100644 (file)
@@ -65,6 +65,7 @@
        html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(rustc_diagnostic_macros)]
 
 #[macro_use] extern crate syntax;
index b1ab86674cf90fa74388effcfa7b49e6c403f3a3..6c10ac7ea5ceaf230f7b449f877237a37b9785ca 100644 (file)
@@ -12,6 +12,7 @@
 
 use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint};
 use rustc::session::Session;
+use rustc::util::nodemap::FxHashMap;
 
 use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT, IdentTT};
 use syntax::ext::base::MacroExpanderFn;
@@ -21,7 +22,6 @@
 use syntax::feature_gate::AttributeType;
 use syntax_pos::Span;
 
-use std::collections::HashMap;
 use std::borrow::ToOwned;
 
 /// Structure used to register plugins.
@@ -53,7 +53,7 @@ pub struct Registry<'a> {
     pub late_lint_passes: Vec<LateLintPassObject>,
 
     #[doc(hidden)]
-    pub lint_groups: HashMap<&'static str, Vec<LintId>>,
+    pub lint_groups: FxHashMap<&'static str, (Vec<LintId>, Option<&'static str>)>,
 
     #[doc(hidden)]
     pub llvm_passes: Vec<String>,
@@ -74,7 +74,7 @@ pub fn new(sess: &'a Session, krate_span: Span) -> Registry<'a> {
             syntax_exts: vec![],
             early_lint_passes: vec![],
             late_lint_passes: vec![],
-            lint_groups: HashMap::new(),
+            lint_groups: FxHashMap::default(),
             llvm_passes: vec![],
             attributes: vec![],
             whitelisted_custom_derives: Vec::new(),
@@ -170,8 +170,15 @@ pub fn register_late_lint_pass(&mut self, lint_pass: LateLintPassObject) {
         self.late_lint_passes.push(lint_pass);
     }
     /// Register a lint group.
-    pub fn register_lint_group(&mut self, name: &'static str, to: Vec<&'static Lint>) {
-        self.lint_groups.insert(name, to.into_iter().map(|x| LintId::of(x)).collect());
+    pub fn register_lint_group(
+        &mut self,
+        name: &'static str,
+        deprecated_name: Option<&'static str>,
+        to: Vec<&'static Lint>
+    ) {
+        self.lint_groups.insert(name,
+                                (to.into_iter().map(|x| LintId::of(x)).collect(),
+                                 deprecated_name));
     }
 
     /// Register an LLVM pass.
index d9c3fc221dce1c6b9deae099665e2ab3f76fded2..5166f69ba03304c49572d760cb514139184e2436 100644 (file)
@@ -13,6 +13,7 @@
        html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(rustc_diagnostic_macros)]
 
 #![recursion_limit="256"]
@@ -24,6 +25,7 @@
 extern crate rustc_data_structures;
 
 use rustc::hir::{self, PatKind};
+use hir::Node;
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
@@ -82,6 +84,7 @@ struct EmbargoVisitor<'a, 'tcx: 'a> {
 }
 
 struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> {
+    access_level: Option<AccessLevel>,
     item_def_id: DefId,
     ev: &'b mut EmbargoVisitor<'a, 'tcx>,
 }
@@ -89,11 +92,11 @@ struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> {
 impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
     fn item_ty_level(&self, item_def_id: DefId) -> Option<AccessLevel> {
         let ty_def_id = match self.tcx.type_of(item_def_id).sty {
-            ty::TyAdt(adt, _) => adt.did,
-            ty::TyForeign(did) => did,
-            ty::TyDynamic(ref obj, ..) if obj.principal().is_some() =>
+            ty::Adt(adt, _) => adt.did,
+            ty::Foreign(did) => did,
+            ty::Dynamic(ref obj, ..) if obj.principal().is_some() =>
                 obj.principal().unwrap().def_id(),
-            ty::TyProjection(ref proj) => proj.trait_ref(self.tcx).def_id,
+            ty::Projection(ref proj) => proj.trait_ref(self.tcx).def_id,
             _ => return Some(AccessLevel::Public)
         };
         if let Some(node_id) = self.tcx.hir.as_local_node_id(ty_def_id) {
@@ -132,6 +135,7 @@ fn update(&mut self, id: ast::NodeId, level: Option<AccessLevel>) -> Option<Acce
     fn reach<'b>(&'b mut self, item_id: ast::NodeId)
                  -> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
         ReachEverythingInTheInterfaceVisitor {
+            access_level: self.prev_level.map(|l| l.min(AccessLevel::Reachable)),
             item_def_id: self.tcx.hir.local_def_id(item_id),
             ev: self,
         }
@@ -214,7 +218,15 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                     }
                 }
             }
-            hir::ItemKind::Existential(..) |
+            // Impl trait return types mark their parent function.
+            // It (and its children) are revisited if the change applies.
+            hir::ItemKind::Existential(ref ty_data) => {
+                if let Some(impl_trait_fn) = ty_data.impl_trait_fn {
+                    if let Some(node_id) = self.tcx.hir.as_local_node_id(impl_trait_fn) {
+                        self.update(node_id, Some(AccessLevel::ReachableFromImplTrait));
+                    }
+                }
+            }
             hir::ItemKind::Use(..) |
             hir::ItemKind::Static(..) |
             hir::ItemKind::Const(..) |
@@ -226,6 +238,10 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             hir::ItemKind::ExternCrate(..) => {}
         }
 
+        // Store this node's access level here to propagate the correct
+        // reachability level through interfaces and children.
+        let orig_level = replace(&mut self.prev_level, item_level);
+
         // Mark all items in interfaces of reachable items as reachable
         match item.node {
             // The interface is empty
@@ -324,9 +340,6 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             }
         }
 
-        let orig_level = self.prev_level;
-        self.prev_level = item_level;
-
         intravisit::walk_item(self, item);
 
         self.prev_level = orig_level;
@@ -443,7 +456,7 @@ fn predicates(&mut self) -> &mut Self {
     fn ty(&mut self) -> &mut Self {
         let ty = self.ev.tcx.type_of(self.item_def_id);
         ty.visit_with(self);
-        if let ty::TyFnDef(def_id, _) = ty.sty {
+        if let ty::FnDef(def_id, _) = ty.sty {
             if def_id == self.item_def_id {
                 self.ev.tcx.fn_sig(def_id).visit_with(self);
             }
@@ -462,7 +475,7 @@ fn impl_trait_ref(&mut self) -> &mut Self {
     fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) {
         if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(trait_ref.def_id) {
             let item = self.ev.tcx.hir.expect_item(node_id);
-            self.ev.update(item.id, Some(AccessLevel::Reachable));
+            self.ev.update(item.id, self.access_level);
         }
     }
 }
@@ -470,20 +483,20 @@ fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) {
 impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
         let ty_def_id = match ty.sty {
-            ty::TyAdt(adt, _) => Some(adt.did),
-            ty::TyForeign(did) => Some(did),
-            ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()),
-            ty::TyProjection(ref proj) => Some(proj.item_def_id),
-            ty::TyFnDef(def_id, ..) |
-            ty::TyClosure(def_id, ..) |
-            ty::TyGenerator(def_id, ..) |
-            ty::TyAnon(def_id, _) => Some(def_id),
+            ty::Adt(adt, _) => Some(adt.did),
+            ty::Foreign(did) => Some(did),
+            ty::Dynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()),
+            ty::Projection(ref proj) => Some(proj.item_def_id),
+            ty::FnDef(def_id, ..) |
+            ty::Closure(def_id, ..) |
+            ty::Generator(def_id, ..) |
+            ty::Anon(def_id, _) => Some(def_id),
             _ => None
         };
 
         if let Some(def_id) = ty_def_id {
             if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(def_id) {
-                self.ev.update(node_id, Some(AccessLevel::Reachable));
+                self.ev.update(node_id, self.access_level);
             }
         }
 
@@ -647,17 +660,17 @@ fn def_id_visibility(&self, did: DefId) -> ty::Visibility {
         match self.tcx.hir.as_local_node_id(did) {
             Some(node_id) => {
                 let vis = match self.tcx.hir.get(node_id) {
-                    hir::map::NodeItem(item) => &item.vis,
-                    hir::map::NodeForeignItem(foreign_item) => &foreign_item.vis,
-                    hir::map::NodeImplItem(impl_item) => &impl_item.vis,
-                    hir::map::NodeTraitItem(..) |
-                    hir::map::NodeVariant(..) => {
+                    Node::Item(item) => &item.vis,
+                    Node::ForeignItem(foreign_item) => &foreign_item.vis,
+                    Node::ImplItem(impl_item) => &impl_item.vis,
+                    Node::TraitItem(..) |
+                    Node::Variant(..) => {
                         return self.def_id_visibility(self.tcx.hir.get_parent_did(node_id));
                     }
-                    hir::map::NodeStructCtor(vdata) => {
+                    Node::StructCtor(vdata) => {
                         let struct_node_id = self.tcx.hir.get_parent(node_id);
                         let struct_vis = match self.tcx.hir.get(struct_node_id) {
-                            hir::map::NodeItem(item) => &item.vis,
+                            Node::Item(item) => &item.vis,
                             node => bug!("unexpected node kind: {:?}", node),
                         };
                         let mut ctor_vis
@@ -896,15 +909,15 @@ fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
 impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
         match ty.sty {
-            ty::TyAdt(&ty::AdtDef { did: def_id, .. }, ..) |
-            ty::TyFnDef(def_id, ..) |
-            ty::TyForeign(def_id) => {
+            ty::Adt(&ty::AdtDef { did: def_id, .. }, ..) |
+            ty::FnDef(def_id, ..) |
+            ty::Foreign(def_id) => {
                 if !self.item_is_accessible(def_id) {
                     let msg = format!("type `{}` is private", ty);
                     self.tcx.sess.span_err(self.span, &msg);
                     return true;
                 }
-                if let ty::TyFnDef(..) = ty.sty {
+                if let ty::FnDef(..) = ty.sty {
                     if self.tcx.fn_sig(def_id).visit_with(self) {
                         return true;
                     }
@@ -919,7 +932,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                     }
                 }
             }
-            ty::TyDynamic(ref predicates, ..) => {
+            ty::Dynamic(ref predicates, ..) => {
                 let is_private = predicates.skip_binder().iter().any(|predicate| {
                     let def_id = match *predicate {
                         ty::ExistentialPredicate::Trait(trait_ref) => trait_ref.def_id,
@@ -935,13 +948,13 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                     return true;
                 }
             }
-            ty::TyProjection(ref proj) => {
+            ty::Projection(ref proj) => {
                 let tcx = self.tcx;
                 if self.check_trait_ref(proj.trait_ref(tcx)) {
                     return true;
                 }
             }
-            ty::TyAnon(def_id, ..) => {
+            ty::Anon(def_id, ..) => {
                 for predicate in &self.tcx.predicates_of(def_id).predicates {
                     let trait_ref = match *predicate {
                         ty::Predicate::Trait(ref poly_trait_predicate) => {
@@ -964,9 +977,9 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                             return true;
                         }
                         for subst in trait_ref.substs.iter() {
-                            // Skip repeated `TyAnon`s to avoid infinite recursion.
+                            // Skip repeated `Anon`s to avoid infinite recursion.
                             if let UnpackedKind::Type(ty) = subst.unpack() {
-                                if let ty::TyAnon(def_id, ..) = ty.sty {
+                                if let ty::Anon(def_id, ..) = ty.sty {
                                     if !self.visited_anon_tys.insert(def_id) {
                                         continue;
                                     }
@@ -1025,7 +1038,7 @@ fn path_is_private_type(&self, path: &hir::Path) -> bool {
             // .. and it corresponds to a private type in the AST (this returns
             // None for type parameters)
             match self.tcx.hir.find(node_id) {
-                Some(hir::map::NodeItem(ref item)) => !item.vis.node.is_pub(),
+                Some(Node::Item(ref item)) => !item.vis.node.is_pub(),
                 Some(_) | None => false,
             }
         } else {
@@ -1388,7 +1401,7 @@ fn predicates(&mut self) -> &mut Self {
     fn ty(&mut self) -> &mut Self {
         let ty = self.tcx.type_of(self.item_def_id);
         ty.visit_with(self);
-        if let ty::TyFnDef(def_id, _) = ty.sty {
+        if let ty::FnDef(def_id, _) = ty.sty {
             if def_id == self.item_def_id {
                 self.tcx.fn_sig(def_id).visit_with(self);
             }
@@ -1434,10 +1447,10 @@ fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) {
 impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
         let ty_def_id = match ty.sty {
-            ty::TyAdt(adt, _) => Some(adt.did),
-            ty::TyForeign(did) => Some(did),
-            ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()),
-            ty::TyProjection(ref proj) => {
+            ty::Adt(adt, _) => Some(adt.did),
+            ty::Foreign(did) => Some(did),
+            ty::Dynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()),
+            ty::Projection(ref proj) => {
                 if self.required_visibility == ty::Visibility::Invisible {
                     // Conservatively approximate the whole type alias as public without
                     // recursing into its components when determining impl publicity.
@@ -1457,8 +1470,8 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
             // Non-local means public (private items can't leave their crate, modulo bugs)
             if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
                 let hir_vis = match self.tcx.hir.find(node_id) {
-                    Some(hir::map::NodeItem(item)) => &item.vis,
-                    Some(hir::map::NodeForeignItem(item)) => &item.vis,
+                    Some(Node::Item(item)) => &item.vis,
+                    Some(Node::ForeignItem(item)) => &item.vis,
                     _ => bug!("expected item of foreign item"),
                 };
 
index 19dc35f854eed5bbf6a05f977e11f7b77c0bbfe3..80f6c263e199969648d80321edbe79fb49ad4612 100644 (file)
@@ -656,7 +656,7 @@ fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, expansion
                 (Def::Static(self.definitions.local_def_id(item.id), m), ValueNS)
             }
             ForeignItemKind::Ty => {
-                (Def::TyForeign(self.definitions.local_def_id(item.id)), TypeNS)
+                (Def::ForeignTy(self.definitions.local_def_id(item.id)), TypeNS)
             }
             ForeignItemKind::Macro(_) => unreachable!(),
         };
@@ -692,7 +692,7 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, chi
                                              span);
                 self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
             }
-            Def::Variant(..) | Def::TyAlias(..) | Def::TyForeign(..) => {
+            Def::Variant(..) | Def::TyAlias(..) | Def::ForeignTy(..) => {
                 self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
             }
             Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => {
index 96df0cbfc07c7956c99c1c90ed124323cfff1d2c..0f6a97423091796dc83d97866b4a8d238c99f4bc 100644 (file)
@@ -14,6 +14,7 @@
 
 #![feature(crate_visibility_modifier)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
 
@@ -35,7 +36,7 @@
 use self::RibKind::*;
 
 use rustc::hir::map::{Definitions, DefCollector};
-use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr};
+use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str};
 use rustc::middle::cstore::CrateStore;
 use rustc::session::Session;
 use rustc::lint;
@@ -69,7 +70,7 @@
 use syntax::ptr::P;
 
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
-use errors::{DiagnosticBuilder, DiagnosticId};
+use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 
 use std::cell::{Cell, RefCell};
 use std::cmp;
@@ -80,7 +81,7 @@
 use rustc_data_structures::sync::Lrc;
 
 use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
-use macros::{InvocationData, LegacyBinding, MacroBinding};
+use macros::{InvocationData, LegacyBinding};
 
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
@@ -201,7 +202,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                     if let Some(impl_span) = maybe_impl_defid.map_or(None,
                             |def_id| resolver.definitions.opt_span(def_id)) {
                         err.span_label(reduce_impl_span_to_impl_keyword(cm, impl_span),
-                                    "`Self` type implicitely declared here, on the `impl`");
+                                    "`Self` type implicitly declared here, on the `impl`");
                     }
                 },
                 Def::TyParam(typaram_defid) => {
@@ -220,9 +221,12 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
             let sugg_msg = "try using a local type parameter instead";
             if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
                 // Suggest the modification to the user
-                err.span_suggestion(sugg_span,
-                                    sugg_msg,
-                                    new_snippet);
+                err.span_suggestion_with_applicability(
+                    sugg_span,
+                    sugg_msg,
+                    new_snippet,
+                    Applicability::MachineApplicable,
+                );
             } else if let Some(sp) = cm.generate_fn_name_span(span) {
                 err.span_label(sp, "try adding a local type parameter in this method instead");
             } else {
@@ -539,7 +543,7 @@ fn is_expected(self, def: Def) -> bool {
                 Def::Trait(..) | Def::TyAlias(..) | Def::AssociatedTy(..) |
                 Def::PrimTy(..) | Def::TyParam(..) | Def::SelfTy(..) |
                 Def::Existential(..) |
-                Def::TyForeign(..) => true,
+                Def::ForeignTy(..) => true,
                 _ => false,
             },
             PathSource::Trait(AliasPossibility::No) => match def {
@@ -1280,23 +1284,23 @@ impl PrimitiveTypeTable {
     fn new() -> PrimitiveTypeTable {
         let mut table = PrimitiveTypeTable { primitive_types: FxHashMap() };
 
-        table.intern("bool", TyBool);
-        table.intern("char", TyChar);
-        table.intern("f32", TyFloat(FloatTy::F32));
-        table.intern("f64", TyFloat(FloatTy::F64));
-        table.intern("isize", TyInt(IntTy::Isize));
-        table.intern("i8", TyInt(IntTy::I8));
-        table.intern("i16", TyInt(IntTy::I16));
-        table.intern("i32", TyInt(IntTy::I32));
-        table.intern("i64", TyInt(IntTy::I64));
-        table.intern("i128", TyInt(IntTy::I128));
-        table.intern("str", TyStr);
-        table.intern("usize", TyUint(UintTy::Usize));
-        table.intern("u8", TyUint(UintTy::U8));
-        table.intern("u16", TyUint(UintTy::U16));
-        table.intern("u32", TyUint(UintTy::U32));
-        table.intern("u64", TyUint(UintTy::U64));
-        table.intern("u128", TyUint(UintTy::U128));
+        table.intern("bool", Bool);
+        table.intern("char", Char);
+        table.intern("f32", Float(FloatTy::F32));
+        table.intern("f64", Float(FloatTy::F64));
+        table.intern("isize", Int(IntTy::Isize));
+        table.intern("i8", Int(IntTy::I8));
+        table.intern("i16", Int(IntTy::I16));
+        table.intern("i32", Int(IntTy::I32));
+        table.intern("i64", Int(IntTy::I64));
+        table.intern("i128", Int(IntTy::I128));
+        table.intern("str", Str);
+        table.intern("usize", Uint(UintTy::Usize));
+        table.intern("u8", Uint(UintTy::U8));
+        table.intern("u16", Uint(UintTy::U16));
+        table.intern("u32", Uint(UintTy::U32));
+        table.intern("u64", Uint(UintTy::U64));
+        table.intern("u128", Uint(UintTy::U128));
         table
     }
 
@@ -1399,7 +1403,7 @@ pub struct Resolver<'a, 'b: 'a> {
     proc_mac_errors: Vec<macros::ProcMacError>,
     /// crate-local macro expanded `macro_export` referred to by a module-relative path
     macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>,
-
+    /// macro-expanded `macro_rules` shadowing existing macros
     disallowed_shadowing: Vec<&'a LegacyBinding<'a>>,
 
     arenas: &'a ResolverArenas<'a>,
@@ -1901,12 +1905,13 @@ fn resolve_ident_in_lexical_scope(&mut self,
         }
 
         ident.span = ident.span.modern();
+        let mut poisoned = None;
         loop {
-            let (opt_module, poisoned) = if let Some(node_id) = record_used_id {
+            let opt_module = if let Some(node_id) = record_used_id {
                 self.hygienic_lexical_parent_with_compatibility_fallback(module, &mut ident.span,
-                                                                         node_id)
+                                                                         node_id, &mut poisoned)
             } else {
-                (self.hygienic_lexical_parent(module, &mut ident.span), None)
+                self.hygienic_lexical_parent(module, &mut ident.span)
             };
             module = unwrap_or!(opt_module, break);
             let orig_current_module = self.current_module;
@@ -1934,7 +1939,6 @@ fn resolve_ident_in_lexical_scope(&mut self,
                     }
                     return Some(LexicalScopeBinding::Item(binding))
                 }
-                _ if poisoned.is_some() => break,
                 Err(Determined) => continue,
                 Err(Undetermined) =>
                     span_bug!(ident.span, "undetermined resolution during main resolution pass"),
@@ -1951,9 +1955,7 @@ fn resolve_ident_in_lexical_scope(&mut self,
                                 "access to extern crates through prelude is experimental").emit();
                 }
 
-                let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span);
-                let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
-                self.populate_module_if_necessary(crate_root);
+                let crate_root = self.load_extern_prelude_crate_if_needed(ident);
 
                 let binding = (crate_root, ty::Visibility::Public,
                                ident.span, Mark::root()).to_name_binding(self.arenas);
@@ -1981,6 +1983,13 @@ fn resolve_ident_in_lexical_scope(&mut self,
         None
     }
 
+    fn load_extern_prelude_crate_if_needed(&mut self, ident: Ident) -> Module<'a> {
+        let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span);
+        let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
+        self.populate_module_if_necessary(&crate_root);
+        crate_root
+    }
+
     fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span)
                                -> Option<Module<'a>> {
         if !module.expansion.is_descendant_of(span.ctxt().outer()) {
@@ -1994,12 +2003,12 @@ fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span)
         None
     }
 
-    fn hygienic_lexical_parent_with_compatibility_fallback(
-        &mut self, module: Module<'a>, span: &mut Span, node_id: NodeId
-    ) -> (Option<Module<'a>>, /* poisoned */ Option<NodeId>)
-    {
+    fn hygienic_lexical_parent_with_compatibility_fallback(&mut self, module: Module<'a>,
+                                                           span: &mut Span, node_id: NodeId,
+                                                           poisoned: &mut Option<NodeId>)
+                                                           -> Option<Module<'a>> {
         if let module @ Some(..) = self.hygienic_lexical_parent(module, span) {
-            return (module, None);
+            return module;
         }
 
         // We need to support the next case under a deprecation warning
@@ -2020,13 +2029,14 @@ fn hygienic_lexical_parent_with_compatibility_fallback(
                 // The macro is a proc macro derive
                 if module.expansion.looks_like_proc_macro_derive() {
                     if parent.expansion.is_descendant_of(span.ctxt().outer()) {
-                        return (module.parent, Some(node_id));
+                        *poisoned = Some(node_id);
+                        return module.parent;
                     }
                 }
             }
         }
 
-        (None, None)
+        None
     }
 
     fn resolve_ident_in_module(&mut self,
@@ -3000,8 +3010,12 @@ fn smart_resolve_path_fragment(&mut self,
                                         enum_path);
                         err.help(&msg);
                     } else {
-                        err.span_suggestion(span, "you can try using the variant's enum",
-                                            enum_path);
+                        err.span_suggestion_with_applicability(
+                            span,
+                            "you can try using the variant's enum",
+                            enum_path,
+                            Applicability::MachineApplicable,
+                        );
                     }
                 }
             }
@@ -3010,20 +3024,32 @@ fn smart_resolve_path_fragment(&mut self,
                     let self_is_available = this.self_value_is_available(path[0].span, span);
                     match candidate {
                         AssocSuggestion::Field => {
-                            err.span_suggestion(span, "try",
-                                                format!("self.{}", path_str));
+                            err.span_suggestion_with_applicability(
+                                span,
+                                "try",
+                                format!("self.{}", path_str),
+                                Applicability::MachineApplicable,
+                            );
                             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_suggestion(span, "try",
-                                                format!("self.{}", path_str));
+                            err.span_suggestion_with_applicability(
+                                span,
+                                "try",
+                                format!("self.{}", path_str),
+                                Applicability::MachineApplicable,
+                            );
                         }
                         AssocSuggestion::MethodWithSelf | AssocSuggestion::AssocItem => {
-                            err.span_suggestion(span, "try",
-                                                format!("Self::{}", path_str));
+                            err.span_suggestion_with_applicability(
+                                span,
+                                "try",
+                                format!("Self::{}", path_str),
+                                Applicability::MachineApplicable,
+                            );
                         }
                     }
                     return (err, candidates);
@@ -3532,7 +3558,7 @@ fn resolve_path(
             } else if opt_ns == Some(MacroNS) {
                 assert!(ns == TypeNS);
                 self.resolve_lexical_macro_path_segment(ident, ns, record_used, record_used,
-                                                        false, path_span).map(MacroBinding::binding)
+                                                        false, path_span).map(|(b, _)| b)
             } else {
                 let record_used_id =
                     if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None };
@@ -3902,7 +3928,7 @@ fn lookup_typo_candidate<FilterFn>(&mut self,
                 }
             }
             // Add primitive types to the mix
-            if filter_fn(Def::PrimTy(TyBool)) {
+            if filter_fn(Def::PrimTy(Bool)) {
                 names.extend(
                     self.primitive_type_table.primitive_types.iter().map(|(name, _)| name)
                 )
@@ -4229,16 +4255,11 @@ fn get_traits_in_module_containing_item(&mut self,
         }
     }
 
-    /// When name resolution fails, this method can be used to look up candidate
-    /// entities with the expected name. It allows filtering them using the
-    /// supplied predicate (which should be used to only accept the types of
-    /// definitions expected e.g. traits). The lookup spans across all crates.
-    ///
-    /// 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_import_candidates<FilterFn>(&mut self,
+    fn lookup_import_candidates_from_module<FilterFn>(&mut self,
                                           lookup_name: Name,
                                           namespace: Namespace,
+                                          start_module: &'a ModuleData<'a>,
+                                          crate_name: Ident,
                                           filter_fn: FilterFn)
                                           -> Vec<ImportSuggestion>
         where FilterFn: Fn(Def) -> bool
@@ -4246,7 +4267,8 @@ fn lookup_import_candidates<FilterFn>(&mut self,
         let mut candidates = Vec::new();
         let mut worklist = Vec::new();
         let mut seen_modules = FxHashSet();
-        worklist.push((self.graph_root, Vec::new(), false));
+        let not_local_module = crate_name != keywords::Crate.ident();
+        worklist.push((start_module, Vec::<ast::PathSegment>::new(), not_local_module));
 
         while let Some((in_module,
                         path_segments,
@@ -4265,17 +4287,14 @@ fn lookup_import_candidates<FilterFn>(&mut self,
                 if ident.name == lookup_name && ns == namespace {
                     if filter_fn(name_binding.def()) {
                         // create the path
-                        let mut segms = if self.session.rust_2018() && !in_module_is_extern {
+                        let mut segms = path_segments.clone();
+                        if self.session.rust_2018() {
                             // crate-local absolute paths start with `crate::` in edition 2018
                             // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
-                            let mut full_segms = vec![
-                                ast::PathSegment::from_ident(keywords::Crate.ident())
-                            ];
-                            full_segms.extend(path_segments.clone());
-                            full_segms
-                        } else {
-                            path_segments.clone()
-                        };
+                            segms.insert(
+                                0, ast::PathSegment::from_ident(crate_name)
+                            );
+                        }
 
                         segms.push(ast::PathSegment::from_ident(ident));
                         let path = Path {
@@ -4301,7 +4320,14 @@ fn lookup_import_candidates<FilterFn>(&mut self,
                     let mut path_segments = path_segments.clone();
                     path_segments.push(ast::PathSegment::from_ident(ident));
 
-                    if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
+                    let is_extern_crate_that_also_appears_in_prelude =
+                        name_binding.is_extern_crate() &&
+                        self.session.rust_2018();
+
+                    let is_visible_to_user =
+                        !in_module_is_extern || name_binding.vis == ty::Visibility::Public;
+
+                    if !is_extern_crate_that_also_appears_in_prelude && is_visible_to_user {
                         // add the module to the lookup
                         let is_extern = in_module_is_extern || name_binding.is_extern_crate();
                         if seen_modules.insert(module.def_id().unwrap()) {
@@ -4315,6 +4341,45 @@ fn lookup_import_candidates<FilterFn>(&mut self,
         candidates
     }
 
+    /// When name resolution fails, this method can be used to look up candidate
+    /// entities with the expected name. It allows filtering them using the
+    /// supplied predicate (which should be used to only accept the types of
+    /// definitions expected e.g. traits). The lookup spans across all crates.
+    ///
+    /// 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_import_candidates<FilterFn>(&mut self,
+                                          lookup_name: Name,
+                                          namespace: Namespace,
+                                          filter_fn: FilterFn)
+                                          -> Vec<ImportSuggestion>
+        where FilterFn: Fn(Def) -> bool
+    {
+        let mut suggestions = vec![];
+
+        suggestions.extend(
+            self.lookup_import_candidates_from_module(
+                lookup_name, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn
+            )
+        );
+
+        if self.session.features_untracked().extern_prelude {
+            let extern_prelude_names = self.extern_prelude.clone();
+            for &krate_name in extern_prelude_names.iter() {
+                let krate_ident = Ident::with_empty_ctxt(krate_name);
+                let external_prelude_module = self.load_extern_prelude_crate_if_needed(krate_ident);
+
+                suggestions.extend(
+                    self.lookup_import_candidates_from_module(
+                        lookup_name, namespace, external_prelude_module, krate_ident, &filter_fn
+                    )
+                );
+            }
+        }
+
+        suggestions
+    }
+
     fn find_module(&mut self,
                    module_def: Def)
                    -> Option<(Module<'a>, ImportSuggestion)>
@@ -4434,6 +4499,42 @@ fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool {
         vis.is_accessible_from(module.normal_ancestor_id, self)
     }
 
+    fn report_ambiguity_error(
+        &self, name: Name, span: Span, _lexical: bool,
+        def1: Def, is_import1: bool, is_glob1: bool, from_expansion1: bool, span1: Span,
+        def2: Def, is_import2: bool, _is_glob2: bool, _from_expansion2: bool, span2: Span,
+    ) {
+        let participle = |is_import: bool| if is_import { "imported" } else { "defined" };
+        let msg1 = format!("`{}` could refer to the name {} here", name, participle(is_import1));
+        let msg2 =
+            format!("`{}` could also refer to the name {} here", name, participle(is_import2));
+        let note = if from_expansion1 {
+            Some(if let Def::Macro(..) = def1 {
+                format!("macro-expanded {} do not shadow",
+                        if is_import1 { "macro imports" } else { "macros" })
+            } else {
+                format!("macro-expanded {} do not shadow when used in a macro invocation path",
+                        if is_import1 { "imports" } else { "items" })
+            })
+        } else if is_glob1 {
+            Some(format!("consider adding an explicit import of `{}` to disambiguate", name))
+        } else {
+            None
+        };
+
+        let mut err = struct_span_err!(self.session, span, E0659, "`{}` is ambiguous", name);
+        err.span_note(span1, &msg1);
+        match def2 {
+            Def::Macro(..) if span2.is_dummy() =>
+                err.note(&format!("`{}` is also a builtin macro", name)),
+            _ => err.span_note(span2, &msg2),
+        };
+        if let Some(note) = note {
+            err.note(&note);
+        }
+        err.emit();
+    }
+
     fn report_errors(&mut self, krate: &Crate) {
         self.report_shadowing_errors();
         self.report_with_use_injections(krate);
@@ -4443,36 +4544,24 @@ fn report_errors(&mut self, krate: &Crate) {
         for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
             let msg = "macro-expanded `macro_export` macros from the current crate \
                        cannot be referred to by absolute paths";
-            self.session.struct_span_err(span_use, msg)
-                        .span_note(span_def, "the macro is defined here")
-                        .emit();
+            self.session.buffer_lint_with_diagnostic(
+                lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
+                CRATE_NODE_ID, span_use, msg,
+                lint::builtin::BuiltinLintDiagnostics::
+                    MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
+            );
         }
 
         for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors {
-            if !reported_spans.insert(span) { continue }
-            let participle = |binding: &NameBinding| {
-                if binding.is_import() { "imported" } else { "defined" }
-            };
-            let msg1 = format!("`{}` could refer to the name {} here", name, participle(b1));
-            let msg2 = format!("`{}` could also refer to the name {} here", name, participle(b2));
-            let note = if b1.expansion == Mark::root() || !lexical && b1.is_glob_import() {
-                format!("consider adding an explicit import of `{}` to disambiguate", name)
-            } else if let Def::Macro(..) = b1.def() {
-                format!("macro-expanded {} do not shadow",
-                        if b1.is_import() { "macro imports" } else { "macros" })
-            } else {
-                format!("macro-expanded {} do not shadow when used in a macro invocation path",
-                        if b1.is_import() { "imports" } else { "items" })
-            };
-
-            let mut err = struct_span_err!(self.session, span, E0659, "`{}` is ambiguous", name);
-            err.span_note(b1.span, &msg1);
-            match b2.def() {
-                Def::Macro(..) if b2.span.is_dummy() =>
-                    err.note(&format!("`{}` is also a builtin macro", name)),
-                _ => err.span_note(b2.span, &msg2),
-            };
-            err.note(&note).emit();
+            if reported_spans.insert(span) {
+                self.report_ambiguity_error(
+                    name, span, lexical,
+                    b1.def(), b1.is_import(), b1.is_glob_import(),
+                    b1.expansion != Mark::root(), b1.span,
+                    b2.def(), b2.is_import(), b2.is_glob_import(),
+                    b2.expansion != Mark::root(), b2.span,
+                );
+            }
         }
 
         for &PrivacyError(span, name, binding) in &self.privacy_errors {
@@ -4595,15 +4684,16 @@ fn report_conflict<'b>(&mut self,
                     format!("other_{}", name)
                 };
 
-                err.span_suggestion(binding.span,
-                                    rename_msg,
-                                    if snippet.ends_with(';') {
-                                        format!("{} as {};",
-                                                &snippet[..snippet.len()-1],
-                                                suggested_name)
-                                    } else {
-                                        format!("{} as {}", snippet, suggested_name)
-                                    });
+                err.span_suggestion_with_applicability(
+                    binding.span,
+                    rename_msg,
+                    if snippet.ends_with(';') {
+                        format!("{} as {};", &snippet[..snippet.len() - 1], suggested_name)
+                    } else {
+                        format!("{} as {}", snippet, suggested_name)
+                    },
+                    Applicability::MachineApplicable,
+                );
             } else {
                 err.span_label(binding.span, rename_msg);
             }
index 8f2e76d8866ddd2fbb18dce796c9a6ff7fdd503c..879b4ea3fe579f8568aeb1b685af9760e46e932e 100644 (file)
 use syntax::tokenstream::{TokenStream, TokenTree, Delimited};
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax_pos::{Span, DUMMY_SP};
+use errors::Applicability;
 
 use std::cell::Cell;
 use std::mem;
 use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::small_vec::ExpectOne;
+
+crate struct FromPrelude(bool);
+crate struct FromExpansion(bool);
 
 #[derive(Clone)]
 pub struct InvocationData<'a> {
@@ -80,6 +85,12 @@ pub struct LegacyBinding<'a> {
     pub span: Span,
 }
 
+impl<'a> LegacyBinding<'a> {
+    fn def(&self) -> Def {
+        Def::Macro(self.def_id, MacroKind::Bang)
+    }
+}
+
 pub struct ProcMacError {
     crate_name: Symbol,
     name: Symbol,
@@ -88,37 +99,6 @@ pub struct ProcMacError {
     warn_msg: &'static str,
 }
 
-#[derive(Copy, Clone)]
-pub enum MacroBinding<'a> {
-    Legacy(&'a LegacyBinding<'a>),
-    Global(&'a NameBinding<'a>),
-    Modern(&'a NameBinding<'a>),
-}
-
-impl<'a> MacroBinding<'a> {
-    pub fn span(self) -> Span {
-        match self {
-            MacroBinding::Legacy(binding) => binding.span,
-            MacroBinding::Global(binding) | MacroBinding::Modern(binding) => binding.span,
-        }
-    }
-
-    pub fn binding(self) -> &'a NameBinding<'a> {
-        match self {
-            MacroBinding::Global(binding) | MacroBinding::Modern(binding) => binding,
-            MacroBinding::Legacy(_) => panic!("unexpected MacroBinding::Legacy"),
-        }
-    }
-
-    pub fn def_ignoring_ambiguity(self) -> Def {
-        match self {
-            MacroBinding::Legacy(binding) => Def::Macro(binding.def_id, MacroKind::Bang),
-            MacroBinding::Global(binding) | MacroBinding::Modern(binding) =>
-                binding.def_ignoring_ambiguity(),
-        }
-    }
-}
-
 impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
     fn next_node_id(&mut self) -> ast::NodeId {
         self.session.next_node_id()
@@ -319,94 +299,38 @@ fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>, allow_deri
         None
     }
 
-    fn resolve_invoc(&mut self, invoc: &Invocation, scope: Mark, force: bool)
-                     -> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
-        let def = match invoc.kind {
-            InvocationKind::Attr { attr: None, .. } => return Ok(None),
-            _ => self.resolve_invoc_to_def(invoc, scope, force)?,
+    fn resolve_macro_invocation(&mut self, invoc: &Invocation, scope: Mark, force: bool)
+                                -> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
+        let (path, kind, derives_in_scope) = match invoc.kind {
+            InvocationKind::Attr { attr: None, .. } =>
+                return Ok(None),
+            InvocationKind::Attr { attr: Some(ref attr), ref traits, .. } =>
+                (&attr.path, MacroKind::Attr, &traits[..]),
+            InvocationKind::Bang { ref mac, .. } =>
+                (&mac.node.path, MacroKind::Bang, &[][..]),
+            InvocationKind::Derive { ref path, .. } =>
+                (path, MacroKind::Derive, &[][..]),
         };
-        if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
-            self.report_proc_macro_stub(invoc.span());
-            return Err(Determinacy::Determined);
-        } else if let Def::NonMacroAttr(attr_kind) = def {
-            // Note that not only attributes, but anything in macro namespace can result in a
-            // `Def::NonMacroAttr` definition (e.g. `inline!()`), so we must report the error
-            // below for these cases.
-            let is_attr_invoc =
-                if let InvocationKind::Attr { .. } = invoc.kind { true } else { false };
-            let path = invoc.path().expect("no path for non-macro attr");
-            match attr_kind {
-                NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper |
-                NonMacroAttrKind::Custom if is_attr_invoc => {
-                    let features = self.session.features_untracked();
-                    if attr_kind == NonMacroAttrKind::Tool &&
-                       !features.tool_attributes {
-                        feature_err(&self.session.parse_sess, "tool_attributes",
-                                    invoc.span(), GateIssue::Language,
-                                    "tool attributes are unstable").emit();
-                    }
-                    if attr_kind == NonMacroAttrKind::Custom {
-                        assert!(path.segments.len() == 1);
-                        let name = path.segments[0].ident.name.as_str();
-                        if name.starts_with("rustc_") {
-                            if !features.rustc_attrs {
-                                let msg = "unless otherwise specified, attributes with the prefix \
-                                        `rustc_` are reserved for internal compiler diagnostics";
-                                feature_err(&self.session.parse_sess, "rustc_attrs", invoc.span(),
-                                            GateIssue::Language, &msg).emit();
-                            }
-                        } else if name.starts_with("derive_") {
-                            if !features.custom_derive {
-                                feature_err(&self.session.parse_sess, "custom_derive", invoc.span(),
-                                            GateIssue::Language, EXPLAIN_DERIVE_UNDERSCORE).emit();
-                            }
-                        } else if !features.custom_attribute {
-                            let msg = format!("The attribute `{}` is currently unknown to the \
-                                               compiler and may have meaning added to it in the \
-                                               future", path);
-                            feature_err(&self.session.parse_sess, "custom_attribute", invoc.span(),
-                                        GateIssue::Language, &msg).emit();
-                        }
-                    }
 
-                    return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr {
-                        mark_used: attr_kind == NonMacroAttrKind::Tool,
-                    })));
-                }
-                _ => {
-                    self.report_non_macro_attr(path.span, def);
-                    return Err(Determinacy::Determined);
-                }
-            }
+        let (def, ext) = self.resolve_macro_to_def(path, kind, scope, derives_in_scope, force)?;
+
+        if let Def::Macro(def_id, _) = def {
+            self.macro_defs.insert(invoc.expansion_data.mark, def_id);
+            let normal_module_def_id =
+                self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id;
+            self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark,
+                                                            normal_module_def_id);
+            invoc.expansion_data.mark.set_default_transparency(ext.default_transparency());
+            invoc.expansion_data.mark.set_is_builtin(def_id.krate == BUILTIN_MACROS_CRATE);
         }
-        let def_id = def.def_id();
-
-        self.macro_defs.insert(invoc.expansion_data.mark, def_id);
-        let normal_module_def_id =
-            self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id;
-        self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark,
-                                                        normal_module_def_id);
-
-        self.unused_macros.remove(&def_id);
-        let ext = self.get_macro(def);
-        invoc.expansion_data.mark.set_default_transparency(ext.default_transparency());
-        invoc.expansion_data.mark.set_is_builtin(def_id.krate == BUILTIN_MACROS_CRATE);
+
         Ok(Some(ext))
     }
 
-    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
-                     -> Result<Lrc<SyntaxExtension>, Determinacy> {
-        self.resolve_macro_to_def(scope, path, kind, force).and_then(|def| {
-            if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
-                self.report_proc_macro_stub(path.span);
-                return Err(Determinacy::Determined);
-            } else if let Def::NonMacroAttr(..) = def {
-                self.report_non_macro_attr(path.span, def);
-                return Err(Determinacy::Determined);
-            }
-            self.unused_macros.remove(&def.def_id());
-            Ok(self.get_macro(def))
-        })
+    fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark,
+                          derives_in_scope: &[ast::Path], force: bool)
+                          -> Result<Lrc<SyntaxExtension>, Determinacy> {
+        Ok(self.resolve_macro_to_def(path, kind, scope, derives_in_scope, force)?.1)
     }
 
     fn check_unused_macros(&self) {
@@ -428,95 +352,76 @@ fn check_unused_macros(&self) {
 }
 
 impl<'a, 'cl> Resolver<'a, 'cl> {
-    fn report_proc_macro_stub(&self, span: Span) {
-        self.session.span_err(span,
-                              "can't use a procedural macro from the same crate that defines it");
-    }
+    fn resolve_macro_to_def(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark,
+                            derives_in_scope: &[ast::Path], force: bool)
+                            -> Result<(Def, Lrc<SyntaxExtension>), Determinacy> {
+        let def = self.resolve_macro_to_def_inner(path, kind, scope, derives_in_scope, force);
 
-    fn report_non_macro_attr(&self, span: Span, def: Def) {
-        self.session.span_err(span, &format!("expected a macro, found {}", def.kind_name()));
-    }
-
-    fn resolve_invoc_to_def(&mut self, invoc: &Invocation, scope: Mark, force: bool)
-                            -> Result<Def, Determinacy> {
-        let (attr, traits) = match invoc.kind {
-            InvocationKind::Attr { ref attr, ref traits, .. } => (attr, traits),
-            InvocationKind::Bang { ref mac, .. } => {
-                return self.resolve_macro_to_def(scope, &mac.node.path, MacroKind::Bang, force);
-            }
-            InvocationKind::Derive { ref path, .. } => {
-                return self.resolve_macro_to_def(scope, path, MacroKind::Derive, force);
+        // Report errors and enforce feature gates for the resolved macro.
+        if def != Err(Determinacy::Undetermined) {
+            // Do not report duplicated errors on every undetermined resolution.
+            for segment in &path.segments {
+                if let Some(args) = &segment.args {
+                    self.session.span_err(args.span(), "generic arguments in macro path");
+                }
             }
-        };
-
-        let path = attr.as_ref().unwrap().path.clone();
-        let def = self.resolve_macro_to_def(scope, &path, MacroKind::Attr, force);
-        if let Ok(Def::NonMacroAttr(NonMacroAttrKind::Custom)) = def {} else {
-            return def;
         }
 
-        // At this point we've found that the `attr` is determinately unresolved and thus can be
-        // interpreted as a custom attribute. Normally custom attributes are feature gated, but
-        // it may be a custom attribute whitelisted by a derive macro and they do not require
-        // a feature gate.
-        //
-        // So here we look through all of the derive annotations in scope and try to resolve them.
-        // If they themselves successfully resolve *and* one of the resolved derive macros
-        // whitelists this attribute's name, then this is a registered attribute and we can convert
-        // it from a "generic custom attrite" into a "known derive helper attribute".
-        enum ConvertToDeriveHelper { Yes, No, DontKnow }
-        let mut convert_to_derive_helper = ConvertToDeriveHelper::No;
-        let attr_name = path.segments[0].ident.name;
-        for path in traits {
-            match self.resolve_macro(scope, path, MacroKind::Derive, force) {
-                Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs, _) = *ext {
-                    if inert_attrs.contains(&attr_name) {
-                        convert_to_derive_helper = ConvertToDeriveHelper::Yes;
-                        break
+        let def = def?;
+
+        match def {
+            Def::Macro(def_id, macro_kind) => {
+                self.unused_macros.remove(&def_id);
+                if macro_kind == MacroKind::ProcMacroStub {
+                    let msg = "can't use a procedural macro from the same crate that defines it";
+                    self.session.span_err(path.span, msg);
+                    return Err(Determinacy::Determined);
+                }
+            }
+            Def::NonMacroAttr(attr_kind) => {
+                if kind == MacroKind::Attr {
+                    let features = self.session.features_untracked();
+                    if attr_kind == NonMacroAttrKind::Custom {
+                        assert!(path.segments.len() == 1);
+                        let name = path.segments[0].ident.name.as_str();
+                        if name.starts_with("rustc_") {
+                            if !features.rustc_attrs {
+                                let msg = "unless otherwise specified, attributes with the prefix \
+                                           `rustc_` are reserved for internal compiler diagnostics";
+                                feature_err(&self.session.parse_sess, "rustc_attrs", path.span,
+                                            GateIssue::Language, &msg).emit();
+                            }
+                        } else if name.starts_with("derive_") {
+                            if !features.custom_derive {
+                                feature_err(&self.session.parse_sess, "custom_derive", path.span,
+                                            GateIssue::Language, EXPLAIN_DERIVE_UNDERSCORE).emit();
+                            }
+                        } else if !features.custom_attribute {
+                            let msg = format!("The attribute `{}` is currently unknown to the \
+                                               compiler and may have meaning added to it in the \
+                                               future", path);
+                            feature_err(&self.session.parse_sess, "custom_attribute", path.span,
+                                        GateIssue::Language, &msg).emit();
+                        }
                     }
-                },
-                Err(Determinacy::Undetermined) =>
-                    convert_to_derive_helper = ConvertToDeriveHelper::DontKnow,
-                Err(Determinacy::Determined) => {}
+                } else {
+                    // Not only attributes, but anything in macro namespace can result in
+                    // `Def::NonMacroAttr` definition (e.g. `inline!()`), so we must report
+                    // an error for those cases.
+                    let msg = format!("expected a macro, found {}", def.kind_name());
+                    self.session.span_err(path.span, &msg);
+                    return Err(Determinacy::Determined);
+                }
             }
+            _ => panic!("expected `Def::Macro` or `Def::NonMacroAttr`"),
         }
 
-        match convert_to_derive_helper {
-            ConvertToDeriveHelper::Yes => Ok(Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper)),
-            ConvertToDeriveHelper::No => def,
-            ConvertToDeriveHelper::DontKnow => Err(Determinacy::determined(force)),
-        }
-    }
-
-    fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
-                            -> Result<Def, Determinacy> {
-        let def = self.resolve_macro_to_def_inner(scope, path, kind, force);
-        if def != Err(Determinacy::Undetermined) {
-            // Do not report duplicated errors on every undetermined resolution.
-            path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
-                self.session.span_err(segment.args.as_ref().unwrap().span(),
-                                      "generic arguments in macro path");
-            });
-        }
-        if kind != MacroKind::Bang && path.segments.len() > 1 &&
-           def != Ok(Def::NonMacroAttr(NonMacroAttrKind::Tool)) {
-            if !self.session.features_untracked().proc_macro_path_invoc {
-                emit_feature_err(
-                    &self.session.parse_sess,
-                    "proc_macro_path_invoc",
-                    path.span,
-                    GateIssue::Language,
-                    "paths of length greater than one in macro invocations are \
-                     currently unstable",
-                );
-            }
-        }
-        def
+        Ok((def, self.get_macro(def)))
     }
 
-    pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
-                                  kind: MacroKind, force: bool)
-                                  -> Result<Def, Determinacy> {
+    pub fn resolve_macro_to_def_inner(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark,
+                                      derives_in_scope: &[ast::Path], force: bool)
+                                      -> Result<Def, Determinacy> {
         let ast::Path { ref segments, span } = *path;
         let mut path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
         let invocation = self.invocations[&scope];
@@ -558,12 +463,12 @@ pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
         }
 
         let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, path[0], false);
-        let result = if let Some(MacroBinding::Legacy(binding)) = legacy_resolution {
-            Ok(Def::Macro(binding.def_id, MacroKind::Bang))
+        let result = if let Some((legacy_binding, _)) = legacy_resolution {
+            Ok(legacy_binding.def())
         } else {
             match self.resolve_lexical_macro_path_segment(path[0], MacroNS, false, force,
                                                           kind == MacroKind::Attr, span) {
-                Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()),
+                Ok((binding, _)) => Ok(binding.def_ignoring_ambiguity()),
                 Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
                 Err(Determinacy::Determined) => {
                     self.found_unresolved_macro = true;
@@ -575,21 +480,56 @@ pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
         self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut()
             .push((scope, path[0], kind, result.ok()));
 
-        result
+        if let Ok(Def::NonMacroAttr(NonMacroAttrKind::Custom)) = result {} else {
+            return result;
+        }
+
+        // At this point we've found that the `attr` is determinately unresolved and thus can be
+        // interpreted as a custom attribute. Normally custom attributes are feature gated, but
+        // it may be a custom attribute whitelisted by a derive macro and they do not require
+        // a feature gate.
+        //
+        // So here we look through all of the derive annotations in scope and try to resolve them.
+        // If they themselves successfully resolve *and* one of the resolved derive macros
+        // whitelists this attribute's name, then this is a registered attribute and we can convert
+        // it from a "generic custom attrite" into a "known derive helper attribute".
+        assert!(kind == MacroKind::Attr);
+        enum ConvertToDeriveHelper { Yes, No, DontKnow }
+        let mut convert_to_derive_helper = ConvertToDeriveHelper::No;
+        for derive in derives_in_scope {
+            match self.resolve_macro_path(derive, MacroKind::Derive, scope, &[], force) {
+                Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs, _) = *ext {
+                    if inert_attrs.contains(&path[0].name) {
+                        convert_to_derive_helper = ConvertToDeriveHelper::Yes;
+                        break
+                    }
+                },
+                Err(Determinacy::Undetermined) =>
+                    convert_to_derive_helper = ConvertToDeriveHelper::DontKnow,
+                Err(Determinacy::Determined) => {}
+            }
+        }
+
+        match convert_to_derive_helper {
+            ConvertToDeriveHelper::Yes => Ok(Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper)),
+            ConvertToDeriveHelper::No => result,
+            ConvertToDeriveHelper::DontKnow => Err(Determinacy::determined(force)),
+        }
     }
 
     // Resolve the initial segment of a non-global macro path
     // (e.g. `foo` in `foo::bar!(); or `foo!();`).
     // This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during
     // expansion and import resolution (perhaps they can be merged in the future).
-    pub fn resolve_lexical_macro_path_segment(&mut self,
-                                              mut ident: Ident,
-                                              ns: Namespace,
-                                              record_used: bool,
-                                              force: bool,
-                                              is_attr: bool,
-                                              path_span: Span)
-                                              -> Result<MacroBinding<'a>, Determinacy> {
+    crate fn resolve_lexical_macro_path_segment(
+        &mut self,
+        mut ident: Ident,
+        ns: Namespace,
+        record_used: bool,
+        force: bool,
+        is_attr: bool,
+        path_span: Span
+    ) -> Result<(&'a NameBinding<'a>, FromPrelude), Determinacy> {
         // General principles:
         // 1. Not controlled (user-defined) names should have higher priority than controlled names
         //    built into the language or standard library. This way we can add new names into the
@@ -629,7 +569,7 @@ pub fn resolve_lexical_macro_path_segment(&mut self,
         //     m::mac!();
         // }
         // This includes names from globs and from macro expansions.
-        let mut potentially_ambiguous_result: Option<MacroBinding> = None;
+        let mut potentially_ambiguous_result: Option<(&NameBinding, FromPrelude)> = None;
 
         enum WhereToResolve<'a> {
             Module(Module<'a>),
@@ -657,11 +597,11 @@ enum WhereToResolve<'a> {
                         path_span,
                     );
                     self.current_module = orig_current_module;
-                    binding.map(MacroBinding::Modern)
+                    binding.map(|binding| (binding, FromPrelude(false)))
                 }
                 WhereToResolve::MacroPrelude => {
                     match self.macro_prelude.get(&ident.name).cloned() {
-                        Some(binding) => Ok(MacroBinding::Global(binding)),
+                        Some(binding) => Ok((binding, FromPrelude(true))),
                         None => Err(Determinacy::Determined),
                     }
                 }
@@ -673,7 +613,7 @@ enum WhereToResolve<'a> {
                         let binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin),
                                        ty::Visibility::Public, ident.span, Mark::root())
                                        .to_name_binding(self.arenas);
-                        Ok(MacroBinding::Global(binding))
+                        Ok((binding, FromPrelude(true)))
                     } else {
                         Err(Determinacy::Determined)
                     }
@@ -696,7 +636,7 @@ enum WhereToResolve<'a> {
 
                         let binding = (crate_root, ty::Visibility::Public,
                                        ident.span, Mark::root()).to_name_binding(self.arenas);
-                        Ok(MacroBinding::Global(binding))
+                        Ok((binding, FromPrelude(true)))
                     } else {
                         Err(Determinacy::Determined)
                     }
@@ -705,7 +645,7 @@ enum WhereToResolve<'a> {
                     if use_prelude && is_known_tool(ident.name) {
                         let binding = (Def::ToolMod, ty::Visibility::Public,
                                        ident.span, Mark::root()).to_name_binding(self.arenas);
-                        Ok(MacroBinding::Global(binding))
+                        Ok((binding, FromPrelude(true)))
                     } else {
                         Err(Determinacy::Determined)
                     }
@@ -722,7 +662,7 @@ enum WhereToResolve<'a> {
                                 false,
                                 path_span,
                             ) {
-                                result = Ok(MacroBinding::Global(binding));
+                                result = Ok((binding, FromPrelude(true)));
                             }
                         }
                     }
@@ -733,7 +673,7 @@ enum WhereToResolve<'a> {
                             self.primitive_type_table.primitive_types.get(&ident.name).cloned() {
                         let binding = (Def::PrimTy(prim_ty), ty::Visibility::Public,
                                        ident.span, Mark::root()).to_name_binding(self.arenas);
-                        Ok(MacroBinding::Global(binding))
+                        Ok((binding, FromPrelude(true)))
                     } else {
                         Err(Determinacy::Determined)
                     }
@@ -772,18 +712,16 @@ macro_rules! continue_search { () => {
                         return Ok(result);
                     }
 
-                    let binding = result.binding();
-
                     // Found a solution that is ambiguous with a previously found solution.
                     // Push an ambiguity error for later reporting and
                     // return something for better recovery.
                     if let Some(previous_result) = potentially_ambiguous_result {
-                        if binding.def() != previous_result.binding().def() {
+                        if result.0.def() != previous_result.0.def() {
                             self.ambiguity_errors.push(AmbiguityError {
                                 span: path_span,
                                 name: ident.name,
-                                b1: previous_result.binding(),
-                                b2: binding,
+                                b1: previous_result.0,
+                                b2: result.0,
                                 lexical: true,
                             });
                             return Ok(previous_result);
@@ -793,7 +731,7 @@ macro_rules! continue_search { () => {
                     // Found a solution that's not an ambiguity yet, but is "suspicious" and
                     // can participate in ambiguities later on.
                     // Remember it and go search for other solutions in outer scopes.
-                    if binding.is_glob_import() || binding.expansion != Mark::root() {
+                    if result.0.is_glob_import() || result.0.expansion != Mark::root() {
                         potentially_ambiguous_result = Some(result);
 
                         continue_search!();
@@ -823,20 +761,19 @@ macro_rules! continue_search { () => {
             let binding = (Def::NonMacroAttr(NonMacroAttrKind::Custom),
                            ty::Visibility::Public, ident.span, Mark::root())
                            .to_name_binding(self.arenas);
-            Ok(MacroBinding::Global(binding))
+            Ok((binding, FromPrelude(true)))
         } else {
             Err(determinacy)
         }
     }
 
-    pub fn resolve_legacy_scope(&mut self,
-                                mut scope: &'a Cell<LegacyScope<'a>>,
-                                ident: Ident,
-                                record_used: bool)
-                                -> Option<MacroBinding<'a>> {
+    crate fn resolve_legacy_scope(&mut self,
+                                  mut scope: &'a Cell<LegacyScope<'a>>,
+                                  ident: Ident,
+                                  record_used: bool)
+                                  -> Option<(&'a LegacyBinding<'a>, FromExpansion)> {
         let ident = ident.modern();
         let mut relative_depth: u32 = 0;
-        let mut binding = None;
         loop {
             match scope.get() {
                 LegacyScope::Empty => break,
@@ -861,23 +798,14 @@ pub fn resolve_legacy_scope(&mut self,
                         if record_used && relative_depth > 0 {
                             self.disallowed_shadowing.push(potential_binding);
                         }
-                        binding = Some(potential_binding);
-                        break
+                        return Some((potential_binding, FromExpansion(relative_depth > 0)));
                     }
                     scope = &potential_binding.parent;
                 }
             };
         }
 
-        let binding = if let Some(binding) = binding {
-            MacroBinding::Legacy(binding)
-        } else if let Some(binding) = self.macro_prelude.get(&ident.name).cloned() {
-            MacroBinding::Global(binding)
-        } else {
-            return None;
-        };
-
-        Some(binding)
+        None
     }
 
     pub fn finalize_current_module_macro_resolutions(&mut self) {
@@ -899,10 +827,10 @@ pub fn finalize_current_module_macro_resolutions(&mut self) {
             let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, true, true,
                                                                      kind == MacroKind::Attr, span);
 
-            let check_consistency = |this: &Self, binding: MacroBinding| {
+            let check_consistency = |this: &Self, new_def: Def| {
                 if let Some(def) = def {
                     if this.ambiguity_errors.is_empty() && this.disallowed_shadowing.is_empty() &&
-                       binding.def_ignoring_ambiguity() != def {
+                       new_def != def && new_def != Def::Err {
                         // Make sure compilation does not succeed if preferred macro resolution
                         // has changed after the macro had been expanded. In theory all such
                         // situations should be reported as ambiguity errors, so this is span-bug.
@@ -921,17 +849,6 @@ pub fn finalize_current_module_macro_resolutions(&mut self) {
             };
 
             match (legacy_resolution, resolution) {
-                (Some(MacroBinding::Legacy(legacy_binding)), Ok(MacroBinding::Modern(binding))) => {
-                    if legacy_binding.def_id != binding.def_ignoring_ambiguity().def_id() {
-                        let msg1 = format!("`{}` could refer to the macro defined here", ident);
-                        let msg2 =
-                            format!("`{}` could also refer to the macro imported here", ident);
-                        self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident))
-                            .span_note(legacy_binding.span, &msg1)
-                            .span_note(binding.span, &msg2)
-                            .emit();
-                    }
-                },
                 (None, Err(_)) => {
                     assert!(def.is_none());
                     let bang = if kind == MacroKind::Bang { "!" } else { "" };
@@ -941,26 +858,34 @@ pub fn finalize_current_module_macro_resolutions(&mut self) {
                     self.suggest_macro_name(&ident.as_str(), kind, &mut err, span);
                     err.emit();
                 },
-                (Some(MacroBinding::Modern(_)), _) | (_, Ok(MacroBinding::Legacy(_))) => {
-                    span_bug!(span, "impossible macro resolution result");
-                }
+                (Some((legacy_binding, FromExpansion(from_expansion))),
+                 Ok((binding, FromPrelude(false)))) |
+                (Some((legacy_binding, FromExpansion(from_expansion @ true))),
+                 Ok((binding, FromPrelude(true)))) => {
+                    if legacy_binding.def() != binding.def_ignoring_ambiguity() {
+                        self.report_ambiguity_error(
+                            ident.name, span, true,
+                            legacy_binding.def(), false, false,
+                            from_expansion, legacy_binding.span,
+                            binding.def(), binding.is_import(), binding.is_glob_import(),
+                            binding.expansion != Mark::root(), binding.span,
+                        );
+                    }
+                },
+                // OK, non-macro-expanded legacy wins over macro prelude even if defs are different
+                (Some((legacy_binding, FromExpansion(false))), Ok((_, FromPrelude(true)))) |
                 // OK, unambiguous resolution
-                (Some(binding), Err(_)) | (None, Ok(binding)) |
-                // OK, legacy wins over global even if their definitions are different
-                (Some(binding @ MacroBinding::Legacy(_)), Ok(MacroBinding::Global(_))) |
-                // OK, modern wins over global even if their definitions are different
-                (Some(MacroBinding::Global(_)), Ok(binding @ MacroBinding::Modern(_))) => {
-                    check_consistency(self, binding);
+                (Some((legacy_binding, _)), Err(_)) => {
+                    check_consistency(self, legacy_binding.def());
                 }
-                (Some(MacroBinding::Global(binding1)), Ok(MacroBinding::Global(binding2))) => {
-                    if binding1.def() != binding2.def() {
-                        span_bug!(span, "mismatch between same global macro resolutions");
+                // OK, unambiguous resolution
+                (None, Ok((binding, FromPrelude(from_prelude)))) => {
+                    check_consistency(self, binding.def_ignoring_ambiguity());
+                    if from_prelude {
+                        self.record_use(ident, MacroNS, binding, span);
+                        self.err_if_macro_use_proc_macro(ident.name, span, binding);
                     }
-                    check_consistency(self, MacroBinding::Global(binding1));
-
-                    self.record_use(ident, MacroNS, binding1, span);
-                    self.err_if_macro_use_proc_macro(ident.name, span, binding1);
-                },
+                }
             };
         }
     }
@@ -1000,9 +925,19 @@ fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
         if let Some(suggestion) = suggestion {
             if suggestion != name {
                 if let MacroKind::Bang = kind {
-                    err.span_suggestion(span, "you could try the macro", suggestion.to_string());
+                    err.span_suggestion_with_applicability(
+                        span,
+                        "you could try the macro",
+                        suggestion.to_string(),
+                        Applicability::MaybeIncorrect
+                    );
                 } else {
-                    err.span_suggestion(span, "try", suggestion.to_string());
+                    err.span_suggestion_with_applicability(
+                        span,
+                        "try",
+                        suggestion.to_string(),
+                        Applicability::MaybeIncorrect
+                    );
                 }
             } else {
                 err.help("have you added the `#[macro_use]` on the module/import?");
@@ -1082,7 +1017,11 @@ pub fn define_macro(&mut self,
     /// Error if `ext` is a Macros 1.1 procedural macro being imported by `#[macro_use]`
     fn err_if_macro_use_proc_macro(&mut self, name: Name, use_span: Span,
                                    binding: &NameBinding<'a>) {
-        let krate = binding.def().def_id().krate;
+        let krate = match binding.def() {
+            Def::NonMacroAttr(..) | Def::Err => return,
+            Def::Macro(def_id, _) => def_id.krate,
+            _ => unreachable!(),
+        };
 
         // Plugin-based syntax extensions are exempt from this check
         if krate == BUILTIN_MACROS_CRATE { return; }
@@ -1123,10 +1062,11 @@ pub fn report_proc_macro_import(&mut self, krate: &ast::Crate) {
             if let Some(span) = span {
                 let found_use = if found_use { "" } else { "\n" };
                 self.session.struct_span_err(err.use_span, err.warn_msg)
-                    .span_suggestion(
+                    .span_suggestion_with_applicability(
                         span,
                         "instead, import the procedural macro like any other item",
                         format!("use {}::{};{}", err.crate_name, err.name, found_use),
+                        Applicability::MachineApplicable
                     ).emit();
             } else {
                 self.session.struct_span_err(err.use_span, err.warn_msg)
index 58390c228869964e8049fa0262ee0b313e7a4239..c60f9293d58e71428481cec776465b558a81d418 100644 (file)
@@ -296,6 +296,8 @@ pub fn resolve_ident_in_module_unadjusted(&mut self,
             };
             match self.resolve_ident_in_module(module, ident, ns, false, path_span) {
                 Err(Determined) => continue,
+                Ok(binding)
+                    if !self.is_accessible_from(binding.vis, single_import.parent) => continue,
                 Ok(_) | Err(Undetermined) => return Err(Undetermined),
             }
         }
@@ -365,8 +367,11 @@ pub fn resolve_ident_in_module_unadjusted(&mut self,
                 path_span,
             );
             self.current_module = orig_current_module;
+
             match result {
                 Err(Determined) => continue,
+                Ok(binding)
+                    if !self.is_accessible_from(binding.vis, glob_import.parent) => continue,
                 Ok(_) | Err(Undetermined) => return Err(Undetermined),
             }
         }
@@ -989,7 +994,7 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
                 let lev_suggestion =
                     match find_best_match_for_name(names, &ident.as_str(), None) {
                         Some(name) => format!(". Did you mean to use `{}`?", name),
-                        None => "".to_owned(),
+                        None => String::new(),
                     };
                 let msg = match module {
                     ModuleOrUniformRoot::Module(module) => {
index 7b94170ef6d992f1cbc71dafeb6ed1edd65bab69..2dbea2155aec2094eb2d7bcfd5ca3370b409449e 100644 (file)
@@ -16,7 +16,7 @@ rustc_target = { path = "../librustc_target" }
 rustc_typeck = { path = "../librustc_typeck" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
-rls-data = "0.16"
+rls-data = "0.18"
 rls-span = "0.4"
 # FIXME(#40527) should move rustc serialize out of tree
 rustc-serialize = "0.3"
index 565986066dad2d3c154ea7de0fb21f3aa0f5fd08..58665b808d98898869ad71570ff6878063599ed7 100644 (file)
@@ -91,7 +91,7 @@ pub struct DumpVisitor<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> {
     // of macro use (callsite) spans. We store these to ensure
     // we only write one macro def per unique macro definition, and
     // one macro use per unique callsite span.
-    // mac_defs: HashSet<Span>,
+    // mac_defs: FxHashSet<Span>,
     macro_calls: FxHashSet<Span>,
 }
 
@@ -107,7 +107,7 @@ pub fn new(
             dumper,
             span: span_utils.clone(),
             cur_scope: CRATE_NODE_ID,
-            // mac_defs: HashSet::new(),
+            // mac_defs: FxHashSet::default(),
             macro_calls: FxHashSet(),
         }
     }
index b2d78850cbab9f2de9d720156f69a8afe0c6294e..56dfac84611922b54012e64663fdff42aad296a0 100644 (file)
@@ -13,6 +13,7 @@
        html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(custom_attribute)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![allow(unused_attributes)]
 
 #![recursion_limit="256"]
@@ -42,7 +43,7 @@
 
 use rustc::hir;
 use rustc::hir::def::Def as HirDef;
-use rustc::hir::map::{Node, NodeTraitItem, NodeImplItem};
+use rustc::hir::Node;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::middle::cstore::ExternCrate;
 use rustc::session::config::CrateType;
@@ -147,7 +148,7 @@ pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
                 filter!(self.span_utils, sub_span, item.span, None);
 
                 Some(Data::DefData(Def {
-                    kind: DefKind::Function,
+                    kind: DefKind::ForeignFunction,
                     id: id_from_node_id(item.id, self),
                     span: self.span_from_span(sub_span.unwrap()),
                     name: item.ident.to_string(),
@@ -170,7 +171,7 @@ pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
                 let span = self.span_from_span(sub_span.unwrap());
 
                 Some(Data::DefData(Def {
-                    kind: DefKind::Static,
+                    kind: DefKind::ForeignStatic,
                     id,
                     span,
                     name: item.ident.to_string(),
@@ -419,7 +420,7 @@ pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> O
         let (qualname, parent_scope, decl_id, docs, attributes) =
             match self.tcx.impl_of_method(self.tcx.hir.local_def_id(id)) {
                 Some(impl_id) => match self.tcx.hir.get_if_local(impl_id) {
-                    Some(Node::NodeItem(item)) => match item.node {
+                    Some(Node::Item(item)) => match item.node {
                         hir::ItemKind::Impl(.., ref ty, _) => {
                             let mut qualname = String::from("<");
                             qualname.push_str(&self.tcx.hir.node_to_pretty_string(ty.id));
@@ -428,7 +429,7 @@ pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> O
                             let mut decl_id = None;
                             let mut docs = String::new();
                             let mut attrs = vec![];
-                            if let Some(NodeImplItem(item)) = self.tcx.hir.find(id) {
+                            if let Some(Node::ImplItem(item)) = self.tcx.hir.find(id) {
                                 docs = self.docs_for_attrs(&item.attrs);
                                 attrs = item.attrs.to_vec();
                             }
@@ -470,7 +471,7 @@ pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> O
                         let mut docs = String::new();
                         let mut attrs = vec![];
 
-                        if let Some(NodeTraitItem(item)) = self.tcx.hir.find(id) {
+                        if let Some(Node::TraitItem(item)) = self.tcx.hir.find(id) {
                             docs = self.docs_for_attrs(&item.attrs);
                             attrs = item.attrs.to_vec();
                         }
@@ -534,13 +535,13 @@ pub fn get_trait_ref_data(&self, trait_ref: &ast::TraitRef) -> Option<Ref> {
     pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
         let hir_node = self.tcx.hir.expect_expr(expr.id);
         let ty = self.tables.expr_ty_adjusted_opt(&hir_node);
-        if ty.is_none() || ty.unwrap().sty == ty::TyError {
+        if ty.is_none() || ty.unwrap().sty == ty::Error {
             return None;
         }
         match expr.node {
             ast::ExprKind::Field(ref sub_ex, ident) => {
                 let hir_node = match self.tcx.hir.find(sub_ex.id) {
-                    Some(Node::NodeExpr(expr)) => expr,
+                    Some(Node::Expr(expr)) => expr,
                     _ => {
                         debug!(
                             "Missing or weird node for sub-expression {} in {:?}",
@@ -551,7 +552,7 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
                     }
                 };
                 match self.tables.expr_ty_adjusted(&hir_node).sty {
-                    ty::TyAdt(def, _) if !def.is_enum() => {
+                    ty::Adt(def, _) if !def.is_enum() => {
                         let variant = &def.non_enum_variant();
                         let index = self.tcx.find_field_index(ident, variant).unwrap();
                         let sub_span = self.span_utils.span_for_last_ident(expr.span);
@@ -563,7 +564,7 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
                             ref_id: id_from_def_id(variant.fields[index].did),
                         }));
                     }
-                    ty::TyTuple(..) => None,
+                    ty::Tuple(..) => None,
                     _ => {
                         debug!("Expected struct or union type, found {:?}", ty);
                         None
@@ -572,7 +573,7 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
             }
             ast::ExprKind::Struct(ref path, ..) => {
                 match self.tables.expr_ty_adjusted(&hir_node).sty {
-                    ty::TyAdt(def, _) if !def.is_enum() => {
+                    ty::Adt(def, _) if !def.is_enum() => {
                         let sub_span = self.span_utils.span_for_last_ident(path.span);
                         filter!(self.span_utils, sub_span, path.span, None);
                         let span = self.span_from_span(sub_span.unwrap());
@@ -627,32 +628,32 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
 
     pub fn get_path_def(&self, id: NodeId) -> HirDef {
         match self.tcx.hir.get(id) {
-            Node::NodeTraitRef(tr) => tr.path.def,
+            Node::TraitRef(tr) => tr.path.def,
 
-            Node::NodeItem(&hir::Item {
+            Node::Item(&hir::Item {
                 node: hir::ItemKind::Use(ref path, _),
                 ..
             }) |
-            Node::NodeVisibility(&Spanned {
+            Node::Visibility(&Spanned {
                 node: hir::VisibilityKind::Restricted { ref path, .. }, .. }) => path.def,
 
-            Node::NodeExpr(&hir::Expr {
+            Node::Expr(&hir::Expr {
                 node: hir::ExprKind::Struct(ref qpath, ..),
                 ..
             }) |
-            Node::NodeExpr(&hir::Expr {
+            Node::Expr(&hir::Expr {
                 node: hir::ExprKind::Path(ref qpath),
                 ..
             }) |
-            Node::NodePat(&hir::Pat {
+            Node::Pat(&hir::Pat {
                 node: hir::PatKind::Path(ref qpath),
                 ..
             }) |
-            Node::NodePat(&hir::Pat {
+            Node::Pat(&hir::Pat {
                 node: hir::PatKind::Struct(ref qpath, ..),
                 ..
             }) |
-            Node::NodePat(&hir::Pat {
+            Node::Pat(&hir::Pat {
                 node: hir::PatKind::TupleStruct(ref qpath, ..),
                 ..
             }) => {
@@ -660,12 +661,12 @@ pub fn get_path_def(&self, id: NodeId) -> HirDef {
                 self.tables.qpath_def(qpath, hir_id)
             }
 
-            Node::NodeBinding(&hir::Pat {
+            Node::Binding(&hir::Pat {
                 node: hir::PatKind::Binding(_, canonical_id, ..),
                 ..
             }) => HirDef::Local(canonical_id),
 
-            Node::NodeTy(ty) => if let hir::Ty {
+            Node::Ty(ty) => if let hir::Ty {
                 node: hir::TyKind::Path(ref qpath),
                 ..
             } = *ty
@@ -674,7 +675,7 @@ pub fn get_path_def(&self, id: NodeId) -> HirDef {
                     hir::QPath::Resolved(_, ref path) => path.def,
                     hir::QPath::TypeRelative(..) => {
                         let ty = hir_ty_to_ty(self.tcx, ty);
-                        if let ty::TyProjection(proj) = ty.sty {
+                        if let ty::Projection(proj) = ty.sty {
                             return HirDef::AssociatedTy(proj.item_def_id);
                         }
                         HirDef::Err
@@ -747,7 +748,7 @@ fn fn_type(path: &ast::Path) -> bool {
             HirDef::Union(def_id) |
             HirDef::Enum(def_id) |
             HirDef::TyAlias(def_id) |
-            HirDef::TyForeign(def_id) |
+            HirDef::ForeignTy(def_id) |
             HirDef::TraitAlias(def_id) |
             HirDef::AssociatedExistential(def_id) |
             HirDef::AssociatedTy(def_id) |
@@ -1050,7 +1051,7 @@ fn output_file(&self, ctx: &SaveContext) -> File {
                     .iter()
                     .any(|ct| *ct == CrateType::Executable);
                 let mut out_name = if executable {
-                    "".to_owned()
+                    String::new()
                 } else {
                     "lib".to_owned()
                 };
index 5f5cc4c5ff7c856b5a493ed715847fd6dc100d33..e4d958e3b6f3520e84ae3a76b6f6fa098a65fc25 100644 (file)
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(box_syntax)]
-#![feature(const_fn)]
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(min_const_fn))]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(slice_patterns)]
 
 #[macro_use]
index 90f8cd90c66ec576ead4159b2899c0e3984d5bc0..16dd27887faad8a254a269357e2772e570700d26 100644 (file)
@@ -21,7 +21,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         target_os: "ios".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "apple".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
index 28baf6f66e7a1dab79f5c6206dbc98bcf1a40753..8f7ee11d575eee8412d08292704091a715149ad2 100644 (file)
@@ -22,8 +22,8 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         target_os: "fuchsia".to_string(),
-        target_env: "".to_string(),
-        target_vendor: "".to_string(),
+        target_env: String::new(),
+        target_vendor: String::new(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             abi_blacklist: super::arm_base::abi_blacklist(),
index afd67112f0d6acbf39eacd285bc255cbf12ad395..540aac2c3383238f8408e5007ec0c22e93c56b1a 100644 (file)
@@ -27,7 +27,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         target_os: "android".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
index ffdb7decd0b472f787ffa6f7b462959da6617448..087b0fa543f0d61e5864565efd041a11b918b3a7 100644 (file)
@@ -24,7 +24,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         target_os: "cloudabi".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index 48177b8c79aedbfaf14f271d5729f5cdc6c33edf..541f0564a01e2cfd82f1db1efdc24e8d75cfb3dd 100644 (file)
@@ -25,7 +25,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         target_os: "freebsd".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
index 6b81c62e48b87c57077f64a2f170ade5732414eb..32fb7002026eb3057f6e5d5505dc294cfbd7ff77 100644 (file)
@@ -24,7 +24,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         target_os: "hermit".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index c300855b02187441afe6a6ead769f95c7f2c5ec1..c4afd1143fc21c952ed867de356bfc6d47ebf075 100644 (file)
@@ -23,7 +23,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         target_os: "netbsd".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index cfba0614adcd6c4b3033b27ac3acd900f874283f..1cf214d09cc7cea47091c062ffae84dce09777ae 100644 (file)
@@ -36,8 +36,8 @@ pub fn target() -> Result<Target, String> {
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
         target_os: "none".to_string(),
-        target_env: "".to_string(),
-        target_vendor: "".to_string(),
+        target_env: String::new(),
+        target_vendor: String::new(),
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
index 25817fce5ce6c579a9c2df380a1e36c0f8fb45bf..81c24fa10fac601e27ec091873da879c1223920a 100644 (file)
@@ -23,7 +23,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         target_os: "openbsd".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index ffd242b2bc20ea99055bdbf705bd2f6b8e3b0b3d..c5e3385a91ca1bd70853c4fd1ba4414e78c7f4d4 100644 (file)
@@ -24,7 +24,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "android".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
diff --git a/src/librustc_target/spec/armebv7r_none_eabi.rs b/src/librustc_target/spec/armebv7r_none_eabi.rs
new file mode 100644 (file)
index 0000000..8d3ff1b
--- /dev/null
@@ -0,0 +1,40 @@
+// 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.
+
+// Targets the Big endian Cortex-R4/R5 processor (ARMv7-R)
+
+use std::default::Default;
+use spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        llvm_target: "armebv7r-unknown-none-eabi".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        target_os: "none".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "".to_string(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+
+        options: TargetOptions {
+            executables: true,
+            linker: Some("rust-lld".to_owned()),
+            relocation_model: "static".to_string(),
+            panic_strategy: PanicStrategy::Abort,
+            max_atomic_width: Some(32),
+            abi_blacklist: super::arm_base::abi_blacklist(),
+            emit_debug_gdb_scripts: false,
+            .. Default::default()
+        },
+    })
+}
index 8bd08d355a7bc033d95296ac1f00744415245e66..0343ea7bd17e9b7712bf2ddc42b8c78bc283a675 100644 (file)
 // Targets the Cortex-R4F/R5F processor (ARMv7-R)
 
 use std::default::Default;
-use spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
-        llvm_target: "armebv7r-none-eabihf".to_string(),
+        llvm_target: "armebv7r-unknown-none-eabihf".to_string(),
         target_endian: "big".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
         data_layout: "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
-        target_env: "".to_string(),
-        target_vendor: "".to_string(),
-        linker_flavor: LinkerFlavor::Gcc,
+        target_env: String::new(),
+        target_vendor: String::new(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
 
         options: TargetOptions {
             executables: true,
+            linker: Some("rust-lld".to_owned()),
             relocation_model: "static".to_string(),
             panic_strategy: PanicStrategy::Abort,
-            features: "+v7,+vfp3,+d16,+fp-only-sp".to_string(),
+            features: "+vfp3,+d16,+fp-only-sp".to_string(),
             max_atomic_width: Some(32),
             abi_blacklist: super::arm_base::abi_blacklist(),
             emit_debug_gdb_scripts: false,
index da7cbb918bd717a6535accfd53381ac62591cafc..0f7b2ad7630e85145f1d6d1e6c87bcc699ec4d65 100644 (file)
@@ -21,7 +21,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(),
         arch: "arm".to_string(),
         target_os: "ios".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "apple".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
index cfdc5cddcfb308361f4c1bf50d77b7a95cbf7ad9..06abe0b2c9e4f3aca8a20a64451b743a2cb760d5 100644 (file)
@@ -28,7 +28,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "android".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
index 393c45e434e616f44d7c1bb9558f54a975d94aaf..44e611f04b48eab684130b00d8977479f8438f33 100644 (file)
@@ -26,7 +26,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "cloudabi".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
diff --git a/src/librustc_target/spec/armv7r_none_eabi.rs b/src/librustc_target/spec/armv7r_none_eabi.rs
new file mode 100644 (file)
index 0000000..43148d5
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Targets the Little-endian Cortex-R4/R5 processor (ARMv7-R)
+
+use std::default::Default;
+use spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        llvm_target: "armv7r-unknown-none-eabi".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        target_os: "none".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "".to_string(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+
+        options: TargetOptions {
+            executables: true,
+            linker: Some("rust-lld".to_owned()),
+            relocation_model: "static".to_string(),
+            panic_strategy: PanicStrategy::Abort,
+            max_atomic_width: Some(32),
+            abi_blacklist: super::arm_base::abi_blacklist(),
+            emit_debug_gdb_scripts: false,
+            .. Default::default()
+        },
+    })
+}
diff --git a/src/librustc_target/spec/armv7r_none_eabihf.rs b/src/librustc_target/spec/armv7r_none_eabihf.rs
new file mode 100644 (file)
index 0000000..036b054
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Targets the Little-endian Cortex-R4F/R5F processor (ARMv7-R)
+
+use std::default::Default;
+use spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        llvm_target: "armv7r-unknown-none-eabihf".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        target_os: "none".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "".to_string(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+
+        options: TargetOptions {
+            executables: true,
+            linker: Some("rust-lld".to_owned()),
+            relocation_model: "static".to_string(),
+            panic_strategy: PanicStrategy::Abort,
+            features: "+vfp3,+d16,+fp-only-sp".to_string(),
+            max_atomic_width: Some(32),
+            abi_blacklist: super::arm_base::abi_blacklist(),
+            emit_debug_gdb_scripts: false,
+            .. Default::default()
+        },
+    })
+}
index c0c577c3b8c6c1a204b768045bb2b7be1055957e..a5f35d0a773675eabf6dda72ff033a3e351e9466 100644 (file)
@@ -21,7 +21,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(),
         arch: "arm".to_string(),
         target_os: "ios".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "apple".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
index 4e716fb207fab080b4f8287f3cfe47ceea865e92..da70a3ad04d46b77249069b4b805767b4d8152e9 100644 (file)
@@ -40,7 +40,7 @@ pub fn target() -> Result<Target, String> {
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
         target_os: "emscripten".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
         arch: "asmjs".to_string(),
index 9eb0327f625ccde7aa9b955d12426244113a6938..15fd384f9ced389543633cb7e353659f721265a3 100644 (file)
@@ -21,7 +21,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128".to_string(),
         arch: "x86".to_string(),
         target_os: "ios".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "apple".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
index d17789dfcc07feb929e520e26038d99774a56668..a298b550fea6570d45ad3e3cb488df3b65e17d9d 100644 (file)
@@ -26,7 +26,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128".to_string(),
         arch: "x86".to_string(),
         target_os: "macos".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "apple".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index 171e08995954535c9a80286f469c03f20c21f845..6aa139893eba1af85a40ec35fa093a82298417c5 100644 (file)
@@ -31,7 +31,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
         arch: "x86".to_string(),
         target_os: "android".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index 335105bb1a869519f9aac1da780bc39a4a91858e..637bca71add71e22321100831017e1450d16ea7c 100644 (file)
@@ -26,7 +26,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
         arch: "x86".to_string(),
         target_os: "cloudabi".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index cb0c471353b307be6cadde616c2ffa243851a97c..fa02f0dd634519f7082b0ea633c0a8900885c81a 100644 (file)
@@ -25,7 +25,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
         arch: "x86".to_string(),
         target_os: "dragonfly".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index 3838a157d10b5f0bb6b7e5a74982e9bd38d1923d..e11a455911d75b4441838e7d1f21abc4be62eac1 100644 (file)
@@ -25,7 +25,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
         arch: "x86".to_string(),
         target_os: "freebsd".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index 98f0787bebaf8e8a04358d8d3c373d811efa7260..775d80b0cfd7e345d7a2cbee1637b81e3d31fa20 100644 (file)
@@ -25,7 +25,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
         arch: "x86".to_string(),
         target_os: "haiku".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index d60ed9885991d7f9dfaa663bc2fa2b3c2dbcf8cb..a9c0c11aab5c6220d6e00d0138dd6fe6f0fc0357 100644 (file)
@@ -25,7 +25,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
         arch: "x86".to_string(),
         target_os: "netbsd".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index f22bf2abe4501f23c30760651c2f67dca6f9cb2c..471d6bd475603739b9ec43b80e569f85c0af4649 100644 (file)
@@ -26,7 +26,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
         arch: "x86".to_string(),
         target_os: "openbsd".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index 4a8ae69b2383e80dc98737651f362961955b01dd..2514909ba75f3082a490e5ede673aa3d0bb3edd1 100644 (file)
@@ -74,6 +74,7 @@
 mod l4re_base;
 mod fuchsia_base;
 mod redox_base;
+mod riscv_base;
 
 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
          RustcEncodable, RustcDecodable)]
@@ -370,7 +371,10 @@ fn $module() {
     ("armv7-apple-ios", armv7_apple_ios),
     ("armv7s-apple-ios", armv7s_apple_ios),
 
+    ("armebv7r-none-eabi", armebv7r_none_eabi),
     ("armebv7r-none-eabihf", armebv7r_none_eabihf),
+    ("armv7r-none-eabi", armv7r_none_eabi),
+    ("armv7r-none-eabihf", armv7r_none_eabihf),
 
     ("x86_64-sun-solaris", x86_64_sun_solaris),
     ("sparcv9-sun-solaris", sparcv9_sun_solaris),
@@ -403,6 +407,7 @@ fn $module() {
     ("aarch64-unknown-hermit", aarch64_unknown_hermit),
     ("x86_64-unknown-hermit", x86_64_unknown_hermit),
 
+    ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
     ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
 
     ("aarch64-unknown-none", aarch64_unknown_none),
@@ -686,7 +691,7 @@ fn default() -> TargetOptions {
             post_link_args: LinkArgs::new(),
             asm_args: Vec::new(),
             cpu: "generic".to_string(),
-            features: "".to_string(),
+            features: String::new(),
             dynamic_linking: false,
             only_cdylib: false,
             executables: false,
@@ -698,7 +703,7 @@ fn default() -> TargetOptions {
             function_sections: true,
             dll_prefix: "lib".to_string(),
             dll_suffix: ".so".to_string(),
-            exe_suffix: "".to_string(),
+            exe_suffix: String::new(),
             staticlib_prefix: "lib".to_string(),
             staticlib_suffix: ".a".to_string(),
             target_family: None,
index 3ac4c459c63841dcbff1eafea39f8c2e6c4e783b..0958a958986933d589232710c7e7fb9eda4e7e89 100644 (file)
@@ -19,8 +19,8 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16".to_string(),
         arch: "msp430".to_string(),
         target_os: "none".to_string(),
-        target_env: "".to_string(),
-        target_vendor: "".to_string(),
+        target_env: String::new(),
+        target_vendor: String::new(),
         linker_flavor: LinkerFlavor::Gcc,
 
         options: TargetOptions {
index c05e40b9c25d7253ad12b545a1c3912dccffd551..740222c9608054400464792a6e1901b732297cf9 100644 (file)
@@ -26,7 +26,7 @@ pub fn target() -> TargetResult {
         data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
         arch: "powerpc".to_string(),
         target_os: "netbsd".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index f8cd1b5b81207b95a5ded060b4bf72ad36b4aa58..b199a50f0ca389a3d8faa5e0e37c54481823fde9 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
-use spec::abi::{Abi};
+use spec::{LinkerFlavor, LldFlavor, PanicStrategy,
+           Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -19,34 +19,22 @@ pub fn target() -> TargetResult {
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
         target_os: "none".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         arch: "riscv32".to_string(),
-        linker_flavor: LinkerFlavor::Ld,
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
 
         options: TargetOptions {
-            linker: Some("riscv32-unknown-elf-ld".to_string()),
+            linker: Some("rust-lld".to_string()),
             cpu: "generic-rv32".to_string(),
             max_atomic_width: Some(32),
             atomic_cas: false, // incomplete +a extension
-            features: "+m,+a".to_string(), // disable +c extension
+            features: "+m,+a,+c".to_string(),
             executables: true,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: "static".to_string(),
             emit_debug_gdb_scripts: false,
-            abi_blacklist: vec![
-                Abi::Cdecl,
-                Abi::Stdcall,
-                Abi::Fastcall,
-                Abi::Vectorcall,
-                Abi::Thiscall,
-                Abi::Aapcs,
-                Abi::Win64,
-                Abi::SysV64,
-                Abi::PtxKernel,
-                Abi::Msp430Interrupt,
-                Abi::X86Interrupt,
-            ],
+            abi_blacklist: super::riscv_base::abi_blacklist(),
             .. Default::default()
         },
     })
diff --git a/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs b/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs
new file mode 100644 (file)
index 0000000..68da1b6
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use spec::{LinkerFlavor, LldFlavor, PanicStrategy,
+           Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
+        llvm_target: "riscv32".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        target_os: "none".to_string(),
+        target_env: String::new(),
+        target_vendor: "unknown".to_string(),
+        arch: "riscv32".to_string(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+
+        options: TargetOptions {
+            linker: Some("rust-lld".to_string()),
+            cpu: "generic-rv32".to_string(),
+            // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86005
+            max_atomic_width: None, //Some(32),
+            atomic_cas: false,
+            features: "+m,+c".to_string(),
+            executables: true,
+            panic_strategy: PanicStrategy::Abort,
+            relocation_model: "static".to_string(),
+            emit_debug_gdb_scripts: false,
+            abi_blacklist: super::riscv_base::abi_blacklist(),
+            .. Default::default()
+        },
+    })
+}
diff --git a/src/librustc_target/spec/riscv_base.rs b/src/librustc_target/spec/riscv_base.rs
new file mode 100644 (file)
index 0000000..701ddf5
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use spec::abi::Abi;
+
+// All the calling conventions trigger an assertion(Unsupported calling
+// convention) in llvm on RISCV
+pub fn abi_blacklist() -> Vec<Abi> {
+    vec![
+        Abi::Cdecl,
+        Abi::Stdcall,
+        Abi::Fastcall,
+        Abi::Vectorcall,
+        Abi::Thiscall,
+        Abi::Aapcs,
+        Abi::Win64,
+        Abi::SysV64,
+        Abi::PtxKernel,
+        Abi::Msp430Interrupt,
+        Abi::X86Interrupt,
+        Abi::AmdGpuKernel,
+    ]
+}
index 1c1bca9b2b87923baa2297e25f97cf11dcbfc472..c663aa344daf8c080665be9ca22278df74b18763 100644 (file)
@@ -24,7 +24,7 @@ pub fn target() -> TargetResult {
         data_layout: "E-m:e-i64:64-n32:64-S128".to_string(),
         arch: "sparc64".to_string(),
         target_os: "netbsd".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index 7dea1b75a3c582848684c8afeca09f715cba49b0..8bc233107b8bb5bf1c49616c65392bb7c76e2c5c 100644 (file)
@@ -30,7 +30,7 @@ pub fn target() -> TargetResult {
         // just be confusing.
         arch: "sparc64".to_string(),
         target_os: "solaris".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "sun".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index fdaf1dc6110b5b539741ceeb3641c9174f3d4d44..4c9a4764eff4097d47067c8aca8a71dff46cd82b 100644 (file)
@@ -42,9 +42,8 @@ pub fn opts() -> TargetOptions {
     // See rust-lang/rfcs#1645 for a discussion about these defaults
     TargetOptions {
         executables: true,
-        // In 99%+ of cases, we want to use the `arm-none-eabi-gcc` compiler (there aren't many
-        // options around)
-        linker: Some("arm-none-eabi-gcc".to_string()),
+        // In most cases, LLD is good enough
+        linker: Some("rust-lld".to_string()),
         // Because these devices have very little resources having an unwinder is too onerous so we
         // default to "abort" because the "unwind" strategy is very rare.
         panic_strategy: PanicStrategy::Abort,
index 26812501814f535b863a24fbea689124de91ab27..99034277abd58eba6071958f5dc7d0e2732a462c 100644 (file)
@@ -10,7 +10,7 @@
 
 // Targets the Cortex-M0, Cortex-M0+ and Cortex-M1 processors (ARMv6-M architecture)
 
-use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -21,9 +21,9 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
-        target_env: "".to_string(),
-        target_vendor: "".to_string(),
-        linker_flavor: LinkerFlavor::Gcc,
+        target_env: String::new(),
+        target_vendor: String::new(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
 
         options: TargetOptions {
             // The ARMv6-M architecture doesn't support unaligned loads/stores so we disable them
index ab85c97b1b5ba07bae4fb84d6fe4b7e29e168dac..17fad29dd29685c3d7a83babe6a42a16d36c5ab3 100644 (file)
@@ -19,7 +19,7 @@
 // To opt-in to hardware accelerated floating point operations, you can use, for example,
 // `-C target-feature=+vfp4` or `-C target-cpu=cortex-m4`.
 
-use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -30,9 +30,9 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
-        target_env: "".to_string(),
-        target_vendor: "".to_string(),
-        linker_flavor: LinkerFlavor::Gcc,
+        target_env: String::new(),
+        target_vendor: String::new(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
 
         options: TargetOptions {
             max_atomic_width: Some(32),
index 4e62f29134edf7e721f1ce546f3dec4e77c51af2..02ede112ed3c649d14decc5bf58c12ad740c6068 100644 (file)
@@ -18,7 +18,7 @@
 //
 // To opt into double precision hardware support, use the `-C target-feature=-fp-only-sp` flag.
 
-use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -29,9 +29,9 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
-        target_env: "".to_string(),
-        target_vendor: "".to_string(),
-        linker_flavor: LinkerFlavor::Gcc,
+        target_env: String::new(),
+        target_vendor: String::new(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
 
         options: TargetOptions {
             // `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the
index 10dc503388afe610bd3c77e9a12b5d8f2926dcfd..f4fffade16351c7de1a8bc0c12e9bc34029deea9 100644 (file)
@@ -10,7 +10,7 @@
 
 // Targets the Cortex-M3 processor (ARMv7-M)
 
-use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -21,9 +21,9 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
-        target_env: "".to_string(),
-        target_vendor: "".to_string(),
-        linker_flavor: LinkerFlavor::Gcc,
+        target_env: String::new(),
+        target_vendor: String::new(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
 
         options: TargetOptions {
             max_atomic_width: Some(32),
index 164df20f84f344841f8e54a8ef58d645bdf625b7..60ad2d232493324c8208480036be3310fe76e6fb 100644 (file)
@@ -43,7 +43,7 @@ pub fn target() -> Result<Target, String> {
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
         target_os: "emscripten".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(),
         arch: "wasm32".to_string(),
index 5077abf1e0eb37b3bb95b2308f21cca0b3d5d53c..b4c09f86b8a97c96c34bd96513a8e20b02b5c38d 100644 (file)
@@ -40,7 +40,7 @@ pub fn target() -> Result<Target, String> {
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
         target_os: "emscripten".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
         arch: "wasm32".to_string(),
index 94e7739b1a05afe66191e8fbd5bebb5dbacf91f8..6c368e09003a39afc7a9aeed62242944a3908735 100644 (file)
@@ -32,7 +32,7 @@ pub fn target() -> Result<Target, String> {
 
         // relatively self-explanatory!
         exe_suffix: ".wasm".to_string(),
-        dll_prefix: "".to_string(),
+        dll_prefix: String::new(),
         dll_suffix: ".wasm".to_string(),
         linker_is_gnu: false,
 
@@ -65,7 +65,7 @@ pub fn target() -> Result<Target, String> {
         // This is basically guaranteed to change in the future, don't rely on
         // this. Use `not(target_os = "emscripten")` for now.
         target_os: "unknown".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(),
         arch: "wasm32".to_string(),
index 176df9f13253d4a59c0cda4d6d0ac6830848a0b6..29049b1427570ce4616541f40baab69dd8c4e83c 100644 (file)
@@ -77,10 +77,10 @@ pub fn opts() -> TargetOptions {
         linker: Some("gcc".to_string()),
         dynamic_linking: true,
         executables: true,
-        dll_prefix: "".to_string(),
+        dll_prefix: String::new(),
         dll_suffix: ".dll".to_string(),
         exe_suffix: ".exe".to_string(),
-        staticlib_prefix: "".to_string(),
+        staticlib_prefix: String::new(),
         staticlib_suffix: ".lib".to_string(),
         no_default_libraries: true,
         target_family: Some("windows".to_string()),
index 1f00e690cd3520f71c7feaed28cd5e685ba20a24..27879de9ab55678ab651c14655d7fe146373d186 100644 (file)
@@ -21,10 +21,10 @@ pub fn opts() -> TargetOptions {
         function_sections: true,
         dynamic_linking: true,
         executables: true,
-        dll_prefix: "".to_string(),
+        dll_prefix: String::new(),
         dll_suffix: ".dll".to_string(),
         exe_suffix: ".exe".to_string(),
-        staticlib_prefix: "".to_string(),
+        staticlib_prefix: String::new(),
         staticlib_suffix: ".lib".to_string(),
         target_family: Some("windows".to_string()),
         is_like_windows: true,
index a4efd7e0066ff6de14fdc80615ccd97b18277280..150590ba68d7656df426a5d97d1d1e301917c8bc 100644 (file)
@@ -26,7 +26,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(),
         arch: "x86_64".to_string(),
         target_os: "macos".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "apple".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index eeb53d72fe8a3f78b6f8eb086595ba35404d1c73..e184ec2435878a5233f593728e79114a194af36b 100644 (file)
@@ -21,7 +21,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(),
         arch: "x86_64".to_string(),
         target_os: "ios".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "apple".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
index e8fa179887c8762cad24244104a6476398f372c9..62148a740dff56833b1495b1f823d7652c429d96 100644 (file)
@@ -25,8 +25,8 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
         arch: "x86_64".to_string(),
         target_os: "fuchsia".to_string(),
-        target_env: "".to_string(),
-        target_vendor: "".to_string(),
+        target_env: String::new(),
+        target_vendor: String::new(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
index 06abe916784dc5625bea03d6d891b37b9e2905f4..ea67dc6bdef12fa8af328193aeb8ce21c2b84825 100644 (file)
@@ -27,7 +27,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
         arch: "x86_64".to_string(),
         target_os: "android".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index ed15cfd9036f5c7b9362c4f4d77b7fa3bb519cc6..af846653af7274eecad7aeef551bc9fd3bee3946 100644 (file)
@@ -33,7 +33,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
         arch: "x86_64".to_string(),
         target_os: "netbsd".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "rumprun".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index e84f21c500664da2b9b1d661f2211733152b703e..beb23dce06249a6782d681f6237514ef947e16ed 100644 (file)
@@ -25,7 +25,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
         arch: "x86_64".to_string(),
         target_os: "solaris".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "sun".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index 21ec6dffcbbce6248d767b3202743b78b57ca154..a98fc80716bcb40d069941b374aa2b29658bab60 100644 (file)
@@ -25,7 +25,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
         arch: "x86_64".to_string(),
         target_os: "bitrig".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index 8dc8bd7a7fad914dbe1949eabc66222ca1325486..16df9000683b7d9972b49bef979ac53def99ed68 100644 (file)
@@ -26,7 +26,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
         arch: "x86_64".to_string(),
         target_os: "cloudabi".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index 50b2871c2ee9c986f383d391fd5404fc8379b206..4c14a321febe6159865635e03dc29608fe3d79c3 100644 (file)
@@ -25,7 +25,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
         arch: "x86_64".to_string(),
         target_os: "dragonfly".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index f0aa81ed4598b2b8acd6ac4281e821bf41773326..4515b3308717eaa0234e5361ad067555c12575fe 100644 (file)
@@ -25,7 +25,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
         arch: "x86_64".to_string(),
         target_os: "freebsd".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index 68fa58b922019f9453bd7bd672cb68f537601a41..7e6b56866e4c70e250619cc65bdf2f7246831661 100644 (file)
@@ -27,7 +27,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
         arch: "x86_64".to_string(),
         target_os: "haiku".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index 9f9f2e6ec43e9bbde72d01e86f94c6b5d639fc60..c879e94e6e65a67f83bcb29405318e94c9b03cdf 100644 (file)
@@ -25,7 +25,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
         arch: "x86_64".to_string(),
         target_os: "hermit".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index 6e8ca6b9e19914be97a9f27341a9198f83adf8e8..de53c9e99ed86a5d900c2a0b211bb62bd3820fb7 100644 (file)
@@ -25,7 +25,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
         arch: "x86_64".to_string(),
         target_os: "netbsd".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index c60b7c86680f810987cbb1ff2e2f0ff62bfa51ee..de22c77d1e0561b316e56c3a565afc6c858f83dd 100644 (file)
@@ -25,7 +25,7 @@ pub fn target() -> TargetResult {
         data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
         arch: "x86_64".to_string(),
         target_os: "openbsd".to_string(),
-        target_env: "".to_string(),
+        target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index 548dfb06109ff41bee2432799fe9ccd9e4225aa7..12a354b499efa871cae21abb7526ab824c29756a 100644 (file)
@@ -25,7 +25,7 @@ pub fn target() -> TargetResult {
         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_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
index 3e1a6ca9aff7c33f40db6c5540cc8ee71428749d..cd21ee601a7d2d47ffe0204b78cdfaac12bbb4a5 100644 (file)
@@ -17,3 +17,4 @@ rustc_data_structures = { path = "../librustc_data_structures" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 chalk-engine = { version = "0.7.0", default-features=false }
+smallvec = { version = "0.6.5", features = ["union"] }
index b0f0b105f3ecb92f3286cd0f9309be2612e59a37..4c28df97bdf50a5024907237b2699463f6ca45b0 100644 (file)
@@ -25,7 +25,7 @@
 use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use rustc::ty::subst::Kind;
 use rustc::ty::{self, TyCtxt};
-use rustc_data_structures::small_vec::SmallVec;
+use smallvec::SmallVec;
 
 use std::fmt::{self, Debug};
 use std::marker::PhantomData;
@@ -237,7 +237,7 @@ fn map_subst_from_canonical(
 //                    _ => false,
 //                },
 //                Kind::Type(ty) => match ty.sty {
-//                    ty::TyInfer(ty::InferTy::CanonicalTy(cvar1)) => cvar == cvar1,
+//                    ty::Infer(ty::InferTy::CanonicalTy(cvar1)) => cvar == cvar1,
 //                    _ => false,
 //                },
 //            })
index 8bffecfc7c90110b82c14d2e1bab30ea273686d2..a27a447ad4b0959d3b8101d69a18444347344c9d 100644 (file)
@@ -81,7 +81,7 @@ fn dropck_outlives<'tcx>(
         // into the types of its fields `(B, Vec<A>)`. These will get
         // pushed onto the stack. Eventually, expanding `Vec<A>` will
         // lead to us trying to push `A` a second time -- to prevent
-        // infinite recusion, we notice that `A` was already pushed
+        // infinite recursion, we notice that `A` was already pushed
         // once and stop.
         let mut ty_stack = vec![(for_ty, 0)];
 
@@ -119,11 +119,11 @@ fn dropck_outlives<'tcx>(
                         match ty.sty {
                             // All parameters live for the duration of the
                             // function.
-                            ty::TyParam(..) => {}
+                            ty::Param(..) => {}
 
                             // A projection that we couldn't resolve - it
                             // might have a destructor.
-                            ty::TyProjection(..) | ty::TyAnon(..) => {
+                            ty::Projection(..) | ty::Anon(..) => {
                                 result.kinds.push(ty.into());
                             }
 
@@ -173,39 +173,39 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
     }
 
     let result = match ty.sty {
-        ty::TyBool
-        | ty::TyChar
-        | ty::TyInt(_)
-        | ty::TyUint(_)
-        | ty::TyFloat(_)
-        | ty::TyStr
-        | ty::TyNever
-        | ty::TyForeign(..)
-        | ty::TyRawPtr(..)
-        | ty::TyRef(..)
-        | ty::TyFnDef(..)
-        | ty::TyFnPtr(_)
-        | ty::TyGeneratorWitness(..) => {
+        ty::Bool
+        | ty::Char
+        | ty::Int(_)
+        | ty::Uint(_)
+        | ty::Float(_)
+        | ty::Str
+        | ty::Never
+        | ty::Foreign(..)
+        | ty::RawPtr(..)
+        | ty::Ref(..)
+        | ty::FnDef(..)
+        | ty::FnPtr(_)
+        | ty::GeneratorWitness(..) => {
             // these types never have a destructor
             Ok(DtorckConstraint::empty())
         }
 
-        ty::TyArray(ety, _) | ty::TySlice(ety) => {
+        ty::Array(ety, _) | ty::Slice(ety) => {
             // single-element containers, behave like their element
             dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ety)
         }
 
-        ty::TyTuple(tys) => tys
+        ty::Tuple(tys) => tys
             .iter()
             .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
             .collect(),
 
-        ty::TyClosure(def_id, substs) => substs
+        ty::Closure(def_id, substs) => substs
             .upvar_tys(def_id, tcx)
             .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
             .collect(),
 
-        ty::TyGenerator(def_id, substs, _movability) => {
+        ty::Generator(def_id, substs, _movability) => {
             // rust-lang/rust#49918: types can be constructed, stored
             // in the interior, and sit idle when generator yields
             // (and is subsequently dropped).
@@ -216,7 +216,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
             // its interior).
             //
             // However, the interior's representation uses things like
-            // TyGeneratorWitness that explicitly assume they are not
+            // GeneratorWitness that explicitly assume they are not
             // traversed in such a manner. So instead, we will
             // simplify things for now by treating all generators as
             // if they were like trait objects, where its upvars must
@@ -242,7 +242,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
             Ok(constraint)
         }
 
-        ty::TyAdt(def, substs) => {
+        ty::Adt(def, substs) => {
             let DtorckConstraint {
                 dtorck_types,
                 outlives,
@@ -259,20 +259,20 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
 
         // Objects must be alive in order for their destructor
         // to be called.
-        ty::TyDynamic(..) => Ok(DtorckConstraint {
+        ty::Dynamic(..) => Ok(DtorckConstraint {
             outlives: vec![ty.into()],
             dtorck_types: vec![],
             overflows: vec![],
         }),
 
         // Types that can't be resolved. Pass them forward.
-        ty::TyProjection(..) | ty::TyAnon(..) | ty::TyParam(..) => Ok(DtorckConstraint {
+        ty::Projection(..) | ty::Anon(..) | ty::Param(..) => Ok(DtorckConstraint {
             outlives: vec![],
             dtorck_types: vec![ty],
             overflows: vec![],
         }),
 
-        ty::TyInfer(..) | ty::TyError => {
+        ty::Infer(..) | ty::Error => {
             // By the time this code runs, all type variables ought to
             // be fully resolved.
             Err(NoSolution)
index ba6b2c57bfac6a15f71b9058d578b75c90957e3b..971dfa751f11a300c5679575c6e33796bc8b521b 100644 (file)
@@ -14,9 +14,9 @@
 #![feature(crate_in_paths)]
 #![feature(crate_visibility_modifier)]
 #![feature(extern_prelude)]
-#![feature(iterator_find_map)]
 #![feature(in_band_lifetimes)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 
 #![recursion_limit="256"]
 
@@ -28,6 +28,7 @@
 extern crate rustc_data_structures;
 extern crate syntax;
 extern crate syntax_pos;
+extern crate smallvec;
 
 mod chalk_context;
 mod dropck_outlives;
index a3c24f8af22fc5b3ae72c5a9aa363e400b98749a..9fd3b318ec14038ef7ff1bf9c5b81b5badcc1125 100644 (file)
@@ -17,7 +17,7 @@
     WhereClause,
 };
 use rustc::ty::query::Providers;
-use rustc::ty::{self, Slice, TyCtxt};
+use rustc::ty::{self, List, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
 use std::mem;
 use syntax::ast;
@@ -162,7 +162,7 @@ fn into_well_formed_goal(self) -> DomainGoal<'tcx> {
         DefPathData::AssocTypeInImpl(..) => program_clauses_for_associated_type_value(tcx, def_id),
         DefPathData::AssocTypeInTrait(..) => program_clauses_for_associated_type_def(tcx, def_id),
         DefPathData::TypeNs(..) => program_clauses_for_type_def(tcx, def_id),
-        _ => Slice::empty(),
+        _ => List::empty(),
     }
 }
 
@@ -319,7 +319,7 @@ fn program_clauses_for_trait<'a, 'tcx>(
 
 fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Clauses<'tcx> {
     if let ImplPolarity::Negative = tcx.impl_polarity(def_id) {
-        return Slice::empty();
+        return List::empty();
     }
 
     // Rule Implemented-From-Impl (see rustc guide)
index b3ba86ad8a4b32af8f7f6629cca53f8891221b8f..ed8fd305977e5e9b7a71359411211774d4d81420 100644 (file)
@@ -11,6 +11,7 @@
 #![sanitizer_runtime]
 #![feature(alloc_system)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(sanitizer_runtime)]
 #![feature(staged_api)]
 #![no_std]
index 184cb9826ba680a96152a87e7aee7b942b9a9536..881fa2604bc8b9dec1b1cc70870c3cf93be771c4 100644 (file)
@@ -10,12 +10,13 @@ crate-type = ["dylib"]
 test = false
 
 [dependencies]
-log = "0.4"
-syntax = { path = "../libsyntax" }
 arena = { path = "../libarena" }
+log = "0.4"
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
 rustc_target = { path = "../librustc_target" }
+smallvec = { version = "0.6.5", features = ["union"] }
+syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
-rustc_errors = { path = "../librustc_errors" }
index ccdb751bc4eeda4eb743283bd6104768313f215b..804aad3c0ecce29b86d51c9025ee1ce13ea96b48 100644 (file)
@@ -12,8 +12,7 @@
 //! representation.  The main routine here is `ast_ty_to_ty()`: each use
 //! is parameterized by an instance of `AstConv`.
 
-use rustc_data_structures::accumulate_vec::AccumulateVec;
-use rustc_data_structures::array_vec::ArrayVec;
+use smallvec::SmallVec;
 use hir::{self, GenericArg, GenericArgs};
 use hir::def::Def;
 use hir::def_id::DefId;
@@ -99,16 +98,10 @@ enum GenericArgPosition {
     MethodCall,
 }
 
-// FIXME(#53525): these error codes should all be unified.
-struct GenericArgMismatchErrorCode {
-    lifetimes: (&'static str, &'static str),
-    types: (&'static str, &'static str),
-}
-
 /// Dummy type used for the `Self` of a `TraitRef` created for converting
 /// a trait object, and which gets removed in `ExistentialTraitRef`.
 /// This type must not appear anywhere in other converted types.
-const TRAIT_OBJECT_DUMMY_SELF: ty::TypeVariants<'static> = ty::TyInfer(ty::FreshTy(0));
+const TRAIT_OBJECT_DUMMY_SELF: ty::TyKind<'static> = ty::Infer(ty::FreshTy(0));
 
 impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
     pub fn ast_region_to_region(&self,
@@ -262,10 +255,6 @@ pub fn check_generic_arg_count_for_call(
             },
             def.parent.is_none() && def.has_self, // `has_self`
             seg.infer_types || suppress_mismatch, // `infer_types`
-            GenericArgMismatchErrorCode {
-                lifetimes: ("E0090", "E0088"),
-                types: ("E0089", "E0087"),
-            },
         )
     }
 
@@ -279,7 +268,6 @@ fn check_generic_arg_count(
         position: GenericArgPosition,
         has_self: bool,
         infer_types: bool,
-        error_codes: GenericArgMismatchErrorCode,
     ) -> bool {
         // At this stage we are guaranteed that the generic arguments are in the correct order, e.g.
         // that lifetimes will proceed types. So it suffices to check the number of each generic
@@ -325,8 +313,7 @@ fn check_generic_arg_count(
             }
         }
 
-        let check_kind_count = |error_code: (&str, &str),
-                                kind,
+        let check_kind_count = |kind,
                                 required,
                                 permitted,
                                 provided,
@@ -371,7 +358,7 @@ fn check_generic_arg_count(
                     quantifier,
                     bound,
                     kind,
-                    if required != 1 { "s" } else { "" },
+                    if bound != 1 { "s" } else { "" },
                 )
             };
 
@@ -384,13 +371,7 @@ fn check_generic_arg_count(
                     bound,
                     provided,
                 ),
-                DiagnosticId::Error({
-                    if provided <= permitted {
-                        error_code.0
-                    } else {
-                        error_code.1
-                    }
-                }.into())
+                DiagnosticId::Error("E0107".into())
             ).span_label(span, label).emit();
 
             provided > required // `suppress_error`
@@ -398,7 +379,6 @@ fn check_generic_arg_count(
 
         if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes {
             check_kind_count(
-                error_codes.lifetimes,
                 "lifetime",
                 param_counts.lifetimes,
                 param_counts.lifetimes,
@@ -409,7 +389,6 @@ fn check_generic_arg_count(
         if !infer_types
             || arg_counts.types > param_counts.types - defaults.types - has_self as usize {
             check_kind_count(
-                error_codes.types,
                 "type",
                 param_counts.types - defaults.types - has_self as usize,
                 param_counts.types - has_self as usize,
@@ -451,18 +430,7 @@ pub fn create_substs_for_generic_args<'a, 'b, A, P, I>(
         // We manually build up the substitution, rather than using convenience
         // methods in subst.rs so that we can iterate over the arguments and
         // parameters in lock-step linearly, rather than trying to match each pair.
-        let mut substs: AccumulateVec<[Kind<'tcx>; 8]> = if count <= 8 {
-            AccumulateVec::Array(ArrayVec::new())
-        } else {
-            AccumulateVec::Heap(Vec::with_capacity(count))
-        };
-
-        fn push_kind<'tcx>(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>, kind: Kind<'tcx>) {
-            match substs {
-                AccumulateVec::Array(ref mut arr) => arr.push(kind),
-                AccumulateVec::Heap(ref mut vec) => vec.push(kind),
-            }
-        }
+        let mut substs: SmallVec<[Kind<'tcx>; 8]> = SmallVec::with_capacity(count);
 
         // Iterate over each segment of the path.
         while let Some((def_id, defs)) = stack.pop() {
@@ -471,7 +439,7 @@ pub fn create_substs_for_generic_args<'a, 'b, A, P, I>(
             // If we have already computed substitutions for parents, we can use those directly.
             while let Some(&param) = params.peek() {
                 if let Some(&kind) = parent_substs.get(param.index as usize) {
-                    push_kind(&mut substs, kind);
+                    substs.push(kind);
                     params.next();
                 } else {
                     break;
@@ -483,7 +451,7 @@ pub fn create_substs_for_generic_args<'a, 'b, A, P, I>(
                 if let Some(&param) = params.peek() {
                     if param.index == 0 {
                         if let GenericParamDefKind::Type { .. } = param.kind {
-                            push_kind(&mut substs, self_ty.map(|ty| ty.into())
+                            substs.push(self_ty.map(|ty| ty.into())
                                 .unwrap_or_else(|| inferred_kind(None, param, true)));
                             params.next();
                         }
@@ -507,7 +475,7 @@ pub fn create_substs_for_generic_args<'a, 'b, A, P, I>(
                         match (arg, &param.kind) {
                             (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime)
                             | (GenericArg::Type(_), GenericParamDefKind::Type { .. }) => {
-                                push_kind(&mut substs, provided_kind(param, arg));
+                                substs.push(provided_kind(param, arg));
                                 args.next();
                                 params.next();
                             }
@@ -521,7 +489,7 @@ pub fn create_substs_for_generic_args<'a, 'b, A, P, I>(
                             (GenericArg::Type(_), GenericParamDefKind::Lifetime) => {
                                 // We expected a lifetime argument, but got a type
                                 // argument. That means we're inferring the lifetimes.
-                                push_kind(&mut substs, inferred_kind(None, param, infer_types));
+                                substs.push(inferred_kind(None, param, infer_types));
                                 params.next();
                             }
                         }
@@ -538,7 +506,7 @@ pub fn create_substs_for_generic_args<'a, 'b, A, P, I>(
                         match param.kind {
                             GenericParamDefKind::Lifetime | GenericParamDefKind::Type { .. } => {
                                 let kind = inferred_kind(Some(&substs), param, infer_types);
-                                push_kind(&mut substs, kind);
+                                substs.push(kind);
                             }
                         }
                         args.next();
@@ -587,10 +555,6 @@ fn create_substs_for_ast_path(&self,
             GenericArgPosition::Type,
             has_self,
             infer_types,
-            GenericArgMismatchErrorCode {
-                lifetimes: ("E0107", "E0107"),
-                types: ("E0243", "E0244"),
-            },
         );
 
         let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
@@ -1065,7 +1029,7 @@ fn conv_object_ty_poly_trait_ref(&self,
             .chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait))
             .chain(existential_projections
                    .map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder())))
-            .collect::<AccumulateVec<[_; 8]>>();
+            .collect::<SmallVec<[_; 8]>>();
         v.sort_by(|a, b| a.stable_cmp(tcx, b));
         let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter()));
 
@@ -1239,8 +1203,8 @@ pub fn associated_path_def_to_ty(&self,
                     Err(ErrorReported) => return (tcx.types.err, Def::Err),
                 }
             }
-            (&ty::TyParam(_), Def::SelfTy(Some(param_did), None)) |
-            (&ty::TyParam(_), Def::TyParam(param_did)) => {
+            (&ty::Param(_), Def::SelfTy(Some(param_did), None)) |
+            (&ty::Param(_), Def::TyParam(param_did)) => {
                 match self.find_bound_for_assoc_item(param_did, assoc_name, span) {
                     Ok(bound) => bound,
                     Err(ErrorReported) => return (tcx.types.err, Def::Err),
@@ -1367,7 +1331,7 @@ pub fn def_to_ty(&self,
                      -> Ty<'tcx> {
         let tcx = self.tcx();
 
-        debug!("base_def_to_ty(def={:?}, opt_self_ty={:?}, path_segments={:?})",
+        debug!("def_to_ty(def={:?}, opt_self_ty={:?}, path_segments={:?})",
                path.def, opt_self_ty, path.segments);
 
         let span = path.span;
@@ -1387,7 +1351,7 @@ pub fn def_to_ty(&self,
                 )
             }
             Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) |
-            Def::Union(did) | Def::TyForeign(did) => {
+            Def::Union(did) | Def::ForeignTy(did) => {
                 assert_eq!(opt_self_ty, None);
                 self.prohibit_generics(path.segments.split_last().unwrap().1);
                 self.ast_path_to_ty(span, did, path.segments.last().unwrap())
@@ -1438,12 +1402,12 @@ pub fn def_to_ty(&self,
                 assert_eq!(opt_self_ty, None);
                 self.prohibit_generics(&path.segments);
                 match prim_ty {
-                    hir::TyBool => tcx.types.bool,
-                    hir::TyChar => tcx.types.char,
-                    hir::TyInt(it) => tcx.mk_mach_int(it),
-                    hir::TyUint(uit) => tcx.mk_mach_uint(uit),
-                    hir::TyFloat(ft) => tcx.mk_mach_float(ft),
-                    hir::TyStr => tcx.mk_str()
+                    hir::Bool => tcx.types.bool,
+                    hir::Char => tcx.types.char,
+                    hir::Int(it) => tcx.mk_mach_int(it),
+                    hir::Uint(uit) => tcx.mk_mach_uint(uit),
+                    hir::Float(ft) => tcx.mk_mach_float(ft),
+                    hir::Str => tcx.mk_str()
                 }
             }
             Def::Err => {
@@ -1474,7 +1438,7 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
             }
             hir::TyKind::Rptr(ref region, ref mt) => {
                 let r = self.ast_region_to_region(region, None);
-                debug!("TyRef r={:?}", r);
+                debug!("Ref r={:?}", r);
                 let t = self.ast_ty_to_ty(&mt.ty);
                 tcx.mk_ref(r, ty::TypeAndMut {ty: t, mutbl: mt.mutbl})
             }
@@ -1513,7 +1477,7 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
                 let length_def_id = tcx.hir.local_def_id(length.id);
                 let substs = Substs::identity_for_item(tcx, length_def_id);
                 let length = ty::Const::unevaluated(tcx, length_def_id, substs, tcx.types.usize);
-                let array_ty = tcx.mk_ty(ty::TyArray(self.ast_ty_to_ty(&ty), length));
+                let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length));
                 self.normalize_ty(ast_ty.span, array_ty)
             }
             hir::TyKind::Typeof(ref _e) => {
@@ -1525,7 +1489,7 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
                 tcx.types.err
             }
             hir::TyKind::Infer => {
-                // TyInfer also appears as the type of arguments or return
+                // Infer also appears as the type of arguments or return
                 // values in a ExprKind::Closure, or as
                 // the type of local variables. Both of these cases are
                 // handled specially and will not descend into this routine.
@@ -1666,7 +1630,7 @@ pub fn ty_of_fn(&self,
     /// we return `None`.
     fn compute_object_lifetime_bound(&self,
         span: Span,
-        existential_predicates: ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>)
+        existential_predicates: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>)
         -> Option<ty::Region<'tcx>> // if None, use the default
     {
         let tcx = self.tcx();
index d8c090dd6a7e01178f6b6764bdaeb4baf273f551..6b5abbfa4a6f75ea00f216596694b489605d3b7c 100644 (file)
@@ -53,7 +53,7 @@ pub fn check_pat_walk(
             PatKind::Lit(ref lt) => {
                 let ty = self.check_expr(lt);
                 match ty.sty {
-                    ty::TypeVariants::TyRef(..) => false,
+                    ty::Ref(..) => false,
                     _ => true,
                 }
             }
@@ -74,7 +74,7 @@ pub fn check_pat_walk(
 
             // Peel off as many `&` or `&mut` from the discriminant as possible. For example,
             // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
-            // the `Some(5)` which is not of type TyRef.
+            // the `Some(5)` which is not of type Ref.
             //
             // For each ampersand peeled off, update the binding mode and push the original
             // type into the adjustments vector.
@@ -84,8 +84,8 @@ pub fn check_pat_walk(
             expected = loop {
                 debug!("inspecting {:?} with type {:?}", exp_ty, exp_ty.sty);
                 match exp_ty.sty {
-                    ty::TypeVariants::TyRef(_, inner_ty, inner_mutability) => {
-                        debug!("current discriminant is TyRef, inserting implicit deref");
+                    ty::Ref(_, inner_ty, inner_mutability) => {
+                        debug!("current discriminant is Ref, inserting implicit deref");
                         // Preserve the reference type. We'll need it later during HAIR lowering.
                         pat_adjustments.push(exp_ty);
 
@@ -150,8 +150,8 @@ pub fn check_pat_walk(
                 if let hir::ExprKind::Lit(ref lt) = lt.node {
                     if let ast::LitKind::ByteStr(_) = lt.node {
                         let expected_ty = self.structurally_resolved_type(pat.span, expected);
-                        if let ty::TyRef(_, r_ty, _) = expected_ty.sty {
-                            if let ty::TySlice(_) = r_ty.sty {
+                        if let ty::Ref(_, r_ty, _) = expected_ty.sty {
+                            if let ty::Slice(_) = r_ty.sty {
                                 pat_ty = tcx.mk_imm_ref(tcx.types.re_static,
                                                          tcx.mk_slice(tcx.types.u8))
                             }
@@ -285,7 +285,7 @@ pub fn check_pat_walk(
                 let mut expected_len = elements.len();
                 if ddpos.is_some() {
                     // Require known type only when `..` is present
-                    if let ty::TyTuple(ref tys) =
+                    if let ty::Tuple(ref tys) =
                             self.structurally_resolved_type(pat.span, expected).sty {
                         expected_len = tys.len();
                     }
@@ -297,7 +297,7 @@ pub fn check_pat_walk(
                     //       from all tuple elements isn't trivial.
                     TypeVariableOrigin::TypeInference(pat.span)));
                 let element_tys = tcx.mk_type_list(element_tys_iter);
-                let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys));
+                let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
                 self.demand_eqtype(pat.span, expected, pat_ty);
                 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
                     self.check_pat_walk(elem, &element_tys[i], def_bm, true);
@@ -333,7 +333,7 @@ pub fn check_pat_walk(
                     // hack detailed in (*) below.
                     debug!("check_pat_walk: expected={:?}", expected);
                     let (rptr_ty, inner_ty) = match expected.sty {
-                        ty::TyRef(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
+                        ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
                             (expected, r_ty)
                         }
                         _ => {
@@ -375,7 +375,7 @@ pub fn check_pat_walk(
             PatKind::Slice(ref before, ref slice, ref after) => {
                 let expected_ty = self.structurally_resolved_type(pat.span, expected);
                 let (inner_ty, slice_ty) = match expected_ty.sty {
-                    ty::TyArray(inner_ty, size) => {
+                    ty::Array(inner_ty, size) => {
                         let size = size.unwrap_usize(tcx);
                         let min_len = before.len() as u64 + after.len() as u64;
                         if slice.is_none() {
@@ -400,16 +400,16 @@ pub fn check_pat_walk(
                             (inner_ty, tcx.types.err)
                         }
                     }
-                    ty::TySlice(inner_ty) => (inner_ty, expected_ty),
+                    ty::Slice(inner_ty) => (inner_ty, expected_ty),
                     _ => {
                         if !expected_ty.references_error() {
                             let mut err = struct_span_err!(
                                 tcx.sess, pat.span, E0529,
                                 "expected an array or slice, found `{}`",
                                 expected_ty);
-                            if let ty::TyRef(_, ty, _) = expected_ty.sty {
+                            if let ty::Ref(_, ty, _) = expected_ty.sty {
                                 match ty.sty {
-                                    ty::TyArray(..) | ty::TySlice(..) => {
+                                    ty::Array(..) | ty::Slice(..) => {
                                         err.help("the semantics of slice patterns changed \
                                                   recently; see issue #23121");
                                     }
@@ -493,7 +493,7 @@ pub fn check_pat_walk(
     pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
         if let PatKind::Binding(..) = inner.node {
             if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
-                if let ty::TyDynamic(..) = mt.ty.sty {
+                if let ty::Dynamic(..) = mt.ty.sty {
                     // This is "x = SomeTrait" being reduced from
                     // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
                     let type_str = self.ty_to_string(expected);
@@ -820,7 +820,7 @@ fn check_pat_tuple_struct(&self,
         if subpats.len() == variant.fields.len() ||
                 subpats.len() < variant.fields.len() && ddpos.is_some() {
             let substs = match pat_ty.sty {
-                ty::TyAdt(_, substs) => substs,
+                ty::Adt(_, substs) => substs,
                 ref ty => bug!("unexpected pattern type {:?}", ty),
             };
             for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
@@ -856,7 +856,7 @@ fn check_struct_pat_fields(&self,
         let tcx = self.tcx;
 
         let (substs, adt) = match adt_ty.sty {
-            ty::TyAdt(adt, substs) => (substs, adt),
+            ty::Adt(adt, substs) => (substs, adt),
             _ => span_bug!(span, "struct pattern is not an ADT")
         };
         let kind_name = adt.variant_descr();
index 09562614982b81eda5c9878a210310c2a1dd8b51..743a2390ec43d5a9fcac17d62f0e0f4f689c0646 100644 (file)
@@ -177,7 +177,7 @@ pub fn adjust_steps_as_infer_ok(&self, needs: Needs)
                 self.fcx.try_overloaded_deref(self.span, source, needs)
                     .and_then(|InferOk { value: method, obligations: o }| {
                         obligations.extend(o);
-                        if let ty::TyRef(region, _, mutbl) = method.sig.output().sty {
+                        if let ty::Ref(region, _, mutbl) = method.sig.output().sty {
                             Some(OverloadedDeref {
                                 region,
                                 mutbl,
index ec127d26ab30763331f081eb1a87bc9ce9c76afa..53186c64befd3aaac1cb84da6af62772645ef1e6 100644 (file)
@@ -20,6 +20,7 @@
 use rustc_target::spec::abi;
 use syntax::ast::Ident;
 use syntax_pos::Span;
+use errors::Applicability;
 
 use rustc::hir;
 
@@ -95,13 +96,13 @@ fn try_overloaded_call_step(&self,
 
         // If the callee is a bare function or a closure, then we're all set.
         match adjusted_ty.sty {
-            ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+            ty::FnDef(..) | ty::FnPtr(_) => {
                 let adjustments = autoderef.adjust_steps(Needs::None);
                 self.apply_adjustments(callee_expr, adjustments);
                 return Some(CallStep::Builtin(adjusted_ty));
             }
 
-            ty::TyClosure(def_id, substs) => {
+            ty::Closure(def_id, substs) => {
                 assert_eq!(def_id.krate, LOCAL_CRATE);
 
                 // Check whether this is a call to a closure where we
@@ -135,7 +136,7 @@ fn try_overloaded_call_step(&self,
             // over the top. The simplest fix by far is to just ignore
             // this case and deref again, so we wind up with
             // `FnMut::call_mut(&mut *x, ())`.
-            ty::TyRef(..) if autoderef.step_count() == 0 => {
+            ty::Ref(..) if autoderef.step_count() == 0 => {
                 return None;
             }
 
@@ -175,7 +176,7 @@ fn try_overloaded_call_traits(&self,
                     let method = self.register_infer_ok_obligations(ok);
                     let mut autoref = None;
                     if borrow {
-                        if let ty::TyRef(region, _, mutbl) = method.sig.inputs()[0].sty {
+                        if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].sty {
                             let mutbl = match mutbl {
                                 hir::MutImmutable => AutoBorrowMutability::Immutable,
                                 hir::MutMutable => AutoBorrowMutability::Mutable {
@@ -206,13 +207,13 @@ fn confirm_builtin_call(&self,
                             expected: Expectation<'tcx>)
                             -> Ty<'tcx> {
         let (fn_sig, def_span) = match callee_ty.sty {
-            ty::TyFnDef(def_id, _) => {
+            ty::FnDef(def_id, _) => {
                 (callee_ty.fn_sig(self.tcx), self.tcx.hir.span_if_local(def_id))
             }
-            ty::TyFnPtr(sig) => (sig, None),
+            ty::FnPtr(sig) => (sig, None),
             ref t => {
                 let mut unit_variant = None;
-                if let &ty::TyAdt(adt_def, ..) = t {
+                if let &ty::Adt(adt_def, ..) = t {
                     if adt_def.is_enum() {
                         if let hir::ExprKind::Call(ref expr, _) = call_expr.node {
                             unit_variant = Some(self.tcx.hir.node_to_pretty_string(expr.id))
@@ -234,10 +235,13 @@ fn confirm_builtin_call(&self,
                 err.span_label(call_expr.span, "not a function");
 
                 if let Some(ref path) = unit_variant {
-                    err.span_suggestion(call_expr.span,
-                                        &format!("`{}` is a unit variant, you need to write it \
-                                                  without the parenthesis", path),
-                                        path.to_string());
+                    err.span_suggestion_with_applicability(
+                        call_expr.span,
+                        &format!("`{}` is a unit variant, you need to write it \
+                                 without the parenthesis", path),
+                        path.to_string(),
+                        Applicability::MachineApplicable
+                    );
                 }
 
                 if let hir::ExprKind::Call(ref expr, _) = call_expr.node {
index 29d2fe2c7b63eaf93fe11b5d0b55306d805c89a2..52e5e57f74759a64f9a18fffe86fe1b6db13048c 100644 (file)
@@ -103,10 +103,10 @@ fn pointer_kind(&self, t: Ty<'tcx>, span: Span) ->
         }
 
         Ok(match t.sty {
-            ty::TySlice(_) | ty::TyStr => Some(PointerKind::Length),
-            ty::TyDynamic(ref tty, ..) =>
+            ty::Slice(_) | ty::Str => Some(PointerKind::Length),
+            ty::Dynamic(ref tty, ..) =>
                 Some(PointerKind::Vtable(tty.principal().map(|p| p.def_id()))),
-            ty::TyAdt(def, substs) if def.is_struct() => {
+            ty::Adt(def, substs) if def.is_struct() => {
                 match def.non_enum_variant().fields.last() {
                     None => Some(PointerKind::Thin),
                     Some(f) => {
@@ -115,25 +115,25 @@ fn pointer_kind(&self, t: Ty<'tcx>, span: Span) ->
                     }
                 }
             }
-            ty::TyTuple(fields) => match fields.last() {
+            ty::Tuple(fields) => match fields.last() {
                 None => Some(PointerKind::Thin),
                 Some(f) => self.pointer_kind(f, span)?
             },
 
             // Pointers to foreign types are thin, despite being unsized
-            ty::TyForeign(..) => Some(PointerKind::Thin),
+            ty::Foreign(..) => Some(PointerKind::Thin),
             // We should really try to normalize here.
-            ty::TyProjection(ref pi) => Some(PointerKind::OfProjection(pi)),
-            ty::TyAnon(def_id, substs) => Some(PointerKind::OfAnon(def_id, substs)),
-            ty::TyParam(ref p) => Some(PointerKind::OfParam(p)),
+            ty::Projection(ref pi) => Some(PointerKind::OfProjection(pi)),
+            ty::Anon(def_id, substs) => Some(PointerKind::OfAnon(def_id, substs)),
+            ty::Param(ref p) => Some(PointerKind::OfParam(p)),
             // Insufficient type information.
-            ty::TyInfer(_) => None,
+            ty::Infer(_) => None,
 
-            ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) |
-            ty::TyFloat(_) | ty::TyArray(..) | ty::TyGeneratorWitness(..) |
-            ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyFnDef(..) |
-            ty::TyFnPtr(..) | ty::TyClosure(..) | ty::TyGenerator(..) |
-            ty::TyAdt(..) | ty::TyNever | ty::TyError => {
+            ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
+            ty::Float(_) | ty::Array(..) | ty::GeneratorWitness(..) |
+            ty::RawPtr(_) | ty::Ref(..) | ty::FnDef(..) |
+            ty::FnPtr(..) | ty::Closure(..) | ty::Generator(..) |
+            ty::Adt(..) | ty::Never | ty::Error => {
                 self.tcx.sess.delay_span_bug(
                     span, &format!("`{:?}` should be sized but is not?", t));
                 return Err(ErrorReported);
@@ -199,7 +199,7 @@ pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
         // cases now. We do a more thorough check at the end, once
         // inference is more completely known.
         match cast_ty.sty {
-            ty::TyDynamic(..) | ty::TySlice(..) => {
+            ty::Dynamic(..) | ty::Slice(..) => {
                 check.report_cast_to_unsized_type(fcx);
                 Err(ErrorReported)
             }
@@ -319,7 +319,7 @@ fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
                                          fcx.resolve_type_vars_if_possible(&self.expr_ty),
                                          tstr);
         match self.expr_ty.sty {
-            ty::TyRef(_, _, mt) => {
+            ty::Ref(_, _, mt) => {
                 let mtstr = match mt {
                     hir::MutMutable => "mut ",
                     hir::MutImmutable => "",
@@ -343,7 +343,7 @@ fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
                                tstr);
                 }
             }
-            ty::TyAdt(def, ..) if def.is_box() => {
+            ty::Adt(def, ..) if def.is_box() => {
                 match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) {
                     Ok(s) => {
                         err.span_suggestion(self.cast_span,
@@ -429,7 +429,7 @@ fn do_check(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Result<CastKind, CastError>
             (Some(t_from), Some(t_cast)) => (t_from, t_cast),
             // Function item types may need to be reified before casts.
             (None, Some(t_cast)) => {
-                if let ty::TyFnDef(..) = self.expr_ty.sty {
+                if let ty::FnDef(..) = self.expr_ty.sty {
                     // Attempt a coercion to a fn pointer type.
                     let f = self.expr_ty.fn_sig(fcx.tcx);
                     let res = fcx.try_coerce(self.expr,
@@ -477,12 +477,12 @@ fn do_check(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Result<CastKind, CastError>
             (RPtr(p), Int(_)) |
             (RPtr(p), Float) => {
                 match p.ty.sty {
-                    ty::TypeVariants::TyInt(_) |
-                    ty::TypeVariants::TyUint(_) |
-                    ty::TypeVariants::TyFloat(_) => {
+                    ty::Int(_) |
+                    ty::Uint(_) |
+                    ty::Float(_) => {
                         Err(CastError::NeedDeref)
                     }
-                    ty::TypeVariants::TyInfer(t) => {
+                    ty::Infer(t) => {
                         match t {
                             ty::InferTy::IntVar(_) |
                             ty::InferTy::FloatVar(_) => Err(CastError::NeedDeref),
@@ -583,7 +583,7 @@ fn check_ref_cast(&self,
         // array-ptr-cast.
 
         if m_expr.mutbl == hir::MutImmutable && m_cast.mutbl == hir::MutImmutable {
-            if let ty::TyArray(ety, _) = m_expr.ty.sty {
+            if let ty::Array(ety, _) = m_expr.ty.sty {
                 // Due to the limitations of LLVM global constants,
                 // region pointers end up pointing at copies of
                 // vector elements instead of the original values.
index 242b69294a5bcf8797062c7384da00e2b610891f..a283e032e0e023a11654a66d81575c0300a236bf 100644 (file)
@@ -190,7 +190,7 @@ fn deduce_expectations_from_expected_type(
         );
 
         match expected_ty.sty {
-            ty::TyDynamic(ref object_type, ..) => {
+            ty::Dynamic(ref object_type, ..) => {
                 let sig = object_type
                     .projection_bounds()
                     .filter_map(|pb| {
@@ -203,8 +203,8 @@ fn deduce_expectations_from_expected_type(
                     .and_then(|p| self.tcx.lang_items().fn_trait_kind(p.def_id()));
                 (sig, kind)
             }
-            ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
-            ty::TyFnPtr(sig) => {
+            ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
+            ty::FnPtr(sig) => {
                 let expected_sig = ExpectedSig {
                     cause_span: None,
                     sig: sig.skip_binder().clone(),
@@ -269,9 +269,9 @@ fn deduce_expectations_from_obligations(
 
                     // NB: This predicate is created by breaking down a
                     // `ClosureType: FnFoo()` predicate, where
-                    // `ClosureType` represents some `TyClosure`. It can't
+                    // `ClosureType` represents some `Closure`. It can't
                     // possibly be referring to the current closure,
-                    // because we haven't produced the `TyClosure` for
+                    // because we haven't produced the `Closure` for
                     // this closure yet; this is exactly why the other
                     // code is looking for a self type of a unresolved
                     // inference variable.
@@ -317,7 +317,7 @@ fn deduce_sig_from_projection(
         );
 
         let input_tys = match arg_param_ty.sty {
-            ty::TyTuple(tys) => tys.into_iter(),
+            ty::Tuple(tys) => tys.into_iter(),
             _ => {
                 return None;
             }
@@ -353,7 +353,7 @@ fn self_type_matches_expected_vid(
             trait_ref, self_ty
         );
         match self_ty.sty {
-            ty::TyInfer(ty::TyVar(v)) if expected_vid == v => Some(trait_ref),
+            ty::Infer(ty::TyVar(v)) if expected_vid == v => Some(trait_ref),
             _ => None,
         }
     }
index e3b0b8cccf31c073e069913044ed20d9fd62a88d..763adb007c3a4d791e8fbea3a4ad5bc702f26e60 100644 (file)
@@ -210,11 +210,11 @@ fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
         // Note: does not attempt to resolve type variables we encounter.
         // See above for details.
         match b.sty {
-            ty::TyRawPtr(mt_b) => {
+            ty::RawPtr(mt_b) => {
                 return self.coerce_unsafe_ptr(a, b, mt_b.mutbl);
             }
 
-            ty::TyRef(r_b, ty, mutbl) => {
+            ty::Ref(r_b, ty, mutbl) => {
                 let mt_b = ty::TypeAndMut { ty, mutbl };
                 return self.coerce_borrowed_pointer(a, b, r_b, mt_b);
             }
@@ -223,7 +223,7 @@ fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
         }
 
         match a.sty {
-            ty::TyFnDef(..) => {
+            ty::FnDef(..) => {
                 // Function items are coercible to any closure
                 // type; function pointers are not (that would
                 // require double indirection).
@@ -231,12 +231,12 @@ fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
                 // items to drop the unsafe qualifier.
                 self.coerce_from_fn_item(a, b)
             }
-            ty::TyFnPtr(a_f) => {
+            ty::FnPtr(a_f) => {
                 // We permit coercion of fn pointers to drop the
                 // unsafe qualifier.
                 self.coerce_from_fn_pointer(a, a_f, b)
             }
-            ty::TyClosure(def_id_a, substs_a) => {
+            ty::Closure(def_id_a, substs_a) => {
                 // Non-capturing closures are coercible to
                 // function pointers
                 self.coerce_closure_to_fn(a, def_id_a, substs_a, b)
@@ -267,7 +267,7 @@ fn coerce_borrowed_pointer(&self,
         // yield.
 
         let (r_a, mt_a) = match a.sty {
-            ty::TyRef(r_a, ty, mutbl) => {
+            ty::Ref(r_a, ty, mutbl) => {
                 let mt_a = ty::TypeAndMut { ty, mutbl };
                 coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
                 (r_a, mt_a)
@@ -429,7 +429,7 @@ fn coerce_borrowed_pointer(&self,
         // Now apply the autoref. We have to extract the region out of
         // the final ref type we got.
         let r_borrow = match ty.sty {
-            ty::TyRef(r_borrow, _, _) => r_borrow,
+            ty::Ref(r_borrow, _, _) => r_borrow,
             _ => span_bug!(span, "expected a ref type, got {:?}", ty),
         };
         let mutbl = match mt_b.mutbl {
@@ -473,7 +473,7 @@ fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tc
 
         // Handle reborrows before selecting `Source: CoerceUnsized<Target>`.
         let reborrow = match (&source.sty, &target.sty) {
-            (&ty::TyRef(_, ty_a, mutbl_a), &ty::TyRef(_, _, mutbl_b)) => {
+            (&ty::Ref(_, ty_a, mutbl_a), &ty::Ref(_, _, mutbl_b)) => {
                 coerce_mutbls(mutbl_a, mutbl_b)?;
 
                 let coercion = Coercion(self.cause.span);
@@ -498,7 +498,7 @@ fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tc
                     })
                 }))
             }
-            (&ty::TyRef(_, ty_a, mt_a), &ty::TyRawPtr(ty::TypeAndMut { mutbl: mt_b, .. })) => {
+            (&ty::Ref(_, ty_a, mt_a), &ty::RawPtr(ty::TypeAndMut { mutbl: mt_b, .. })) => {
                 coerce_mutbls(mt_a, mt_b)?;
 
                 Some((Adjustment {
@@ -562,7 +562,7 @@ fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tc
                 ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
                     if unsize_did == tr.def_id() {
                         let sty = &tr.skip_binder().input_types().nth(1).unwrap().sty;
-                        if let ty::TyTuple(..) = sty {
+                        if let ty::Tuple(..) = sty {
                             debug!("coerce_unsized: found unsized tuple coercion");
                             has_unsized_tuple_coercion = true;
                         }
@@ -619,7 +619,7 @@ fn coerce_from_safe_fn<F, G>(&self,
         where F: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
               G: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>
     {
-        if let ty::TyFnPtr(fn_ty_b) = b.sty {
+        if let ty::FnPtr(fn_ty_b) = b.sty {
             match (fn_ty_a.unsafety(), fn_ty_b.unsafety()) {
                 (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
                     let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
@@ -659,7 +659,7 @@ fn coerce_from_fn_item(&self,
         debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b);
 
         match b.sty {
-            ty::TyFnPtr(_) => {
+            ty::FnPtr(_) => {
                 let a_sig = a.fn_sig(self.tcx);
                 let InferOk { value: a_sig, mut obligations } =
                     self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig);
@@ -699,7 +699,7 @@ fn coerce_closure_to_fn(&self,
 
         let node_id_a = self.tcx.hir.as_local_node_id(def_id_a).unwrap();
         match b.sty {
-            ty::TyFnPtr(_) if self.tcx.with_freevars(node_id_a, |v| v.is_empty()) => {
+            ty::FnPtr(_) if self.tcx.with_freevars(node_id_a, |v| v.is_empty()) => {
                 // We coerce the closure, which has fn type
                 //     `extern "rust-call" fn((arg0,arg1,...)) -> _`
                 // to
@@ -722,8 +722,8 @@ fn coerce_unsafe_ptr(&self,
         debug!("coerce_unsafe_ptr(a={:?}, b={:?})", a, b);
 
         let (is_ref, mt_a) = match a.sty {
-            ty::TyRef(_, ty, mutbl) => (true, ty::TypeAndMut { ty, mutbl }),
-            ty::TyRawPtr(mt) => (false, mt),
+            ty::Ref(_, ty, mutbl) => (true, ty::TypeAndMut { ty, mutbl }),
+            ty::RawPtr(mt) => (false, mt),
             _ => {
                 return self.unify_and(a, b, identity);
             }
@@ -811,7 +811,7 @@ fn try_find_coercion_lub<E>(&self,
 
         // Special-case that coercion alone cannot handle:
         // Two function item types of differing IDs or Substs.
-        if let (&ty::TyFnDef(..), &ty::TyFnDef(..)) = (&prev_ty.sty, &new_ty.sty) {
+        if let (&ty::FnDef(..), &ty::FnDef(..)) = (&prev_ty.sty, &new_ty.sty) {
             // Don't reify if the function types have a LUB, i.e. they
             // are the same function and their parameters have a LUB.
             let lub_ty = self.commit_if_ok(|_| {
@@ -881,7 +881,7 @@ fn try_find_coercion_lub<E>(&self,
                     Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl_adj)), .. }
                 ] => {
                     match self.node_ty(expr.hir_id).sty {
-                        ty::TyRef(_, _, mt_orig) => {
+                        ty::Ref(_, _, mt_orig) => {
                             let mutbl_adj: hir::Mutability = mutbl_adj.into();
                             // Reborrow that we can safely ignore, because
                             // the next adjustment can only be a Deref
index 00cc36ecd428c8863d9b156104ad215e38a328ec..4e22ead8db987a0514b885a992a43eac35332084 100644 (file)
 use syntax_pos::Span;
 use rustc::hir;
 use rustc::hir::def::Def;
-use rustc::hir::map::{NodeItem, NodeExpr};
+use rustc::hir::Node;
 use rustc::hir::{Item, ItemKind, print};
 use rustc::ty::{self, Ty, AssociatedItem};
 use rustc::ty::adjustment::AllowTwoPhase;
-use errors::{DiagnosticBuilder, SourceMapper};
+use errors::{Applicability, DiagnosticBuilder, SourceMapper};
 
 use super::method::probe;
 
@@ -114,7 +114,7 @@ pub fn demand_coerce_diag(&self,
         // If the expected type is an enum with any variants whose sole
         // field is of the found type, suggest such variants. See Issue
         // #42764.
-        if let ty::TyAdt(expected_adt, substs) = expected.sty {
+        if let ty::Adt(expected_adt, substs) = expected.sty {
             let mut compatible_variants = vec![];
             for variant in &expected_adt.variants {
                 if variant.fields.len() == 1 {
@@ -199,13 +199,13 @@ fn can_use_as_ref(&self, expr: &hir::Expr) -> Option<(Span, &'static str, String
         if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.node {
             if let hir::def::Def::Local(id) = path.def {
                 let parent = self.tcx.hir.get_parent_node(id);
-                if let Some(NodeExpr(hir::Expr {
+                if let Some(Node::Expr(hir::Expr {
                     id,
                     node: hir::ExprKind::Closure(_, decl, ..),
                     ..
                 })) = self.tcx.hir.find(parent) {
                     let parent = self.tcx.hir.get_parent_node(*id);
-                    if let (Some(NodeExpr(hir::Expr {
+                    if let (Some(Node::Expr(hir::Expr {
                         node: hir::ExprKind::MethodCall(path, span, expr),
                         ..
                     })), 1) = (self.tcx.hir.find(parent), decl.inputs.len()) {
@@ -259,9 +259,9 @@ pub fn check_ref(&self,
         }
 
         match (&expected.sty, &checked_ty.sty) {
-            (&ty::TyRef(_, exp, _), &ty::TyRef(_, check, _)) => match (&exp.sty, &check.sty) {
-                (&ty::TyStr, &ty::TyArray(arr, _)) |
-                (&ty::TyStr, &ty::TySlice(arr)) if arr == self.tcx.types.u8 => {
+            (&ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.sty, &check.sty) {
+                (&ty::Str, &ty::Array(arr, _)) |
+                (&ty::Str, &ty::Slice(arr)) if arr == self.tcx.types.u8 => {
                     if let hir::ExprKind::Lit(_) = expr.node {
                         if let Ok(src) = cm.span_to_snippet(sp) {
                             if src.starts_with("b\"") {
@@ -272,8 +272,8 @@ pub fn check_ref(&self,
                         }
                     }
                 },
-                (&ty::TyArray(arr, _), &ty::TyStr) |
-                (&ty::TySlice(arr), &ty::TyStr) if arr == self.tcx.types.u8 => {
+                (&ty::Array(arr, _), &ty::Str) |
+                (&ty::Slice(arr), &ty::Str) if arr == self.tcx.types.u8 => {
                     if let hir::ExprKind::Lit(_) = expr.node {
                         if let Ok(src) = cm.span_to_snippet(sp) {
                             if src.starts_with("\"") {
@@ -286,7 +286,7 @@ pub fn check_ref(&self,
                 }
                 _ => {}
             },
-            (&ty::TyRef(_, _, mutability), _) => {
+            (&ty::Ref(_, _, mutability), _) => {
                 // Check if it can work when put into a ref. For example:
                 //
                 // ```
@@ -325,7 +325,7 @@ pub fn check_ref(&self,
                     }
                 }
             }
-            (_, &ty::TyRef(_, checked, _)) => {
+            (_, &ty::Ref(_, checked, _)) => {
                 // We have `&T`, check if what was expected was `T`. If so,
                 // we may want to suggest adding a `*`, or removing
                 // a `&`.
@@ -351,11 +351,14 @@ pub fn check_ref(&self,
                             if !self.infcx.type_moves_by_default(self.param_env,
                                                                 checked,
                                                                 sp) {
-                                let sp = cm.call_span_if_macro(sp);
-                                if let Ok(code) = cm.span_to_snippet(sp) {
-                                    return Some((sp,
-                                                 "consider dereferencing the borrow",
-                                                 format!("*{}", code)));
+                                // do not suggest if the span comes from a macro (#52783)
+                                if let (Ok(code),
+                                        true) = (cm.span_to_snippet(sp), sp == expr.span) {
+                                    return Some((
+                                        sp,
+                                        "consider dereferencing the borrow",
+                                        format!("*{}", code),
+                                    ));
                                 }
                             }
                         }
@@ -377,7 +380,7 @@ pub fn check_for_cast(&self,
         match self.tcx.hir.find(parent_id) {
             Some(parent) => {
                 // Shouldn't suggest `.into()` on `const`s.
-                if let NodeItem(Item { node: ItemKind::Const(_, _), .. }) = parent {
+                if let Node::Item(Item { node: ItemKind::Const(_, _), .. }) = parent {
                     // FIXME(estebank): modify once we decide to suggest `as` casts
                     return false;
                 }
@@ -418,189 +421,240 @@ pub fn check_for_cast(&self,
                                           if needs_paren { ")" } else { "" });
 
             match (&expected_ty.sty, &checked_ty.sty) {
-                (&ty::TyInt(ref exp), &ty::TyInt(ref found)) => {
+                (&ty::Int(ref exp), &ty::Int(ref found)) => {
                     match (found.bit_width(), exp.bit_width()) {
                         (Some(found), Some(exp)) if found > exp => {
                             if can_cast {
-                                err.span_suggestion(expr.span,
-                                                    &format!("{}, which {}", msg, will_truncate),
-                                                    cast_suggestion);
+                                err.span_suggestion_with_applicability(
+                                    expr.span,
+                                    &format!("{}, which {}", msg, will_truncate),
+                                    cast_suggestion,
+                                    Applicability::MaybeIncorrect // lossy conversion
+                                );
                             }
                         }
                         (None, _) | (_, None) => {
                             if can_cast {
-                                err.span_suggestion(expr.span,
-                                                    &format!("{}, which {}",
-                                                             msg,
-                                                             depending_on_isize),
-                                                    cast_suggestion);
+                                err.span_suggestion_with_applicability(
+                                    expr.span,
+                                    &format!("{}, which {}", msg, depending_on_isize),
+                                    cast_suggestion,
+                                    Applicability::MaybeIncorrect // lossy conversion
+                                );
                             }
                         }
                         _ => {
-                            err.span_suggestion(expr.span,
-                                                &format!("{}, which {}", msg, will_sign_extend),
-                                                into_suggestion);
+                            err.span_suggestion_with_applicability(
+                                expr.span,
+                                &format!("{}, which {}", msg, will_sign_extend),
+                                into_suggestion,
+                                Applicability::MachineApplicable
+                            );
                         }
                     }
                     true
                 }
-                (&ty::TyUint(ref exp), &ty::TyUint(ref found)) => {
+                (&ty::Uint(ref exp), &ty::Uint(ref found)) => {
                     match (found.bit_width(), exp.bit_width()) {
                         (Some(found), Some(exp)) if found > exp => {
                             if can_cast {
-                                err.span_suggestion(expr.span,
-                                                    &format!("{}, which {}", msg, will_truncate),
-                                                    cast_suggestion);
+                                err.span_suggestion_with_applicability(
+                                    expr.span,
+                                    &format!("{}, which {}", msg, will_truncate),
+                                    cast_suggestion,
+                                    Applicability::MaybeIncorrect  // lossy conversion
+                                );
                             }
                         }
                         (None, _) | (_, None) => {
                             if can_cast {
-                                err.span_suggestion(expr.span,
-                                                    &format!("{}, which {}",
-                                                             msg,
-                                                             depending_on_usize),
-                                                    cast_suggestion);
+                                err.span_suggestion_with_applicability(
+                                    expr.span,
+                                    &format!("{}, which {}", msg, depending_on_usize),
+                                    cast_suggestion,
+                                    Applicability::MaybeIncorrect  // lossy conversion
+                                );
                             }
                         }
                         _ => {
-                            err.span_suggestion(expr.span,
-                                                &format!("{}, which {}", msg, will_zero_extend),
-                                                into_suggestion);
+                            err.span_suggestion_with_applicability(
+                                expr.span,
+                                &format!("{}, which {}", msg, will_zero_extend),
+                                into_suggestion,
+                                Applicability::MachineApplicable
+                            );
                         }
                     }
                     true
                 }
-                (&ty::TyInt(ref exp), &ty::TyUint(ref found)) => {
+                (&ty::Int(ref exp), &ty::Uint(ref found)) => {
                     if can_cast {
                         match (found.bit_width(), exp.bit_width()) {
                             (Some(found), Some(exp)) if found > exp - 1 => {
-                                err.span_suggestion(expr.span,
-                                                    &format!("{}, which {}", msg, will_truncate),
-                                                    cast_suggestion);
+                                err.span_suggestion_with_applicability(
+                                    expr.span,
+                                    &format!("{}, which {}", msg, will_truncate),
+                                    cast_suggestion,
+                                    Applicability::MaybeIncorrect  // lossy conversion
+                                );
                             }
                             (None, None) => {
-                                err.span_suggestion(expr.span,
-                                                    &format!("{}, which {}", msg, will_truncate),
-                                                    cast_suggestion);
+                                err.span_suggestion_with_applicability(
+                                    expr.span,
+                                    &format!("{}, which {}", msg, will_truncate),
+                                    cast_suggestion,
+                                    Applicability::MaybeIncorrect  // lossy conversion
+                                );
                             }
                             (None, _) => {
-                                err.span_suggestion(expr.span,
-                                                    &format!("{}, which {}",
-                                                             msg,
-                                                             depending_on_isize),
-                                                    cast_suggestion);
+                                err.span_suggestion_with_applicability(
+                                    expr.span,
+                                    &format!("{}, which {}", msg, depending_on_isize),
+                                    cast_suggestion,
+                                    Applicability::MaybeIncorrect  // lossy conversion
+                                );
                             }
                             (_, None) => {
-                                err.span_suggestion(expr.span,
-                                                    &format!("{}, which {}",
-                                                             msg,
-                                                             depending_on_usize),
-                                                    cast_suggestion);
+                                err.span_suggestion_with_applicability(
+                                    expr.span,
+                                    &format!("{}, which {}", msg, depending_on_usize),
+                                    cast_suggestion,
+                                    Applicability::MaybeIncorrect  // lossy conversion
+                                );
                             }
                             _ => {
-                                err.span_suggestion(expr.span,
-                                                    &format!("{}, which {}", msg, will_zero_extend),
-                                                    cast_suggestion);
+                                err.span_suggestion_with_applicability(
+                                    expr.span,
+                                    &format!("{}, which {}", msg, will_zero_extend),
+                                    cast_suggestion,
+                                    Applicability::MachineApplicable
+                                );
                             }
                         }
                     }
                     true
                 }
-                (&ty::TyUint(ref exp), &ty::TyInt(ref found)) => {
+                (&ty::Uint(ref exp), &ty::Int(ref found)) => {
                     if can_cast {
                         match (found.bit_width(), exp.bit_width()) {
                             (Some(found), Some(exp)) if found - 1 > exp => {
-                                err.span_suggestion(expr.span,
-                                                    &format!("{}, which {}", msg, will_truncate),
-                                                    cast_suggestion);
+                                err.span_suggestion_with_applicability(
+                                    expr.span,
+                                    &format!("{}, which {}", msg, will_truncate),
+                                    cast_suggestion,
+                                    Applicability::MaybeIncorrect  // lossy conversion
+                                );
                             }
                             (None, None) => {
-                                err.span_suggestion(expr.span,
-                                                    &format!("{}, which {}", msg, will_sign_extend),
-                                                    cast_suggestion);
+                                err.span_suggestion_with_applicability(
+                                    expr.span,
+                                    &format!("{}, which {}", msg, will_sign_extend),
+                                    cast_suggestion,
+                                    Applicability::MachineApplicable  // lossy conversion
+                                );
                             }
                             (None, _) => {
-                                err.span_suggestion(expr.span,
-                                                    &format!("{}, which {}",
-                                                             msg,
-                                                             depending_on_usize),
-                                                    cast_suggestion);
+                                err.span_suggestion_with_applicability(
+                                    expr.span,
+                                    &format!("{}, which {}", msg, depending_on_usize),
+                                    cast_suggestion,
+                                    Applicability::MaybeIncorrect  // lossy conversion
+                                );
                             }
                             (_, None) => {
-                                err.span_suggestion(expr.span,
-                                                    &format!("{}, which {}",
-                                                             msg,
-                                                             depending_on_isize),
-                                                    cast_suggestion);
+                                err.span_suggestion_with_applicability(
+                                    expr.span,
+                                    &format!("{}, which {}", msg, depending_on_isize),
+                                    cast_suggestion,
+                                    Applicability::MaybeIncorrect  // lossy conversion
+                                );
                             }
                             _ => {
-                                err.span_suggestion(expr.span,
-                                                    &format!("{}, which {}", msg, will_sign_extend),
-                                                    cast_suggestion);
+                                err.span_suggestion_with_applicability(
+                                    expr.span,
+                                    &format!("{}, which {}", msg, will_sign_extend),
+                                    cast_suggestion,
+                                    Applicability::MachineApplicable
+                                );
                             }
                         }
                     }
                     true
                 }
-                (&ty::TyFloat(ref exp), &ty::TyFloat(ref found)) => {
+                (&ty::Float(ref exp), &ty::Float(ref found)) => {
                     if found.bit_width() < exp.bit_width() {
-                        err.span_suggestion(expr.span,
-                                            &format!("{} in a lossless way",
-                                                     msg),
-                                            into_suggestion);
+                        err.span_suggestion_with_applicability(
+                            expr.span,
+                            &format!("{} in a lossless way", msg),
+                            into_suggestion,
+                            Applicability::MachineApplicable
+                        );
                     } else if can_cast {
-                        err.span_suggestion(expr.span,
-                                            &format!("{}, producing the closest possible value",
-                                                     msg),
-                                            cast_suggestion);
+                        err.span_suggestion_with_applicability(
+                            expr.span,
+                            &format!("{}, producing the closest possible value", msg),
+                            cast_suggestion,
+                            Applicability::MaybeIncorrect  // lossy conversion
+                        );
                     }
                     true
                 }
-                (&ty::TyUint(_), &ty::TyFloat(_)) | (&ty::TyInt(_), &ty::TyFloat(_)) => {
+                (&ty::Uint(_), &ty::Float(_)) | (&ty::Int(_), &ty::Float(_)) => {
                     if can_cast {
-                        err.span_suggestion(expr.span,
-                                            &format!("{}, rounding the float towards zero",
-                                                     msg),
-                                            cast_suggestion);
+                        err.span_suggestion_with_applicability(
+                            expr.span,
+                            &format!("{}, rounding the float towards zero", msg),
+                            cast_suggestion,
+                            Applicability::MaybeIncorrect  // lossy conversion
+                        );
                         err.warn("casting here will cause undefined behavior if the rounded value \
                                   cannot be represented by the target integer type, including \
                                   `Inf` and `NaN` (this is a bug and will be fixed)");
                     }
                     true
                 }
-                (&ty::TyFloat(ref exp), &ty::TyUint(ref found)) => {
+                (&ty::Float(ref exp), &ty::Uint(ref found)) => {
                     // if `found` is `None` (meaning found is `usize`), don't suggest `.into()`
                     if exp.bit_width() > found.bit_width().unwrap_or(256) {
-                        err.span_suggestion(expr.span,
-                                            &format!("{}, producing the floating point \
-                                                      representation of the integer",
-                                                      msg),
-                                            into_suggestion);
+                        err.span_suggestion_with_applicability(
+                            expr.span,
+                            &format!("{}, producing the floating point representation of the \
+                                      integer",
+                                      msg),
+                            into_suggestion,
+                            Applicability::MachineApplicable
+                        );
                     } else if can_cast {
-                        err.span_suggestion(expr.span,
-                                            &format!("{}, producing the floating point \
-                                                      representation of the integer, rounded if \
-                                                      necessary",
-                                                      msg),
-                                            cast_suggestion);
+                        err.span_suggestion_with_applicability(expr.span,
+                            &format!("{}, producing the floating point representation of the \
+                                      integer, rounded if necessary",
+                                      msg),
+                            cast_suggestion,
+                            Applicability::MaybeIncorrect  // lossy conversion
+                        );
                     }
                     true
                 }
-                (&ty::TyFloat(ref exp), &ty::TyInt(ref found)) => {
+                (&ty::Float(ref exp), &ty::Int(ref found)) => {
                     // if `found` is `None` (meaning found is `isize`), don't suggest `.into()`
                     if exp.bit_width() > found.bit_width().unwrap_or(256) {
-                        err.span_suggestion(expr.span,
-                                            &format!("{}, producing the floating point \
-                                                      representation of the integer",
-                                                      msg),
-                                            into_suggestion);
+                        err.span_suggestion_with_applicability(
+                            expr.span,
+                            &format!("{}, producing the floating point representation of the \
+                                      integer",
+                                      msg),
+                            into_suggestion,
+                            Applicability::MachineApplicable
+                        );
                     } else if can_cast {
-                        err.span_suggestion(expr.span,
-                                            &format!("{}, producing the floating point \
-                                                      representation of the integer, rounded if \
-                                                      necessary",
-                                                      msg),
-                                            cast_suggestion);
+                        err.span_suggestion_with_applicability(
+                            expr.span,
+                            &format!("{}, producing the floating point representation of the \
+                                      integer, rounded if necessary",
+                                      msg),
+                            cast_suggestion,
+                            Applicability::MaybeIncorrect  // lossy conversion
+                        );
                     }
                     true
                 }
index f9166851f6fcc75bfac80b0f48c39bd64b916310..9d3cbf910e05958f3633f0d6c02fe9af944b1471 100644 (file)
@@ -45,7 +45,7 @@ pub fn check_drop_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let dtor_self_type = tcx.type_of(drop_impl_did);
     let dtor_predicates = tcx.predicates_of(drop_impl_did);
     match dtor_self_type.sty {
-        ty::TyAdt(adt_def, self_to_impl_substs) => {
+        ty::Adt(adt_def, self_to_impl_substs) => {
             ensure_drop_params_and_item_params_correspond(tcx,
                                                           drop_impl_did,
                                                           dtor_self_type,
index 6e0c0bac186f4a652fddfb7c78851ea5d805006b..f0afc58b3cec57a6420cbbcd9422042a038290c2 100644 (file)
@@ -121,7 +121,7 @@ pub fn resolve_interior<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
     // Replace all regions inside the generator interior with late bound regions
     // Note that each region slot in the types gets a new fresh late bound region,
     // which means that none of the regions inside relate to any other, even if
-    // typeck had previously found contraints that would cause them to be related.
+    // typeck had previously found constraints that would cause them to be related.
     let mut counter = 0;
     let type_list = fcx.tcx.fold_regions(&type_list, &mut false, |_, current_depth| {
         counter += 1;
index af4356dc8de7816e1da472accfdf96903b0059c9..c7db3debf5a0d6dfacd6b276249715e1202d0a95 100644 (file)
 
 use std::iter;
 
-fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                   it: &hir::ForeignItem,
-                                   n_tps: usize,
-                                   abi: Abi,
-                                   inputs: Vec<Ty<'tcx>>,
-                                   output: Ty<'tcx>) {
+fn equate_intrinsic_type<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    it: &hir::ForeignItem,
+    n_tps: usize,
+    abi: Abi,
+    safety: hir::Unsafety,
+    inputs: Vec<Ty<'tcx>>,
+    output: Ty<'tcx>,
+) {
     let def_id = tcx.hir.local_def_id(it.id);
 
     match it.node {
@@ -65,7 +68,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         inputs.into_iter(),
         output,
         false,
-        hir::Unsafety::Unsafe,
+        safety,
         abi
     )));
     let cause = ObligationCause::new(it.span, it.id, ObligationCauseCode::IntrinsicType);
@@ -78,7 +81,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                       it: &hir::ForeignItem) {
     let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str());
     let name = it.name.as_str();
-    let (n_tps, inputs, output) = if name.starts_with("atomic_") {
+    let (n_tps, inputs, output, unsafety) = if name.starts_with("atomic_") {
         let split : Vec<&str> = name.split('_').collect();
         assert!(split.len() >= 2, "Atomic intrinsic not correct format");
 
@@ -109,10 +112,14 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 return;
             }
         };
-        (n_tps, inputs, output)
+        (n_tps, inputs, output, hir::Unsafety::Unsafe)
     } else if &name[..] == "abort" || &name[..] == "unreachable" {
-        (0, Vec::new(), tcx.types.never)
+        (0, Vec::new(), tcx.types.never, hir::Unsafety::Unsafe)
     } else {
+        let unsafety = match &name[..] {
+            "size_of" | "min_align_of" => hir::Unsafety::Normal,
+            _ => hir::Unsafety::Unsafe,
+        };
         let (n_tps, inputs, output) = match &name[..] {
             "breakpoint" => (0, Vec::new(), tcx.mk_nil()),
             "size_of" |
@@ -327,9 +334,9 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 return;
             }
         };
-        (n_tps, inputs, output)
+        (n_tps, inputs, output, unsafety)
     };
-    equate_intrinsic_type(tcx, it, n_tps, Abi::RustIntrinsic, inputs, output)
+    equate_intrinsic_type(tcx, it, n_tps, Abi::RustIntrinsic, unsafety, inputs, output)
 }
 
 /// Type-check `extern "platform-intrinsic" { ... }` functions.
@@ -439,7 +446,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     };
 
-    equate_intrinsic_type(tcx, it, n_tps, Abi::PlatformIntrinsic,
+    equate_intrinsic_type(tcx, it, n_tps, Abi::PlatformIntrinsic, hir::Unsafety::Unsafe,
                           inputs, output)
 }
 
@@ -463,35 +470,35 @@ fn match_intrinsic_type_to_type<'a, 'tcx>(
 
     match *expected {
         Void => match t.sty {
-            ty::TyTuple(ref v) if v.is_empty() => {},
+            ty::Tuple(ref v) if v.is_empty() => {},
             _ => simple_error(&format!("`{}`", t), "()"),
         },
         // (The width we pass to LLVM doesn't concern the type checker.)
         Integer(signed, bits, _llvm_width) => match (signed, bits, &t.sty) {
-            (true,  8,  &ty::TyInt(ast::IntTy::I8)) |
-            (false, 8,  &ty::TyUint(ast::UintTy::U8)) |
-            (true,  16, &ty::TyInt(ast::IntTy::I16)) |
-            (false, 16, &ty::TyUint(ast::UintTy::U16)) |
-            (true,  32, &ty::TyInt(ast::IntTy::I32)) |
-            (false, 32, &ty::TyUint(ast::UintTy::U32)) |
-            (true,  64, &ty::TyInt(ast::IntTy::I64)) |
-            (false, 64, &ty::TyUint(ast::UintTy::U64)) |
-            (true,  128, &ty::TyInt(ast::IntTy::I128)) |
-            (false, 128, &ty::TyUint(ast::UintTy::U128)) => {},
+            (true,  8,  &ty::Int(ast::IntTy::I8)) |
+            (false, 8,  &ty::Uint(ast::UintTy::U8)) |
+            (true,  16, &ty::Int(ast::IntTy::I16)) |
+            (false, 16, &ty::Uint(ast::UintTy::U16)) |
+            (true,  32, &ty::Int(ast::IntTy::I32)) |
+            (false, 32, &ty::Uint(ast::UintTy::U32)) |
+            (true,  64, &ty::Int(ast::IntTy::I64)) |
+            (false, 64, &ty::Uint(ast::UintTy::U64)) |
+            (true,  128, &ty::Int(ast::IntTy::I128)) |
+            (false, 128, &ty::Uint(ast::UintTy::U128)) => {},
             _ => simple_error(&format!("`{}`", t),
                               &format!("`{}{n}`",
                                        if signed {"i"} else {"u"},
                                        n = bits)),
         },
         Float(bits) => match (bits, &t.sty) {
-            (32, &ty::TyFloat(ast::FloatTy::F32)) |
-            (64, &ty::TyFloat(ast::FloatTy::F64)) => {},
+            (32, &ty::Float(ast::FloatTy::F32)) |
+            (64, &ty::Float(ast::FloatTy::F64)) => {},
             _ => simple_error(&format!("`{}`", t),
                               &format!("`f{n}`", n = bits)),
         },
         Pointer(ref inner_expected, ref _llvm_type, const_) => {
             match t.sty {
-                ty::TyRawPtr(ty::TypeAndMut { ty, mutbl }) => {
+                ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => {
                     if (mutbl == hir::MutImmutable) != const_ {
                         simple_error(&format!("`{}`", t),
                                      if const_ {"const pointer"} else {"mut pointer"})
@@ -537,7 +544,7 @@ fn match_intrinsic_type_to_type<'a, 'tcx>(
         }
         Aggregate(_flatten, ref expected_contents) => {
             match t.sty {
-                ty::TyTuple(contents) => {
+                ty::Tuple(contents) => {
                     if contents.len() != expected_contents.len() {
                         simple_error(&format!("tuple with length {}", contents.len()),
                                      &format!("tuple with length {}", expected_contents.len()));
index fbb49c95edf0311ec8ed1fcb2106ed5f914c29f8..6057c18663a6e7f6fcc74153fa265b7117c2f418 100644 (file)
@@ -293,7 +293,7 @@ fn extract_existential_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure
             .include_raw_pointers()
             .filter_map(|(ty, _)| {
                 match ty.sty {
-                    ty::TyDynamic(ref data, ..) => data.principal().map(|p| closure(self, ty, p)),
+                    ty::Dynamic(ref data, ..) => data.principal().map(|p| closure(self, ty, p)),
                     _ => None,
                 }
             })
@@ -479,7 +479,7 @@ fn convert_place_derefs_to_mutable(&self) {
                     if let Adjust::Deref(Some(ref mut deref)) = adjustment.kind {
                         if let Some(ok) = self.try_overloaded_deref(expr.span, source, needs) {
                             let method = self.register_infer_ok_obligations(ok);
-                            if let ty::TyRef(region, _, mutbl) = method.sig.output().sty {
+                            if let ty::Ref(region, _, mutbl) = method.sig.output().sty {
                                 *deref = OverloadedDeref {
                                     region,
                                     mutbl,
@@ -538,7 +538,7 @@ fn convert_place_op_to_mutable(&self,
         debug!("convert_place_op_to_mutable: method={:?}", method);
         self.write_method_call(expr.hir_id, method);
 
-        let (region, mutbl) = if let ty::TyRef(r, _, mutbl) = method.sig.inputs()[0].sty {
+        let (region, mutbl) = if let ty::Ref(r, _, mutbl) = method.sig.inputs()[0].sty {
             (r, mutbl)
         } else {
             span_bug!(expr.span, "input to place op is not a ref?");
@@ -605,7 +605,7 @@ fn predicates_require_illegal_sized_bound(&self,
             })
             .any(|trait_pred| {
                 match trait_pred.skip_binder().self_ty().sty {
-                    ty::TyDynamic(..) => true,
+                    ty::Dynamic(..) => true,
                     _ => false,
                 }
             })
index 68e851446dc964014f96de7c533abef8e0659c4a..85a437283fa681e66c18de97c7cb2d5f959f958d 100644 (file)
@@ -314,7 +314,7 @@ fn create_steps(&self,
                     from_unsafe_deref: reached_raw_pointer,
                     unsize: false,
                 };
-                if let ty::TyRawPtr(_) = ty.sty {
+                if let ty::RawPtr(_) = ty.sty {
                     // all the subsequent steps will be from_unsafe_deref
                     reached_raw_pointer = true;
                 }
@@ -324,7 +324,7 @@ fn create_steps(&self,
 
         let final_ty = autoderef.maybe_ambiguous_final_ty();
         match final_ty.sty {
-            ty::TyInfer(ty::TyVar(_)) => {
+            ty::Infer(ty::TyVar(_)) => {
                 // Ended in an inference variable. If we are doing
                 // a real method lookup, this is a hard error because it's
                 // possible that there will be multiple applicable methods.
@@ -356,7 +356,7 @@ fn create_steps(&self,
                     // just ignore it.
                 }
             }
-            ty::TyArray(elem_ty, _) => {
+            ty::Array(elem_ty, _) => {
                 let dereferences = steps.len() - 1;
 
                 steps.push(CandidateStep {
@@ -368,7 +368,7 @@ fn create_steps(&self,
                     unsize: true,
                 });
             }
-            ty::TyError => return None,
+            ty::Error => return None,
             _ => (),
         }
 
@@ -450,33 +450,33 @@ fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
         let lang_items = self.tcx.lang_items();
 
         match self_ty.sty {
-            ty::TyDynamic(ref data, ..) => {
+            ty::Dynamic(ref data, ..) => {
                 if let Some(p) = data.principal() {
                     self.assemble_inherent_candidates_from_object(self_ty, p);
                     self.assemble_inherent_impl_candidates_for_type(p.def_id());
                 }
             }
-            ty::TyAdt(def, _) => {
+            ty::Adt(def, _) => {
                 self.assemble_inherent_impl_candidates_for_type(def.did);
             }
-            ty::TyForeign(did) => {
+            ty::Foreign(did) => {
                 self.assemble_inherent_impl_candidates_for_type(did);
             }
-            ty::TyParam(p) => {
+            ty::Param(p) => {
                 self.assemble_inherent_candidates_from_param(self_ty, p);
             }
-            ty::TyChar => {
+            ty::Char => {
                 let lang_def_id = lang_items.char_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyStr => {
+            ty::Str => {
                 let lang_def_id = lang_items.str_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
 
                 let lang_def_id = lang_items.str_alloc_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TySlice(_) => {
+            ty::Slice(_) => {
                 let lang_def_id = lang_items.slice_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
 
@@ -489,70 +489,70 @@ fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
                 let lang_def_id = lang_items.slice_u8_alloc_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
+            ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
                 let lang_def_id = lang_items.const_ptr_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
+            ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
                 let lang_def_id = lang_items.mut_ptr_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(ast::IntTy::I8) => {
+            ty::Int(ast::IntTy::I8) => {
                 let lang_def_id = lang_items.i8_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(ast::IntTy::I16) => {
+            ty::Int(ast::IntTy::I16) => {
                 let lang_def_id = lang_items.i16_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(ast::IntTy::I32) => {
+            ty::Int(ast::IntTy::I32) => {
                 let lang_def_id = lang_items.i32_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(ast::IntTy::I64) => {
+            ty::Int(ast::IntTy::I64) => {
                 let lang_def_id = lang_items.i64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(ast::IntTy::I128) => {
+            ty::Int(ast::IntTy::I128) => {
                 let lang_def_id = lang_items.i128_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(ast::IntTy::Isize) => {
+            ty::Int(ast::IntTy::Isize) => {
                 let lang_def_id = lang_items.isize_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(ast::UintTy::U8) => {
+            ty::Uint(ast::UintTy::U8) => {
                 let lang_def_id = lang_items.u8_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(ast::UintTy::U16) => {
+            ty::Uint(ast::UintTy::U16) => {
                 let lang_def_id = lang_items.u16_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(ast::UintTy::U32) => {
+            ty::Uint(ast::UintTy::U32) => {
                 let lang_def_id = lang_items.u32_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(ast::UintTy::U64) => {
+            ty::Uint(ast::UintTy::U64) => {
                 let lang_def_id = lang_items.u64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(ast::UintTy::U128) => {
+            ty::Uint(ast::UintTy::U128) => {
                 let lang_def_id = lang_items.u128_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(ast::UintTy::Usize) => {
+            ty::Uint(ast::UintTy::Usize) => {
                 let lang_def_id = lang_items.usize_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyFloat(ast::FloatTy::F32) => {
+            ty::Float(ast::FloatTy::F32) => {
                 let lang_def_id = lang_items.f32_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
 
                 let lang_def_id = lang_items.f32_runtime_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyFloat(ast::FloatTy::F64) => {
+            ty::Float(ast::FloatTy::F64) => {
                 let lang_def_id = lang_items.f64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
 
@@ -652,7 +652,7 @@ fn assemble_inherent_candidates_from_param(&mut self,
                 match *predicate {
                     ty::Predicate::Trait(ref trait_predicate) => {
                         match trait_predicate.skip_binder().trait_ref.self_ty().sty {
-                            ty::TyParam(ref p) if *p == param_ty => {
+                            ty::Param(ref p) if *p == param_ty => {
                                 Some(trait_predicate.to_poly_trait_ref())
                             }
                             _ => None,
@@ -919,7 +919,7 @@ fn pick_by_value_method(&mut self, step: &CandidateStep<'tcx>) -> Option<PickRes
                 pick.autoderefs = step.autoderefs;
 
                 // Insert a `&*` or `&mut *` if this is a reference type:
-                if let ty::TyRef(_, _, mutbl) = step.self_ty.sty {
+                if let ty::Ref(_, _, mutbl) = step.self_ty.sty {
                     pick.autoderefs += 1;
                     pick.autoref = Some(mutbl);
                 }
index 31ec62ba70a956478917afc6d7ad410e66eb0562..abc32ed2ea0433d2576dac7fd5e86d0f2f0f029e 100644 (file)
@@ -13,6 +13,7 @@
 
 use check::FnCtxt;
 use rustc::hir::map as hir_map;
+use hir::Node;
 use rustc_data_structures::sync::Lrc;
 use rustc::ty::{self, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable};
 use hir::def::Def;
@@ -24,7 +25,7 @@
 
 use syntax::ast;
 use syntax::util::lev_distance::find_best_match_for_name;
-use errors::DiagnosticBuilder;
+use errors::{Applicability, DiagnosticBuilder};
 use syntax_pos::{Span, FileName};
 
 
@@ -32,7 +33,7 @@
 use rustc::hir;
 use rustc::hir::print;
 use rustc::infer::type_variable::TypeVariableOrigin;
-use rustc::ty::TyAdt;
+use rustc::ty::Adt;
 
 use std::cmp::Ordering;
 
@@ -45,9 +46,9 @@ fn is_fn_ty(&self, ty: &Ty<'tcx>, span: Span) -> bool {
         match ty.sty {
             // Not all of these (e.g. unsafe fns) implement FnOnce
             // so we look for these beforehand
-            ty::TyClosure(..) |
-            ty::TyFnDef(..) |
-            ty::TyFnPtr(_) => true,
+            ty::Closure(..) |
+            ty::FnDef(..) |
+            ty::FnPtr(_) => true,
             // If it's not a simple function, look for things which implement FnOnce
             _ => {
                 let fn_once = match tcx.lang_items().require(FnOnceTraitLangItem) {
@@ -199,7 +200,7 @@ pub fn report_method_error(&self,
                 let item_kind = if is_method {
                     "method"
                 } else if actual.is_enum() {
-                    if let TyAdt(ref adt_def, _) = actual.sty {
+                    if let Adt(ref adt_def, _) = actual.sty {
                         let names = adt_def.variants.iter().map(|s| &s.name);
                         suggestion = find_best_match_for_name(names,
                                                               &item_name.as_str(),
@@ -275,7 +276,7 @@ pub fn report_method_error(&self,
                                         );
 
                                         match (filename, parent_node) {
-                                            (FileName::Real(_), hir_map::NodeLocal(hir::Local {
+                                            (FileName::Real(_), Node::Local(hir::Local {
                                                 source: hir::LocalSource::Normal,
                                                 ty,
                                                 ..
@@ -338,7 +339,7 @@ pub fn report_method_error(&self,
                 if let Some(expr) = rcvr_expr {
                     for (ty, _) in self.autoderef(span, rcvr_ty) {
                         match ty.sty {
-                            ty::TyAdt(def, substs) if !def.is_enum() => {
+                            ty::Adt(def, substs) if !def.is_enum() => {
                                 let variant = &def.non_enum_variant();
                                 if let Some(index) = self.tcx.find_field_index(item_name, variant) {
                                     let field = &variant.fields[index];
@@ -407,11 +408,12 @@ macro_rules! report_function {
                 }
                 if static_sources.len() == 1 {
                     if let Some(expr) = rcvr_expr {
-                        err.span_suggestion(expr.span.to(span),
+                        err.span_suggestion_with_applicability(expr.span.to(span),
                                             "use associated function syntax instead",
                                             format!("{}::{}",
                                                     self.ty_to_string(actual),
-                                                    item_name));
+                                                    item_name),
+                                            Applicability::MachineApplicable);
                     } else {
                         err.help(&format!("try with `{}::{}`",
                                           self.ty_to_string(actual), item_name));
@@ -638,13 +640,13 @@ fn type_derefs_to_local(&self,
                             -> bool {
         fn is_local(ty: Ty) -> bool {
             match ty.sty {
-                ty::TyAdt(def, _) => def.did.is_local(),
-                ty::TyForeign(did) => did.is_local(),
+                ty::Adt(def, _) => def.did.is_local(),
+                ty::Foreign(did) => did.is_local(),
 
-                ty::TyDynamic(ref tr, ..) => tr.principal()
+                ty::Dynamic(ref tr, ..) => tr.principal()
                     .map_or(false, |p| p.def_id().is_local()),
 
-                ty::TyParam(_) => true,
+                ty::Param(_) => true,
 
                 // everything else (primitive types etc.) is effectively
                 // non-local (there are "edge" cases, e.g. (LocalType,), but
index c89f7e0586b0822c44d554ab5052378d51be61d6..7a13d8bdd4bac2508bb79d46b050b383d9165873 100644 (file)
 use rustc::infer::anon_types::AnonTypeDecl;
 use rustc::infer::type_variable::{TypeVariableOrigin};
 use rustc::middle::region;
-use rustc::mir::interpret::{GlobalId};
-use rustc::ty::subst::{UnpackedKind, Subst, Substs};
+use rustc::mir::interpret::{ConstValue, GlobalId};
+use rustc::ty::subst::{CanonicalSubsts, UnpackedKind, Subst, Substs};
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
 use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::query::Providers;
 use rustc::ty::util::{Representability, IntTypeExt, Discr};
-use errors::{DiagnosticBuilder, DiagnosticId};
+use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 
 use require_c_abi_if_variadic;
 use session::{CompileIncomplete, config, Session};
 use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax::attr;
+use syntax::source_map::DUMMY_SP;
 use syntax::source_map::original_sp;
 use syntax::feature_gate::{GateIssue, emit_feature_err};
 use syntax::ptr::P;
 
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::hir::map::Node;
+use rustc::hir::Node;
 use rustc::hir::{self, PatKind, ItemKind};
 use rustc::middle::lang_items;
 
@@ -214,7 +215,7 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     // Anonymized types found in explicit return types and their
     // associated fresh inference variable. Writeback resolves these
     // variables to get the concrete type, which can be used to
-    // deanonymize TyAnon, after typeck is done with all functions.
+    // deanonymize Anon, after typeck is done with all functions.
     anon_types: RefCell<DefIdMap<AnonTypeDecl<'tcx>>>,
 
     /// Each type parameter has an implicit region bound that
@@ -311,7 +312,7 @@ fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Expectation<'tcx>
     /// for examples of where this comes up,.
     fn rvalue_hint(fcx: &FnCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
         match fcx.tcx.struct_tail(ty).sty {
-            ty::TySlice(_) | ty::TyStr | ty::TyDynamic(..) => {
+            ty::Slice(_) | ty::Str | ty::Dynamic(..) => {
                 ExpectRvalueLikeUnsized(ty)
             }
             _ => ExpectHasType(ty)
@@ -760,7 +761,7 @@ fn primary_body_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              -> Option<(hir::BodyId, Option<&'tcx hir::FnDecl>)>
 {
     match tcx.hir.get(id) {
-        hir::map::NodeItem(item) => {
+        Node::Item(item) => {
             match item.node {
                 hir::ItemKind::Const(_, body) |
                 hir::ItemKind::Static(_, _, body) =>
@@ -771,7 +772,7 @@ fn primary_body_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     None,
             }
         }
-        hir::map::NodeTraitItem(item) => {
+        Node::TraitItem(item) => {
             match item.node {
                 hir::TraitItemKind::Const(_, Some(body)) =>
                     Some((body, None)),
@@ -781,7 +782,7 @@ fn primary_body_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     None,
             }
         }
-        hir::map::NodeImplItem(item) => {
+        Node::ImplItem(item) => {
             match item.node {
                 hir::ImplItemKind::Const(_, body) =>
                     Some((body, None)),
@@ -791,7 +792,7 @@ fn primary_body_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     None,
             }
         }
-        hir::map::NodeAnonConst(constant) => Some((constant.body, None)),
+        Node::AnonConst(constant) => Some((constant.body, None)),
         _ => None,
     }
 }
@@ -879,7 +880,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
         fcx.check_casts();
 
-        // Closure and generater analysis may run after fallback
+        // Closure and generator analysis may run after fallback
         // because they don't constrain other type variables.
         fcx.closure_analyze(body);
         assert!(fcx.deferred_call_resolutions.borrow().is_empty());
@@ -1137,7 +1138,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
     if let Some(panic_impl_did) = fcx.tcx.lang_items().panic_impl() {
         if panic_impl_did == fcx.tcx.hir.local_def_id(fn_id) {
             if let Some(panic_info_did) = fcx.tcx.lang_items().panic_info() {
-                if declared_ret_ty.sty != ty::TyNever {
+                if declared_ret_ty.sty != ty::Never {
                     fcx.tcx.sess.span_err(
                         decl.output.span(),
                         "return type should be `!`",
@@ -1148,8 +1149,8 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
                 let span = fcx.tcx.hir.span(fn_id);
                 if inputs.len() == 1 {
                     let arg_is_panic_info = match inputs[0].sty {
-                        ty::TyRef(region, ty, mutbl) => match ty.sty {
-                            ty::TyAdt(ref adt, _) => {
+                        ty::Ref(region, ty, mutbl) => match ty.sty {
+                            ty::Adt(ref adt, _) => {
                                 adt.did == panic_info_did &&
                                     mutbl == hir::Mutability::MutImmutable &&
                                     *region != RegionKind::ReStatic
@@ -1166,13 +1167,12 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
                         );
                     }
 
-                    if let Node::NodeItem(item) = fcx.tcx.hir.get(fn_id) {
+                    if let Node::Item(item) = fcx.tcx.hir.get(fn_id) {
                         if let ItemKind::Fn(_, _, ref generics, _) = item.node {
                             if !generics.params.is_empty() {
                                 fcx.tcx.sess.span_err(
                                     span,
-                                    "`#[panic_implementation]` function should have no type \
-                                     parameters",
+                                    "should have no type parameters",
                                 );
                             }
                         }
@@ -1190,7 +1190,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
     if let Some(alloc_error_handler_did) = fcx.tcx.lang_items().oom() {
         if alloc_error_handler_did == fcx.tcx.hir.local_def_id(fn_id) {
             if let Some(alloc_layout_did) = fcx.tcx.lang_items().alloc_layout() {
-                if declared_ret_ty.sty != ty::TyNever {
+                if declared_ret_ty.sty != ty::Never {
                     fcx.tcx.sess.span_err(
                         decl.output.span(),
                         "return type should be `!`",
@@ -1201,7 +1201,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
                 let span = fcx.tcx.hir.span(fn_id);
                 if inputs.len() == 1 {
                     let arg_is_alloc_layout = match inputs[0].sty {
-                        ty::TyAdt(ref adt, _) => {
+                        ty::Adt(ref adt, _) => {
                             adt.did == alloc_layout_did
                         },
                         _ => false,
@@ -1214,7 +1214,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
                         );
                     }
 
-                    if let Node::NodeItem(item) = fcx.tcx.hir.get(fn_id) {
+                    if let Node::Item(item) = fcx.tcx.hir.get(fn_id) {
                         if let ItemKind::Fn(_, _, ref generics, _) = item.node {
                             if !generics.params.is_empty() {
                                 fcx.tcx.sess.span_err(
@@ -1375,7 +1375,11 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt, id: DefId, span: Span) {
     };
     let param_env = ty::ParamEnv::reveal_all();
     if let Ok(static_) = tcx.const_eval(param_env.and(cid)) {
-        let alloc = tcx.const_value_to_allocation(static_);
+        let alloc = if let ConstValue::ByRef(_, allocation, _) = static_.val {
+            allocation
+        } else {
+            bug!("Matching on non-ByRef static")
+        };
         if alloc.relocations.len() != 0 {
             let msg = "statics with a custom `#[link_section]` must be a \
                        simple list of bytes on the wasm target with no \
@@ -1434,7 +1438,7 @@ fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         hir::ImplItemKind::Type(_) => ty::AssociatedKind::Type
     };
 
-    let parent = ancestors.defs(tcx, trait_item.ident, kind, trait_def.def_id).skip(1).next()
+    let parent = ancestors.defs(tcx, trait_item.ident, kind, trait_def.def_id).nth(1)
         .map(|node_item| node_item.map(|parent| parent.defaultness));
 
     if let Some(parent) = parent {
@@ -1633,7 +1637,7 @@ fn check_representable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId) {
     let t = tcx.type_of(def_id);
     match t.sty {
-        ty::TyAdt(def, substs) if def.is_struct() => {
+        ty::Adt(def, substs) if def.is_struct() => {
             let fields = &def.non_enum_variant().fields;
             if fields.is_empty() {
                 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
@@ -1647,7 +1651,7 @@ pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId
                 return;
             }
             match e.sty {
-                ty::TyParam(_) => { /* struct<T>(T, T, T, T) is ok */ }
+                ty::Param(_) => { /* struct<T>(T, T, T, T) is ok */ }
                 _ if e.is_machine()  => { /* struct(u8, u8, u8, u8) is ok */ }
                 _ => {
                     span_err!(tcx.sess, sp, E0077,
@@ -1693,7 +1697,7 @@ fn check_packed_inner<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return false;
     }
     match t.sty {
-        ty::TyAdt(def, substs) if def.is_struct() || def.is_union() => {
+        ty::Adt(def, substs) if def.is_struct() || def.is_union() => {
             if tcx.adt_def(def.did).repr.align > 0 {
                 return true;
             }
@@ -1702,7 +1706,7 @@ fn check_packed_inner<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             for field in &def.non_enum_variant().fields {
                 let f = field.ty(tcx, substs);
                 match f.sty {
-                    ty::TyAdt(def, _) => {
+                    ty::Adt(def, _) => {
                         if check_packed_inner(tcx, def.did, stack) {
                             return true;
                         }
@@ -1982,7 +1986,7 @@ pub fn misc(&self, span: Span) -> ObligationCause<'tcx> {
     fn resolve_type_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
         debug!("resolve_type_vars_with_obligations(ty={:?})", ty);
 
-        // No TyInfer()? Nothing needs doing.
+        // No Infer()? Nothing needs doing.
         if !ty.has_infer_types() {
             debug!("resolve_type_vars_with_obligations: ty={:?}", ty);
             return ty;
@@ -2058,11 +2062,47 @@ pub fn write_field_index(&self, node_id: ast::NodeId, index: usize) {
     pub fn write_method_call(&self,
                              hir_id: hir::HirId,
                              method: MethodCallee<'tcx>) {
+        debug!("write_method_call(hir_id={:?}, method={:?})", hir_id, method);
         self.tables
             .borrow_mut()
             .type_dependent_defs_mut()
             .insert(hir_id, Def::Method(method.def_id));
+
         self.write_substs(hir_id, method.substs);
+
+        // When the method is confirmed, the `method.substs` includes
+        // parameters from not just the method, but also the impl of
+        // the method -- in particular, the `Self` type will be fully
+        // resolved. However, those are not something that the "user
+        // specified" -- i.e., those types come from the inferred type
+        // of the receiver, not something the user wrote. So when we
+        // create the user-substs, we want to replace those earlier
+        // types with just the types that the user actually wrote --
+        // that is, those that appear on the *method itself*.
+        //
+        // As an example, if the user wrote something like
+        // `foo.bar::<u32>(...)` -- the `Self` type here will be the
+        // type of `foo` (possibly adjusted), but we don't want to
+        // include that. We want just the `[_, u32]` part.
+        if !method.substs.is_noop() {
+            let method_generics = self.tcx.generics_of(method.def_id);
+            if !method_generics.params.is_empty() {
+                let user_substs = self.infcx.probe(|_| {
+                    let just_method_substs = Substs::for_item(self.tcx, method.def_id, |param, _| {
+                        let i = param.index as usize;
+                        if i < method_generics.parent_count {
+                            self.infcx.var_for_def(DUMMY_SP, param)
+                        } else {
+                            method.substs[i]
+                        }
+                    });
+                    self.infcx.canonicalize_response(&just_method_substs)
+                });
+
+                debug!("write_method_call: user_substs = {:?}", user_substs);
+                self.write_user_substs(hir_id, user_substs);
+            }
+        }
     }
 
     pub fn write_substs(&self, node_id: hir::HirId, substs: &'tcx Substs<'tcx>) {
@@ -2076,6 +2116,36 @@ pub fn write_substs(&self, node_id: hir::HirId, substs: &'tcx Substs<'tcx>) {
         }
     }
 
+    /// Given the substs that we just converted from the HIR, try to
+    /// canonicalize them and store them as user-given substitutions
+    /// (i.e., substitutions that must be respected by the NLL check).
+    ///
+    /// This should be invoked **before any unifications have
+    /// occurred**, so that annotations like `Vec<_>` are preserved
+    /// properly.
+    pub fn write_user_substs_from_substs(&self, hir_id: hir::HirId, substs: &'tcx Substs<'tcx>) {
+        if !substs.is_noop() {
+            let user_substs = self.infcx.canonicalize_response(&substs);
+            debug!("instantiate_value_path: user_substs = {:?}", user_substs);
+            self.write_user_substs(hir_id, user_substs);
+        }
+    }
+
+    pub fn write_user_substs(&self, hir_id: hir::HirId, substs: CanonicalSubsts<'tcx>) {
+        debug!(
+            "write_user_substs({:?}, {:?}) in fcx {}",
+            hir_id,
+            substs,
+            self.tag(),
+        );
+
+        if !substs.is_identity() {
+            self.tables.borrow_mut().user_substs_mut().insert(hir_id, substs);
+        } else {
+            debug!("write_user_substs: skipping identity substs");
+        }
+    }
+
     pub fn apply_adjustments(&self, expr: &hir::Expr, adj: Vec<Adjustment<'tcx>>) {
         debug!("apply_adjustments(expr={:?}, adj={:?})", expr, adj);
 
@@ -2331,8 +2401,8 @@ fn resolve_generator_interiors(&self, def_id: DefId) {
     // feature(never_type) is enabled, unconstrained ints with i32,
     // unconstrained floats with f64.
     // Fallback becomes very dubious if we have encountered type-checking errors.
-    // In that case, fallback to TyError.
-    // The return value indicates whether fallback has occured.
+    // In that case, fallback to Error.
+    // The return value indicates whether fallback has occurred.
     fn fallback_if_possible(&self, ty: Ty<'tcx>) -> bool {
         use rustc::ty::error::UnconstrainedNumeric::Neither;
         use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
@@ -2481,7 +2551,7 @@ fn try_index_step(&self,
             let mut self_ty = adjusted_ty;
             if unsize {
                 // We only unsize arrays here.
-                if let ty::TyArray(element_ty, _) = adjusted_ty.sty {
+                if let ty::Array(element_ty, _) = adjusted_ty.sty {
                     self_ty = self.tcx.mk_slice(element_ty);
                 } else {
                     continue;
@@ -2500,7 +2570,7 @@ fn try_index_step(&self,
                 let method = self.register_infer_ok_obligations(ok);
 
                 let mut adjustments = autoderef.adjust_steps(needs);
-                if let ty::TyRef(region, _, r_mutbl) = method.sig.inputs()[0].sty {
+                if let ty::Ref(region, _, r_mutbl) = method.sig.inputs()[0].sty {
                     let mutbl = match r_mutbl {
                         hir::MutImmutable => AutoBorrowMutability::Immutable,
                         hir::MutMutable => AutoBorrowMutability::Mutable {
@@ -2678,10 +2748,11 @@ fn check_argument_types(&self,
                 let sugg_span = tcx.sess.source_map().end_point(expr_sp);
                 // remove closing `)` from the span
                 let sugg_span = sugg_span.shrink_to_lo();
-                err.span_suggestion(
+                err.span_suggestion_with_applicability(
                     sugg_span,
                     "expected the unit value `()`; create it with empty parentheses",
-                    String::from("()"));
+                    String::from("()"),
+                    Applicability::MachineApplicable);
             } else {
                 err.span_label(sp, format!("expected {}{} parameter{}",
                                             if variadic {"at least "} else {""},
@@ -2694,15 +2765,15 @@ fn check_argument_types(&self,
         let formal_tys = if tuple_arguments == TupleArguments {
             let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]);
             match tuple_type.sty {
-                ty::TyTuple(arg_types) if arg_types.len() != args.len() => {
+                ty::Tuple(arg_types) if arg_types.len() != args.len() => {
                     param_count_error(arg_types.len(), args.len(), "E0057", false, false);
                     expected_arg_tys = &[];
                     self.err_args(args.len())
                 }
-                ty::TyTuple(arg_types) => {
+                ty::Tuple(arg_types) => {
                     expected_arg_tys = match expected_arg_tys.get(0) {
                         Some(&ty) => match ty.sty {
-                            ty::TyTuple(ref tys) => &tys,
+                            ty::Tuple(ref tys) => &tys,
                             _ => &[]
                         },
                         None => &[]
@@ -2831,16 +2902,16 @@ fn variadic_error<'tcx>(s: &Session, span: Span, t: Ty<'tcx>, cast_ty: &str) {
                 // in C but we just error out instead and require explicit casts.
                 let arg_ty = self.structurally_resolved_type(arg.span, arg_ty);
                 match arg_ty.sty {
-                    ty::TyFloat(ast::FloatTy::F32) => {
+                    ty::Float(ast::FloatTy::F32) => {
                         variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
                     }
-                    ty::TyInt(ast::IntTy::I8) | ty::TyInt(ast::IntTy::I16) | ty::TyBool => {
+                    ty::Int(ast::IntTy::I8) | ty::Int(ast::IntTy::I16) | ty::Bool => {
                         variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
                     }
-                    ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => {
+                    ty::Uint(ast::UintTy::U8) | ty::Uint(ast::UintTy::U16) => {
                         variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
                     }
-                    ty::TyFnDef(..) => {
+                    ty::FnDef(..) => {
                         let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx));
                         let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty);
                         variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string());
@@ -2876,10 +2947,10 @@ fn check_lit(&self,
             ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => {
                 let opt_ty = expected.to_option(self).and_then(|ty| {
                     match ty.sty {
-                        ty::TyInt(_) | ty::TyUint(_) => Some(ty),
-                        ty::TyChar => Some(tcx.types.u8),
-                        ty::TyRawPtr(..) => Some(tcx.types.usize),
-                        ty::TyFnDef(..) | ty::TyFnPtr(_) => Some(tcx.types.usize),
+                        ty::Int(_) | ty::Uint(_) => Some(ty),
+                        ty::Char => Some(tcx.types.u8),
+                        ty::RawPtr(..) => Some(tcx.types.usize),
+                        ty::FnDef(..) | ty::FnPtr(_) => Some(tcx.types.usize),
                         _ => None
                     }
                 });
@@ -2890,7 +2961,7 @@ fn check_lit(&self,
             ast::LitKind::FloatUnsuffixed(_) => {
                 let opt_ty = expected.to_option(self).and_then(|ty| {
                     match ty.sty {
-                        ty::TyFloat(_) => Some(ty),
+                        ty::Float(_) => Some(ty),
                         _ => None
                     }
                 });
@@ -2943,7 +3014,11 @@ fn check_expr_meets_expectation_or_error(&self,
                         self.tcx.sess.source_map().span_to_snippet(lhs.span),
                         self.tcx.sess.source_map().span_to_snippet(rhs.span))
                     {
-                        err.span_suggestion(expr.span, msg, format!("{} == {}", left, right));
+                        err.span_suggestion_with_applicability(
+                            expr.span,
+                            msg,
+                            format!("{} == {}", left, right),
+                            Applicability::MaybeIncorrect);
                     } else {
                         err.help(msg);
                     }
@@ -3179,7 +3254,7 @@ fn check_field(&self,
         let mut autoderef = self.autoderef(expr.span, expr_t);
         while let Some((base_t, _)) = autoderef.next() {
             match base_t.sty {
-                ty::TyAdt(base_def, substs) if !base_def.is_enum() => {
+                ty::Adt(base_def, substs) if !base_def.is_enum() => {
                     debug!("struct named {:?}",  base_t);
                     let (ident, def_scope) =
                         self.tcx.adjust_ident(field, base_def.did, self.body_id);
@@ -3201,7 +3276,7 @@ fn check_field(&self,
                         private_candidate = Some((base_def.did, field_ty));
                     }
                 }
-                ty::TyTuple(ref tys) => {
+                ty::Tuple(ref tys) => {
                     let fstr = field.as_str();
                     if let Ok(index) = fstr.parse::<usize>() {
                         if fstr == index.to_string() {
@@ -3246,7 +3321,7 @@ fn check_field(&self,
                 let mut err = self.no_such_field_err(field.span, field, expr_t);
 
                 match expr_t.sty {
-                    ty::TyAdt(def, _) if !def.is_enum() => {
+                    ty::Adt(def, _) if !def.is_enum() => {
                         if let Some(suggested_field_name) =
                             Self::suggest_field_name(def.non_enum_variant(),
                                                      &field.as_str(), vec![]) {
@@ -3262,7 +3337,7 @@ fn check_field(&self,
                                 }
                             };
                     }
-                    ty::TyRawPtr(..) => {
+                    ty::RawPtr(..) => {
                         let base = self.tcx.hir.node_to_pretty_string(base.id);
                         let msg = format!("`{}` is a native pointer; try dereferencing it", base);
                         let suggestion = format!("(*{}).{}", base, field);
@@ -3336,7 +3411,7 @@ fn report_unknown_field(&self,
         let mut err = self.type_error_struct_with_diag(
             field.ident.span,
             |actual| match ty.sty {
-                ty::TyAdt(adt, ..) if adt.is_enum() => {
+                ty::Adt(adt, ..) if adt.is_enum() => {
                     struct_span_err!(self.tcx.sess, field.ident.span, E0559,
                                     "{} `{}::{}` has no field named `{}`",
                                     kind_name, actual, variant.name, field.ident)
@@ -3357,7 +3432,7 @@ fn report_unknown_field(&self,
                            format!("field does not exist - did you mean `{}`?", field_name));
         } else {
             match ty.sty {
-                ty::TyAdt(adt, ..) => {
+                ty::Adt(adt, ..) => {
                     if adt.is_enum() {
                         err.span_label(field.ident.span,
                                        format!("`{}::{}` does not have this field",
@@ -3395,7 +3470,7 @@ fn check_expr_struct_fields(&self,
         self.demand_eqtype(span, adt_ty_hint, adt_ty);
 
         let (substs, adt_kind, kind_name) = match &adt_ty.sty{
-            &ty::TyAdt(adt, substs) => {
+            &ty::Adt(adt, substs) => {
                 (substs, adt.adt_kind(), adt.variant_descr())
             }
             _ => span_bug!(span, "non-ADT passed to check_expr_struct_fields")
@@ -3466,7 +3541,7 @@ fn check_expr_struct_fields(&self,
             displayable_field_names.sort();
 
             let truncated_fields_error = if len <= 3 {
-                "".to_string()
+                String::new()
             } else {
                 format!(" and {} other field{}", (len - 3), if len - 3 == 1 {""} else {"s"})
             };
@@ -3520,7 +3595,7 @@ pub fn check_struct_path(&self,
             }
             Def::Variant(..) => {
                 match ty.sty {
-                    ty::TyAdt(adt, substs) => {
+                    ty::Adt(adt, substs) => {
                         Some((adt.variant_of_def(def), adt.did, substs))
                     }
                     _ => bug!("unexpected type: {:?}", ty.sty)
@@ -3529,7 +3604,7 @@ pub fn check_struct_path(&self,
             Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) |
             Def::AssociatedTy(..) | Def::SelfTy(..) => {
                 match ty.sty {
-                    ty::TyAdt(adt, substs) if !adt.is_enum() => {
+                    ty::Adt(adt, substs) if !adt.is_enum() => {
                         Some((adt.non_enum_variant(), adt.did, substs))
                     }
                     _ => None,
@@ -3539,6 +3614,10 @@ pub fn check_struct_path(&self,
         };
 
         if let Some((variant, did, substs)) = variant {
+            debug!("check_struct_path: did={:?} substs={:?}", did, substs);
+            let hir_id = self.tcx.hir.node_to_hir_id(node_id);
+            self.write_user_substs_from_substs(hir_id, substs);
+
             // Check bounds on type arguments used in the path.
             let bounds = self.instantiate_bounds(path_span, did, substs);
             let cause = traits::ObligationCause::new(path_span, self.body_id,
@@ -3578,7 +3657,7 @@ fn check_expr_struct(&self,
         };
 
         // Prohibit struct expressions when non exhaustive flag is set.
-        if let ty::TyAdt(adt, _) = struct_ty.sty {
+        if let ty::Adt(adt, _) = struct_ty.sty {
             if !adt.did.is_local() && adt.is_non_exhaustive() {
                 span_err!(self.tcx.sess, expr.span, E0639,
                           "cannot create non-exhaustive {} using struct expression",
@@ -3595,7 +3674,7 @@ fn check_expr_struct(&self,
             if !error_happened {
                 self.check_expr_has_type_or_error(base_expr, struct_ty);
                 match struct_ty.sty {
-                    ty::TyAdt(adt, substs) if adt.is_struct() => {
+                    ty::Adt(adt, substs) if adt.is_struct() => {
                         let fru_field_types = adt.non_enum_variant().fields.iter().map(|f| {
                             self.normalize_associated_types_in(expr.span, &f.ty(self.tcx, substs))
                         }).collect();
@@ -3625,7 +3704,7 @@ fn check_expr_struct(&self,
     /// strict, _|_ can appear in the type of an expression that does not,
     /// itself, diverge: for example, fn() -> _|_.)
     /// Note that inspecting a type's structure *directly* may expose the fact
-    /// that there are actually multiple representations for `TyError`, so avoid
+    /// that there are actually multiple representations for `Error`, so avoid
     /// that when err needs to be handled differently.
     fn check_expr_with_expectation_and_needs(&self,
                                                    expr: &'gcx hir::Expr,
@@ -3684,7 +3763,7 @@ fn check_expr_kind(&self,
             hir::ExprKind::Box(ref subexpr) => {
                 let expected_inner = expected.to_option(self).map_or(NoExpectation, |ty| {
                     match ty.sty {
-                        ty::TyAdt(def, _) if def.is_box()
+                        ty::Adt(def, _) if def.is_box()
                             => Expectation::rvalue_hint(self, ty.boxed_ty()),
                         _ => NoExpectation
                     }
@@ -3728,7 +3807,7 @@ fn check_expr_kind(&self,
                             } else if let Some(ok) = self.try_overloaded_deref(
                                     expr.span, oprnd_t, needs) {
                                 let method = self.register_infer_ok_obligations(ok);
-                                if let ty::TyRef(region, _, mutbl) = method.sig.inputs()[0].sty {
+                                if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].sty {
                                     let mutbl = match mutbl {
                                         hir::MutImmutable => AutoBorrowMutability::Immutable,
                                         hir::MutMutable => AutoBorrowMutability::Mutable {
@@ -3755,7 +3834,7 @@ fn check_expr_kind(&self,
                         hir::UnNot => {
                             let result = self.check_user_unop(expr, oprnd_t, unop);
                             // If it's builtin, we can reuse the type, this helps inference.
-                            if !(oprnd_t.is_integral() || oprnd_t.sty == ty::TyBool) {
+                            if !(oprnd_t.is_integral() || oprnd_t.sty == ty::Bool) {
                                 oprnd_t = result;
                             }
                         }
@@ -3773,7 +3852,7 @@ fn check_expr_kind(&self,
             hir::ExprKind::AddrOf(mutbl, ref oprnd) => {
                 let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
                     match ty.sty {
-                        ty::TyRef(_, ty, _) | ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => {
+                        ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
                             if self.is_place_expr(&oprnd) {
                                 // Places may legitimately have unsized types.
                                 // For example, dereferences of a fat pointer and
@@ -4086,7 +4165,7 @@ fn check_expr_kind(&self,
             hir::ExprKind::Array(ref args) => {
                 let uty = expected.to_option(self).and_then(|uty| {
                     match uty.sty {
-                        ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
+                        ty::Array(ty, _) | ty::Slice(ty) => Some(ty),
                         _ => None
                     }
                 });
@@ -4133,7 +4212,7 @@ fn check_expr_kind(&self,
                 let uty = match expected {
                     ExpectHasType(uty) => {
                         match uty.sty {
-                            ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
+                            ty::Array(ty, _) | ty::Slice(ty) => Some(ty),
                             _ => None
                         }
                     }
@@ -4165,7 +4244,7 @@ fn check_expr_kind(&self,
                 if element_ty.references_error() {
                     tcx.types.err
                 } else if let Ok(count) = count {
-                    tcx.mk_ty(ty::TyArray(t, count))
+                    tcx.mk_ty(ty::Array(t, count))
                 } else {
                     tcx.types.err
                 }
@@ -4174,7 +4253,7 @@ fn check_expr_kind(&self,
                 let flds = expected.only_has_type(self).and_then(|ty| {
                     let ty = self.resolve_type_vars_with_obligations(ty);
                     match ty.sty {
-                        ty::TyTuple(ref flds) => Some(&flds[..]),
+                        ty::Tuple(ref flds) => Some(&flds[..]),
                         _ => None
                     }
                 });
@@ -4228,7 +4307,7 @@ fn check_expr_kind(&self,
                                                    "cannot index into a value of type `{}`",
                                                    base_t);
                             // Try to give some advice about indexing tuples.
-                            if let ty::TyTuple(..) = base_t.sty {
+                            if let ty::Tuple(..) = base_t.sty {
                                 let mut needs_note = true;
                                 // If the index is an integer, we can show the actual
                                 // fixed expression:
@@ -4237,9 +4316,11 @@ fn check_expr_kind(&self,
                                             ast::LitIntType::Unsuffixed) = lit.node {
                                         let snip = tcx.sess.source_map().span_to_snippet(base.span);
                                         if let Ok(snip) = snip {
-                                            err.span_suggestion(expr.span,
-                                                                "to access tuple elements, use",
-                                                                format!("{}.{}", snip, i));
+                                            err.span_suggestion_with_applicability(
+                                                expr.span,
+                                                "to access tuple elements, use",
+                                                format!("{}.{}", snip, i),
+                                                Applicability::MachineApplicable);
                                             needs_note = false;
                                         }
                                     }
@@ -4464,7 +4545,7 @@ fn check_block_with_expected(&self,
         // In some cases, blocks have just one exit, but other blocks
         // can be targeted by multiple breaks. This can happen both
         // with labeled blocks as well as when we desugar
-        // a `do catch { ... }` expression.
+        // a `try { ... }` expression.
         //
         // Example 1:
         //
@@ -4569,7 +4650,7 @@ pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> {
         if let Some(fn_id) = self.tcx.hir.get_return_block(blk_id) {
             let parent = self.tcx.hir.get(fn_id);
 
-            if let Node::NodeItem(&hir::Item {
+            if let Node::Item(&hir::Item {
                 name, node: hir::ItemKind::Fn(ref decl, ..), ..
             }) = parent {
                 decl.clone().and_then(|decl| {
@@ -4578,7 +4659,7 @@ pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> {
                     // but it will still present it as the reason for the expected type.
                     Some((decl, name != Symbol::intern("main")))
                 })
-            } else if let Node::NodeTraitItem(&hir::TraitItem {
+            } else if let Node::TraitItem(&hir::TraitItem {
                 node: hir::TraitItemKind::Method(hir::MethodSig {
                     ref decl, ..
                 }, ..), ..
@@ -4586,7 +4667,7 @@ pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> {
                 decl.clone().and_then(|decl| {
                     Some((decl, true))
                 })
-            } else if let Node::NodeImplItem(&hir::ImplItem {
+            } else if let Node::ImplItem(&hir::ImplItem {
                 node: hir::ImplItemKind::Method(hir::MethodSig {
                     ref decl, ..
                 }, ..), ..
@@ -4677,9 +4758,11 @@ fn suggest_missing_semicolon(&self,
                 hir::ExprKind::Match(..) |
                 hir::ExprKind::Block(..) => {
                     let sp = self.tcx.sess.source_map().next_point(cause_span);
-                    err.span_suggestion(sp,
-                                        "try adding a semicolon",
-                                        ";".to_string());
+                    err.span_suggestion_with_applicability(
+                        sp,
+                        "try adding a semicolon",
+                        ";".to_string(),
+                        Applicability::MachineApplicable);
                 }
                 _ => (),
             }
@@ -4708,10 +4791,11 @@ fn suggest_missing_return_type(&self,
         // haven't set a return type at all (and aren't `fn main()` or an impl).
         match (&fn_decl.output, found.is_suggestable(), can_suggest, expected.is_nil()) {
             (&hir::FunctionRetTy::DefaultReturn(span), true, true, true) => {
-                err.span_suggestion(span,
-                                    "try adding a return type",
-                                    format!("-> {} ",
-                                            self.resolve_type_vars_with_obligations(found)));
+                err.span_suggestion_with_applicability(
+                    span,
+                    "try adding a return type",
+                    format!("-> {} ", self.resolve_type_vars_with_obligations(found)),
+                    Applicability::MachineApplicable);
             }
             (&hir::FunctionRetTy::DefaultReturn(span), false, true, true) => {
                 err.span_label(span, "possibly return type missing here?");
@@ -4770,7 +4854,11 @@ fn consider_hint_about_removing_semicolon(&self,
         }
         let original_span = original_sp(last_stmt.span, blk.span);
         let span_semi = original_span.with_lo(original_span.hi() - BytePos(1));
-        err.span_suggestion(span_semi, "consider removing this semicolon", "".to_string());
+        err.span_suggestion_with_applicability(
+            span_semi,
+            "consider removing this semicolon",
+            String::new(),
+            Applicability::MachineApplicable);
     }
 
     fn def_ids_for_path_segments(&self,
@@ -5020,7 +5108,7 @@ pub fn instantiate_value_path(&self,
                             // If no type arguments were provided, we have to infer them.
                             // This case also occurs as a result of some malformed input, e.g.
                             // a lifetime argument being given instead of a type paramter.
-                            // Using inference instead of `TyError` gives better error messages.
+                            // Using inference instead of `Error` gives better error messages.
                             self.var_for_def(span, param)
                         }
                     }
@@ -5069,7 +5157,11 @@ pub fn instantiate_value_path(&self,
         debug!("instantiate_value_path: type of {:?} is {:?}",
                node_id,
                ty_substituted);
-        self.write_substs(self.tcx.hir.node_to_hir_id(node_id), substs);
+        let hir_id = self.tcx.hir.node_to_hir_id(node_id);
+        self.write_substs(hir_id, substs);
+
+        self.write_user_substs_from_substs(hir_id, substs);
+
         ty_substituted
     }
 
@@ -5086,7 +5178,7 @@ fn check_rustc_args_require_const(&self,
         // If our calling expression is indeed the function itself, we're good!
         // If not, generate an error that this can only be called directly.
         match self.tcx.hir.get(self.tcx.hir.get_parent_node(node_id)) {
-            Node::NodeExpr(expr) => {
+            Node::Expr(expr) => {
                 match expr.node {
                     hir::ExprKind::Call(ref callee, ..) => {
                         if callee.id == node_id {
@@ -5155,10 +5247,10 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut types_used = vec![false; own_counts.types];
 
     for leaf_ty in ty.walk() {
-        if let ty::TyParam(ty::ParamTy { idx, .. }) = leaf_ty.sty {
+        if let ty::Param(ty::ParamTy { idx, .. }) = leaf_ty.sty {
             debug!("Found use of ty param num {}", idx);
             types_used[idx as usize - own_counts.lifetimes] = true;
-        } else if let ty::TyError = leaf_ty.sty {
+        } else if let ty::Error = leaf_ty.sty {
             // If there is already another error, do not emit
             // an error for not using a type Parameter.
             assert!(tcx.sess.err_count() > 0);
index de211d2209c9a085961f5a1f0592863b1ad7a4e7..b7cf6819e21803638ad4ba85f77b54e865354374 100644 (file)
@@ -13,7 +13,7 @@
 use super::{FnCtxt, Needs};
 use super::method::MethodCallee;
 use rustc::ty::{self, Ty, TypeFoldable};
-use rustc::ty::TypeVariants::{TyRef, TyAdt, TyStr, TyUint, TyNever, TyTuple, TyChar, TyArray};
+use rustc::ty::TyKind::{Ref, Adt, Str, Uint, Never, Tuple, Char, Array};
 use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::infer::type_variable::TypeVariableOrigin;
 use errors;
@@ -204,7 +204,7 @@ fn check_overloaded_binop(&self,
             Ok(method) => {
                 let by_ref_binop = !op.node.is_by_value();
                 if is_assign == IsAssign::Yes || by_ref_binop {
-                    if let ty::TyRef(region, _, mutbl) = method.sig.inputs()[0].sty {
+                    if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].sty {
                         let mutbl = match mutbl {
                             hir::MutImmutable => AutoBorrowMutability::Immutable,
                             hir::MutMutable => AutoBorrowMutability::Mutable {
@@ -221,7 +221,7 @@ fn check_overloaded_binop(&self,
                     }
                 }
                 if by_ref_binop {
-                    if let ty::TyRef(region, _, mutbl) = method.sig.inputs()[1].sty {
+                    if let ty::Ref(region, _, mutbl) = method.sig.inputs()[1].sty {
                         let mutbl = match mutbl {
                             hir::MutImmutable => AutoBorrowMutability::Immutable,
                             hir::MutMutable => AutoBorrowMutability::Mutable {
@@ -265,7 +265,7 @@ fn check_overloaded_binop(&self,
                                     format!("cannot use `{}=` on type `{}`",
                                     op.node.as_str(), lhs_ty));
                             let mut suggested_deref = false;
-                            if let TyRef(_, mut rty, _) = lhs_ty.sty {
+                            if let Ref(_, mut rty, _) = lhs_ty.sty {
                                 if {
                                     !self.infcx.type_moves_by_default(self.param_env,
                                                                         rty,
@@ -276,7 +276,7 @@ fn check_overloaded_binop(&self,
                                             .is_ok()
                                 } {
                                     if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) {
-                                        while let TyRef(_, rty_inner, _) = rty.sty {
+                                        while let Ref(_, rty_inner, _) = rty.sty {
                                             rty = rty_inner;
                                         }
                                         let msg = &format!(
@@ -311,7 +311,7 @@ fn check_overloaded_binop(&self,
                                     // This has nothing here because it means we did string
                                     // concatenation (e.g. "Hello " += "World!"). This means
                                     // we don't want the note in the else clause to be emitted
-                                } else if let ty::TyParam(_) = lhs_ty.sty {
+                                } else if let ty::Param(_) = lhs_ty.sty {
                                     // FIXME: point to span of param
                                     err.note(&format!(
                                         "`{}` might need a bound for `{}`",
@@ -333,7 +333,7 @@ fn check_overloaded_binop(&self,
                                             op.node.as_str(),
                                             lhs_ty);
                             let mut suggested_deref = false;
-                            if let TyRef(_, mut rty, _) = lhs_ty.sty {
+                            if let Ref(_, mut rty, _) = lhs_ty.sty {
                                 if {
                                     !self.infcx.type_moves_by_default(self.param_env,
                                                                         rty,
@@ -344,7 +344,7 @@ fn check_overloaded_binop(&self,
                                             .is_ok()
                                 } {
                                     if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) {
-                                        while let TyRef(_, rty_inner, _) = rty.sty {
+                                        while let Ref(_, rty_inner, _) = rty.sty {
                                             rty = rty_inner;
                                         }
                                         let msg = &format!(
@@ -385,7 +385,7 @@ fn check_overloaded_binop(&self,
                                     // This has nothing here because it means we did string
                                     // concatenation (e.g. "Hello " + "World!"). This means
                                     // we don't want the note in the else clause to be emitted
-                                } else if let ty::TyParam(_) = lhs_ty.sty {
+                                } else if let ty::Param(_) = lhs_ty.sty {
                                     // FIXME: point to span of param
                                     err.note(&format!(
                                         "`{}` might need a bound for `{}`",
@@ -429,8 +429,8 @@ fn check_str_addition(
         // If this function returns true it means a note was printed, so we don't need
         // to print the normal "implementation of `std::ops::Add` might be missing" note
         match (&lhs_ty.sty, &rhs_ty.sty) {
-            (&TyRef(_, l_ty, _), &TyRef(_, r_ty, _))
-            if l_ty.sty == TyStr && r_ty.sty == TyStr => {
+            (&Ref(_, l_ty, _), &Ref(_, r_ty, _))
+            if l_ty.sty == Str && r_ty.sty == Str => {
                 if !is_assign {
                     err.span_label(expr.span,
                                    "`+` can't be used to concatenate two `&str` strings");
@@ -443,8 +443,8 @@ fn check_str_addition(
                 }
                 true
             }
-            (&TyRef(_, l_ty, _), &TyAdt(..))
-            if l_ty.sty == TyStr && &format!("{:?}", rhs_ty) == "std::string::String" => {
+            (&Ref(_, l_ty, _), &Adt(..))
+            if l_ty.sty == Str && &format!("{:?}", rhs_ty) == "std::string::String" => {
                 err.span_label(expr.span,
                     "`+` can't be used to concatenate a `&str` with a `String`");
                 match (
@@ -489,11 +489,11 @@ pub fn check_user_unop(&self,
                     err.span_label(ex.span, format!("cannot apply unary \
                                                     operator `{}`", op.as_str()));
                     match actual.sty {
-                        TyUint(_) if op == hir::UnNeg => {
+                        Uint(_) if op == hir::UnNeg => {
                             err.note("unsigned values cannot be negated");
                         },
-                        TyStr | TyNever | TyChar | TyTuple(_) | TyArray(_,_) => {},
-                        TyRef(_, ref lty, _) if lty.sty == TyStr => {},
+                        Str | Never | Char | Tuple(_) | Array(_,_) => {},
+                        Ref(_, ref lty, _) if lty.sty == Str => {},
                         _ => {
                             let missing_trait = match op {
                                 hir::UnNeg => "std::ops::Neg",
index 8aa5658d291db711a1b2bb60c0deaf26d3ceaf6b..867864b3853d067c2556d6f90b003085248646b7 100644 (file)
@@ -589,7 +589,7 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
                 // For overloaded derefs, base_ty is the input to `Deref::deref`,
                 // but it's a reference type uing the same region as the output.
                 let base_ty = self.resolve_expr_type_adjusted(base);
-                if let ty::TyRef(r_ptr, _, _) = base_ty.sty {
+                if let ty::Ref(r_ptr, _, _) = base_ty.sty {
                     self.mk_subregion_due_to_dereference(expr.span, expr_region, r_ptr);
                 }
 
@@ -702,22 +702,22 @@ fn walk_cast(&mut self,
                from_ty,
                to_ty);
         match (&from_ty.sty, &to_ty.sty) {
-            /*From:*/ (&ty::TyRef(from_r, from_ty, _),
-            /*To:  */  &ty::TyRef(to_r, to_ty, _)) => {
+            /*From:*/ (&ty::Ref(from_r, from_ty, _),
+            /*To:  */  &ty::Ref(to_r, to_ty, _)) => {
                 // Target cannot outlive source, naturally.
                 self.sub_regions(infer::Reborrow(cast_expr.span), to_r, from_r);
                 self.walk_cast(cast_expr, from_ty, to_ty);
             }
 
             /*From:*/ (_,
-            /*To:  */  &ty::TyDynamic(.., r)) => {
+            /*To:  */  &ty::Dynamic(.., r)) => {
                 // When T is existentially quantified as a trait
                 // `Foo+'to`, it must outlive the region bound `'to`.
                 self.type_must_outlive(infer::RelateObjectBound(cast_expr.span), from_ty, r);
             }
 
-            /*From:*/ (&ty::TyAdt(from_def, _),
-            /*To:  */  &ty::TyAdt(to_def, _)) if from_def.is_box() && to_def.is_box() => {
+            /*From:*/ (&ty::Adt(from_def, _),
+            /*To:  */  &ty::Adt(to_def, _)) if from_def.is_box() && to_def.is_box() => {
                 self.walk_cast(cast_expr, from_ty.boxed_ty(), to_ty.boxed_ty());
             }
 
@@ -736,7 +736,7 @@ fn check_expr_fn_block(&mut self,
     fn constrain_callee(&mut self, callee_expr: &hir::Expr) {
         let callee_ty = self.resolve_node_type(callee_expr.hir_id);
         match callee_ty.sty {
-            ty::TyFnDef(..) | ty::TyFnPtr(_) => { }
+            ty::FnDef(..) | ty::FnPtr(_) => { }
             _ => {
                 // this should not happen, but it does if the program is
                 // erroneous
@@ -914,9 +914,9 @@ fn constrain_index(&mut self,
                self.ty_to_string(indexed_ty));
 
         let r_index_expr = ty::ReScope(region::Scope::Node(index_expr.hir_id.local_id));
-        if let ty::TyRef(r_ptr, r_ty, _) = indexed_ty.sty {
+        if let ty::Ref(r_ptr, r_ty, _) = indexed_ty.sty {
             match r_ty.sty {
-                ty::TySlice(_) | ty::TyStr => {
+                ty::Slice(_) | ty::Str => {
                     self.sub_regions(infer::IndexSlice(index_expr.span),
                                      self.tcx.mk_region(r_index_expr), r_ptr);
                 }
@@ -1089,7 +1089,7 @@ fn link_region_from_node_type(&self,
                id, mutbl, cmt_borrowed);
 
         let rptr_ty = self.resolve_node_type(id);
-        if let ty::TyRef(r, _, _) = rptr_ty.sty {
+        if let ty::Ref(r, _, _) = rptr_ty.sty {
             debug!("rptr_ty={}",  rptr_ty);
             self.link_region(span, r, ty::BorrowKind::from_mutbl(mutbl), cmt_borrowed);
         }
@@ -1284,7 +1284,7 @@ fn link_reborrowed_region(&self,
         // how all the types get adjusted.)
         match ref_kind {
             ty::ImmBorrow => {
-                // The reference being reborrowed is a sharable ref of
+                // The reference being reborrowed is a shareable ref of
                 // type `&'a T`. In this case, it doesn't matter where we
                 // *found* the `&T` pointer, the memory it references will
                 // be valid and immutable for `'a`. So we can stop here.
index 61fe90be2177420c9567dfe5a5ff9e30d221dbe0..41df937980ff3430e69f29a35bd1a3b03a421a8d 100644 (file)
@@ -109,9 +109,9 @@ fn analyze_closure(
 
         // Extract the type of the closure.
         let (closure_def_id, substs) = match self.node_ty(closure_hir_id).sty {
-            ty::TyClosure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
-            ty::TyGenerator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
-            ty::TyError => {
+            ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
+            ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
+            ty::Error => {
                 // #51714: skip analysis when we have already encountered type errors
                 return;
             }
index 4b609779540f02f674e9645dab463195e7e4874e..99e0e8775b0cddf413dd35f6780265fe2ecb28d6 100644 (file)
@@ -454,7 +454,7 @@ struct CountParams { params: FxHashSet<u32> }
         impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
             fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
                 match t.sty {
-                    ty::TyParam(p) => {
+                    ty::Param(p) => {
                         self.params.insert(p.idx);
                         t.super_visit_with(self)
                     }
@@ -576,7 +576,7 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
     ty.fold_with(&mut ty::fold::BottomUpFolder {
         tcx: fcx.tcx,
         fldop: |ty| {
-            if let ty::TyAnon(def_id, substs) = ty.sty {
+            if let ty::Anon(def_id, substs) = ty.sty {
                 trace!("check_existential_types: anon_ty, {:?}, {:?}", def_id, substs);
                 let generics = tcx.generics_of(def_id);
                 // only check named existential types
@@ -588,7 +588,7 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
                         for (subst, param) in substs.iter().zip(&generics.params) {
                             match subst.unpack() {
                                 ty::subst::UnpackedKind::Type(ty) => match ty.sty {
-                                    ty::TyParam(..) => {},
+                                    ty::Param(..) => {},
                                     // prevent `fn foo() -> Foo<u32>` from being defining
                                     _ => {
                                         tcx
@@ -674,7 +674,7 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
                         }
                     }
                 } // if is_named_existential_type
-            } // if let TyAnon
+            } // if let Anon
             ty
         },
         reg_op: |reg| reg,
index b37f489b2c721419002f3ad2d96fae2e51153ecd..0d8401c1c86efafd66ea4c4606283f795fc21b09 100644 (file)
 use rustc::hir::def_id::{DefId, DefIndex};
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::infer::InferCtxt;
+use rustc::ty::adjustment::{Adjust, Adjustment};
+use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder};
 use rustc::ty::subst::UnpackedKind;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::adjustment::{Adjust, Adjustment};
-use rustc::ty::fold::{TypeFoldable, TypeFolder, BottomUpFolder};
 use rustc::util::nodemap::DefIdSet;
+use rustc_data_structures::sync::Lrc;
+use std::mem;
 use syntax::ast;
 use syntax_pos::Span;
-use std::mem;
-use rustc_data_structures::sync::Lrc;
 
 ///////////////////////////////////////////////////////////////////////////
 // Entry point
@@ -35,7 +35,11 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::Type
         let item_id = self.tcx.hir.body_owner(body.id());
         let item_def_id = self.tcx.hir.local_def_id(item_id);
 
-        let mut wbcx = WritebackCx::new(self, body);
+        // This attribute causes us to dump some writeback information
+        // in the form of errors, which is used for unit tests.
+        let rustc_dump_user_substs = self.tcx.has_attr(item_def_id, "rustc_dump_user_substs");
+
+        let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_substs);
         for arg in &body.arguments {
             wbcx.visit_node_id(arg.pat.span, arg.hir_id);
         }
@@ -55,8 +59,7 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::Type
         );
         debug!(
             "used_trait_imports({:?}) = {:?}",
-            item_def_id,
-            used_trait_imports
+            item_def_id, used_trait_imports
         );
         wbcx.tables.used_trait_imports = used_trait_imports;
 
@@ -64,8 +67,7 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::Type
 
         debug!(
             "writeback: tables for {:?} are {:#?}",
-            item_def_id,
-            wbcx.tables
+            item_def_id, wbcx.tables
         );
 
         self.tcx.alloc_tables(wbcx.tables)
@@ -86,12 +88,15 @@ struct WritebackCx<'cx, 'gcx: 'cx + 'tcx, 'tcx: 'cx> {
     tables: ty::TypeckTables<'gcx>,
 
     body: &'gcx hir::Body,
+
+    rustc_dump_user_substs: bool,
 }
 
 impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
     fn new(
         fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>,
         body: &'gcx hir::Body,
+        rustc_dump_user_substs: bool,
     ) -> WritebackCx<'cx, 'gcx, 'tcx> {
         let owner = fcx.tcx.hir.definitions().node_to_hir_id(body.id().node_id);
 
@@ -99,6 +104,7 @@ fn new(
             fcx,
             tables: ty::TypeckTables::empty(Some(DefId::local(owner.owner))),
             body,
+            rustc_dump_user_substs,
         }
     }
 
@@ -118,8 +124,8 @@ fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'gcx>) {
     // operating on scalars, we clear the overload.
     fn fix_scalar_builtin_expr(&mut self, e: &hir::Expr) {
         match e.node {
-            hir::ExprKind::Unary(hir::UnNeg, ref inner) |
-            hir::ExprKind::Unary(hir::UnNot, ref inner) => {
+            hir::ExprKind::Unary(hir::UnNeg, ref inner)
+            hir::ExprKind::Unary(hir::UnNot, ref inner) => {
                 let inner_ty = self.fcx.node_ty(inner.hir_id);
                 let inner_ty = self.fcx.resolve_type_vars_if_possible(&inner_ty);
 
@@ -174,12 +180,11 @@ fn fix_index_builtin_expr(&mut self, e: &hir::Expr) {
 
             match tables.expr_ty_adjusted(&base).sty {
                 // All valid indexing looks like this
-                ty::TyRef(_, base_ty, _) => {
+                ty::Ref(_, base_ty, _) => {
                     let index_ty = tables.expr_ty_adjusted(&index);
                     let index_ty = self.fcx.resolve_type_vars_if_possible(&index_ty);
 
-                    if base_ty.builtin_index().is_some()
-                        && index_ty == self.fcx.tcx.types.usize {
+                    if base_ty.builtin_index().is_some() && index_ty == self.fcx.tcx.types.usize {
                         // Remove the method call record
                         tables.type_dependent_defs_mut().remove(e.hir_id);
                         tables.node_substs_mut().remove(e.hir_id);
@@ -191,24 +196,26 @@ fn fix_index_builtin_expr(&mut self, e: &hir::Expr) {
                                 // of size information - we need to get rid of it
                                 // Since this is "after" the other adjustment to be
                                 // discarded, we do an extra `pop()`
-                                Some(Adjustment { kind: Adjust::Unsize, .. }) => {
+                                Some(Adjustment {
+                                    kind: Adjust::Unsize,
+                                    ..
+                                }) => {
                                     // So the borrow discard actually happens here
                                     a.pop();
-                                },
+                                }
                                 _ => {}
                             }
                         });
                     }
-                },
+                }
                 // Might encounter non-valid indexes at this point, so there
                 // has to be a fall-through
-                _ => {},
+                _ => {}
             }
         }
     }
 }
 
-
 ///////////////////////////////////////////////////////////////////////////
 // Impl of Visitor for Resolver
 //
@@ -262,7 +269,9 @@ fn visit_pat(&mut self, p: &'gcx hir::Pat) {
                 if let Some(&bm) = self.fcx.tables.borrow().pat_binding_modes().get(p.hir_id) {
                     self.tables.pat_binding_modes_mut().insert(p.hir_id, bm);
                 } else {
-                    self.tcx().sess.delay_span_bug(p.span, "missing binding mode");
+                    self.tcx()
+                        .sess
+                        .delay_span_bug(p.span, "missing binding mode");
                 }
             }
             hir::PatKind::Struct(_, ref fields, _) => {
@@ -310,8 +319,7 @@ fn visit_upvar_borrow_map(&mut self) {
             };
             debug!(
                 "Upvar capture for {:?} resolved to {:?}",
-                upvar_id,
-                new_upvar_capture
+                upvar_id, new_upvar_capture
             );
             self.tables
                 .upvar_capture_map
@@ -417,7 +425,7 @@ fn visit_anon_types(&mut self, span: Span) {
                     fldop: |ty| {
                         trace!("checking type {:?}: {:#?}", ty, ty.sty);
                         // find a type parameter
-                        if let ty::TyParam(..) = ty.sty {
+                        if let ty::Param(..) = ty.sty {
                             // look it up in the substitution list
                             assert_eq!(anon_defn.substs.len(), generics.params.len());
                             for (subst, param) in anon_defn.substs.iter().zip(&generics.params) {
@@ -425,8 +433,7 @@ fn visit_anon_types(&mut self, span: Span) {
                                     if subst == ty {
                                         // found it in the substitution list, replace with the
                                         // parameter from the existential type
-                                        return self
-                                            .tcx()
+                                        return self.tcx()
                                             .global_tcx()
                                             .mk_ty_param(param.index, param.name);
                                     }
@@ -464,14 +471,16 @@ fn visit_anon_types(&mut self, span: Span) {
                                                 name: p.name,
                                             };
                                             trace!("replace {:?} with {:?}", region, reg);
-                                            return self.tcx().global_tcx()
+                                            return self.tcx()
+                                                .global_tcx()
                                                 .mk_region(ty::ReEarlyBound(reg));
                                         }
                                     }
                                 }
                                 trace!("anon_defn: {:#?}", anon_defn);
                                 trace!("generics: {:#?}", generics);
-                                self.tcx().sess
+                                self.tcx()
+                                    .sess
                                     .struct_span_err(
                                         span,
                                         "non-defining existential type use in defining scope",
@@ -480,7 +489,7 @@ fn visit_anon_types(&mut self, span: Span) {
                                         span,
                                         format!(
                                             "lifetime `{}` is part of concrete type but not used \
-                                            in parameter list of existential type",
+                                             in parameter list of existential type",
                                             region,
                                         ),
                                     )
@@ -488,17 +497,27 @@ fn visit_anon_types(&mut self, span: Span) {
                                 self.tcx().global_tcx().mk_region(ty::ReStatic)
                             }
                         }
-                    }
+                    },
                 })
             };
 
-            let old = self.tables.concrete_existential_types.insert(def_id, definition_ty);
+            if let ty::Anon(defin_ty_def_id, _substs) = definition_ty.sty {
+                if def_id == defin_ty_def_id {
+                    // Concrete type resolved to the existential type itself
+                    // Force a cycle error
+                    self.tcx().at(span).type_of(defin_ty_def_id);
+                }
+            }
+
+            let old = self.tables
+                .concrete_existential_types
+                .insert(def_id, definition_ty);
             if let Some(old) = old {
                 if old != definition_ty {
                     span_bug!(
                         span,
                         "visit_anon_types tried to write \
-                        different types for the same existential type: {:?}, {:?}, {:?}",
+                         different types for the same existential type: {:?}, {:?}, {:?}",
                         def_id,
                         definition_ty,
                         old,
@@ -510,13 +529,18 @@ fn visit_anon_types(&mut self, span: Span) {
 
     fn visit_field_id(&mut self, node_id: ast::NodeId) {
         let hir_id = self.tcx().hir.node_to_hir_id(node_id);
-        if let Some(index) = self.fcx.tables.borrow_mut().field_indices_mut().remove(hir_id) {
+        if let Some(index) = self.fcx
+            .tables
+            .borrow_mut()
+            .field_indices_mut()
+            .remove(hir_id)
+        {
             self.tables.field_indices_mut().insert(hir_id, index);
         }
     }
 
     fn visit_node_id(&mut self, span: Span, hir_id: hir::HirId) {
-        // Export associated path extensions and method resultions.
+        // Export associated path extensions and method resolutions.
         if let Some(def) = self.fcx
             .tables
             .borrow_mut()
@@ -542,6 +566,22 @@ fn visit_node_id(&mut self, span: Span, hir_id: hir::HirId) {
             assert!(!substs.needs_infer() && !substs.has_skol());
             self.tables.node_substs_mut().insert(hir_id, substs);
         }
+
+        // Copy over any user-substs
+        if let Some(user_substs) = self.fcx.tables.borrow().user_substs(hir_id) {
+            let user_substs = self.tcx().lift_to_global(&user_substs).unwrap();
+            self.tables.user_substs_mut().insert(hir_id, user_substs);
+
+            // Unit-testing mechanism:
+            if self.rustc_dump_user_substs {
+                let node_id = self.tcx().hir.hir_to_node_id(hir_id);
+                let span = self.tcx().hir.span(node_id);
+                self.tcx().sess.span_err(
+                    span,
+                    &format!("user substs: {:?}", user_substs),
+                );
+            }
+        }
     }
 
     fn visit_adjustments(&mut self, span: Span, hir_id: hir::HirId) {
@@ -559,8 +599,7 @@ fn visit_adjustments(&mut self, span: Span, hir_id: hir::HirId) {
                 let resolved_adjustment = self.resolve(&adjustment, &span);
                 debug!(
                     "Adjustments for node {:?}: {:?}",
-                    hir_id,
-                    resolved_adjustment
+                    hir_id, resolved_adjustment
                 );
                 self.tables
                     .adjustments_mut()
@@ -584,8 +623,7 @@ fn visit_pat_adjustments(&mut self, span: Span, hir_id: hir::HirId) {
                 let resolved_adjustment = self.resolve(&adjustment, &span);
                 debug!(
                     "pat_adjustments for node {:?}: {:?}",
-                    hir_id,
-                    resolved_adjustment
+                    hir_id, resolved_adjustment
                 );
                 self.tables
                     .pat_adjustments_mut()
@@ -701,7 +739,8 @@ fn new(
     fn report_error(&self, t: Ty<'tcx>) {
         if !self.tcx.sess.has_errors() {
             self.infcx
-                .need_type_info_err(Some(self.body.id()), self.span.to_span(&self.tcx), t).emit();
+                .need_type_info_err(Some(self.body.id()), self.span.to_span(&self.tcx), t)
+                .emit();
         }
     }
 }
index 086243314330d7d8ae119c5a550363a26761ea86..fa152b386a8257fff3851f8040bc08e2f3171f56 100644 (file)
@@ -11,6 +11,7 @@
 use lint;
 use rustc::ty::TyCtxt;
 
+use errors::Applicability;
 use syntax::ast;
 use syntax_pos::Span;
 
@@ -132,15 +133,21 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
 
         // If the crate is fully unused, we suggest removing it altogether.
         // We do this in any edition.
-        if let Some(&span) = unused_extern_crates.get(&extern_crate.def_id) {
-            assert_eq!(extern_crate.def_id.krate, LOCAL_CRATE);
-            let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index);
-            let id = tcx.hir.hir_to_node_id(hir_id);
-            let msg = "unused extern crate";
-            tcx.struct_span_lint_node(lint, id, span, msg)
-                .span_suggestion_short(span, "remove it", "".to_string())
-                .emit();
-            continue;
+        if extern_crate.warn_if_unused {
+            if let Some(&span) = unused_extern_crates.get(&extern_crate.def_id) {
+                assert_eq!(extern_crate.def_id.krate, LOCAL_CRATE);
+                let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index);
+                let id = tcx.hir.hir_to_node_id(hir_id);
+                let msg = "unused extern crate";
+                tcx.struct_span_lint_node(lint, id, span, msg)
+                    .span_suggestion_short_with_applicability(
+                        span,
+                        "remove it",
+                        String::new(),
+                        Applicability::MachineApplicable)
+                    .emit();
+                continue;
+            }
         }
 
         // If we are not in Rust 2018 edition, then we don't make any further
@@ -171,7 +178,12 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
         };
         let replacement = visibility_qualified(&item.vis, &base_replacement);
         tcx.struct_span_lint_node(lint, id, extern_crate.span, msg)
-            .span_suggestion_short(extern_crate.span, &help, replacement)
+            .span_suggestion_short_with_applicability(
+                extern_crate.span,
+                &help,
+                replacement,
+                Applicability::MachineApplicable,
+            )
             .emit();
     }
 }
@@ -192,6 +204,10 @@ struct ExternCrateToLint {
     /// crate_name`), and -- perhaps surprisingly -- this stores the
     /// *original* name (`item.name` will contain the new name)
     orig_name: Option<ast::Name>,
+
+    /// if `false`, the original name started with `_`, so we shouldn't lint
+    /// about it going unused (but we should still emit idiom lints).
+    warn_if_unused: bool,
 }
 
 impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> {
@@ -203,6 +219,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                     def_id: extern_crate_def_id,
                     span: item.span,
                     orig_name,
+                    warn_if_unused: !item.name.as_str().starts_with('_'),
                 }
             );
         }
index ba65d0606b37267ee00a4f837b1b420628b707e6..efc35fad820c820c8c52924be8729e890ad1ba81 100644 (file)
@@ -23,7 +23,7 @@
 use rustc::infer;
 
 use rustc::hir::def_id::DefId;
-use rustc::hir::map as hir_map;
+use hir::Node;
 use rustc::hir::{self, ItemKind};
 
 pub fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId) {
@@ -55,12 +55,12 @@ fn check<F>(&self, trait_def_id: Option<DefId>, mut f: F) -> &Self
 
 fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: DefId) {
     match tcx.type_of(impl_did).sty {
-        ty::TyAdt(..) => {}
+        ty::Adt(..) => {}
         _ => {
             // Destructors only work on nominal types.
             if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_did) {
                 match tcx.hir.find(impl_node_id) {
-                    Some(hir_map::NodeItem(item)) => {
+                    Some(Node::Item(item)) => {
                         let span = match item.node {
                             ItemKind::Impl(.., ref ty, _) => ty.span,
                             _ => item.span,
@@ -217,23 +217,23 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
             (mt_a.ty, mt_b.ty, unsize_trait, None)
         };
         let (source, target, trait_def_id, kind) = match (&source.sty, &target.sty) {
-            (&ty::TyRef(r_a, ty_a, mutbl_a), &ty::TyRef(r_b, ty_b, mutbl_b)) => {
+            (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => {
                 infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a);
                 let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
                 let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
                 check_mutbl(mt_a, mt_b, &|ty| gcx.mk_imm_ref(r_b, ty))
             }
 
-            (&ty::TyRef(_, ty_a, mutbl_a), &ty::TyRawPtr(mt_b)) => {
+            (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(mt_b)) => {
                 let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
                 check_mutbl(mt_a, mt_b, &|ty| gcx.mk_imm_ptr(ty))
             }
 
-            (&ty::TyRawPtr(mt_a), &ty::TyRawPtr(mt_b)) => {
+            (&ty::RawPtr(mt_a), &ty::RawPtr(mt_b)) => {
                 check_mutbl(mt_a, mt_b, &|ty| gcx.mk_imm_ptr(ty))
             }
 
-            (&ty::TyAdt(def_a, substs_a), &ty::TyAdt(def_b, substs_b)) if def_a.is_struct() &&
+            (&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b)) if def_a.is_struct() &&
                                                                           def_b.is_struct() => {
                 if def_a != def_b {
                     let source_path = gcx.item_path_str(def_a.did);
index f37167d1f6688cb2ab0b31e959fffa249bffd9c6..52e37b8d0ce11fc9b8ace90f4d6d6ef1102db6c0 100644 (file)
@@ -102,16 +102,16 @@ fn visit_item(&mut self, item: &hir::Item) {
         let self_ty = self.tcx.type_of(def_id);
         let lang_items = self.tcx.lang_items();
         match self_ty.sty {
-            ty::TyAdt(def, _) => {
+            ty::Adt(def, _) => {
                 self.check_def_id(item, def.did);
             }
-            ty::TyForeign(did) => {
+            ty::Foreign(did) => {
                 self.check_def_id(item, did);
             }
-            ty::TyDynamic(ref data, ..) if data.principal().is_some() => {
+            ty::Dynamic(ref data, ..) if data.principal().is_some() => {
                 self.check_def_id(item, data.principal().unwrap().def_id());
             }
-            ty::TyChar => {
+            ty::Char => {
                 self.check_primitive_impl(def_id,
                                           lang_items.char_impl(),
                                           None,
@@ -119,7 +119,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "char",
                                           item.span);
             }
-            ty::TyStr => {
+            ty::Str => {
                 self.check_primitive_impl(def_id,
                                           lang_items.str_impl(),
                                           lang_items.str_alloc_impl(),
@@ -127,7 +127,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "str",
                                           item.span);
             }
-            ty::TySlice(slice_item) if slice_item == self.tcx.types.u8 => {
+            ty::Slice(slice_item) if slice_item == self.tcx.types.u8 => {
                 self.check_primitive_impl(def_id,
                                           lang_items.slice_u8_impl(),
                                           lang_items.slice_u8_alloc_impl(),
@@ -135,7 +135,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "[u8]",
                                           item.span);
             }
-            ty::TySlice(_) => {
+            ty::Slice(_) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.slice_impl(),
                                           lang_items.slice_alloc_impl(),
@@ -143,7 +143,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "[T]",
                                           item.span);
             }
-            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
+            ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.const_ptr_impl(),
                                           None,
@@ -151,7 +151,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "*const T",
                                           item.span);
             }
-            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
+            ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.mut_ptr_impl(),
                                           None,
@@ -159,7 +159,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "*mut T",
                                           item.span);
             }
-            ty::TyInt(ast::IntTy::I8) => {
+            ty::Int(ast::IntTy::I8) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.i8_impl(),
                                           None,
@@ -167,7 +167,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "i8",
                                           item.span);
             }
-            ty::TyInt(ast::IntTy::I16) => {
+            ty::Int(ast::IntTy::I16) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.i16_impl(),
                                           None,
@@ -175,7 +175,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "i16",
                                           item.span);
             }
-            ty::TyInt(ast::IntTy::I32) => {
+            ty::Int(ast::IntTy::I32) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.i32_impl(),
                                           None,
@@ -183,7 +183,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "i32",
                                           item.span);
             }
-            ty::TyInt(ast::IntTy::I64) => {
+            ty::Int(ast::IntTy::I64) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.i64_impl(),
                                           None,
@@ -191,7 +191,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "i64",
                                           item.span);
             }
-            ty::TyInt(ast::IntTy::I128) => {
+            ty::Int(ast::IntTy::I128) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.i128_impl(),
                                           None,
@@ -199,7 +199,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "i128",
                                           item.span);
             }
-            ty::TyInt(ast::IntTy::Isize) => {
+            ty::Int(ast::IntTy::Isize) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.isize_impl(),
                                           None,
@@ -207,7 +207,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "isize",
                                           item.span);
             }
-            ty::TyUint(ast::UintTy::U8) => {
+            ty::Uint(ast::UintTy::U8) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.u8_impl(),
                                           None,
@@ -215,7 +215,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "u8",
                                           item.span);
             }
-            ty::TyUint(ast::UintTy::U16) => {
+            ty::Uint(ast::UintTy::U16) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.u16_impl(),
                                           None,
@@ -223,7 +223,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "u16",
                                           item.span);
             }
-            ty::TyUint(ast::UintTy::U32) => {
+            ty::Uint(ast::UintTy::U32) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.u32_impl(),
                                           None,
@@ -231,7 +231,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "u32",
                                           item.span);
             }
-            ty::TyUint(ast::UintTy::U64) => {
+            ty::Uint(ast::UintTy::U64) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.u64_impl(),
                                           None,
@@ -239,7 +239,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "u64",
                                           item.span);
             }
-            ty::TyUint(ast::UintTy::U128) => {
+            ty::Uint(ast::UintTy::U128) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.u128_impl(),
                                           None,
@@ -247,7 +247,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "u128",
                                           item.span);
             }
-            ty::TyUint(ast::UintTy::Usize) => {
+            ty::Uint(ast::UintTy::Usize) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.usize_impl(),
                                           None,
@@ -255,7 +255,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "usize",
                                           item.span);
             }
-            ty::TyFloat(ast::FloatTy::F32) => {
+            ty::Float(ast::FloatTy::F32) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.f32_impl(),
                                           lang_items.f32_runtime_impl(),
@@ -263,7 +263,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "f32",
                                           item.span);
             }
-            ty::TyFloat(ast::FloatTy::F64) => {
+            ty::Float(ast::FloatTy::F64) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.f64_impl(),
                                           lang_items.f64_runtime_impl(),
@@ -271,7 +271,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "f64",
                                           item.span);
             }
-            ty::TyError => {
+            ty::Error => {
                 return;
             }
             _ => {
index 1b04c5da59b2853bf40274096d14ecb3475630e0..168cf47fb5266e3df036ca3f0a4a76551b93f28b 100644 (file)
@@ -157,7 +157,7 @@ fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeI
     tcx.specialization_graph_of(trait_def_id);
 
     // check for overlap with the automatic `impl Trait for Trait`
-    if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty {
+    if let ty::Dynamic(ref data, ..) = trait_ref.self_ty().sty {
         // This is something like impl Trait1 for Trait2. Illegal
         // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
 
index 4a3747017dfc139357985d753dca970ea9a3caed..f9b89488232d26e5b098b7efffa7bdd1a4faa041 100644 (file)
@@ -114,8 +114,8 @@ fn visit_item(&mut self, item: &hir::Item) {
                    !trait_def_id.is_local() {
                     let self_ty = trait_ref.self_ty();
                     let opt_self_def_id = match self_ty.sty {
-                        ty::TyAdt(self_def, _) => Some(self_def.did),
-                        ty::TyForeign(did) => Some(did),
+                        ty::Adt(self_def, _) => Some(self_def.did),
+                        ty::Foreign(did) => Some(did),
                         _ => None,
                     };
 
index 956d542ab7d4e108a5edd61bf6fef3b5777ac635..b956c72b3a2da53c0d8fde1b847165a1a108b7ac 100644 (file)
 //! crate as a kind of pass. This should eventually be factored away.
 
 use astconv::{AstConv, Bounds};
-use lint;
 use constrained_type_params as ctp;
+use lint;
 use middle::lang_items::SizedTraitLangItem;
 use middle::resolve_lifetime as rl;
+use middle::weak_lang_items;
 use rustc::mir::mono::Linkage;
-use rustc::ty::subst::Substs;
-use rustc::ty::{ToPredicate, ReprOptions};
-use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
 use rustc::ty::query::Providers;
-use rustc::ty::util::IntTypeExt;
+use rustc::ty::subst::Substs;
 use rustc::ty::util::Discr;
+use rustc::ty::util::IntTypeExt;
+use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
+use rustc::ty::{ReprOptions, ToPredicate};
 use rustc::util::captures::Captures;
 use rustc::util::nodemap::FxHashMap;
 use rustc_target::spec::abi;
 use syntax::ast::MetaItemKind;
 use syntax::attr::{InlineAttr, list_contains_name, mark_used};
 use syntax::source_map::Spanned;
-use syntax::symbol::{Symbol, keywords};
 use syntax::feature_gate;
+use syntax::symbol::{keywords, Symbol};
 use syntax_pos::{Span, DUMMY_SP};
 
-use rustc::hir::{self, map as hir_map, CodegenFnAttrs, CodegenFnAttrFlags, Unsafety};
-use rustc::hir::GenericParamKind;
-use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
-use rustc::hir::def::{Def, CtorKind};
+use rustc::hir::def::{CtorKind, Def};
+use rustc::hir::Node;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::GenericParamKind;
+use rustc::hir::{self, CodegenFnAttrFlags, CodegenFnAttrs, Unsafety};
 
 ///////////////////////////////////////////////////////////////////////////
 // Main entry point
 
 pub fn collect_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let mut visitor = CollectItemTypesVisitor { tcx: tcx };
-    tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+    tcx.hir
+        .krate()
+        .visit_all_item_likes(&mut visitor.as_deep_visitor());
 }
 
 pub fn provide(providers: &mut Providers) {
@@ -93,7 +97,7 @@ pub fn provide(providers: &mut Providers) {
 /// `ItemCtxt` is parameterized by a `DefId` that it uses to satisfy
 /// `get_type_parameter_bounds` requests, drawing the information from
 /// the AST (`hir::Generics`), recursively.
-pub struct ItemCtxt<'a,'tcx:'a> {
+pub struct ItemCtxt<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     item_def_id: DefId,
 }
@@ -101,7 +105,7 @@ pub struct ItemCtxt<'a,'tcx:'a> {
 ///////////////////////////////////////////////////////////////////////////
 
 struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> {
@@ -118,7 +122,9 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
         for param in &generics.params {
             match param.kind {
                 hir::GenericParamKind::Lifetime { .. } => {}
-                hir::GenericParamKind::Type { default: Some(_), .. } => {
+                hir::GenericParamKind::Type {
+                    default: Some(_), ..
+                } => {
                     let def_id = self.tcx.hir.local_def_id(param.id);
                     self.tcx.type_of(def_id);
                 }
@@ -152,34 +158,33 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
 // Utility types and common code for the above passes.
 
 impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId)
-           -> ItemCtxt<'a,'tcx> {
-        ItemCtxt {
-            tcx,
-            item_def_id,
-        }
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) -> ItemCtxt<'a, 'tcx> {
+        ItemCtxt { tcx, item_def_id }
     }
 }
 
-impl<'a,'tcx> ItemCtxt<'a,'tcx> {
+impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
     pub fn to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
         AstConv::ast_ty_to_ty(self, ast_ty)
     }
 }
 
 impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
-    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.tcx }
+    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
+        self.tcx
+    }
 
-    fn get_type_parameter_bounds(&self,
-                                 span: Span,
-                                 def_id: DefId)
-                                 -> ty::GenericPredicates<'tcx>
-    {
-        self.tcx.at(span).type_param_predicates((self.item_def_id, def_id))
+    fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
+        self.tcx
+            .at(span)
+            .type_param_predicates((self.item_def_id, def_id))
     }
 
-    fn re_infer(&self, _span: Span, _def: Option<&ty::GenericParamDef>)
-                -> Option<ty::Region<'tcx>> {
+    fn re_infer(
+        &self,
+        _span: Span,
+        _def: Option<&ty::GenericParamDef>,
+    ) -> Option<ty::Region<'tcx>> {
         None
     }
 
@@ -190,23 +195,27 @@ fn ty_infer(&self, span: Span) -> Ty<'tcx> {
             E0121,
             "the type placeholder `_` is not allowed within types on item signatures"
         ).span_label(span, "not allowed in type signatures")
-        .emit();
+            .emit();
         self.tcx().types.err
     }
 
-    fn projected_ty_from_poly_trait_ref(&self,
-                                        span: Span,
-                                        item_def_id: DefId,
-                                        poly_trait_ref: ty::PolyTraitRef<'tcx>)
-                                        -> Ty<'tcx>
-    {
+    fn projected_ty_from_poly_trait_ref(
+        &self,
+        span: Span,
+        item_def_id: DefId,
+        poly_trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Ty<'tcx> {
         if let Some(trait_ref) = poly_trait_ref.no_late_bound_regions() {
             self.tcx().mk_projection(item_def_id, trait_ref.substs)
         } else {
             // no late-bound regions, we can just ignore the binder
-            span_err!(self.tcx().sess, span, E0212,
+            span_err!(
+                self.tcx().sess,
+                span,
+                E0212,
                 "cannot extract an associated type from a higher-ranked trait bound \
-                 in this context");
+                 in this context"
+            );
             self.tcx().types.err
         }
     }
@@ -226,10 +235,10 @@ fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
     }
 }
 
-fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                   (item_def_id, def_id): (DefId, DefId))
-                                   -> ty::GenericPredicates<'tcx> {
-    use rustc::hir::map::*;
+fn type_param_predicates<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    (item_def_id, def_id): (DefId, DefId),
+) -> ty::GenericPredicates<'tcx> {
     use rustc::hir::*;
 
     // In the AST, bounds can derive from two places. Either
@@ -250,55 +259,61 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         tcx.generics_of(item_def_id).parent
     };
 
-    let mut result = parent.map_or(ty::GenericPredicates {
-        parent: None,
-        predicates: vec![]
-    }, |parent| {
-        let icx = ItemCtxt::new(tcx, parent);
-        icx.get_type_parameter_bounds(DUMMY_SP, def_id)
-    });
+    let mut result = parent.map_or(
+        ty::GenericPredicates {
+            parent: None,
+            predicates: vec![],
+        },
+        |parent| {
+            let icx = ItemCtxt::new(tcx, parent);
+            icx.get_type_parameter_bounds(DUMMY_SP, def_id)
+        },
+    );
 
     let item_node_id = tcx.hir.as_local_node_id(item_def_id).unwrap();
     let ast_generics = match tcx.hir.get(item_node_id) {
-        NodeTraitItem(item) => &item.generics,
+        Node::TraitItem(item) => &item.generics,
 
-        NodeImplItem(item) => &item.generics,
+        Node::ImplItem(item) => &item.generics,
 
-        NodeItem(item) => {
+        Node::Item(item) => {
             match item.node {
-                ItemKind::Fn(.., ref generics, _) |
-                ItemKind::Impl(_, _, _, ref generics, ..) |
-                ItemKind::Ty(_, ref generics) |
-                ItemKind::Existential(ExistTy { ref generics, impl_trait_fn: None, ..}) |
-                ItemKind::Enum(_, ref generics) |
-                ItemKind::Struct(_, ref generics) |
-                ItemKind::Union(_, ref generics) => generics,
+                ItemKind::Fn(.., ref generics, _)
+                | ItemKind::Impl(_, _, _, ref generics, ..)
+                | ItemKind::Ty(_, ref generics)
+                | ItemKind::Existential(ExistTy {
+                    ref generics,
+                    impl_trait_fn: None,
+                    ..
+                })
+                | ItemKind::Enum(_, ref generics)
+                | ItemKind::Struct(_, ref generics)
+                | ItemKind::Union(_, ref generics) => generics,
                 ItemKind::Trait(_, _, ref generics, ..) => {
                     // Implied `Self: Trait` and supertrait bounds.
                     if param_id == item_node_id {
-                        result.predicates.push(
-                            ty::TraitRef::identity(tcx, item_def_id).to_predicate()
-                        );
+                        result
+                            .predicates
+                            .push(ty::TraitRef::identity(tcx, item_def_id).to_predicate());
                     }
                     generics
                 }
-                _ => return result
+                _ => return result,
             }
         }
 
-        NodeForeignItem(item) => {
-            match item.node {
-                ForeignItemKind::Fn(_, _, ref generics) => generics,
-                _ => return result
-            }
-        }
+        Node::ForeignItem(item) => match item.node {
+            ForeignItemKind::Fn(_, _, ref generics) => generics,
+            _ => return result,
+        },
 
-        _ => return result
+        _ => return result,
     };
 
     let icx = ItemCtxt::new(tcx, item_def_id);
-    result.predicates.extend(
-        icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty));
+    result
+        .predicates
+        .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty));
     result
 }
 
@@ -307,32 +322,33 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
     /// AST. We do this to avoid having to convert *all* the bounds, which
     /// would create artificial cycles. Instead we can only convert the
     /// bounds for a type parameter `X` if `X::Foo` is used.
-    fn type_parameter_bounds_in_generics(&self,
-                                         ast_generics: &hir::Generics,
-                                         param_id: ast::NodeId,
-                                         ty: Ty<'tcx>)
-                                         -> Vec<ty::Predicate<'tcx>>
-    {
-        let from_ty_params =
-            ast_generics.params.iter()
-                .filter_map(|param| match param.kind {
-                    GenericParamKind::Type { .. } if param.id == param_id => Some(&param.bounds),
-                    _ => None
-                })
-                .flat_map(|bounds| bounds.iter())
-                .flat_map(|b| predicates_from_bound(self, ty, b));
-
-        let from_where_clauses =
-            ast_generics.where_clause
-                .predicates
-                .iter()
-                .filter_map(|wp| match *wp {
-                    hir::WherePredicate::BoundPredicate(ref bp) => Some(bp),
-                    _ => None
-                })
-                .filter(|bp| is_param(self.tcx, &bp.bounded_ty, param_id))
-                .flat_map(|bp| bp.bounds.iter())
-                .flat_map(|b| predicates_from_bound(self, ty, b));
+    fn type_parameter_bounds_in_generics(
+        &self,
+        ast_generics: &hir::Generics,
+        param_id: ast::NodeId,
+        ty: Ty<'tcx>,
+    ) -> Vec<ty::Predicate<'tcx>> {
+        let from_ty_params = ast_generics
+            .params
+            .iter()
+            .filter_map(|param| match param.kind {
+                GenericParamKind::Type { .. } if param.id == param_id => Some(&param.bounds),
+                _ => None,
+            })
+            .flat_map(|bounds| bounds.iter())
+            .flat_map(|b| predicates_from_bound(self, ty, b));
+
+        let from_where_clauses = ast_generics
+            .where_clause
+            .predicates
+            .iter()
+            .filter_map(|wp| match *wp {
+                hir::WherePredicate::BoundPredicate(ref bp) => Some(bp),
+                _ => None,
+            })
+            .filter(|bp| is_param(self.tcx, &bp.bounded_ty, param_id))
+            .flat_map(|bp| bp.bounds.iter())
+            .flat_map(|b| predicates_from_bound(self, ty, b));
 
         from_ty_params.chain(from_where_clauses).collect()
     }
@@ -342,18 +358,17 @@ fn type_parameter_bounds_in_generics(&self,
 /// parameter with id `param_id`. We use this so as to avoid running
 /// `ast_ty_to_ty`, because we want to avoid triggering an all-out
 /// conversion of the type to avoid inducing unnecessary cycles.
-fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                      ast_ty: &hir::Ty,
-                      param_id: ast::NodeId)
-                      -> bool
-{
+fn is_param<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    ast_ty: &hir::Ty,
+    param_id: ast::NodeId,
+) -> bool {
     if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = ast_ty.node {
         match path.def {
-            Def::SelfTy(Some(def_id), None) |
-            Def::TyParam(def_id) => {
+            Def::SelfTy(Some(def_id), None) | Def::TyParam(def_id) => {
                 def_id == tcx.hir.local_def_id(param_id)
             }
-            _ => false
+            _ => false,
         }
     } else {
         false
@@ -366,10 +381,10 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
     let def_id = tcx.hir.local_def_id(item_id);
     match it.node {
         // These don't define types.
-        hir::ItemKind::ExternCrate(_) |
-        hir::ItemKind::Use(..) |
-        hir::ItemKind::Mod(_) |
-        hir::ItemKind::GlobalAsm(_) => {}
+        hir::ItemKind::ExternCrate(_)
+        | hir::ItemKind::Use(..)
+        | hir::ItemKind::Mod(_)
+        hir::ItemKind::GlobalAsm(_) => {}
         hir::ItemKind::ForeignMod(ref foreign_mod) => {
             for item in &foreign_mod.items {
                 let def_id = tcx.hir.local_def_id(item.id);
@@ -386,25 +401,28 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
             tcx.type_of(def_id);
             tcx.predicates_of(def_id);
             convert_enum_variant_types(tcx, def_id, &enum_definition.variants);
-        },
+        }
         hir::ItemKind::Impl(..) => {
             tcx.generics_of(def_id);
             tcx.type_of(def_id);
             tcx.impl_trait_ref(def_id);
             tcx.predicates_of(def_id);
-        },
+        }
         hir::ItemKind::Trait(..) => {
             tcx.generics_of(def_id);
             tcx.trait_def(def_id);
             tcx.at(it.span).super_predicates_of(def_id);
             tcx.predicates_of(def_id);
-        },
+        }
         hir::ItemKind::TraitAlias(..) => {
-            span_err!(tcx.sess, it.span, E0645,
-                      "trait aliases are not yet implemented (see issue #41517)");
-        },
-        hir::ItemKind::Struct(ref struct_def, _) |
-        hir::ItemKind::Union(ref struct_def, _) => {
+            span_err!(
+                tcx.sess,
+                it.span,
+                E0645,
+                "trait aliases are not yet implemented (see issue #41517)"
+            );
+        }
+        hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
             tcx.generics_of(def_id);
             tcx.type_of(def_id);
             tcx.predicates_of(def_id);
@@ -419,16 +437,19 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
             if !struct_def.is_struct() {
                 convert_variant_ctor(tcx, struct_def.id());
             }
-        },
+        }
 
         // Desugared from `impl Trait` -> visited by the function's return type
-        hir::ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(_), .. }) => {}
-
-        hir::ItemKind::Existential(..) |
-        hir::ItemKind::Ty(..) |
-        hir::ItemKind::Static(..) |
-        hir::ItemKind::Const(..) |
-        hir::ItemKind::Fn(..) => {
+        hir::ItemKind::Existential(hir::ExistTy {
+            impl_trait_fn: Some(_),
+            ..
+        }) => {}
+
+        hir::ItemKind::Existential(..)
+        | hir::ItemKind::Ty(..)
+        | hir::ItemKind::Static(..)
+        | hir::ItemKind::Const(..)
+        | hir::ItemKind::Fn(..) => {
             tcx.generics_of(def_id);
             tcx.type_of(def_id);
             tcx.predicates_of(def_id);
@@ -445,9 +466,9 @@ fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: ast:
     tcx.generics_of(def_id);
 
     match trait_item.node {
-        hir::TraitItemKind::Const(..) |
-        hir::TraitItemKind::Type(_, Some(_)) |
-        hir::TraitItemKind::Method(..) => {
+        hir::TraitItemKind::Const(..)
+        | hir::TraitItemKind::Type(_, Some(_))
+        hir::TraitItemKind::Method(..) => {
             tcx.type_of(def_id);
             if let hir::TraitItemKind::Method(..) = trait_item.node {
                 tcx.fn_sig(def_id);
@@ -470,17 +491,18 @@ fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item_id: ast::N
     }
 }
 
-fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                  ctor_id: ast::NodeId) {
+fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ctor_id: ast::NodeId) {
     let def_id = tcx.hir.local_def_id(ctor_id);
     tcx.generics_of(def_id);
     tcx.type_of(def_id);
     tcx.predicates_of(def_id);
 }
 
-fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                        def_id: DefId,
-                                        variants: &[hir::Variant]) {
+fn convert_enum_variant_types<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId,
+    variants: &[hir::Variant],
+) {
     let def = tcx.adt_def(def_id);
     let repr_type = def.repr.discr_type();
     let initial = repr_type.initial_discriminant(tcx);
@@ -489,21 +511,30 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // fill the discriminant values and field types
     for variant in variants {
         let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
-        prev_discr = Some(if let Some(ref e) = variant.node.disr_expr {
-            let expr_did = tcx.hir.local_def_id(e.id);
-            def.eval_explicit_discr(tcx, expr_did)
-        } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
-            Some(discr)
-        } else {
-            struct_span_err!(tcx.sess, variant.span, E0370,
-                             "enum discriminant overflowed")
-                .span_label(variant.span, format!("overflowed on value after {}",
-                                                   prev_discr.unwrap()))
-                .note(&format!("explicitly set `{} = {}` if that is desired outcome",
-                               variant.node.name, wrapped_discr))
-                .emit();
-            None
-        }.unwrap_or(wrapped_discr));
+        prev_discr = Some(
+            if let Some(ref e) = variant.node.disr_expr {
+                let expr_did = tcx.hir.local_def_id(e.id);
+                def.eval_explicit_discr(tcx, expr_did)
+            } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
+                Some(discr)
+            } else {
+                struct_span_err!(
+                    tcx.sess,
+                    variant.span,
+                    E0370,
+                    "enum discriminant overflowed"
+                ).span_label(
+                    variant.span,
+                    format!("overflowed on value after {}", prev_discr.unwrap()),
+                )
+                    .note(&format!(
+                        "explicitly set `{} = {}` if that is desired outcome",
+                        variant.node.name, wrapped_discr
+                    ))
+                    .emit();
+                None
+            }.unwrap_or(wrapped_discr),
+        );
 
         for f in variant.node.data.fields() {
             let def_id = tcx.hir.local_def_id(f.id);
@@ -518,34 +549,42 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-fn convert_struct_variant<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                    did: DefId,
-                                    name: ast::Name,
-                                    discr: ty::VariantDiscr,
-                                    def: &hir::VariantData)
-                                    -> ty::VariantDef {
+fn convert_struct_variant<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    did: DefId,
+    name: ast::Name,
+    discr: ty::VariantDiscr,
+    def: &hir::VariantData,
+) -> ty::VariantDef {
     let mut seen_fields: FxHashMap<ast::Ident, Span> = FxHashMap();
     let node_id = tcx.hir.as_local_node_id(did).unwrap();
-    let fields = def.fields().iter().map(|f| {
-        let fid = tcx.hir.local_def_id(f.id);
-        let dup_span = seen_fields.get(&f.ident.modern()).cloned();
-        if let Some(prev_span) = dup_span {
-            struct_span_err!(tcx.sess, f.span, E0124,
-                             "field `{}` is already declared",
-                             f.ident)
-                .span_label(f.span, "field already declared")
-                .span_label(prev_span, format!("`{}` first declared here", f.ident))
-                .emit();
-        } else {
-            seen_fields.insert(f.ident.modern(), f.span);
-        }
+    let fields = def
+        .fields()
+        .iter()
+        .map(|f| {
+            let fid = tcx.hir.local_def_id(f.id);
+            let dup_span = seen_fields.get(&f.ident.modern()).cloned();
+            if let Some(prev_span) = dup_span {
+                struct_span_err!(
+                    tcx.sess,
+                    f.span,
+                    E0124,
+                    "field `{}` is already declared",
+                    f.ident
+                ).span_label(f.span, "field already declared")
+                    .span_label(prev_span, format!("`{}` first declared here", f.ident))
+                    .emit();
+            } else {
+                seen_fields.insert(f.ident.modern(), f.span);
+            }
 
-        ty::FieldDef {
-            did: fid,
-            ident: f.ident,
-            vis: ty::Visibility::from_hir(&f.vis, node_id, tcx)
-        }
-    }).collect();
+            ty::FieldDef {
+                did: fid,
+                ident: f.ident,
+                vis: ty::Visibility::from_hir(&f.vis, node_id, tcx),
+            }
+        })
+        .collect();
     ty::VariantDef {
         did,
         name,
@@ -555,34 +594,37 @@ fn convert_struct_variant<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                     def_id: DefId)
-                     -> &'tcx ty::AdtDef {
-    use rustc::hir::map::*;
+fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::AdtDef {
     use rustc::hir::*;
 
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
     let item = match tcx.hir.get(node_id) {
-        NodeItem(item) => item,
-        _ => bug!()
+        Node::Item(item) => item,
+        _ => bug!(),
     };
 
     let repr = ReprOptions::new(tcx, def_id);
     let (kind, variants) = match item.node {
         ItemKind::Enum(ref def, _) => {
             let mut distance_from_explicit = 0;
-            (AdtKind::Enum, def.variants.iter().map(|v| {
-                let did = tcx.hir.local_def_id(v.node.data.id());
-                let discr = if let Some(ref e) = v.node.disr_expr {
-                    distance_from_explicit = 0;
-                    ty::VariantDiscr::Explicit(tcx.hir.local_def_id(e.id))
-                } else {
-                    ty::VariantDiscr::Relative(distance_from_explicit)
-                };
-                distance_from_explicit += 1;
+            (
+                AdtKind::Enum,
+                def.variants
+                    .iter()
+                    .map(|v| {
+                        let did = tcx.hir.local_def_id(v.node.data.id());
+                        let discr = if let Some(ref e) = v.node.disr_expr {
+                            distance_from_explicit = 0;
+                            ty::VariantDiscr::Explicit(tcx.hir.local_def_id(e.id))
+                        } else {
+                            ty::VariantDiscr::Relative(distance_from_explicit)
+                        };
+                        distance_from_explicit += 1;
 
-                convert_struct_variant(tcx, did, v.node.name, discr, &v.node.data)
-            }).collect())
+                        convert_struct_variant(tcx, did, v.node.name, discr, &v.node.data)
+                    })
+                    .collect(),
+            )
         }
         ItemKind::Struct(ref def, _) => {
             // Use separate constructor id for unit/tuple structs and reuse did for braced structs.
@@ -591,18 +633,28 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             } else {
                 None
             };
-            (AdtKind::Struct, vec![
-                convert_struct_variant(tcx, ctor_id.unwrap_or(def_id), item.name,
-                                       ty::VariantDiscr::Relative(0), def)
-            ])
-        }
-        ItemKind::Union(ref def, _) => {
-            (AdtKind::Union, vec![
-                convert_struct_variant(tcx, def_id, item.name,
-                                       ty::VariantDiscr::Relative(0), def)
-            ])
+            (
+                AdtKind::Struct,
+                vec![convert_struct_variant(
+                    tcx,
+                    ctor_id.unwrap_or(def_id),
+                    item.name,
+                    ty::VariantDiscr::Relative(0),
+                    def,
+                )],
+            )
         }
-        _ => bug!()
+        ItemKind::Union(ref def, _) => (
+            AdtKind::Union,
+            vec![convert_struct_variant(
+                tcx,
+                def_id,
+                item.name,
+                ty::VariantDiscr::Relative(0),
+                def,
+            )],
+        ),
+        _ => bug!(),
     };
     tcx.alloc_adt_def(def_id, kind, variants, repr)
 }
@@ -610,33 +662,29 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 /// Ensures that the super-predicates of the trait with def-id
 /// trait_def_id are converted and stored. This also ensures that
 /// the transitive super-predicates are converted;
-fn super_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                 trait_def_id: DefId)
-                                 -> ty::GenericPredicates<'tcx> {
+fn super_predicates_of<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    trait_def_id: DefId,
+) -> ty::GenericPredicates<'tcx> {
     debug!("super_predicates(trait_def_id={:?})", trait_def_id);
     let trait_node_id = tcx.hir.as_local_node_id(trait_def_id).unwrap();
 
     let item = match tcx.hir.get(trait_node_id) {
-        hir_map::NodeItem(item) => item,
-        _ => bug!("trait_node_id {} is not an item", trait_node_id)
+        Node::Item(item) => item,
+        _ => bug!("trait_node_id {} is not an item", trait_node_id),
     };
 
     let (generics, bounds) = match item.node {
         hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits),
         hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits),
-        _ => span_bug!(item.span,
-                       "super_predicates invoked on non-trait"),
+        _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
     };
 
     let icx = ItemCtxt::new(tcx, trait_def_id);
 
     // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
     let self_param_ty = tcx.mk_self_type();
-    let superbounds1 = compute_bounds(&icx,
-                                      self_param_ty,
-                                      bounds,
-                                      SizedByDefault::No,
-                                      item.span);
+    let superbounds1 = compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span);
 
     let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
 
@@ -655,13 +703,11 @@ fn super_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     ty::GenericPredicates {
         parent: None,
-        predicates: superbounds
+        predicates: superbounds,
     }
 }
 
-fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                       def_id: DefId)
-                       -> &'tcx ty::TraitDef {
+fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::TraitDef {
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
     let item = tcx.hir.expect_item(node_id);
 
@@ -676,25 +722,25 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let mut err = tcx.sess.struct_span_err(
             item.span,
             "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
-             which traits can use parenthetical notation");
-        help!(&mut err,
+             which traits can use parenthetical notation",
+        );
+        help!(
+            &mut err,
             "add `#![feature(unboxed_closures)]` to \
-             the crate attributes to use it");
+             the crate attributes to use it"
+        );
         err.emit();
     }
 
     let def_path_hash = tcx.def_path_hash(def_id);
-    let def = ty::TraitDef::new(def_id,
-                                unsafety,
-                                paren_sugar,
-                                is_auto,
-                                def_path_hash);
+    let def = ty::TraitDef::new(def_id, unsafety, paren_sugar, is_auto, def_path_hash);
     tcx.alloc_trait_def(def)
 }
 
-fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                    node: hir_map::Node<'tcx>)
-                                    -> Option<Span> {
+fn has_late_bound_regions<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    node: Node<'tcx>,
+) -> Option<Span> {
     struct LateBoundRegionsDetector<'a, 'tcx: 'a> {
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         outer_index: ty::DebruijnIndex,
@@ -707,49 +753,57 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
         }
 
         fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
-            if self.has_late_bound_regions.is_some() { return }
+            if self.has_late_bound_regions.is_some() {
+                return;
+            }
             match ty.node {
                 hir::TyKind::BareFn(..) => {
                     self.outer_index.shift_in(1);
                     intravisit::walk_ty(self, ty);
                     self.outer_index.shift_out(1);
                 }
-                _ => intravisit::walk_ty(self, ty)
+                _ => intravisit::walk_ty(self, ty),
             }
         }
 
-        fn visit_poly_trait_ref(&mut self,
-                                tr: &'tcx hir::PolyTraitRef,
-                                m: hir::TraitBoundModifier) {
-            if self.has_late_bound_regions.is_some() { return }
+        fn visit_poly_trait_ref(
+            &mut self,
+            tr: &'tcx hir::PolyTraitRef,
+            m: hir::TraitBoundModifier,
+        ) {
+            if self.has_late_bound_regions.is_some() {
+                return;
+            }
             self.outer_index.shift_in(1);
             intravisit::walk_poly_trait_ref(self, tr, m);
             self.outer_index.shift_out(1);
         }
 
         fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) {
-            if self.has_late_bound_regions.is_some() { return }
+            if self.has_late_bound_regions.is_some() {
+                return;
+            }
 
             let hir_id = self.tcx.hir.node_to_hir_id(lt.id);
             match self.tcx.named_region(hir_id) {
                 Some(rl::Region::Static) | Some(rl::Region::EarlyBound(..)) => {}
-                Some(rl::Region::LateBound(debruijn, _, _)) |
-                Some(rl::Region::LateBoundAnon(debruijn, _))
-                    if debruijn < self.outer_index => {}
-                Some(rl::Region::LateBound(..)) |
-                Some(rl::Region::LateBoundAnon(..)) |
-                Some(rl::Region::Free(..)) |
-                None => {
+                Some(rl::Region::LateBound(debruijn, _, _))
+                | Some(rl::Region::LateBoundAnon(debruijn, _)) if debruijn < self.outer_index => {}
+                Some(rl::Region::LateBound(..))
+                | Some(rl::Region::LateBoundAnon(..))
+                | Some(rl::Region::Free(..))
+                | None => {
                     self.has_late_bound_regions = Some(lt.span);
                 }
             }
         }
     }
 
-    fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                        generics: &'tcx hir::Generics,
-                                        decl: &'tcx hir::FnDecl)
-                                        -> Option<Span> {
+    fn has_late_bound_regions<'a, 'tcx>(
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        generics: &'tcx hir::Generics,
+        decl: &'tcx hir::FnDecl,
+    ) -> Option<Span> {
         let mut visitor = LateBoundRegionsDetector {
             tcx,
             outer_index: ty::INNERMOST,
@@ -763,7 +817,7 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         return Some(param.span);
                     }
                 }
-                _ => {},
+                _ => {}
             }
         }
         visitor.visit_fn_decl(decl);
@@ -771,58 +825,55 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     match node {
-        hir_map::NodeTraitItem(item) => match item.node {
-            hir::TraitItemKind::Method(ref sig, _) =>
-                has_late_bound_regions(tcx, &item.generics, &sig.decl),
+        Node::TraitItem(item) => match item.node {
+            hir::TraitItemKind::Method(ref sig, _) => {
+                has_late_bound_regions(tcx, &item.generics, &sig.decl)
+            }
             _ => None,
         },
-        hir_map::NodeImplItem(item) => match item.node {
-            hir::ImplItemKind::Method(ref sig, _) =>
-                has_late_bound_regions(tcx, &item.generics, &sig.decl),
+        Node::ImplItem(item) => match item.node {
+            hir::ImplItemKind::Method(ref sig, _) => {
+                has_late_bound_regions(tcx, &item.generics, &sig.decl)
+            }
             _ => None,
         },
-        hir_map::NodeForeignItem(item) => match item.node {
-            hir::ForeignItemKind::Fn(ref fn_decl, _, ref generics) =>
-                has_late_bound_regions(tcx, generics, fn_decl),
+        Node::ForeignItem(item) => match item.node {
+            hir::ForeignItemKind::Fn(ref fn_decl, _, ref generics) => {
+                has_late_bound_regions(tcx, generics, fn_decl)
+            }
             _ => None,
         },
-        hir_map::NodeItem(item) => match item.node {
-            hir::ItemKind::Fn(ref fn_decl, .., ref generics, _) =>
-                has_late_bound_regions(tcx, generics, fn_decl),
+        Node::Item(item) => match item.node {
+            hir::ItemKind::Fn(ref fn_decl, .., ref generics, _) => {
+                has_late_bound_regions(tcx, generics, fn_decl)
+            }
             _ => None,
         },
-        _ => None
+        _ => None,
     }
 }
 
-fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                         def_id: DefId)
-                         -> &'tcx ty::Generics {
-    use rustc::hir::map::*;
+fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Generics {
     use rustc::hir::*;
 
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
 
     let node = tcx.hir.get(node_id);
     let parent_def_id = match node {
-        NodeImplItem(_) |
-        NodeTraitItem(_) |
-        NodeVariant(_) |
-        NodeStructCtor(_) |
-        NodeField(_) => {
+        Node::ImplItem(_) | Node::TraitItem(_) | Node::Variant(_)
+        | Node::StructCtor(_) | Node::Field(_) => {
             let parent_id = tcx.hir.get_parent(node_id);
             Some(tcx.hir.local_def_id(parent_id))
         }
-        NodeExpr(&hir::Expr { node: hir::ExprKind::Closure(..), .. }) => {
-            Some(tcx.closure_base_def_id(def_id))
-        }
-        NodeItem(item) => {
-            match item.node {
-                ItemKind::Existential(hir::ExistTy { impl_trait_fn, .. }) => impl_trait_fn,
-                _ => None,
-            }
+        Node::Expr(&hir::Expr {
+            node: hir::ExprKind::Closure(..),
+            ..
+        }) => Some(tcx.closure_base_def_id(def_id)),
+        Node::Item(item) => match item.node {
+            ItemKind::Existential(hir::ExistTy { impl_trait_fn, .. }) => impl_trait_fn,
+            _ => None,
         },
-        _ => None
+        _ => None,
     };
 
     let mut opt_self = None;
@@ -830,26 +881,27 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     let no_generics = hir::Generics::empty();
     let ast_generics = match node {
-        NodeTraitItem(item) => &item.generics,
+        Node::TraitItem(item) => &item.generics,
 
-        NodeImplItem(item) => &item.generics,
+        Node::ImplItem(item) => &item.generics,
 
-        NodeItem(item) => {
+        Node::Item(item) => {
             match item.node {
-                ItemKind::Fn(.., ref generics, _) |
-                ItemKind::Impl(_, _, _, ref generics, ..) => generics,
-
-                ItemKind::Ty(_, ref generics) |
-                ItemKind::Enum(_, ref generics) |
-                ItemKind::Struct(_, ref generics) |
-                ItemKind::Existential(hir::ExistTy { ref generics, .. }) |
-                ItemKind::Union(_, ref generics) => {
+                ItemKind::Fn(.., ref generics, _) | ItemKind::Impl(_, _, _, ref generics, ..) => {
+                    generics
+                }
+
+                ItemKind::Ty(_, ref generics)
+                | ItemKind::Enum(_, ref generics)
+                | ItemKind::Struct(_, ref generics)
+                | ItemKind::Existential(hir::ExistTy { ref generics, .. })
+                | ItemKind::Union(_, ref generics) => {
                     allow_defaults = true;
                     generics
                 }
 
-                ItemKind::Trait(_, _, ref generics, ..) |
-                ItemKind::TraitAlias(ref generics, ..) => {
+                ItemKind::Trait(_, _, ref generics, ..)
+                ItemKind::TraitAlias(ref generics, ..) => {
                     // Add in the self type parameter.
                     //
                     // Something of a hack: use the node id for the trait, also as
@@ -876,13 +928,11 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
         }
 
-        NodeForeignItem(item) => {
-            match item.node {
-                ForeignItemKind::Static(..) => &no_generics,
-                ForeignItemKind::Fn(_, _, ref generics) => generics,
-                ForeignItemKind::Type => &no_generics,
-            }
-        }
+        Node::ForeignItem(item) => match item.node {
+            ForeignItemKind::Static(..) => &no_generics,
+            ForeignItemKind::Fn(_, _, ref generics) => generics,
+            ForeignItemKind::Type => &no_generics,
+        },
 
         _ => &no_generics,
     };
@@ -901,15 +951,17 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut params: Vec<_> = opt_self.into_iter().collect();
 
     let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
-    params.extend(early_lifetimes.enumerate().map(|(i, param)| {
-        ty::GenericParamDef {
-            name: param.name.ident().as_interned_str(),
-            index: own_start + i as u32,
-            def_id: tcx.hir.local_def_id(param.id),
-            pure_wrt_drop: param.pure_wrt_drop,
-            kind: ty::GenericParamDefKind::Lifetime,
-        }
-    }));
+    params.extend(
+        early_lifetimes
+            .enumerate()
+            .map(|(i, param)| ty::GenericParamDef {
+                name: param.name.ident().as_interned_str(),
+                index: own_start + i as u32,
+                def_id: tcx.hir.local_def_id(param.id),
+                pure_wrt_drop: param.pure_wrt_drop,
+                kind: ty::GenericParamDefKind::Lifetime,
+            }),
+    );
 
     let hir_id = tcx.hir.node_to_hir_id(node_id);
     let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id);
@@ -917,45 +969,65 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Now create the real type parameters.
     let type_start = own_start - has_self as u32 + params.len() as u32;
     let mut i = 0;
-    params.extend(ast_generics.params.iter().filter_map(|param| match param.kind {
-        GenericParamKind::Type { ref default, synthetic, .. } => {
-            if param.name.ident().name == keywords::SelfType.name() {
-                span_bug!(param.span,  "`Self` should not be the name of a regular parameter");
-            }
+    params.extend(
+        ast_generics
+            .params
+            .iter()
+            .filter_map(|param| match param.kind {
+                GenericParamKind::Type {
+                    ref default,
+                    synthetic,
+                    ..
+                } => {
+                    if param.name.ident().name == keywords::SelfType.name() {
+                        span_bug!(
+                            param.span,
+                            "`Self` should not be the name of a regular parameter"
+                        );
+                    }
 
-            if !allow_defaults && default.is_some() {
-                if !tcx.features().default_type_parameter_fallback {
-                    tcx.lint_node(
-                        lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
-                        param.id,
-                        param.span,
-                        &format!("defaults for type parameters are only allowed in \
-                                    `struct`, `enum`, `type`, or `trait` definitions."));
-                }
-            }
+                    if !allow_defaults && default.is_some() {
+                        if !tcx.features().default_type_parameter_fallback {
+                            tcx.lint_node(
+                                lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
+                                param.id,
+                                param.span,
+                                &format!(
+                                    "defaults for type parameters are only allowed in \
+                                     `struct`, `enum`, `type`, or `trait` definitions."
+                                ),
+                            );
+                        }
+                    }
 
-            let ty_param = ty::GenericParamDef {
-                index: type_start + i as u32,
-                name: param.name.ident().as_interned_str(),
-                def_id: tcx.hir.local_def_id(param.id),
-                pure_wrt_drop: param.pure_wrt_drop,
-                kind: ty::GenericParamDefKind::Type {
-                    has_default: default.is_some(),
-                    object_lifetime_default:
-                        object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]),
-                    synthetic,
-                },
-            };
-            i += 1;
-            Some(ty_param)
-        }
-        _ => None,
-    }));
+                    let ty_param = ty::GenericParamDef {
+                        index: type_start + i as u32,
+                        name: param.name.ident().as_interned_str(),
+                        def_id: tcx.hir.local_def_id(param.id),
+                        pure_wrt_drop: param.pure_wrt_drop,
+                        kind: ty::GenericParamDefKind::Type {
+                            has_default: default.is_some(),
+                            object_lifetime_default: object_lifetime_defaults
+                                .as_ref()
+                                .map_or(rl::Set1::Empty, |o| o[i]),
+                            synthetic,
+                        },
+                    };
+                    i += 1;
+                    Some(ty_param)
+                }
+                _ => None,
+            }),
+    );
 
     // provide junk type parameter defs - the only place that
     // cares about anything but the length is instantiation,
     // and we don't do that for closures.
-    if let NodeExpr(&hir::Expr { node: hir::ExprKind::Closure(.., gen), .. }) = node {
+    if let Node::Expr(&hir::Expr {
+        node: hir::ExprKind::Closure(.., gen),
+        ..
+    }) = node
+    {
         let dummy_args = if gen.is_some() {
             &["<yield_ty>", "<return_ty>", "<witness>"][..]
         } else {
@@ -963,8 +1035,10 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         };
 
         params.extend(
-            dummy_args.iter().enumerate().map(|(i, &arg)|
-                ty::GenericParamDef {
+            dummy_args
+                .iter()
+                .enumerate()
+                .map(|(i, &arg)| ty::GenericParamDef {
                     index: type_start + i as u32,
                     name: Symbol::intern(arg).as_interned_str(),
                     def_id,
@@ -974,8 +1048,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         object_lifetime_default: rl::Set1::Empty,
                         synthetic: None,
                     },
-                }
-            )
+                }),
         );
 
         tcx.with_freevars(node_id, |fv| {
@@ -995,9 +1068,10 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         });
     }
 
-    let param_def_id_to_index = params.iter()
-                                      .map(|param| (param.def_id, param.index))
-                                      .collect();
+    let param_def_id_to_index = params
+        .iter()
+        .map(|param| (param.def_id, param.index))
+        .collect();
 
     tcx.alloc_generics(ty::Generics {
         parent: parent_def_id,
@@ -1009,17 +1083,16 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     })
 }
 
-fn report_assoc_ty_on_inherent_impl<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    span: Span,
-) {
-    span_err!(tcx.sess, span, E0202, "associated types are not allowed in inherent impls");
+fn report_assoc_ty_on_inherent_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span) {
+    span_err!(
+        tcx.sess,
+        span,
+        E0202,
+        "associated types are not allowed in inherent impls"
+    );
 }
 
-fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                     def_id: DefId)
-                     -> Ty<'tcx> {
-    use rustc::hir::map::*;
+fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
     use rustc::hir::*;
 
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
@@ -1027,109 +1100,132 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let icx = ItemCtxt::new(tcx, def_id);
 
     match tcx.hir.get(node_id) {
-        NodeTraitItem(item) => {
-            match item.node {
-                TraitItemKind::Method(..) => {
-                    let substs = Substs::identity_for_item(tcx, def_id);
-                    tcx.mk_fn_def(def_id, substs)
-                }
-                TraitItemKind::Const(ref ty, _) |
-                TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
-                TraitItemKind::Type(_, None) => {
-                    span_bug!(item.span, "associated type missing default");
-                }
+        Node::TraitItem(item) => match item.node {
+            TraitItemKind::Method(..) => {
+                let substs = Substs::identity_for_item(tcx, def_id);
+                tcx.mk_fn_def(def_id, substs)
             }
-        }
+            TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
+            TraitItemKind::Type(_, None) => {
+                span_bug!(item.span, "associated type missing default");
+            }
+        },
 
-        NodeImplItem(item) => {
-            match item.node {
-                ImplItemKind::Method(..) => {
-                    let substs = Substs::identity_for_item(tcx, def_id);
-                    tcx.mk_fn_def(def_id, substs)
+        Node::ImplItem(item) => match item.node {
+            ImplItemKind::Method(..) => {
+                let substs = Substs::identity_for_item(tcx, def_id);
+                tcx.mk_fn_def(def_id, substs)
+            }
+            ImplItemKind::Const(ref ty, _) => icx.to_ty(ty),
+            ImplItemKind::Existential(_) => {
+                if tcx
+                    .impl_trait_ref(tcx.hir.get_parent_did(node_id))
+                    .is_none()
+                {
+                    report_assoc_ty_on_inherent_impl(tcx, item.span);
                 }
-                ImplItemKind::Const(ref ty, _) => icx.to_ty(ty),
-                ImplItemKind::Existential(_) => {
-                    if tcx.impl_trait_ref(tcx.hir.get_parent_did(node_id)).is_none() {
-                        report_assoc_ty_on_inherent_impl(tcx, item.span);
-                    }
 
-                    find_existential_constraints(tcx, def_id)
+                find_existential_constraints(tcx, def_id)
+            }
+            ImplItemKind::Type(ref ty) => {
+                if tcx
+                    .impl_trait_ref(tcx.hir.get_parent_did(node_id))
+                    .is_none()
+                {
+                    report_assoc_ty_on_inherent_impl(tcx, item.span);
                 }
-                ImplItemKind::Type(ref ty) => {
-                    if tcx.impl_trait_ref(tcx.hir.get_parent_did(node_id)).is_none() {
-                        report_assoc_ty_on_inherent_impl(tcx, item.span);
-                    }
 
-                    icx.to_ty(ty)
-                }
+                icx.to_ty(ty)
             }
-        }
+        },
 
-        NodeItem(item) => {
+        Node::Item(item) => {
             match item.node {
-                ItemKind::Static(ref t, ..) | ItemKind::Const(ref t, _) |
-                ItemKind::Ty(ref t, _) | ItemKind::Impl(.., ref t, _) => {
-                    icx.to_ty(t)
-                }
+                ItemKind::Static(ref t, ..)
+                | ItemKind::Const(ref t, _)
+                | ItemKind::Ty(ref t, _)
+                | ItemKind::Impl(.., ref t, _) => icx.to_ty(t),
                 ItemKind::Fn(..) => {
                     let substs = Substs::identity_for_item(tcx, def_id);
                     tcx.mk_fn_def(def_id, substs)
                 }
-                ItemKind::Enum(..) |
-                ItemKind::Struct(..) |
-                ItemKind::Union(..) => {
+                ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
                     let def = tcx.adt_def(def_id);
                     let substs = Substs::identity_for_item(tcx, def_id);
                     tcx.mk_adt(def, substs)
                 }
-                ItemKind::Existential(hir::ExistTy { impl_trait_fn: None, .. }) => {
-                    find_existential_constraints(tcx, def_id)
-                },
+                ItemKind::Existential(hir::ExistTy {
+                    impl_trait_fn: None,
+                    ..
+                }) => find_existential_constraints(tcx, def_id),
                 // existential types desugared from impl Trait
-                ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(owner), .. }) => {
-                    tcx.typeck_tables_of(owner).concrete_existential_types[&def_id]
-                },
-                ItemKind::Trait(..) | ItemKind::TraitAlias(..) |
-                ItemKind::Mod(..) |
-                ItemKind::ForeignMod(..) |
-                ItemKind::GlobalAsm(..) |
-                ItemKind::ExternCrate(..) |
-                ItemKind::Use(..) => {
+                ItemKind::Existential(hir::ExistTy {
+                    impl_trait_fn: Some(owner),
+                    ..
+                }) => {
+                    tcx.typeck_tables_of(owner)
+                        .concrete_existential_types
+                        .get(&def_id)
+                        .cloned()
+                        .unwrap_or_else(|| {
+                            // This can occur if some error in the
+                            // owner fn prevented us from populating
+                            // the `concrete_existential_types` table.
+                            tcx.sess.delay_span_bug(
+                                DUMMY_SP,
+                                &format!(
+                                    "owner {:?} has no existential type for {:?} in its tables",
+                                    owner, def_id,
+                                ),
+                            );
+                            tcx.types.err
+                        })
+                }
+                ItemKind::Trait(..)
+                | ItemKind::TraitAlias(..)
+                | ItemKind::Mod(..)
+                | ItemKind::ForeignMod(..)
+                | ItemKind::GlobalAsm(..)
+                | ItemKind::ExternCrate(..)
+                | ItemKind::Use(..) => {
                     span_bug!(
                         item.span,
                         "compute_type_of_item: unexpected item type: {:?}",
-                        item.node);
+                        item.node
+                    );
                 }
             }
         }
 
-        NodeForeignItem(foreign_item) => {
-            match foreign_item.node {
-                ForeignItemKind::Fn(..) => {
-                    let substs = Substs::identity_for_item(tcx, def_id);
-                    tcx.mk_fn_def(def_id, substs)
-                }
-                ForeignItemKind::Static(ref t, _) => icx.to_ty(t),
-                ForeignItemKind::Type => tcx.mk_foreign(def_id),
+        Node::ForeignItem(foreign_item) => match foreign_item.node {
+            ForeignItemKind::Fn(..) => {
+                let substs = Substs::identity_for_item(tcx, def_id);
+                tcx.mk_fn_def(def_id, substs)
             }
-        }
+            ForeignItemKind::Static(ref t, _) => icx.to_ty(t),
+            ForeignItemKind::Type => tcx.mk_foreign(def_id),
+        },
 
-        NodeStructCtor(&ref def) |
-        NodeVariant(&Spanned { node: hir::VariantKind { data: ref def, .. }, .. }) => {
-            match *def {
-                VariantData::Unit(..) | VariantData::Struct(..) => {
-                    tcx.type_of(tcx.hir.get_parent_did(node_id))
-                }
-                VariantData::Tuple(..) => {
-                    let substs = Substs::identity_for_item(tcx, def_id);
-                    tcx.mk_fn_def(def_id, substs)
-                }
+        Node::StructCtor(&ref def)
+        | Node::Variant(&Spanned {
+            node: hir::VariantKind { data: ref def, .. },
+            ..
+        }) => match *def {
+            VariantData::Unit(..) | VariantData::Struct(..) => {
+                tcx.type_of(tcx.hir.get_parent_did(node_id))
             }
-        }
+            VariantData::Tuple(..) => {
+                let substs = Substs::identity_for_item(tcx, def_id);
+                tcx.mk_fn_def(def_id, substs)
+            }
+        },
 
-        NodeField(field) => icx.to_ty(&field.ty),
+        Node::Field(field) => icx.to_ty(&field.ty),
 
-        NodeExpr(&hir::Expr { node: hir::ExprKind::Closure(.., gen), .. }) => {
+        Node::Expr(&hir::Expr {
+            node: hir::ExprKind::Closure(.., gen),
+            ..
+        }) => {
             if gen.is_some() {
                 let hir_id = tcx.hir.node_to_hir_id(node_id);
                 return tcx.typeck_tables_of(def_id).node_id_to_type(hir_id);
@@ -1142,31 +1238,50 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             tcx.mk_closure(def_id, substs)
         }
 
-        NodeAnonConst(_) => match tcx.hir.get(tcx.hir.get_parent_node(node_id)) {
-            NodeTy(&hir::Ty { node: hir::TyKind::Array(_, ref constant), .. }) |
-            NodeTy(&hir::Ty { node: hir::TyKind::Typeof(ref constant), .. }) |
-            NodeExpr(&hir::Expr { node: ExprKind::Repeat(_, ref constant), .. })
-                if constant.id == node_id => tcx.types.usize,
+        Node::AnonConst(_) => match tcx.hir.get(tcx.hir.get_parent_node(node_id)) {
+            Node::Ty(&hir::Ty {
+                node: hir::TyKind::Array(_, ref constant),
+                ..
+            })
+            | Node::Ty(&hir::Ty {
+                node: hir::TyKind::Typeof(ref constant),
+                ..
+            })
+            | Node::Expr(&hir::Expr {
+                node: ExprKind::Repeat(_, ref constant),
+                ..
+            }) if constant.id == node_id =>
+            {
+                tcx.types.usize
+            }
 
-            NodeVariant(&Spanned { node: VariantKind { disr_expr: Some(ref e), .. }, .. })
-                if e.id == node_id => {
-                    tcx.adt_def(tcx.hir.get_parent_did(node_id))
-                        .repr.discr_type().to_ty(tcx)
-                }
+            Node::Variant(&Spanned {
+                node:
+                    VariantKind {
+                        disr_expr: Some(ref e),
+                        ..
+                    },
+                ..
+            }) if e.id == node_id =>
+            {
+                tcx.adt_def(tcx.hir.get_parent_did(node_id))
+                    .repr
+                    .discr_type()
+                    .to_ty(tcx)
+            }
 
             x => {
                 bug!("unexpected const parent in type_of_def_id(): {:?}", x);
             }
         },
 
-        NodeGenericParam(param) => {
-            match param.kind {
-                hir::GenericParamKind::Type { default: Some(ref ty), .. } => {
-                    icx.to_ty(ty)
-                }
-                _ => bug!("unexpected non-type NodeGenericParam"),
-            }
-        }
+        Node::GenericParam(param) => match param.kind {
+            hir::GenericParamKind::Type {
+                default: Some(ref ty),
+                ..
+            } => icx.to_ty(ty),
+            _ => bug!("unexpected non-type NodeGenericParam"),
+        },
 
         x => {
             bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
@@ -1178,7 +1293,6 @@ fn find_existential_constraints<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
 ) -> ty::Ty<'tcx> {
-    use rustc::hir::map::*;
     use rustc::hir::*;
 
     struct ConstraintLocator<'a, 'tcx: 'a> {
@@ -1245,7 +1359,11 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem) {
             intravisit::walk_trait_item(self, it);
         }
     }
-    let mut locator = ConstraintLocator { def_id, tcx, found: None };
+    let mut locator = ConstraintLocator {
+        def_id,
+        tcx,
+        found: None,
+    };
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
     let parent = tcx.hir.get_parent(node_id);
     trace!("parent_id: {:?}", parent);
@@ -1254,10 +1372,13 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem) {
     } else {
         trace!("parent: {:?}", tcx.hir.get(parent));
         match tcx.hir.get(parent) {
-            NodeItem(ref it) => intravisit::walk_item(&mut locator, it),
-            NodeImplItem(ref it) => intravisit::walk_impl_item(&mut locator, it),
-            NodeTraitItem(ref it) => intravisit::walk_trait_item(&mut locator, it),
-            other => bug!("{:?} is not a valid parent of an existential type item", other),
+            Node::Item(ref it) => intravisit::walk_item(&mut locator, it),
+            Node::ImplItem(ref it) => intravisit::walk_impl_item(&mut locator, it),
+            Node::TraitItem(ref it) => intravisit::walk_trait_item(&mut locator, it),
+            other => bug!(
+                "{:?} is not a valid parent of an existential type item",
+                other
+            ),
         }
     }
     match locator.found {
@@ -1270,49 +1391,63 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem) {
     }
 }
 
-fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    def_id: DefId)
-                    -> ty::PolyFnSig<'tcx> {
-    use rustc::hir::map::*;
+fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::PolyFnSig<'tcx> {
     use rustc::hir::*;
+    use rustc::hir::Node::*;
 
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
 
     let icx = ItemCtxt::new(tcx, def_id);
 
     match tcx.hir.get(node_id) {
-        NodeTraitItem(hir::TraitItem { node: TraitItemKind::Method(sig, _), .. }) |
-        NodeImplItem(hir::ImplItem { node: ImplItemKind::Method(sig, _), .. }) => {
-            AstConv::ty_of_fn(&icx, sig.header.unsafety, sig.header.abi, &sig.decl)
-        }
-
-        NodeItem(hir::Item { node: ItemKind::Fn(decl, header, _, _), .. }) => {
-            AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl)
-        }
-
-        NodeForeignItem(&hir::ForeignItem { node: ForeignItemKind::Fn(ref fn_decl, _, _), .. }) => {
+        TraitItem(hir::TraitItem {
+            node: TraitItemKind::Method(sig, _),
+            ..
+        })
+        | ImplItem(hir::ImplItem {
+            node: ImplItemKind::Method(sig, _),
+            ..
+        }) => AstConv::ty_of_fn(&icx, sig.header.unsafety, sig.header.abi, &sig.decl),
+
+        Item(hir::Item {
+            node: ItemKind::Fn(decl, header, _, _),
+            ..
+        }) => AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl),
+
+        ForeignItem(&hir::ForeignItem {
+            node: ForeignItemKind::Fn(ref fn_decl, _, _),
+            ..
+        }) => {
             let abi = tcx.hir.get_foreign_abi(node_id);
             compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi)
         }
 
-        NodeStructCtor(&VariantData::Tuple(ref fields, _)) |
-        NodeVariant(&Spanned { node: hir::VariantKind {
-            data: VariantData::Tuple(ref fields, _), ..
-        }, .. }) => {
+        StructCtor(&VariantData::Tuple(ref fields, _))
+        | Variant(&Spanned {
+            node:
+                hir::VariantKind {
+                    data: VariantData::Tuple(ref fields, _),
+                    ..
+                },
+            ..
+        }) => {
             let ty = tcx.type_of(tcx.hir.get_parent_did(node_id));
-            let inputs = fields.iter().map(|f| {
-                tcx.type_of(tcx.hir.local_def_id(f.id))
-            });
+            let inputs = fields
+                .iter()
+                .map(|f| tcx.type_of(tcx.hir.local_def_id(f.id)));
             ty::Binder::bind(tcx.mk_fn_sig(
                 inputs,
                 ty,
                 false,
                 hir::Unsafety::Normal,
-                abi::Abi::Rust
+                abi::Abi::Rust,
             ))
         }
 
-        NodeExpr(&hir::Expr { node: hir::ExprKind::Closure(..), .. }) => {
+        Expr(&hir::Expr {
+            node: hir::ExprKind::Closure(..),
+            ..
+        }) => {
             // Closure signatures are not like other function
             // signatures and cannot be accessed through `fn_sig`. For
             // example, a closure signature excludes the `self`
@@ -1337,9 +1472,10 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-fn impl_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                            def_id: DefId)
-                            -> Option<ty::TraitRef<'tcx>> {
+fn impl_trait_ref<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId,
+) -> Option<ty::TraitRef<'tcx>> {
     let icx = ItemCtxt::new(tcx, def_id);
 
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
@@ -1350,37 +1486,40 @@ fn impl_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty)
             })
         }
-        _ => bug!()
+        _ => bug!(),
     }
 }
 
-fn impl_polarity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                           def_id: DefId)
-                           -> hir::ImplPolarity {
+fn impl_polarity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> hir::ImplPolarity {
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
     match tcx.hir.expect_item(node_id).node {
         hir::ItemKind::Impl(_, polarity, ..) => polarity,
-        ref item => bug!("impl_polarity: {:?} not an impl", item)
+        ref item => bug!("impl_polarity: {:?} not an impl", item),
     }
 }
 
 // Is it marked with ?Sized
-fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &dyn AstConv<'gcx, 'tcx>,
-                                ast_bounds: &[hir::GenericBound],
-                                span: Span) -> bool
-{
+fn is_unsized<'gcx: 'tcx, 'tcx>(
+    astconv: &dyn AstConv<'gcx, 'tcx>,
+    ast_bounds: &[hir::GenericBound],
+    span: Span,
+) -> bool {
     let tcx = astconv.tcx();
 
     // Try to find an unbound in bounds.
     let mut unbound = None;
     for ab in ast_bounds {
-        if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab  {
+        if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab {
             if unbound.is_none() {
                 unbound = Some(ptr.trait_ref.clone());
             } else {
-                span_err!(tcx.sess, span, E0203,
-                          "type parameter has more than one relaxed default \
-                                                bound, only one is supported");
+                span_err!(
+                    tcx.sess,
+                    span,
+                    E0203,
+                    "type parameter has more than one relaxed default \
+                     bound, only one is supported"
+                );
             }
         }
     }
@@ -1391,10 +1530,12 @@ fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &dyn AstConv<'gcx, 'tcx>,
             // FIXME(#8559) currently requires the unbound to be built-in.
             if let Ok(kind_id) = kind_id {
                 if tpb.path.def != Def::Trait(kind_id) {
-                    tcx.sess.span_warn(span,
-                                       "default bound relaxed for a type parameter, but \
-                                       this does nothing because the given bound is not \
-                                       a default. Only `?Sized` is supported");
+                    tcx.sess.span_warn(
+                        span,
+                        "default bound relaxed for a type parameter, but \
+                         this does nothing because the given bound is not \
+                         a default. Only `?Sized` is supported",
+                    );
                 }
             }
         }
@@ -1415,25 +1556,33 @@ fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &dyn AstConv<'gcx, 'tcx>,
 /// `resolve_lifetime::early_bound_lifetimes`.
 fn early_bound_lifetimes_from_generics<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    generics: &'a hir::Generics)
-    -> impl Iterator<Item=&'a hir::GenericParam> + Captures<'tcx>
-{
-    generics.params.iter().filter(move |param| match param.kind {
-        GenericParamKind::Lifetime { .. } => {
-            let hir_id = tcx.hir.node_to_hir_id(param.id);
-            !tcx.is_late_bound(hir_id)
-        }
-        _ => false,
-    })
+    generics: &'a hir::Generics,
+) -> impl Iterator<Item = &'a hir::GenericParam> + Captures<'tcx> {
+    generics
+        .params
+        .iter()
+        .filter(move |param| match param.kind {
+            GenericParamKind::Lifetime { .. } => {
+                let hir_id = tcx.hir.node_to_hir_id(param.id);
+                !tcx.is_late_bound(hir_id)
+            }
+            _ => false,
+        })
 }
 
-fn predicates_defined_on<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                   def_id: DefId)
-                                   -> ty::GenericPredicates<'tcx> {
+fn predicates_defined_on<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId,
+) -> ty::GenericPredicates<'tcx> {
     let explicit = tcx.explicit_predicates_of(def_id);
     let predicates = if tcx.sess.features_untracked().infer_outlives_requirements {
-        [&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat()
-    } else { explicit.predicates };
+        [
+            &explicit.predicates[..],
+            &tcx.inferred_outlives_of(def_id)[..],
+        ].concat()
+    } else {
+        explicit.predicates
+    };
 
     ty::GenericPredicates {
         parent: explicit.parent,
@@ -1441,11 +1590,14 @@ fn predicates_defined_on<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                           def_id: DefId)
-                           -> ty::GenericPredicates<'tcx> {
-    let ty::GenericPredicates { parent, mut predicates } =
-        tcx.predicates_defined_on(def_id);
+fn predicates_of<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId,
+) -> ty::GenericPredicates<'tcx> {
+    let ty::GenericPredicates {
+        parent,
+        mut predicates,
+    } = tcx.predicates_defined_on(def_id);
 
     if tcx.is_trait(def_id) {
         // For traits, add `Self: Trait` predicate. This is
@@ -1470,7 +1622,6 @@ fn explicit_predicates_of<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
 ) -> ty::GenericPredicates<'tcx> {
-    use rustc::hir::map::*;
     use rustc::hir::*;
 
     debug!("explicit_predicates_of(def_id={:?})", def_id);
@@ -1487,29 +1638,29 @@ fn explicit_predicates_of<'a, 'tcx>(
     let mut predicates = vec![];
 
     let ast_generics = match node {
-        NodeTraitItem(item) => {
-            &item.generics
-        }
+        Node::TraitItem(item) => &item.generics,
 
-        NodeImplItem(item) => match item.node {
+        Node::ImplItem(item) => match item.node {
             ImplItemKind::Existential(ref bounds) => {
                 let substs = Substs::identity_for_item(tcx, def_id);
                 let anon_ty = tcx.mk_anon(def_id, substs);
 
                 // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
-                let bounds = compute_bounds(&icx,
-                                            anon_ty,
-                                            bounds,
-                                            SizedByDefault::Yes,
-                                            tcx.def_span(def_id));
+                let bounds = compute_bounds(
+                    &icx,
+                    anon_ty,
+                    bounds,
+                    SizedByDefault::Yes,
+                    tcx.def_span(def_id),
+                );
 
                 predicates.extend(bounds.predicates(tcx, anon_ty));
                 &item.generics
-            },
+            }
             _ => &item.generics,
-        }
+        },
 
-        NodeItem(item) => {
+        Node::Item(item) => {
             match item.node {
                 ItemKind::Impl(_, _, defaultness, ref generics, ..) => {
                     if defaultness.is_default() {
@@ -1517,26 +1668,32 @@ fn explicit_predicates_of<'a, 'tcx>(
                     }
                     generics
                 }
-                ItemKind::Fn(.., ref generics, _) |
-                ItemKind::Ty(_, ref generics) |
-                ItemKind::Enum(_, ref generics) |
-                ItemKind::Struct(_, ref generics) |
-                ItemKind::Union(_, ref generics) => generics,
+                ItemKind::Fn(.., ref generics, _)
+                | ItemKind::Ty(_, ref generics)
+                | ItemKind::Enum(_, ref generics)
+                | ItemKind::Struct(_, ref generics)
+                ItemKind::Union(_, ref generics) => generics,
 
                 ItemKind::Trait(_, _, ref generics, .., ref items) => {
                     is_trait = Some((ty::TraitRef::identity(tcx, def_id), items));
                     generics
                 }
-                ItemKind::Existential(ExistTy { ref bounds, impl_trait_fn, ref generics }) => {
+                ItemKind::Existential(ExistTy {
+                    ref bounds,
+                    impl_trait_fn,
+                    ref generics,
+                }) => {
                     let substs = Substs::identity_for_item(tcx, def_id);
                     let anon_ty = tcx.mk_anon(def_id, substs);
 
                     // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
-                    let bounds = compute_bounds(&icx,
-                                                anon_ty,
-                                                bounds,
-                                                SizedByDefault::Yes,
-                                                tcx.def_span(def_id));
+                    let bounds = compute_bounds(
+                        &icx,
+                        anon_ty,
+                        bounds,
+                        SizedByDefault::Yes,
+                        tcx.def_span(def_id),
+                    );
 
                     if impl_trait_fn.is_some() {
                         // impl Trait
@@ -1555,13 +1712,11 @@ fn explicit_predicates_of<'a, 'tcx>(
             }
         }
 
-        NodeForeignItem(item) => {
-            match item.node {
-                ForeignItemKind::Static(..) => &no_generics,
-                ForeignItemKind::Fn(_, _, ref generics) => generics,
-                ForeignItemKind::Type => &no_generics,
-            }
-        }
+        Node::ForeignItem(item) => match item.node {
+            ForeignItemKind::Static(..) => &no_generics,
+            ForeignItemKind::Fn(_, _, ref generics) => generics,
+            ForeignItemKind::Type => &no_generics,
+        },
 
         _ => &no_generics,
     };
@@ -1612,7 +1767,7 @@ fn explicit_predicates_of<'a, 'tcx>(
                     }
                     _ => bug!(),
                 });
-            },
+            }
             _ => bug!(),
         }
     }
@@ -1646,20 +1801,19 @@ fn explicit_predicates_of<'a, 'tcx>(
                         &hir::GenericBound::Trait(ref poly_trait_ref, _) => {
                             let mut projections = Vec::new();
 
-                            let trait_ref =
-                                AstConv::instantiate_poly_trait_ref(&icx,
-                                                                    poly_trait_ref,
-                                                                    ty,
-                                                                    &mut projections);
+                            let trait_ref = AstConv::instantiate_poly_trait_ref(
+                                &icx,
+                                poly_trait_ref,
+                                ty,
+                                &mut projections,
+                            );
 
                             predicates.push(trait_ref.to_predicate());
                             predicates.extend(projections.iter().map(|p| p.to_predicate()));
                         }
 
                         &hir::GenericBound::Outlives(ref lifetime) => {
-                            let region = AstConv::ast_region_to_region(&icx,
-                                                                       lifetime,
-                                                                       None);
+                            let region = AstConv::ast_region_to_region(&icx, lifetime, None);
                             let pred = ty::Binder::bind(ty::OutlivesPredicate(ty, region));
                             predicates.push(ty::Predicate::TypeOutlives(pred))
                         }
@@ -1698,16 +1852,16 @@ fn explicit_predicates_of<'a, 'tcx>(
                 }
             };
 
-            let assoc_ty = tcx.mk_projection(
-                tcx.hir.local_def_id(trait_item.id),
-                self_trait_ref.substs,
-            );
+            let assoc_ty =
+                tcx.mk_projection(tcx.hir.local_def_id(trait_item.id), self_trait_ref.substs);
 
-            let bounds = compute_bounds(&ItemCtxt::new(tcx, def_id),
-                                        assoc_ty,
-                                        bounds,
-                                        SizedByDefault::Yes,
-                                        trait_item.span);
+            let bounds = compute_bounds(
+                &ItemCtxt::new(tcx, def_id),
+                assoc_ty,
+                bounds,
+                SizedByDefault::Yes,
+                trait_item.span,
+            );
 
             bounds.predicates(tcx, assoc_ty).into_iter()
         }))
@@ -1718,13 +1872,19 @@ fn explicit_predicates_of<'a, 'tcx>(
     // before uses of `U`.  This avoids false ambiguity errors
     // in trait checking. See `setup_constraining_predicates`
     // for details.
-    if let NodeItem(&Item { node: ItemKind::Impl(..), .. }) = node {
+    if let Node::Item(&Item {
+        node: ItemKind::Impl(..),
+        ..
+    }) = node
+    {
         let self_ty = tcx.type_of(def_id);
         let trait_ref = tcx.impl_trait_ref(def_id);
-        ctp::setup_constraining_predicates(tcx,
-                                           &mut predicates,
-                                           trait_ref,
-                                           &mut ctp::parameters_for_impl(self_ty, trait_ref));
+        ctp::setup_constraining_predicates(
+            tcx,
+            &mut predicates,
+            trait_ref,
+            &mut ctp::parameters_for_impl(self_ty, trait_ref),
+        );
     }
 
     ty::GenericPredicates {
@@ -1733,18 +1893,21 @@ fn explicit_predicates_of<'a, 'tcx>(
     }
 }
 
-pub enum SizedByDefault { Yes, No, }
+pub enum SizedByDefault {
+    Yes,
+    No,
+}
 
 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
 /// built-in trait (formerly known as kind): Send.
-pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &dyn AstConv<'gcx, 'tcx>,
-                                        param_ty: Ty<'tcx>,
-                                        ast_bounds: &[hir::GenericBound],
-                                        sized_by_default: SizedByDefault,
-                                        span: Span)
-                                        -> Bounds<'tcx>
-{
+pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
+    astconv: &dyn AstConv<'gcx, 'tcx>,
+    param_ty: Ty<'tcx>,
+    ast_bounds: &[hir::GenericBound],
+    sized_by_default: SizedByDefault,
+    span: Span,
+) -> Bounds<'tcx> {
     let mut region_bounds = vec![];
     let mut trait_bounds = vec![];
     for ast_bound in ast_bounds {
@@ -1757,13 +1920,15 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &dyn AstConv<'gcx, 'tcx>,
 
     let mut projection_bounds = vec![];
 
-    let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
-        astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds)
-    }).collect();
+    let mut trait_bounds: Vec<_> = trait_bounds
+        .iter()
+        .map(|&bound| astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds))
+        .collect();
 
-    let region_bounds = region_bounds.into_iter().map(|r| {
-        astconv.ast_region_to_region(r, None)
-    }).collect();
+    let region_bounds = region_bounds
+        .into_iter()
+        .map(|r| astconv.ast_region_to_region(r, None))
+        .collect();
 
     trait_bounds.sort_by_key(|t| t.def_id());
 
@@ -1786,21 +1951,20 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &dyn AstConv<'gcx, 'tcx>,
 /// because this can be anywhere from 0 predicates (`T:?Sized` adds no
 /// predicates) to 1 (`T:Foo`) to many (`T:Bar<X=i32>` adds `T:Bar`
 /// and `<T as Bar>::X == i32`).
-fn predicates_from_bound<'tcx>(astconv: &dyn AstConv<'tcx, 'tcx>,
-                               param_ty: Ty<'tcx>,
-                               bound: &hir::GenericBound)
-                               -> Vec<ty::Predicate<'tcx>>
-{
+fn predicates_from_bound<'tcx>(
+    astconv: &dyn AstConv<'tcx, 'tcx>,
+    param_ty: Ty<'tcx>,
+    bound: &hir::GenericBound,
+) -> Vec<ty::Predicate<'tcx>> {
     match *bound {
         hir::GenericBound::Trait(ref tr, hir::TraitBoundModifier::None) => {
             let mut projections = Vec::new();
-            let pred = astconv.instantiate_poly_trait_ref(tr,
-                                                          param_ty,
-                                                          &mut projections);
-            projections.into_iter()
-                       .map(|p| p.to_predicate())
-                       .chain(Some(pred.to_predicate()))
-                       .collect()
+            let pred = astconv.instantiate_poly_trait_ref(tr, param_ty, &mut projections);
+            projections
+                .into_iter()
+                .map(|p| p.to_predicate())
+                .chain(Some(pred.to_predicate()))
+                .collect()
         }
         hir::GenericBound::Outlives(ref lifetime) => {
             let region = astconv.ast_region_to_region(lifetime, None);
@@ -1815,21 +1979,35 @@ fn compute_sig_of_foreign_fn_decl<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
     decl: &hir::FnDecl,
-    abi: abi::Abi)
-    -> ty::PolyFnSig<'tcx>
-{
-    let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), hir::Unsafety::Unsafe, abi, decl);
+    abi: abi::Abi,
+) -> ty::PolyFnSig<'tcx> {
+    let unsafety = if abi == abi::Abi::RustIntrinsic {
+        match &*tcx.item_name(def_id).as_str() {
+            "size_of" | "min_align_of" => hir::Unsafety::Normal,
+            _ => hir::Unsafety::Unsafe,
+        }
+    } else {
+        hir::Unsafety::Unsafe
+    };
+    let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), unsafety, abi, decl);
 
     // feature gate SIMD types in FFI, since I (huonw) am not sure the
     // ABIs are handled at all correctly.
-    if abi != abi::Abi::RustIntrinsic && abi != abi::Abi::PlatformIntrinsic
-            && !tcx.features().simd_ffi {
+    if abi != abi::Abi::RustIntrinsic
+        && abi != abi::Abi::PlatformIntrinsic
+        && !tcx.features().simd_ffi
+    {
         let check = |ast_ty: &hir::Ty, ty: Ty| {
             if ty.is_simd() {
-                tcx.sess.struct_span_err(ast_ty.span,
-                              &format!("use of SIMD type `{}` in FFI is highly experimental and \
-                                        may result in invalid code",
-                                       tcx.hir.node_to_pretty_string(ast_ty.id)))
+                tcx.sess
+                    .struct_span_err(
+                        ast_ty.span,
+                        &format!(
+                            "use of SIMD type `{}` in FFI is highly experimental and \
+                             may result in invalid code",
+                            tcx.hir.node_to_pretty_string(ast_ty.id)
+                        ),
+                    )
                     .help("add #![feature(simd_ffi)] to the crate attributes to enable")
                     .emit();
             }
@@ -1845,13 +2023,11 @@ fn compute_sig_of_foreign_fn_decl<'a, 'tcx>(
     fty
 }
 
-fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             def_id: DefId)
-                             -> bool {
+fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
     match tcx.hir.get_if_local(def_id) {
-        Some(hir_map::NodeForeignItem(..)) => true,
+        Some(Node::ForeignItem(..)) => true,
         Some(_) => false,
-        _ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id)
+        _ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id),
     }
 }
 
@@ -1868,7 +2044,7 @@ fn from_target_feature(
             let msg = "#[target_feature] attribute must be of the form \
                        #[target_feature(..)]";
             tcx.sess.span_err(attr.span, &msg);
-            return
+            return;
         }
     };
     let rust_features = tcx.features();
@@ -1878,7 +2054,7 @@ fn from_target_feature(
             let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \
                        currently";
             tcx.sess.span_err(item.span, &msg);
-            continue
+            continue;
         }
 
         // Must be of the form `enable = "..."` ( a string)
@@ -1888,19 +2064,21 @@ fn from_target_feature(
                 let msg = "#[target_feature] attribute must be of the form \
                            #[target_feature(enable = \"..\")]";
                 tcx.sess.span_err(item.span, &msg);
-                continue
+                continue;
             }
         };
 
         // We allow comma separation to enable multiple features
         for feature in value.as_str().split(',') {
-
             // Only allow whitelisted features per platform
             let feature_gate = match whitelist.get(feature) {
                 Some(g) => g,
                 None => {
-                    let msg = format!("the feature named `{}` is not valid for \
-                                       this target", feature);
+                    let msg = format!(
+                        "the feature named `{}` is not valid for \
+                         this target",
+                        feature
+                    );
                     let mut err = tcx.sess.struct_span_err(item.span, &msg);
 
                     if feature.starts_with("+") {
@@ -1910,7 +2088,7 @@ fn from_target_feature(
                         }
                     }
                     err.emit();
-                    continue
+                    continue;
                 }
             };
 
@@ -1935,10 +2113,9 @@ fn from_target_feature(
                     feature_gate.as_ref().unwrap(),
                     item.span,
                     feature_gate::GateIssue::Language,
-                    &format!("the target feature `{}` is currently unstable",
-                             feature),
+                    &format!("the target feature `{}` is currently unstable", feature),
                 );
-                continue
+                continue;
             }
             target_features.push(Symbol::intern(feature));
         }
@@ -1973,7 +2150,8 @@ fn linkage_by_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, name: &
             if let Some(span) = span {
                 tcx.sess.span_fatal(span, "invalid linkage specified")
             } else {
-                tcx.sess.fatal(&format!("invalid linkage specified: {}", name))
+                tcx.sess
+                    .fatal(&format!("invalid linkage specified: {}", name))
             }
         }
     }
@@ -2026,16 +2204,24 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen
                         mark_used(attr);
                         inline_span = Some(attr.span);
                         if items.len() != 1 {
-                            span_err!(tcx.sess.diagnostic(), attr.span, E0534,
-                                        "expected one argument");
+                            span_err!(
+                                tcx.sess.diagnostic(),
+                                attr.span,
+                                E0534,
+                                "expected one argument"
+                            );
                             InlineAttr::None
                         } else if list_contains_name(&items[..], "always") {
                             InlineAttr::Always
                         } else if list_contains_name(&items[..], "never") {
                             InlineAttr::Never
                         } else {
-                            span_err!(tcx.sess.diagnostic(), items[0].span, E0535,
-                                        "invalid argument");
+                            span_err!(
+                                tcx.sess.diagnostic(),
+                                items[0].span,
+                                E0535,
+                                "invalid argument"
+                            );
 
                             InlineAttr::None
                         }
@@ -2048,15 +2234,21 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen
                 if s.as_str().contains("\0") {
                     // `#[export_name = ...]` will be converted to a null-terminated string,
                     // so it may not contain any null characters.
-                    struct_span_err!(tcx.sess, attr.span, E0648,
-                                     "`export_name` may not contain null characters")
-                        .emit();
+                    struct_span_err!(
+                        tcx.sess,
+                        attr.span,
+                        E0648,
+                        "`export_name` may not contain null characters"
+                    ).emit();
                 }
                 codegen_fn_attrs.export_name = Some(s);
             } else {
-                struct_span_err!(tcx.sess, attr.span, E0558,
-                                 "`export_name` attribute has invalid format")
-                    .span_label(attr.span, "did you mean #[export_name=\"*\"]?")
+                struct_span_err!(
+                    tcx.sess,
+                    attr.span,
+                    E0558,
+                    "`export_name` attribute has invalid format"
+                ).span_label(attr.span, "did you mean #[export_name=\"*\"]?")
                     .emit();
             }
         } else if attr.check_name("target_feature") {
@@ -2065,7 +2257,13 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen
                            `unsafe` function";
                 tcx.sess.span_err(attr.span, msg);
             }
-            from_target_feature(tcx, id, attr, &whitelist, &mut codegen_fn_attrs.target_features);
+            from_target_feature(
+                tcx,
+                id,
+                attr,
+                &whitelist,
+                &mut codegen_fn_attrs.target_features,
+            );
         } else if attr.check_name("linkage") {
             if let Some(val) = attr.value_str() {
                 codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str()));
@@ -2073,13 +2271,18 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen
         } else if attr.check_name("link_section") {
             if let Some(val) = attr.value_str() {
                 if val.as_str().bytes().any(|b| b == 0) {
-                    let msg = format!("illegal null byte in link_section \
-                                       value: `{}`", &val);
+                    let msg = format!(
+                        "illegal null byte in link_section \
+                         value: `{}`",
+                        &val
+                    );
                     tcx.sess.span_err(attr.span, &msg);
                 } else {
                     codegen_fn_attrs.link_section = Some(val);
                 }
             }
+        } else if attr.check_name("link_name") {
+            codegen_fn_attrs.link_name = attr.value_str();
         }
     }
 
@@ -2090,11 +2293,34 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen
     if codegen_fn_attrs.target_features.len() > 0 {
         if codegen_fn_attrs.inline == InlineAttr::Always {
             if let Some(span) = inline_span {
-                tcx.sess.span_err(span, "cannot use #[inline(always)] with \
-                                         #[target_feature]");
+                tcx.sess.span_err(
+                    span,
+                    "cannot use #[inline(always)] with \
+                     #[target_feature]",
+                );
             }
         }
     }
 
+    // Weak lang items have the same semantics as "std internal" symbols in the
+    // sense that they're preserved through all our LTO passes and only
+    // strippable by the linker.
+    //
+    // Additionally weak lang items have predetermined symbol names.
+    if tcx.is_weak_lang_item(id) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
+    }
+    if let Some(name) = weak_lang_items::link_name(&attrs) {
+        codegen_fn_attrs.export_name = Some(name);
+        codegen_fn_attrs.link_name = Some(name);
+    }
+
+    // Internal symbols to the standard library all have no_mangle semantics in
+    // that they have defined symbol names present in the function name. This
+    // also applies to weak symbols where they all have known symbol names.
+    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
+    }
+
     codegen_fn_attrs
 }
index 5f55b9b06ef1b122d804e090a99b53c6be398b38..37b0b83ccd0880851c6a523e55575e245e11b396 100644 (file)
@@ -62,11 +62,11 @@ struct ParameterCollector {
 impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
     fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
         match t.sty {
-            ty::TyProjection(..) | ty::TyAnon(..) if !self.include_nonconstraining => {
+            ty::Projection(..) | ty::Anon(..) if !self.include_nonconstraining => {
                 // projections are not injective
                 return false;
             }
-            ty::TyParam(data) => {
+            ty::Param(data) => {
                 self.parameters.push(Parameter::from(data));
             }
             _ => {}
index c01102272aeb4e7bc269ac970b14f7666cb9d1d4..80c1ca944bb9eb01769303d3dab1de22da94a4c4 100644 (file)
@@ -1041,9 +1041,11 @@ enum NightsWatch {}
 "##,
 
 E0087: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
 Too many type arguments were supplied for a function. For example:
 
-```compile_fail,E0087
+```compile_fail,E0107
 fn foo<T>() {}
 
 fn main() {
@@ -1057,9 +1059,11 @@ fn main() {
 "##,
 
 E0088: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
 You gave too many lifetime arguments. Erroneous code example:
 
-```compile_fail,E0088
+```compile_fail,E0107
 fn f() {}
 
 fn main() {
@@ -1103,9 +1107,11 @@ fn main() {
 "##,
 
 E0089: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
 Too few type arguments were supplied for a function. For example:
 
-```compile_fail,E0089
+```compile_fail,E0107
 fn foo<T, U>() {}
 
 fn main() {
@@ -1116,7 +1122,7 @@ fn main() {
 Note that if a function takes multiple type arguments but you want the compiler
 to infer some of them, you can use type placeholders:
 
-```compile_fail,E0089
+```compile_fail,E0107
 fn foo<T, U>(x: T) {}
 
 fn main() {
@@ -1129,9 +1135,11 @@ fn main() {
 "##,
 
 E0090: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
 You gave too few lifetime arguments. Example:
 
-```compile_fail,E0090
+```compile_fail,E0107
 fn foo<'a: 'b, 'b: 'a>() {}
 
 fn main() {
@@ -1258,18 +1266,34 @@ fn main() {
 "##,
 
 E0107: r##"
-This error means that an incorrect number of lifetime parameters were provided
-for a type (like a struct or enum) or trait:
+This error means that an incorrect number of generic arguments were provided:
 
 ```compile_fail,E0107
-struct Foo<'a, 'b>(&'a str, &'b str);
-enum Bar { A, B, C }
+struct Foo<T> { x: T }
+
+struct Bar { x: Foo }             // error: wrong number of type arguments:
+                                  //        expected 1, found 0
+struct Baz<S, T> { x: Foo<S, T> } // error: wrong number of type arguments:
+                                  //        expected 1, found 2
 
-struct Baz<'a> {
-    foo: Foo<'a>, // error: expected 2, found 1
-    bar: Bar<'a>, // error: expected 0, found 1
+fn foo<T, U>(x: T, y: U) {}
+
+fn main() {
+    let x: bool = true;
+    foo::<bool>(x);                 // error: wrong number of type arguments:
+                                    //        expected 2, found 1
+    foo::<bool, i32, i32>(x, 2, 4); // error: wrong number of type arguments:
+                                    //        expected 2, found 3
+}
+
+fn f() {}
+
+fn main() {
+    f::<'static>(); // error: wrong number of lifetime arguments:
+                    //        expected 0, found 1
 }
 ```
+
 "##,
 
 E0109: r##"
@@ -2397,13 +2421,15 @@ fn baz<I>(x: &<I as Foo>::A) where I: Foo<A=Bar> {}
 "##,
 
 E0243: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
 This error indicates that not enough type parameters were found in a type or
 trait.
 
 For example, the `Foo` struct below is defined to be generic in `T`, but the
 type parameter is missing in the definition of `Bar`:
 
-```compile_fail,E0243
+```compile_fail,E0107
 struct Foo<T> { x: T }
 
 struct Bar { x: Foo }
@@ -2411,13 +2437,15 @@ struct Bar { x: Foo }
 "##,
 
 E0244: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
 This error indicates that too many type parameters were found in a type or
 trait.
 
 For example, the `Foo` struct below has no type parameters, but is supplied
 with two in the definition of `Bar`:
 
-```compile_fail,E0244
+```compile_fail,E0107
 struct Foo { x: bool }
 
 struct Bar<S, T> { x: Foo<S, T> }
@@ -4630,7 +4658,7 @@ struct LengthWithUnit<U> {
 Erroneous code example:
 
 ```compile_fail,E0691
-#![feature(repr_align, attr_literals)]
+#![feature(repr_align)]
 
 #[repr(align(32))]
 struct ForceAlign32;
@@ -4657,7 +4685,7 @@ struct LengthWithUnit<U> {
 if you need to keep the field for some reason:
 
 ```
-#![feature(repr_align, attr_literals)]
+#![feature(repr_align)]
 
 use std::marker::PhantomData;
 
index b7921301957ce294fbd1faeb51805c3877fd672e..11260b8f11e12c6a9386e9dad1b224298050a090 100644 (file)
@@ -152,7 +152,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // }
     // ```
     //
-    // In a concession to backwards compatbility, we continue to
+    // In a concession to backwards compatibility, we continue to
     // permit those, so long as the lifetimes aren't used in
     // associated types. I believe this is sound, because lifetimes
     // used elsewhere are not projected back out.
index 62f93ea20e48cc09dbaf3ec2c816d45ca221c5c0..f465ff4d62163e63148d7bf39eae8376ad433156 100644 (file)
@@ -75,8 +75,8 @@
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
 #![feature(exhaustive_patterns)]
-#![feature(iterator_find_map)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(quote)]
 #![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
@@ -96,6 +96,7 @@
 extern crate rustc_data_structures;
 extern crate rustc_errors as errors;
 extern crate rustc_target;
+extern crate smallvec;
 
 use rustc::hir;
 use rustc::lint;
 use rustc::session;
 use rustc::util;
 
-use hir::map as hir_map;
+use hir::Node;
 use rustc::infer::InferOk;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -185,9 +186,9 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let main_def_id = tcx.hir.local_def_id(main_id);
     let main_t = tcx.type_of(main_def_id);
     match main_t.sty {
-        ty::TyFnDef(..) => {
+        ty::FnDef(..) => {
             match tcx.hir.find(main_id) {
-                Some(hir_map::NodeItem(it)) => {
+                Some(Node::Item(it)) => {
                     match it.node {
                         hir::ItemKind::Fn(.., ref generics, _) => {
                             let mut error = false;
@@ -257,9 +258,9 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let start_def_id = tcx.hir.local_def_id(start_id);
     let start_t = tcx.type_of(start_def_id);
     match start_t.sty {
-        ty::TyFnDef(..) => {
+        ty::FnDef(..) => {
             match tcx.hir.find(start_id) {
-                Some(hir_map::NodeItem(it)) => {
+                Some(Node::Item(it)) => {
                     match it.node {
                         hir::ItemKind::Fn(.., ref generics, _) => {
                             let mut error = false;
index e378f1a2dce36e0a8b7dd12fc1273bdfe297f162..092e4d62e2e9fa5724d4618bea8f6bf957897cb8 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use rustc::hir;
+use hir::Node;
 use rustc::hir::def_id::DefId;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::subst::{Kind, Subst, UnpackedKind};
@@ -65,13 +66,12 @@ fn visit_item(&mut self, item: &hir::Item) {
 
         debug!("InferVisitor::visit_item(item={:?})", item_did);
 
-        let node_id = self
-            .tcx
+        let node_id = self.tcx
             .hir
             .as_local_node_id(item_did)
             .expect("expected local def-id");
         let item = match self.tcx.hir.get(node_id) {
-            hir::map::NodeItem(item) => item,
+            Node::Item(item) => item,
             _ => bug!(),
         };
 
@@ -85,7 +85,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                     // Calculating the predicate requirements necessary
                     // for item_did.
                     //
-                    // For field of type &'a T (reference) or TyAdt
+                    // For field of type &'a T (reference) or Adt
                     // (struct/enum/union) there will be outlive
                     // requirements for adt_def.
                     let field_ty = self.tcx.type_of(field_def.did);
@@ -108,8 +108,7 @@ fn visit_item(&mut self, item: &hir::Item) {
         // Therefore mark `predicates_added` as true and which will ensure
         // we walk the crates again and re-calculate predicates for all
         // items.
-        let item_predicates_len: usize = self
-            .global_inferred_outlives
+        let item_predicates_len: usize = self.global_inferred_outlives
             .get(&item_did)
             .map(|p| p.len())
             .unwrap_or(0);
@@ -138,16 +137,16 @@ fn insert_required_predicates_to_be_wf<'tcx>(
             // a predicate requirement of T: 'a (T outlives 'a).
             //
             // We also want to calculate potential predicates for the T
-            ty::TyRef(region, rty, _) => {
-                debug!("TyRef");
+            ty::Ref(region, rty, _) => {
+                debug!("Ref");
                 insert_outlives_predicate(tcx, rty.into(), region, required_predicates);
             }
 
-            // For each TyAdt (struct/enum/union) type `Foo<'a, T>`, we
+            // For each Adt (struct/enum/union) type `Foo<'a, T>`, we
             // can load the current set of inferred and explicit
             // predicates from `global_inferred_outlives` and filter the
             // ones that are TypeOutlives.
-            ty::TyAdt(def, substs) => {
+            ty::Adt(def, substs) => {
                 // First check the inferred predicates
                 //
                 // Example 1:
@@ -166,7 +165,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                 // round we will get `U: 'b`. We then apply the substitution
                 // `['b => 'a, U => T]` and thus get the requirement that `T:
                 // 'a` holds for `Foo`.
-                debug!("TyAdt");
+                debug!("Adt");
                 if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did) {
                     for unsubstituted_predicate in unsubstituted_predicates {
                         // `unsubstituted_predicate` is `U: 'b` in the
@@ -191,45 +190,52 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                     substs,
                     required_predicates,
                     explicit_map,
-                    false,
+                    IgnoreSelfTy(false),
                 );
             }
 
-            ty::TyDynamic(obj, ..) => {
+            ty::Dynamic(obj, ..) => {
                 // This corresponds to `dyn Trait<..>`. In this case, we should
                 // use the explicit predicates as well.
 
-                // We are passing type `ty` as a placeholder value with the function
-                // `with_self_ty`, since there is no concrete type `Self` for a
-                // `dyn Trait` at this stage. Therefore when checking explicit
-                // predicates in `check_explicit_predicates` we need to ignore
-                // checking the explicit_map for Self type.
-                debug!("TyDynamic");
+                debug!("Dynamic");
                 debug!("field_ty = {}", &field_ty);
                 debug!("ty in field = {}", &ty);
                 if let Some(ex_trait_ref) = obj.principal() {
+                    // Here, we are passing the type `usize` as a
+                    // placeholder value with the function
+                    // `with_self_ty`, since there is no concrete type
+                    // `Self` for a `dyn Trait` at this
+                    // stage. Therefore when checking explicit
+                    // predicates in `check_explicit_predicates` we
+                    // need to ignore checking the explicit_map for
+                    // Self type.
+                    let substs = ex_trait_ref
+                        .with_self_ty(tcx, tcx.types.usize)
+                        .skip_binder()
+                        .substs;
                     check_explicit_predicates(
                         tcx,
                         &ex_trait_ref.skip_binder().def_id,
-                        ex_trait_ref.with_self_ty(tcx, ty).skip_binder().substs,
+                        substs,
                         required_predicates,
                         explicit_map,
-                        true,
+                        IgnoreSelfTy(true),
                     );
                 }
             }
 
-            ty::TyProjection(obj) => {
+            ty::Projection(obj) => {
                 // This corresponds to `<T as Foo<'a>>::Bar`. In this case, we should use the
                 // explicit predicates as well.
-                debug!("TyProjection");
+                debug!("Projection");
                 check_explicit_predicates(
                     tcx,
                     &tcx.associated_item(obj.item_def_id).container.id(),
                     obj.substs,
                     required_predicates,
                     explicit_map,
-                    false,
+                    IgnoreSelfTy(false),
                 );
             }
 
@@ -238,6 +244,8 @@ fn insert_required_predicates_to_be_wf<'tcx>(
     }
 }
 
+pub struct IgnoreSelfTy(bool);
+
 /// We also have to check the explicit predicates
 /// declared on the type.
 ///
@@ -259,7 +267,7 @@ pub fn check_explicit_predicates<'tcx>(
     substs: &[Kind<'tcx>],
     required_predicates: &mut RequiredPredicates<'tcx>,
     explicit_map: &mut ExplicitPredicatesMap<'tcx>,
-    ignore_self_ty: bool,
+    ignore_self_ty: IgnoreSelfTy,
 ) {
     debug!("def_id = {:?}", &def_id);
     debug!("substs = {:?}", &substs);
@@ -297,7 +305,7 @@ pub fn check_explicit_predicates<'tcx>(
         // to apply the substs, and not filter this predicate, we might then falsely
         // conclude that e.g. `X: 'x` was a reasonable inferred requirement.
         if let UnpackedKind::Type(ty) = outlives_predicate.0.unpack() {
-            if ty.is_self() && ignore_self_ty {
+            if ty.is_self() && ignore_self_ty.0 {
                 debug!("skipping self ty = {:?}", &ty);
                 continue;
             }
@@ -307,5 +315,4 @@ pub fn check_explicit_predicates<'tcx>(
         debug!("predicate = {:?}", &predicate);
         insert_outlives_predicate(tcx, predicate.0.into(), predicate.1, required_predicates);
     }
-    // }
 }
index 74ef62e0c63c6633a8dc542932974b8990b1cf8b..63a424936eb4c75d9ac08fec999dbbc882c51b04 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use hir::map as hir_map;
+use hir::Node;
 use rustc::hir;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::ty::query::Providers;
@@ -40,7 +40,7 @@ fn inferred_outlives_of<'a, 'tcx>(
         .expect("expected local def-id");
 
     match tcx.hir.get(id) {
-        hir_map::NodeItem(item) => match item.node {
+        Node::Item(item) => match item.node {
             hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => {
                 let crate_map = tcx.inferred_outlives_crate(LOCAL_CRATE);
 
@@ -59,8 +59,7 @@ fn inferred_outlives_of<'a, 'tcx>(
                             ty::Predicate::TypeOutlives(p) => p.to_string(),
 
                             err => bug!("unexpected predicate {:?}", err),
-                        })
-                        .collect();
+                        }).collect();
                     pred.sort();
 
                     let span = tcx.def_span(item_def_id);
@@ -117,11 +116,9 @@ fn inferred_outlives_crate<'tcx>(
                             ty::Binder::bind(ty::OutlivesPredicate(region1, region2)),
                         ),
                     },
-                )
-                .collect();
+                ).collect();
             (def_id, Lrc::new(vec))
-        })
-        .collect();
+        }).collect();
 
     let empty_predicate = Lrc::new(Vec::new());
 
index ffd9da8c8b95c803ec870ff93738027effccda2d..12863cc66a053ecb02149a573d1c276dd0e34628 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc::session::Session;
 use syntax_pos::Span;
-use errors::{DiagnosticId, DiagnosticBuilder};
+use errors::{Applicability, DiagnosticId, DiagnosticBuilder};
 use rustc::ty::{Ty, TypeFoldable};
 
 pub trait StructuredDiagnostic<'tcx> {
@@ -73,9 +73,12 @@ fn common(&self) -> DiagnosticBuilder<'tcx> {
             )
         };
         if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) {
-            err.span_suggestion(self.span,
-                                &format!("cast the value to `{}`", self.cast_ty),
-                                format!("{} as {}", snippet, self.cast_ty));
+            err.span_suggestion_with_applicability(
+                self.span,
+                &format!("cast the value to `{}`", self.cast_ty),
+                format!("{} as {}", snippet, self.cast_ty),
+                Applicability::MachineApplicable,
+            );
         } else {
             err.help(&format!("cast the value to `{}`", self.cast_ty));
         }
index 9fecf5e73e761ac1cdffaa5ef31f3e757b79bcd0..a79215497182e252e1072e6ce73a2ecde2a0d3d2 100644 (file)
@@ -152,7 +152,7 @@ fn build_constraints_for_item(&mut self, def_id: DefId) {
         let inferred_start = self.terms_cx.inferred_starts[&id];
         let current_item = &CurrentItem { inferred_start };
         match tcx.type_of(def_id).sty {
-            ty::TyAdt(def, _) => {
+            ty::Adt(def, _) => {
                 // Not entirely obvious: constraints on structs/enums do not
                 // affect the variance of their type parameters. See discussion
                 // in comment at top of module.
@@ -166,7 +166,7 @@ fn build_constraints_for_item(&mut self, def_id: DefId) {
                 }
             }
 
-            ty::TyFnDef(..) => {
+            ty::FnDef(..) => {
                 self.add_constraints_from_sig(current_item,
                                               tcx.fn_sig(def_id),
                                               self.covariant);
@@ -261,52 +261,52 @@ fn add_constraints_from_ty(&mut self,
                variance);
 
         match ty.sty {
-            ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
-            ty::TyStr | ty::TyNever | ty::TyForeign(..) => {
+            ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) |
+            ty::Str | ty::Never | ty::Foreign(..) => {
                 // leaf type -- noop
             }
 
-            ty::TyFnDef(..) |
-            ty::TyGenerator(..) |
-            ty::TyClosure(..) => {
+            ty::FnDef(..) |
+            ty::Generator(..) |
+            ty::Closure(..) => {
                 bug!("Unexpected closure type in variance computation");
             }
 
-            ty::TyRef(region, ty, mutbl) => {
+            ty::Ref(region, ty, mutbl) => {
                 let contra = self.contravariant(variance);
                 self.add_constraints_from_region(current, region, contra);
                 self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance);
             }
 
-            ty::TyArray(typ, _) |
-            ty::TySlice(typ) => {
+            ty::Array(typ, _) |
+            ty::Slice(typ) => {
                 self.add_constraints_from_ty(current, typ, variance);
             }
 
-            ty::TyRawPtr(ref mt) => {
+            ty::RawPtr(ref mt) => {
                 self.add_constraints_from_mt(current, mt, variance);
             }
 
-            ty::TyTuple(subtys) => {
+            ty::Tuple(subtys) => {
                 for &subty in subtys {
                     self.add_constraints_from_ty(current, subty, variance);
                 }
             }
 
-            ty::TyAdt(def, substs) => {
+            ty::Adt(def, substs) => {
                 self.add_constraints_from_substs(current, def.did, substs, variance);
             }
 
-            ty::TyProjection(ref data) => {
+            ty::Projection(ref data) => {
                 let tcx = self.tcx();
                 self.add_constraints_from_trait_ref(current, data.trait_ref(tcx), variance);
             }
 
-            ty::TyAnon(_, substs) => {
+            ty::Anon(_, substs) => {
                 self.add_constraints_from_invariant_substs(current, substs, variance);
             }
 
-            ty::TyDynamic(ref data, r) => {
+            ty::Dynamic(ref data, r) => {
                 // The type `Foo<T+'a>` is contravariant w/r/t `'a`:
                 let contra = self.contravariant(variance);
                 self.add_constraints_from_region(current, r, contra);
@@ -323,21 +323,21 @@ fn add_constraints_from_ty(&mut self,
                 }
             }
 
-            ty::TyParam(ref data) => {
+            ty::Param(ref data) => {
                 self.add_constraint(current, data.idx, variance);
             }
 
-            ty::TyFnPtr(sig) => {
+            ty::FnPtr(sig) => {
                 self.add_constraints_from_sig(current, sig, variance);
             }
 
-            ty::TyError => {
+            ty::Error => {
                 // we encounter this when walking the trait references for object
-                // types, where we use TyError as the Self type
+                // types, where we use Error as the Self type
             }
 
-            ty::TyGeneratorWitness(..) |
-            ty::TyInfer(..) => {
+            ty::GeneratorWitness(..) |
+            ty::Infer(..) => {
                 bug!("unexpected type encountered in \
                       variance inference: {}",
                      ty);
index 3d70550c1dfb20603f7aa3aaf5c14220c8549ab5..aaa0fd8e099efa47c492f1987ccdfc57853bd0dd 100644 (file)
@@ -15,6 +15,7 @@
 
 use arena;
 use rustc::hir;
+use hir::Node;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::ty::{self, CrateVariancesMap, TyCtxt};
 use rustc::ty::query::Providers;
@@ -61,7 +62,7 @@ fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId)
         span_bug!(tcx.hir.span(id), "asked to compute variance for wrong kind of item")
     };
     match tcx.hir.get(id) {
-        hir::map::NodeItem(item) => match item.node {
+        Node::Item(item) => match item.node {
             hir::ItemKind::Enum(..) |
             hir::ItemKind::Struct(..) |
             hir::ItemKind::Union(..) |
@@ -70,25 +71,25 @@ fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId)
             _ => unsupported()
         },
 
-        hir::map::NodeTraitItem(item) => match item.node {
+        Node::TraitItem(item) => match item.node {
             hir::TraitItemKind::Method(..) => {}
 
             _ => unsupported()
         },
 
-        hir::map::NodeImplItem(item) => match item.node {
+        Node::ImplItem(item) => match item.node {
             hir::ImplItemKind::Method(..) => {}
 
             _ => unsupported()
         },
 
-        hir::map::NodeForeignItem(item) => match item.node {
+        Node::ForeignItem(item) => match item.node {
             hir::ForeignItemKind::Fn(..) => {}
 
             _ => unsupported()
         },
 
-        hir::map::NodeVariant(_) | hir::map::NodeStructCtor(_) => {}
+        Node::Variant(_) | Node::StructCtor(_) => {}
 
         _ => unsupported()
     }
index 340a7b1d08ede4989026f51b505ab8e70b090401..7116a42cead83b5dacb5a99706b07075e52845dc 100644 (file)
@@ -101,7 +101,7 @@ fn create_map(&self) -> FxHashMap<DefId, Lrc<Vec<ty::Variance>>> {
             debug!("id={} variances={:?}", id, variances);
 
             // Functions can have unused type parameters: make those invariant.
-            if let ty::TyFnDef(..) = tcx.type_of(def_id).sty {
+            if let ty::FnDef(..) = tcx.type_of(def_id).sty {
                 for variance in &mut variances {
                     if *variance == ty::Bivariant {
                         *variance = ty::Invariant;
index 1331bd5186f19ba5dee8a70cc9c53edecbe26070..de5a680ccf9d1625cede99f4e723100248406739 100644 (file)
@@ -824,7 +824,7 @@ fn sort_where_bounds(&self, mut bounds: &mut Vec<GenericBound>) {
     // In fact, the iteration of an FxHashMap can even vary between platforms,
     // since FxHasher has different behavior for 32-bit and 64-bit platforms.
     //
-    // Obviously, it's extremely undesireable for documentation rendering
+    // Obviously, it's extremely undesirable for documentation rendering
     // to be depndent on the platform it's run on. Apart from being confusing
     // to end users, it makes writing tests much more difficult, as predicates
     // can appear in any order in the final result.
@@ -836,7 +836,7 @@ fn sort_where_bounds(&self, mut bounds: &mut Vec<GenericBound>) {
     // predicates and bounds, however, we ensure that for a given codebase, all
     // auto-trait impls always render in exactly the same way.
     //
-    // Using the Debug impementation for sorting prevents us from needing to
+    // Using the Debug implementation for sorting prevents us from needing to
     // write quite a bit of almost entirely useless code (e.g. how should two
     // Types be sorted relative to each other). It also allows us to solve the
     // problem for both WherePredicates and GenericBounds at the same time. This
index 83e0827340dafbb3e4fa9fe5a1af05d1c65be175..e7e371cd5678569fafbbc64bf074eaf495daf8df 100644 (file)
@@ -65,98 +65,96 @@ pub fn get_blanket_impls<F>(
             return impls;
         }
         let ty = self.cx.tcx.type_of(def_id);
-        if self.cx.access_levels.borrow().is_doc_reachable(def_id) || ty.is_primitive() {
-            let generics = self.cx.tcx.generics_of(def_id);
-            let real_name = name.clone().map(|name| Ident::from_str(&name));
-            let param_env = self.cx.tcx.param_env(def_id);
-            for &trait_def_id in self.cx.all_traits.iter() {
-                if !self.cx.access_levels.borrow().is_doc_reachable(trait_def_id) ||
-                   self.cx.generated_synthetics
-                          .borrow_mut()
-                          .get(&(def_id, trait_def_id))
-                          .is_some() {
-                    continue
-                }
-                self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| {
-                    self.cx.tcx.infer_ctxt().enter(|infcx| {
-                        let t_generics = infcx.tcx.generics_of(impl_def_id);
-                        let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id)
-                                                 .expect("Cannot get impl trait");
-
-                        match trait_ref.self_ty().sty {
-                            ty::TypeVariants::TyParam(_) => {},
-                            _ => return,
-                        }
-
-                        let substs = infcx.fresh_substs_for_item(DUMMY_SP, def_id);
-                        let ty = ty.subst(infcx.tcx, substs);
-                        let param_env = param_env.subst(infcx.tcx, substs);
-
-                        let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
-                        let trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
-
-                        // Require the type the impl is implemented on to match
-                        // our type, and ignore the impl if there was a mismatch.
-                        let cause = traits::ObligationCause::dummy();
-                        let eq_result = infcx.at(&cause, param_env)
-                                             .eq(trait_ref.self_ty(), ty);
-                        if let Ok(InferOk { value: (), obligations }) = eq_result {
-                            // FIXME(eddyb) ignoring `obligations` might cause false positives.
-                            drop(obligations);
-
-                            let may_apply = infcx.predicate_may_hold(&traits::Obligation::new(
-                                cause.clone(),
-                                param_env,
-                                trait_ref.to_predicate(),
-                            ));
-                            if !may_apply {
-                                return
-                            }
-                            self.cx.generated_synthetics.borrow_mut()
-                                                        .insert((def_id, trait_def_id));
-                            let trait_ = hir::TraitRef {
-                                path: get_path_for_type(infcx.tcx,
-                                                        trait_def_id,
-                                                        hir::def::Def::Trait),
-                                ref_id: ast::DUMMY_NODE_ID,
-                                hir_ref_id: hir::DUMMY_HIR_ID,
-                            };
-                            let provided_trait_methods =
-                                infcx.tcx.provided_trait_methods(trait_def_id)
-                                         .into_iter()
-                                         .map(|meth| meth.ident.to_string())
-                                         .collect();
-
-                            let ty = self.cx.get_real_ty(def_id, def_ctor, &real_name, generics);
-                            let predicates = infcx.tcx.predicates_of(impl_def_id);
-
-                            impls.push(Item {
-                                source: infcx.tcx.def_span(impl_def_id).clean(self.cx),
-                                name: None,
-                                attrs: Default::default(),
-                                visibility: None,
-                                def_id: self.cx.next_def_id(impl_def_id.krate),
-                                stability: None,
-                                deprecation: None,
-                                inner: ImplItem(Impl {
-                                    unsafety: hir::Unsafety::Normal,
-                                    generics: (t_generics, &predicates).clean(self.cx),
-                                    provided_trait_methods,
-                                    trait_: Some(trait_.clean(self.cx)),
-                                    for_: ty.clean(self.cx),
-                                    items: infcx.tcx.associated_items(impl_def_id)
-                                                    .collect::<Vec<_>>()
-                                                    .clean(self.cx),
-                                    polarity: None,
-                                    synthetic: false,
-                                    blanket_impl: Some(infcx.tcx.type_of(impl_def_id)
-                                                                .clean(self.cx)),
-                                }),
-                            });
+        let generics = self.cx.tcx.generics_of(def_id);
+        let real_name = name.clone().map(|name| Ident::from_str(&name));
+        let param_env = self.cx.tcx.param_env(def_id);
+        for &trait_def_id in self.cx.all_traits.iter() {
+            if !self.cx.access_levels.borrow().is_doc_reachable(trait_def_id) ||
+               self.cx.generated_synthetics
+                      .borrow_mut()
+                      .get(&(def_id, trait_def_id))
+                      .is_some() {
+                continue
+            }
+            self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| {
+                self.cx.tcx.infer_ctxt().enter(|infcx| {
+                    let t_generics = infcx.tcx.generics_of(impl_def_id);
+                    let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id)
+                                             .expect("Cannot get impl trait");
+
+                    match trait_ref.self_ty().sty {
+                        ty::Param(_) => {},
+                        _ => return,
+                    }
+
+                    let substs = infcx.fresh_substs_for_item(DUMMY_SP, def_id);
+                    let ty = ty.subst(infcx.tcx, substs);
+                    let param_env = param_env.subst(infcx.tcx, substs);
+
+                    let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
+                    let trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
+
+                    // Require the type the impl is implemented on to match
+                    // our type, and ignore the impl if there was a mismatch.
+                    let cause = traits::ObligationCause::dummy();
+                    let eq_result = infcx.at(&cause, param_env)
+                                         .eq(trait_ref.self_ty(), ty);
+                    if let Ok(InferOk { value: (), obligations }) = eq_result {
+                        // FIXME(eddyb) ignoring `obligations` might cause false positives.
+                        drop(obligations);
+
+                        let may_apply = infcx.predicate_may_hold(&traits::Obligation::new(
+                            cause.clone(),
+                            param_env,
+                            trait_ref.to_predicate(),
+                        ));
+                        if !may_apply {
+                            return
                         }
-                    });
+                        self.cx.generated_synthetics.borrow_mut()
+                                                    .insert((def_id, trait_def_id));
+                        let trait_ = hir::TraitRef {
+                            path: get_path_for_type(infcx.tcx,
+                                                    trait_def_id,
+                                                    hir::def::Def::Trait),
+                            ref_id: ast::DUMMY_NODE_ID,
+                            hir_ref_id: hir::DUMMY_HIR_ID,
+                        };
+                        let provided_trait_methods =
+                            infcx.tcx.provided_trait_methods(trait_def_id)
+                                     .into_iter()
+                                     .map(|meth| meth.ident.to_string())
+                                     .collect();
+
+                        let ty = self.cx.get_real_ty(def_id, def_ctor, &real_name, generics);
+                        let predicates = infcx.tcx.predicates_of(impl_def_id);
+
+                        impls.push(Item {
+                            source: infcx.tcx.def_span(impl_def_id).clean(self.cx),
+                            name: None,
+                            attrs: Default::default(),
+                            visibility: None,
+                            def_id: self.cx.next_def_id(impl_def_id.krate),
+                            stability: None,
+                            deprecation: None,
+                            inner: ImplItem(Impl {
+                                unsafety: hir::Unsafety::Normal,
+                                generics: (t_generics, &predicates).clean(self.cx),
+                                provided_trait_methods,
+                                trait_: Some(trait_.clean(self.cx)),
+                                for_: ty.clean(self.cx),
+                                items: infcx.tcx.associated_items(impl_def_id)
+                                                .collect::<Vec<_>>()
+                                                .clean(self.cx),
+                                polarity: None,
+                                synthetic: false,
+                                blanket_impl: Some(infcx.tcx.type_of(impl_def_id)
+                                                            .clean(self.cx)),
+                            }),
+                        });
+                    }
                 });
-            }
+            });
         }
         impls
     }
index d5aab1fb098e155cf6db2285759924787b7041ac..f90f1e54da22c375c4f43559e39e492499295c7e 100644 (file)
@@ -31,7 +31,7 @@ pub enum Cfg {
     True,
     /// Denies all configurations.
     False,
-    /// A generic configration option, e.g. `test` or `target_os = "linux"`.
+    /// A generic configuration option, e.g. `test` or `target_os = "linux"`.
     Cfg(Symbol, Option<Symbol>),
     /// Negate a configuration requirement, i.e. `not(x)`.
     Not(Box<Cfg>),
index 4db211b7f1e70f6bba0aa6299c8fa76ea7a372d5..cd9f4eb42dfc675008268ad4c3efd39e6952c848 100644 (file)
@@ -20,24 +20,24 @@ pub fn get_def_from_def_id<F>(cx: &DocContext,
     let ty = cx.tcx.type_of(def_id);
 
     match ty.sty {
-        ty::TyAdt(adt, _) => callback(&match adt.adt_kind() {
+        ty::Adt(adt, _) => callback(&match adt.adt_kind() {
             AdtKind::Struct => Def::Struct,
             AdtKind::Enum => Def::Enum,
             AdtKind::Union => Def::Union,
         }),
-        ty::TyInt(_) |
-        ty::TyUint(_) |
-        ty::TyFloat(_) |
-        ty::TyStr |
-        ty::TyBool |
-        ty::TyChar => callback(&move |_: DefId| {
+        ty::Int(_) |
+        ty::Uint(_) |
+        ty::Float(_) |
+        ty::Str |
+        ty::Bool |
+        ty::Char => callback(&move |_: DefId| {
             match ty.sty {
-                ty::TyInt(x) => Def::PrimTy(hir::TyInt(x)),
-                ty::TyUint(x) => Def::PrimTy(hir::TyUint(x)),
-                ty::TyFloat(x) => Def::PrimTy(hir::TyFloat(x)),
-                ty::TyStr => Def::PrimTy(hir::TyStr),
-                ty::TyBool => Def::PrimTy(hir::TyBool),
-                ty::TyChar => Def::PrimTy(hir::TyChar),
+                ty::Int(x) => Def::PrimTy(hir::Int(x)),
+                ty::Uint(x) => Def::PrimTy(hir::Uint(x)),
+                ty::Float(x) => Def::PrimTy(hir::Float(x)),
+                ty::Str => Def::PrimTy(hir::Str),
+                ty::Bool => Def::PrimTy(hir::Bool),
+                ty::Char => Def::PrimTy(hir::Char),
                 _ => unreachable!(),
             }
         }),
index 1c66c39b660b246cc5f32fab320488718139d8e5..75d7488d26a75ac67b9ae9c7474293511f1f15bb 100644 (file)
@@ -83,7 +83,7 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa
             ret.extend(build_impls(cx, did, true));
             clean::EnumItem(build_enum(cx, did))
         }
-        Def::TyForeign(did) => {
+        Def::ForeignTy(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Foreign);
             ret.extend(build_impls(cx, did, false));
             clean::ForeignTypeItem
index 6cb37c0e6de142a16c32d067990b714534fb013b..5c23d0f6b399083a1172e7ee631ca9d5f721fde1 100644 (file)
@@ -568,7 +568,7 @@ fn clean(&self, cx: &DocContext) -> Item {
         let name = if self.name.is_some() {
             self.name.expect("No name provided").clean(cx)
         } else {
-            "".to_string()
+            String::new()
         };
 
         // maintain a stack of mod ids, for doc comment path resolution
@@ -1077,7 +1077,7 @@ fn external_generic_args(cx: &DocContext, trait_did: Option<DefId>, has_self: bo
         Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => {
             assert_eq!(types.len(), 1);
             let inputs = match types[0].sty {
-                ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
+                ty::Tuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
                 _ => {
                     return GenericArgs::AngleBracketed {
                         lifetimes,
@@ -1089,7 +1089,7 @@ fn external_generic_args(cx: &DocContext, trait_did: Option<DefId>, has_self: bo
             let output = None;
             // FIXME(#20299) return type comes from a projection now
             // match types[1].sty {
-            //     ty::TyTuple(ref v) if v.is_empty() => None, // -> ()
+            //     ty::Tuple(ref v) if v.is_empty() => None, // -> ()
             //     _ => Some(types[1].clean(cx))
             // };
             GenericArgs::Parenthesized {
@@ -1133,9 +1133,9 @@ fn clean(&self, cx: &DocContext) -> GenericBound {
         // collect any late bound regions
         let mut late_bounds = vec![];
         for ty_s in trait_ref.input_types().skip(1) {
-            if let ty::TyTuple(ts) = ty_s.sty {
+            if let ty::Tuple(ts) = ty_s.sty {
                 for &ty_s in ts {
-                    if let ty::TyRef(ref reg, _, _) = ty_s.sty {
+                    if let ty::Ref(ref reg, _, _) = ty_s.sty {
                         if let &ty::RegionKind::ReLateBound(..) = *reg {
                             debug!("  hit an ReLateBound {:?}", reg);
                             if let Some(Lifetime(name)) = reg.clean(cx) {
@@ -1760,7 +1760,7 @@ fn clean(&self, cx: &DocContext) -> FnDecl {
                 values: sig.skip_binder().inputs().iter().map(|t| {
                     Argument {
                         type_: t.clean(cx),
-                        name: names.next().map_or("".to_string(), |name| name.to_string()),
+                        name: names.next().map_or(String::new(), |name| name.to_string()),
                     }
                 }).collect(),
             },
@@ -1979,7 +1979,7 @@ fn clean(&self, cx: &DocContext) -> Item {
                     let self_arg_ty = *sig.input(0).skip_binder();
                     if self_arg_ty == self_ty {
                         decl.inputs.values[0].type_ = Generic(String::from("Self"));
-                    } else if let ty::TyRef(_, ty, _) = self_arg_ty.sty {
+                    } else if let ty::Ref(_, ty, _) = self_arg_ty.sty {
                         if ty == self_ty {
                             match decl.inputs.values[0].type_ {
                                 BorrowedRef{ref mut type_, ..} => {
@@ -2378,6 +2378,7 @@ fn from(float_ty: ast::FloatTy) -> PrimitiveType {
 impl Clean<Type> for hir::Ty {
     fn clean(&self, cx: &DocContext) -> Type {
         use rustc::hir::*;
+
         match self.node {
             TyKind::Never => Never,
             TyKind::Ptr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
@@ -2415,6 +2416,14 @@ fn clean(&self, cx: &DocContext) -> Type {
                     if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did) {
                         return ImplTrait(bounds);
                     }
+                } else if let Def::Existential(did) = path.def {
+                    // This block is for returned impl trait only.
+                    if let Some(node_id) = cx.tcx.hir.as_local_node_id(did) {
+                        let item = cx.tcx.hir.expect_item(node_id);
+                        if let hir::ItemKind::Existential(ref ty) = item.node {
+                            return ImplTrait(ty.bounds.clean(cx));
+                        }
+                    }
                 }
 
                 let mut alias = None;
@@ -2506,7 +2515,7 @@ fn clean(&self, cx: &DocContext) -> Type {
             TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
                 let mut def = Def::Err;
                 let ty = hir_ty_to_ty(cx.tcx, self);
-                if let ty::TyProjection(proj) = ty.sty {
+                if let ty::Projection(proj) = ty.sty {
                     def = Def::Trait(proj.trait_ref(cx.tcx).def_id);
                 }
                 let trait_path = hir::Path {
@@ -2545,15 +2554,15 @@ fn clean(&self, cx: &DocContext) -> Type {
 impl<'tcx> Clean<Type> for Ty<'tcx> {
     fn clean(&self, cx: &DocContext) -> Type {
         match self.sty {
-            ty::TyNever => Never,
-            ty::TyBool => Primitive(PrimitiveType::Bool),
-            ty::TyChar => Primitive(PrimitiveType::Char),
-            ty::TyInt(int_ty) => Primitive(int_ty.into()),
-            ty::TyUint(uint_ty) => Primitive(uint_ty.into()),
-            ty::TyFloat(float_ty) => Primitive(float_ty.into()),
-            ty::TyStr => Primitive(PrimitiveType::Str),
-            ty::TySlice(ty) => Slice(box ty.clean(cx)),
-            ty::TyArray(ty, n) => {
+            ty::Never => Never,
+            ty::Bool => Primitive(PrimitiveType::Bool),
+            ty::Char => Primitive(PrimitiveType::Char),
+            ty::Int(int_ty) => Primitive(int_ty.into()),
+            ty::Uint(uint_ty) => Primitive(uint_ty.into()),
+            ty::Float(float_ty) => Primitive(float_ty.into()),
+            ty::Str => Primitive(PrimitiveType::Str),
+            ty::Slice(ty) => Slice(box ty.clean(cx)),
+            ty::Array(ty, n) => {
                 let mut n = cx.tcx.lift(&n).expect("array lift failed");
                 if let ConstValue::Unevaluated(def_id, substs) = n.val {
                     let param_env = cx.tcx.param_env(def_id);
@@ -2568,15 +2577,15 @@ fn clean(&self, cx: &DocContext) -> Type {
                 let n = print_const(cx, n);
                 Array(box ty.clean(cx), n)
             }
-            ty::TyRawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
-            ty::TyRef(r, ty, mutbl) => BorrowedRef {
+            ty::RawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
+            ty::Ref(r, ty, mutbl) => BorrowedRef {
                 lifetime: r.clean(cx),
                 mutability: mutbl.clean(cx),
                 type_: box ty.clean(cx),
             },
-            ty::TyFnDef(..) |
-            ty::TyFnPtr(_) => {
-                let ty = cx.tcx.lift(self).expect("TyFnPtr lift failed");
+            ty::FnDef(..) |
+            ty::FnPtr(_) => {
+                let ty = cx.tcx.lift(self).expect("FnPtr lift failed");
                 let sig = ty.fn_sig(cx.tcx);
                 BareFunction(box BareFunctionDecl {
                     unsafety: sig.unsafety(),
@@ -2585,7 +2594,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                     abi: sig.abi(),
                 })
             }
-            ty::TyAdt(def, substs) => {
+            ty::Adt(def, substs) => {
                 let did = def.did;
                 let kind = match def.adt_kind() {
                     AdtKind::Struct => TypeKind::Struct,
@@ -2602,7 +2611,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                     is_generic: false,
                 }
             }
-            ty::TyForeign(did) => {
+            ty::Foreign(did) => {
                 inline::record_extern_fqn(cx, did, TypeKind::Foreign);
                 let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
                                          None, false, vec![], Substs::empty());
@@ -2613,7 +2622,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                     is_generic: false,
                 }
             }
-            ty::TyDynamic(ref obj, ref reg) => {
+            ty::Dynamic(ref obj, ref reg) => {
                 if let Some(principal) = obj.principal() {
                     let did = principal.def_id();
                     inline::record_extern_fqn(cx, did, TypeKind::Trait);
@@ -2657,17 +2666,17 @@ fn clean(&self, cx: &DocContext) -> Type {
                     Never
                 }
             }
-            ty::TyTuple(ref t) => Tuple(t.clean(cx)),
+            ty::Tuple(ref t) => Tuple(t.clean(cx)),
 
-            ty::TyProjection(ref data) => data.clean(cx),
+            ty::Projection(ref data) => data.clean(cx),
 
-            ty::TyParam(ref p) => Generic(p.name.to_string()),
+            ty::Param(ref p) => Generic(p.name.to_string()),
 
-            ty::TyAnon(def_id, substs) => {
+            ty::Anon(def_id, substs) => {
                 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
                 // by looking up the projections associated with the def_id.
                 let predicates_of = cx.tcx.predicates_of(def_id);
-                let substs = cx.tcx.lift(&substs).expect("TyAnon lift failed");
+                let substs = cx.tcx.lift(&substs).expect("Anon lift failed");
                 let bounds = predicates_of.instantiate(cx.tcx, substs);
                 let mut regions = vec![];
                 let mut has_sized = false;
@@ -2717,11 +2726,11 @@ fn clean(&self, cx: &DocContext) -> Type {
                 ImplTrait(bounds)
             }
 
-            ty::TyClosure(..) | ty::TyGenerator(..) => Tuple(vec![]), // FIXME(pcwalton)
+            ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
 
-            ty::TyGeneratorWitness(..) => panic!("TyGeneratorWitness"),
-            ty::TyInfer(..) => panic!("TyInfer"),
-            ty::TyError => panic!("TyError"),
+            ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
+            ty::Infer(..) => panic!("Infer"),
+            ty::Error => panic!("Error"),
         }
     }
 }
@@ -3587,7 +3596,7 @@ fn clean(&self, cx: &DocContext) -> Item {
                 ForeignStaticItem(Static {
                     type_: ty.clean(cx),
                     mutability: if mutbl {Mutable} else {Immutable},
-                    expr: "".to_string(),
+                    expr: String::new(),
                 })
             }
             hir::ForeignItemKind::Type => {
@@ -3619,7 +3628,7 @@ fn to_src(&self, cx: &DocContext) -> String {
         debug!("converting span {:?} to snippet", self.clean(cx));
         let sn = match cx.sess().source_map().span_to_snippet(*self) {
             Ok(x) => x.to_string(),
-            Err(_) => "".to_string()
+            Err(_) => String::new()
         };
         debug!("got snippet {}", sn);
         sn
@@ -3700,12 +3709,12 @@ fn resolve_type(cx: &DocContext,
 
     let is_generic = match path.def {
         Def::PrimTy(p) => match p {
-            hir::TyStr => return Primitive(PrimitiveType::Str),
-            hir::TyBool => return Primitive(PrimitiveType::Bool),
-            hir::TyChar => return Primitive(PrimitiveType::Char),
-            hir::TyInt(int_ty) => return Primitive(int_ty.into()),
-            hir::TyUint(uint_ty) => return Primitive(uint_ty.into()),
-            hir::TyFloat(float_ty) => return Primitive(float_ty.into()),
+            hir::Str => return Primitive(PrimitiveType::Str),
+            hir::Bool => return Primitive(PrimitiveType::Bool),
+            hir::Char => return Primitive(PrimitiveType::Char),
+            hir::Int(int_ty) => return Primitive(int_ty.into()),
+            hir::Uint(uint_ty) => return Primitive(uint_ty.into()),
+            hir::Float(float_ty) => return Primitive(float_ty.into()),
         },
         Def::SelfTy(..) if path.segments.len() == 1 => {
             return Generic(keywords::SelfType.name().to_string());
@@ -3731,7 +3740,7 @@ pub fn register_def(cx: &DocContext, def: Def) -> DefId {
         Def::Struct(i) => (i, TypeKind::Struct),
         Def::Union(i) => (i, TypeKind::Union),
         Def::Mod(i) => (i, TypeKind::Module),
-        Def::TyForeign(i) => (i, TypeKind::Foreign),
+        Def::ForeignTy(i) => (i, TypeKind::Foreign),
         Def::Const(i) => (i, TypeKind::Const),
         Def::Static(i, _) => (i, TypeKind::Static),
         Def::Variant(i) => (cx.tcx.parent_def_id(i).expect("cannot get parent def id"),
@@ -3815,19 +3824,19 @@ fn clean(&self, _: &DocContext) -> Stability {
             feature: self.feature.to_string(),
             since: match self.level {
                 attr::Stable {ref since} => since.to_string(),
-                _ => "".to_string(),
+                _ => String::new(),
             },
             deprecated_since: match self.rustc_depr {
                 Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(),
-                _=> "".to_string(),
+                _=> String::new(),
             },
             deprecated_reason: match self.rustc_depr {
                 Some(ref depr) => depr.reason.to_string(),
-                _ => "".to_string(),
+                _ => String::new(),
             },
             unstable_reason: match self.level {
                 attr::Unstable { reason: Some(ref reason), .. } => reason.to_string(),
-                _ => "".to_string(),
+                _ => String::new(),
             },
             issue: match self.level {
                 attr::Unstable {issue, ..} => Some(issue),
@@ -3846,8 +3855,8 @@ fn clean(&self, dc: &DocContext) -> Stability {
 impl Clean<Deprecation> for attr::Deprecation {
     fn clean(&self, _: &DocContext) -> Deprecation {
         Deprecation {
-            since: self.since.as_ref().map_or("".to_string(), |s| s.to_string()),
-            note: self.note.as_ref().map_or("".to_string(), |s| s.to_string()),
+            since: self.since.as_ref().map_or(String::new(), |s| s.to_string()),
+            note: self.note.as_ref().map_or(String::new(), |s| s.to_string()),
         }
     }
 }
index 58034d1df5a1fa3f7051118c9b4ef3eb5a5fb4f2..7643aade83b7df8f48c99db21990565fefe27631 100644 (file)
@@ -620,7 +620,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
         clean::BorrowedRef{ lifetime: ref l, mutability, type_: ref ty} => {
             let lt = match *l {
                 Some(ref l) => format!("{} ", *l),
-                _ => "".to_string(),
+                _ => String::new(),
             };
             let m = MutableSpace(mutability);
             let amp = if f.alternate() {
index af7c0a04215c12f6356698aaef3029192f965ab5..582f31ce7c716620ff05e973024444984061ac2d 100644 (file)
@@ -156,13 +156,13 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
                 root_path = page.root_path,
                 suffix=page.resource_suffix)
     } else {
-        "".to_owned()
+        String::new()
     },
     content   = *t,
     root_path = page.root_path,
     css_class = page.css_class,
     logo      = if layout.logo.is_empty() {
-        "".to_string()
+        String::new()
     } else {
         format!("<a href='{}{}/index.html'>\
                  <img src='{}' alt='logo' width='100'></a>",
@@ -173,7 +173,7 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
     description = page.description,
     keywords = page.keywords,
     favicon   = if layout.favicon.is_empty() {
-        "".to_string()
+        String::new()
     } else {
         format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
     },
index c104b883340615d88948f4d1b48f464c42cd0abc..18ad862c11bb0915953059768629af09e8959ccb 100644 (file)
@@ -29,8 +29,9 @@
 
 #![allow(non_camel_case_types)]
 
+use rustc_data_structures::fx::FxHashMap;
 use std::cell::RefCell;
-use std::collections::{HashMap, VecDeque};
+use std::collections::VecDeque;
 use std::default::Default;
 use std::fmt::{self, Write};
 use std::borrow::Cow;
@@ -417,14 +418,14 @@ fn next(&mut self) -> Option<Self::Item> {
 /// references.
 struct Footnotes<'a, I: Iterator<Item = Event<'a>>> {
     inner: I,
-    footnotes: HashMap<String, (Vec<Event<'a>>, u16)>,
+    footnotes: FxHashMap<String, (Vec<Event<'a>>, u16)>,
 }
 
 impl<'a, I: Iterator<Item = Event<'a>>> Footnotes<'a, I> {
     fn new(iter: I) -> Self {
         Footnotes {
             inner: iter,
-            footnotes: HashMap::new(),
+            footnotes: FxHashMap::default(),
         }
     }
     fn get_entry(&mut self, key: &str) -> &mut (Vec<Event<'a>>, u16) {
@@ -865,7 +866,7 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
 
 #[derive(Default)]
 pub struct IdMap {
-    map: HashMap<String, usize>,
+    map: FxHashMap<String, usize>,
 }
 
 impl IdMap {
@@ -880,7 +881,7 @@ pub fn populate<I: IntoIterator<Item=String>>(&mut self, ids: I) {
     }
 
     pub fn reset(&mut self) {
-        self.map = HashMap::new();
+        self.map = FxHashMap::default();
     }
 
     pub fn derive(&mut self, candidate: String) -> String {
index 44a9710e30f7ddc257b606604a931b8e0806745c..368c056f021c135b359c70bc2ec00c9908bb79ca 100644 (file)
@@ -38,7 +38,7 @@
 use std::borrow::Cow;
 use std::cell::RefCell;
 use std::cmp::Ordering;
-use std::collections::{BTreeMap, HashSet, VecDeque};
+use std::collections::{BTreeMap, VecDeque};
 use std::default::Default;
 use std::error;
 use std::fmt::{self, Display, Formatter, Write as FmtWrite};
@@ -315,7 +315,7 @@ pub struct Cache {
     // the access levels from crateanalysis.
     pub access_levels: Arc<AccessLevels<DefId>>,
 
-    /// The version of the crate being documented, if given fron the `--crate-version` flag.
+    /// The version of the crate being documented, if given from the `--crate-version` flag.
     pub crate_version: Option<String>,
 
     // Private fields only used when initially crawling a crate to build a cache
@@ -479,6 +479,7 @@ pub fn initial_ids() -> Vec<String> {
 
 /// Generates the documentation for `crate` into the directory `dst`
 pub fn run(mut krate: clean::Crate,
+           extern_urls: BTreeMap<String, String>,
            external_html: &ExternalHtml,
            playground_url: Option<String>,
            dst: PathBuf,
@@ -504,8 +505,8 @@ pub fn run(mut krate: clean::Crate,
         local_sources: FxHashMap(),
         issue_tracker_base_url: None,
         layout: layout::Layout {
-            logo: "".to_string(),
-            favicon: "".to_string(),
+            logo: String::new(),
+            favicon: String::new(),
             external_html: external_html.clone(),
             krate: krate.name.clone(),
         },
@@ -611,8 +612,9 @@ pub fn run(mut krate: clean::Crate,
             },
             _ => PathBuf::new(),
         };
+        let extern_url = extern_urls.get(&e.name).map(|u| &**u);
         cache.extern_locations.insert(n, (e.name.clone(), src_root,
-                                          extern_location(e, &cx.dst)));
+                                          extern_location(e, extern_url, &cx.dst)));
 
         let did = DefId { krate: n, index: CRATE_DEF_INDEX };
         cache.external_paths.insert(did, (vec![e.name.to_string()], ItemType::Module));
@@ -741,7 +743,7 @@ fn write_shared(cx: &Context,
 
     // To avoid "light.css" to be overwritten, we'll first run over the received themes and only
     // then we'll run over the "official" styles.
-    let mut themes: HashSet<String> = HashSet::new();
+    let mut themes: FxHashSet<String> = FxHashSet::default();
 
     for entry in &cx.shared.themes {
         let mut content = Vec::with_capacity(100000);
@@ -1096,13 +1098,23 @@ fn clean_srcpath<F>(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) wh
 
 /// Attempts to find where an external crate is located, given that we're
 /// rendering in to the specified source destination.
-fn extern_location(e: &clean::ExternalCrate, dst: &Path) -> ExternalLocation {
+fn extern_location(e: &clean::ExternalCrate, extern_url: Option<&str>, dst: &Path)
+    -> ExternalLocation
+{
     // See if there's documentation generated into the local directory
     let local_location = dst.join(&e.name);
     if local_location.is_dir() {
         return Local;
     }
 
+    if let Some(url) = extern_url {
+        let mut url = url.to_string();
+        if !url.ends_with("/") {
+            url.push('/');
+        }
+        return Remote(url);
+    }
+
     // Failing that, see if there's an attribute specifying where to find this
     // external crate
     e.attrs.lists("doc")
@@ -1539,35 +1551,36 @@ fn cmp(&self, other: &ItemEntry) -> ::std::cmp::Ordering {
 
 #[derive(Debug)]
 struct AllTypes {
-    structs: HashSet<ItemEntry>,
-    enums: HashSet<ItemEntry>,
-    unions: HashSet<ItemEntry>,
-    primitives: HashSet<ItemEntry>,
-    traits: HashSet<ItemEntry>,
-    macros: HashSet<ItemEntry>,
-    functions: HashSet<ItemEntry>,
-    typedefs: HashSet<ItemEntry>,
-    existentials: HashSet<ItemEntry>,
-    statics: HashSet<ItemEntry>,
-    constants: HashSet<ItemEntry>,
-    keywords: HashSet<ItemEntry>,
+    structs: FxHashSet<ItemEntry>,
+    enums: FxHashSet<ItemEntry>,
+    unions: FxHashSet<ItemEntry>,
+    primitives: FxHashSet<ItemEntry>,
+    traits: FxHashSet<ItemEntry>,
+    macros: FxHashSet<ItemEntry>,
+    functions: FxHashSet<ItemEntry>,
+    typedefs: FxHashSet<ItemEntry>,
+    existentials: FxHashSet<ItemEntry>,
+    statics: FxHashSet<ItemEntry>,
+    constants: FxHashSet<ItemEntry>,
+    keywords: FxHashSet<ItemEntry>,
 }
 
 impl AllTypes {
     fn new() -> AllTypes {
+        let new_set = |cap| FxHashSet::with_capacity_and_hasher(cap, Default::default());
         AllTypes {
-            structs: HashSet::with_capacity(100),
-            enums: HashSet::with_capacity(100),
-            unions: HashSet::with_capacity(100),
-            primitives: HashSet::with_capacity(26),
-            traits: HashSet::with_capacity(100),
-            macros: HashSet::with_capacity(100),
-            functions: HashSet::with_capacity(100),
-            typedefs: HashSet::with_capacity(100),
-            existentials: HashSet::with_capacity(100),
-            statics: HashSet::with_capacity(100),
-            constants: HashSet::with_capacity(100),
-            keywords: HashSet::with_capacity(100),
+            structs: new_set(100),
+            enums: new_set(100),
+            unions: new_set(100),
+            primitives: new_set(26),
+            traits: new_set(100),
+            macros: new_set(100),
+            functions: new_set(100),
+            typedefs: new_set(100),
+            existentials: new_set(100),
+            statics: new_set(100),
+            constants: new_set(100),
+            keywords: new_set(100),
         }
     }
 
@@ -1595,7 +1608,7 @@ fn append(&mut self, item_name: String, item_type: &ItemType) {
     }
 }
 
-fn print_entries(f: &mut fmt::Formatter, e: &HashSet<ItemEntry>, title: &str,
+fn print_entries(f: &mut fmt::Formatter, e: &FxHashSet<ItemEntry>, title: &str,
                  class: &str) -> fmt::Result {
     if !e.is_empty() {
         let mut e: Vec<&ItemEntry> = e.iter().collect();
@@ -2183,7 +2196,7 @@ fn shorter<'a>(s: Option<&'a str>) -> String {
                 !chr.is_whitespace()
             })
         }).collect::<Vec<_>>().join("\n"),
-        None => "".to_string()
+        None => String::new()
     }
 }
 
@@ -2479,7 +2492,7 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: usize, idx2: usize) -> Ordering
                        stab_docs = stab_docs,
                        docs = MarkdownSummaryLine(doc_value, &myitem.links()),
                        class = myitem.type_(),
-                       stab = myitem.stability_class().unwrap_or("".to_string()),
+                       stab = myitem.stability_class().unwrap_or(String::new()),
                        unsafety_flag = unsafety_flag,
                        href = item_path(myitem.type_(), myitem.name.as_ref().unwrap()),
                        title_type = myitem.type_(),
@@ -2943,12 +2956,16 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
                 </h2>
             ")?;
 
+            let mut foreign_cache = FxHashSet();
             for implementor in foreign {
-                let assoc_link = AssocItemLink::GotoSource(
-                    implementor.impl_item.def_id, &implementor.inner_impl().provided_trait_methods
-                );
-                render_impl(w, cx, &implementor, assoc_link,
-                            RenderMode::Normal, implementor.impl_item.stable_since(), false)?;
+                if foreign_cache.insert(implementor.inner_impl().to_string()) {
+                    let assoc_link = AssocItemLink::GotoSource(
+                        implementor.impl_item.def_id,
+                        &implementor.inner_impl().provided_trait_methods
+                    );
+                    render_impl(w, cx, &implementor, assoc_link,
+                                RenderMode::Normal, implementor.impl_item.stable_since(), false)?;
+                }
             }
         }
 
@@ -4185,7 +4202,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
                 }
             }
             let format_impls = |impls: Vec<&Impl>| {
-                let mut links = HashSet::new();
+                let mut links = FxHashSet::default();
                 impls.iter()
                            .filter_map(|i| {
                                let is_negative_impl = is_negative_impl(i.inner_impl());
index b63abec1f0e8b0cc145e27a57bca142d257bddab..51ed62678292662fd4201c4e1ddcf630819c1c88 100644 (file)
@@ -52,6 +52,8 @@
 
     var themesWidth = null;
 
+    var titleBeforeSearch = document.title;
+
     if (!String.prototype.startsWith) {
         String.prototype.startsWith = function(searchString, position) {
             position = position || 0;
             }
         }
     }
+
+    function expandSection(id) {
+        var elem = document.getElementById(id);
+        if (elem && isHidden(elem)) {
+            var h3 = elem.parentNode.previousSibling;
+            if (h3 && h3.tagName !== 'H3') {
+                h3 = h3.previousSibling; // skip div.docblock
+            }
+
+            if (h3) {
+                var collapses = h3.getElementsByClassName("collapse-toggle");
+                if (collapses.length > 0) {
+                    // The element is not visible, we need to make it appear!
+                    collapseDocs(collapses[0], "show");
+                }
+            }
+        }
+    }
+
     highlightSourceLines(null);
     window.onhashchange = highlightSourceLines;
 
             ev.preventDefault();
             addClass(search, "hidden");
             removeClass(document.getElementById("main"), "hidden");
+            document.title = titleBeforeSearch;
         }
         defocusSearchBar();
     }
         }
     }
 
+    function findParentElement(elem, tagName) {
+        do {
+            if (elem && elem.tagName === tagName) {
+                return elem;
+            }
+        } while (elem = elem.parentNode);
+        return null;
+    }
+
     document.onkeypress = handleShortcut;
     document.onkeydown = handleShortcut;
     document.onclick = function(ev) {
         } else if (!hasClass(document.getElementById("help"), "hidden")) {
             addClass(document.getElementById("help"), "hidden");
             removeClass(document.body, "blur");
+        } else {
+            // Making a collapsed element visible on onhashchange seems
+            // too late
+            var a = findParentElement(ev.target, 'A');
+            if (a && a.hash) {
+                expandSection(a.hash.replace(/^#/, ''));
+            }
         }
     };
 
                 return literalSearch === true ? false : lev_distance;
             }
 
-            function checkPath(startsWith, lastElem, ty) {
-                if (startsWith.length === 0) {
+            function checkPath(contains, lastElem, ty) {
+                if (contains.length === 0) {
                     return 0;
                 }
                 var ret_lev = MAX_LEV_DISTANCE + 1;
                     path.push(ty.parent.name.toLowerCase());
                 }
 
-                if (startsWith.length > path.length) {
+                if (contains.length > path.length) {
                     return MAX_LEV_DISTANCE + 1;
                 }
                 for (var i = 0; i < path.length; ++i) {
-                    if (i + startsWith.length > path.length) {
+                    if (i + contains.length > path.length) {
                         break;
                     }
                     var lev_total = 0;
                     var aborted = false;
-                    for (var x = 0; x < startsWith.length; ++x) {
-                        var lev = levenshtein(path[i + x], startsWith[x]);
+                    for (var x = 0; x < contains.length; ++x) {
+                        var lev = levenshtein(path[i + x], contains[x]);
                         if (lev > MAX_LEV_DISTANCE) {
                             aborted = true;
                             break;
                         lev_total += lev;
                     }
                     if (aborted === false) {
-                        ret_lev = Math.min(ret_lev, Math.round(lev_total / startsWith.length));
+                        ret_lev = Math.min(ret_lev, Math.round(lev_total / contains.length));
                     }
                 }
                 return ret_lev;
                     }
                 }
                 val = paths[paths.length - 1];
-                var startsWith = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1);
+                var contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1);
 
                 for (j = 0; j < nSearchWords; ++j) {
                     var lev_distance;
                     }
                     var lev_add = 0;
                     if (paths.length > 1) {
-                        var lev = checkPath(startsWith, paths[paths.length - 1], ty);
+                        var lev = checkPath(contains, paths[paths.length - 1], ty);
                         if (lev > MAX_LEV_DISTANCE) {
                             continue;
                         } else if (lev > 0) {
                     }
 
                     lev += lev_add;
-                    if (lev > 0 && val.length > 3 && searchWords[j].startsWith(val)) {
+                    if (lev > 0 && val.length > 3 && searchWords[j].indexOf(val) > -1) {
                         if (val.length < 6) {
                             lev -= 1;
                         } else {
     autoCollapse(getPageId(), getCurrentValue("rustdoc-collapse") === "true");
 
     if (window.location.hash && window.location.hash.length > 0) {
-        var hash = getPageId();
-        if (hash !== null) {
-            var elem = document.getElementById(hash);
-            if (elem && elem.offsetParent === null) {
-                if (elem.parentNode && elem.parentNode.previousSibling) {
-                    var collapses = elem.parentNode
-                                        .previousSibling
-                                        .getElementsByClassName("collapse-toggle");
-                    if (collapses.length > 0) {
-                        // The element is not visible, we need to make it appear!
-                        collapseDocs(collapses[0], "show");
-                    }
-                }
-            }
-        }
+        expandSection(window.location.hash.replace(/^#/, ''));
     }
 }());
 
index 57a111daa897718b5920d831350a3a228f992716..5145e9f449b17571d8edc8cba762888379771b4b 100644 (file)
@@ -497,6 +497,27 @@ h4 > code, h3 > code, .invisible > code {
        font-size: 90%;
 }
 
+.content .stability {
+       position: relative;
+       margin-left: 33px;
+       margin-top: -13px;
+}
+
+.content .stability::before {
+       content: '˪';
+       font-size: 30px;
+       position: absolute;
+       top: -9px;
+       left: -13px;
+}
+.methods > .stability {
+       margin-top: -8px;
+}
+
+#main > .stability {
+       margin-top: 0;
+}
+
 nav {
        border-bottom: 1px solid;
        padding-bottom: 10px;
@@ -545,10 +566,8 @@ a {
        left: -5px;
 }
 .small-section-header > .anchor {
-       left: -20px;
-}
-.small-section-header > .anchor:not(.field) {
        left: -28px;
+       padding-right: 10px; /* avoid gap that causes hover to disappear */
 }
 .anchor:before {
        content: '\2002\00a7\2002';
@@ -745,6 +764,7 @@ a.test-arrow:hover{
 .section-header:hover a:before {
        position: absolute;
        left: -25px;
+       padding-right: 10px; /* avoid gap that causes hover to disappear */
        content: '\2002\00a7\2002';
 }
 
index 2ed7f7a926a4808a02843d7bbc87d6cff5073f7c..12d2208489368a52e7466c1f964990eebcdd2229 100644 (file)
@@ -407,3 +407,7 @@ kbd {
 .search-results td span.grey {
        color: #ccc;
 }
+
+.impl-items code {
+       background-color: rgba(0, 0, 0, 0);
+}
index f7cb51163ecfc2153f861b1e61aa3e1ad0ef8369..043d7ae23c2e4aaa6876541d41ce131b68316844 100644 (file)
@@ -401,3 +401,7 @@ kbd {
 .search-results td span.grey {
        color: #999;
 }
+
+.impl-items code {
+       background-color: rgba(0, 0, 0, 0);
+}
index a8ae6a94d5c4d329ebac5199dc239e346afd6cca..1acae86f0068f5f7ba61180eac9d9717791690ca 100644 (file)
@@ -16,8 +16,8 @@
 #![feature(rustc_private)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(iterator_find_map)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(set_stdio)]
 #![feature(slice_sort_by_cached_key)]
 #![feature(test)]
@@ -162,6 +162,10 @@ fn opts() -> Vec<RustcOptGroup> {
         stable("extern", |o| {
             o.optmulti("", "extern", "pass an --extern to rustc", "NAME=PATH")
         }),
+        unstable("extern-html-root-url", |o| {
+            o.optmulti("", "extern-html-root-url",
+                       "base URL to use for dependencies", "NAME=URL")
+        }),
         stable("plugin-path", |o| {
             o.optmulti("", "plugin-path", "removed", "DIR")
         }),
@@ -453,6 +457,13 @@ fn main_args(args: &[String]) -> isize {
             return 1;
         }
     };
+    let extern_urls = match parse_extern_html_roots(&matches) {
+        Ok(ex) => ex,
+        Err(err) => {
+            diag.struct_err(err).emit();
+            return 1;
+        }
+    };
 
     let test_args = matches.opt_strs("test-args");
     let test_args: Vec<String> = test_args.iter()
@@ -466,7 +477,8 @@ fn main_args(args: &[String]) -> isize {
 
     let output = matches.opt_str("o").map(|s| PathBuf::from(&s));
     let css_file_extension = matches.opt_str("e").map(|s| PathBuf::from(&s));
-    let cfgs = matches.opt_strs("cfg");
+    let mut cfgs = matches.opt_strs("cfg");
+    cfgs.push("rustdoc".to_string());
 
     if let Some(ref p) = css_file_extension {
         if !p.is_file() {
@@ -553,7 +565,7 @@ fn main_args(args: &[String]) -> isize {
         info!("going to format");
         match output_format.as_ref().map(|s| &**s) {
             Some("html") | None => {
-                html::render::run(krate, &external_html, playground_url,
+                html::render::run(krate, extern_urls, &external_html, playground_url,
                                   output.unwrap_or(PathBuf::from("doc")),
                                   resource_suffix.unwrap_or(String::new()),
                                   passes.into_iter().collect(),
@@ -612,6 +624,23 @@ fn parse_externs(matches: &getopts::Matches) -> Result<Externs, String> {
     Ok(Externs::new(externs))
 }
 
+/// Extracts `--extern-html-root-url` arguments from `matches` and returns a map of crate names to
+/// the given URLs. If an `--extern-html-root-url` argument was ill-formed, returns an error
+/// describing the issue.
+fn parse_extern_html_roots(matches: &getopts::Matches)
+    -> Result<BTreeMap<String, String>, &'static str>
+{
+    let mut externs = BTreeMap::new();
+    for arg in &matches.opt_strs("extern-html-root-url") {
+        let mut parts = arg.splitn(2, '=');
+        let name = parts.next().ok_or("--extern-html-root-url must not be empty")?;
+        let url = parts.next().ok_or("--extern-html-root-url must be of the form name=url")?;
+        externs.insert(name.to_string(), url.to_string());
+    }
+
+    Ok(externs)
+}
+
 /// Interprets the input file as a rust source file, passing it through the
 /// compiler all the way through the analysis passes. The rustdoc output is then
 /// generated from the cleaned AST of the crate.
@@ -643,7 +672,8 @@ fn rust_input<R, F>(cratefile: PathBuf,
     for s in &matches.opt_strs("L") {
         paths.add_path(s, ErrorOutputType::default());
     }
-    let cfgs = matches.opt_strs("cfg");
+    let mut cfgs = matches.opt_strs("cfg");
+    cfgs.push("rustdoc".to_string());
     let triple = matches.opt_str("target").map(|target| {
         if target.ends_with(".json") {
             TargetTriple::TargetPath(PathBuf::from(target))
index 28d504c2ee0c8b259094dfcf29402476422d5599..cced30d1a0c205fc0fe19d6e73f6fb68d07f6a10 100644 (file)
@@ -149,7 +149,7 @@ fn resolve(&self, path_str: &str, is_val: bool, current_item: &Option<String>)
                         Ok((ty.def, Some(format!("{}.{}", out, item_name))))
                     } else {
                         match cx.tcx.type_of(did).sty {
-                            ty::TyAdt(def, _) => {
+                            ty::Adt(def, _) => {
                                 if let Some(item) = if def.is_enum() {
                                     def.all_fields().find(|item| item.ident.name == item_name)
                                 } else {
@@ -403,9 +403,7 @@ fn macro_resolve(cx: &DocContext, path_str: &str) -> Option<Def> {
     let path = ast::Path { segments: vec![segment], span: DUMMY_SP };
     let mut resolver = cx.resolver.borrow_mut();
     let mark = Mark::root();
-    let res = resolver
-        .resolve_macro_to_def_inner(mark, &path, MacroKind::Bang, false);
-    if let Ok(def) = res {
+    if let Ok(def) = resolver.resolve_macro_to_def_inner(&path, MacroKind::Bang, mark, &[], false) {
         if let SyntaxExtension::DeclMacro { .. } = *resolver.get_macro(def) {
             return Some(def);
         }
@@ -569,23 +567,23 @@ fn handle_variant(cx: &DocContext, def: Def) -> Result<(Def, Option<String>), ()
 }
 
 const PRIMITIVES: &[(&str, Def)] = &[
-    ("u8",    Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U8))),
-    ("u16",   Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U16))),
-    ("u32",   Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U32))),
-    ("u64",   Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U64))),
-    ("u128",  Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U128))),
-    ("usize", Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::Usize))),
-    ("i8",    Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I8))),
-    ("i16",   Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I16))),
-    ("i32",   Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I32))),
-    ("i64",   Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I64))),
-    ("i128",  Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I128))),
-    ("isize", Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::Isize))),
-    ("f32",   Def::PrimTy(hir::PrimTy::TyFloat(syntax::ast::FloatTy::F32))),
-    ("f64",   Def::PrimTy(hir::PrimTy::TyFloat(syntax::ast::FloatTy::F64))),
-    ("str",   Def::PrimTy(hir::PrimTy::TyStr)),
-    ("bool",  Def::PrimTy(hir::PrimTy::TyBool)),
-    ("char",  Def::PrimTy(hir::PrimTy::TyChar)),
+    ("u8",    Def::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::U8))),
+    ("u16",   Def::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::U16))),
+    ("u32",   Def::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::U32))),
+    ("u64",   Def::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::U64))),
+    ("u128",  Def::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::U128))),
+    ("usize", Def::PrimTy(hir::PrimTy::Uint(syntax::ast::UintTy::Usize))),
+    ("i8",    Def::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::I8))),
+    ("i16",   Def::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::I16))),
+    ("i32",   Def::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::I32))),
+    ("i64",   Def::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::I64))),
+    ("i128",  Def::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::I128))),
+    ("isize", Def::PrimTy(hir::PrimTy::Int(syntax::ast::IntTy::Isize))),
+    ("f32",   Def::PrimTy(hir::PrimTy::Float(syntax::ast::FloatTy::F32))),
+    ("f64",   Def::PrimTy(hir::PrimTy::Float(syntax::ast::FloatTy::F64))),
+    ("str",   Def::PrimTy(hir::PrimTy::Str)),
+    ("bool",  Def::PrimTy(hir::PrimTy::Bool)),
+    ("char",  Def::PrimTy(hir::PrimTy::Char)),
 ];
 
 fn is_primitive(path_str: &str, is_val: bool) -> Option<Def> {
index 96a67e078875800bbc06e84183ee88a242a4b7d5..73cc363009de5992063af609be74e7d6a97f51b7 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::HashSet;
+use rustc_data_structures::fx::FxHashSet;
 use std::fs::File;
 use std::hash::{Hash, Hasher};
 use std::io::Read;
@@ -31,7 +31,7 @@ macro_rules! try_something {
 #[derive(Debug, Clone, Eq)]
 pub struct CssPath {
     pub name: String,
-    pub children: HashSet<CssPath>,
+    pub children: FxHashSet<CssPath>,
 }
 
 // This PartialEq implementation IS NOT COMMUTATIVE!!!
@@ -66,7 +66,7 @@ impl CssPath {
     fn new(name: String) -> CssPath {
         CssPath {
             name,
-            children: HashSet::new(),
+            children: FxHashSet::default(),
         }
     }
 }
@@ -211,7 +211,7 @@ fn build_rule(v: &[u8], positions: &[usize]) -> String {
              .join(" ")
 }
 
-fn inner(v: &[u8], events: &[Events], pos: &mut usize) -> HashSet<CssPath> {
+fn inner(v: &[u8], events: &[Events], pos: &mut usize) -> FxHashSet<CssPath> {
     let mut paths = Vec::with_capacity(50);
 
     while *pos < events.len() {
index 68ddf72da0617bb4d9011c11425dd67ce7abb68d..451e24d6c0dc938ecf90a79c4bdb6462a388ba23 100644 (file)
@@ -18,7 +18,7 @@
 use syntax::source_map::Spanned;
 use syntax_pos::{self, Span};
 
-use rustc::hir::map as hir_map;
+use rustc::hir::Node;
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::middle::privacy::AccessLevel;
@@ -267,7 +267,7 @@ fn inherits_doc_hidden(cx: &core::DocContext, mut node: ast::NodeId) -> bool {
                 Def::Struct(did) |
                 Def::Union(did) |
                 Def::Enum(did) |
-                Def::TyForeign(did) |
+                Def::ForeignTy(did) |
                 Def::TyAlias(did) if !self_is_hidden => {
                     self.cx.access_levels.borrow_mut().map.insert(did, AccessLevel::Public);
                 },
@@ -295,7 +295,7 @@ fn inherits_doc_hidden(cx: &core::DocContext, mut node: ast::NodeId) -> bool {
         if !self.view_item_stack.insert(def_node_id) { return false }
 
         let ret = match tcx.hir.get(def_node_id) {
-            hir_map::NodeItem(&hir::Item { node: hir::ItemKind::Mod(ref m), .. }) if glob => {
+            Node::Item(&hir::Item { node: hir::ItemKind::Mod(ref m), .. }) if glob => {
                 let prev = mem::replace(&mut self.inlining, true);
                 for i in &m.item_ids {
                     let i = self.cx.tcx.hir.expect_item(i.id);
@@ -304,13 +304,13 @@ fn inherits_doc_hidden(cx: &core::DocContext, mut node: ast::NodeId) -> bool {
                 self.inlining = prev;
                 true
             }
-            hir_map::NodeItem(it) if !glob => {
+            Node::Item(it) if !glob => {
                 let prev = mem::replace(&mut self.inlining, true);
                 self.visit_item(it, renamed, om);
                 self.inlining = prev;
                 true
             }
-            hir_map::NodeForeignItem(it) if !glob => {
+            Node::ForeignItem(it) if !glob => {
                 // generate a fresh `extern {}` block if we want to inline a foreign item.
                 om.foreigns.push(hir::ForeignMod {
                     abi: tcx.hir.get_foreign_abi(it.id),
index a896c4a634c3660fef9501949ca8178114ae9274..66140d9c01f82b860e9e494d6a748c6c19edf3d3 100644 (file)
@@ -7,3 +7,6 @@ version = "0.0.0"
 name = "serialize"
 path = "lib.rs"
 crate-type = ["dylib", "rlib"]
+
+[dependencies]
+smallvec = { version = "0.6.5", features = ["union"] }
index da705081ff34d20f6c011af30df358cca2b1f316..3e028d755c6d4a5dd89634954b8ad836bc1baa16 100644 (file)
 use std::rc::Rc;
 use std::sync::Arc;
 
-impl<
-    T: Encodable
-> Encodable for LinkedList<T> {
+use smallvec::{Array, SmallVec};
+
+impl<A> Encodable for SmallVec<A>
+    where A: Array,
+          A::Item: Encodable
+{
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_seq(self.len(), |s| {
+            for (i, e) in self.iter().enumerate() {
+                s.emit_seq_elt(i, |s| e.encode(s))?;
+            }
+            Ok(())
+        })
+    }
+}
+
+impl<A> Decodable for SmallVec<A>
+    where A: Array,
+          A::Item: Decodable
+{
+    fn decode<D: Decoder>(d: &mut D) -> Result<SmallVec<A>, D::Error> {
+        d.read_seq(|d, len| {
+            let mut vec = SmallVec::with_capacity(len);
+            // FIXME(#48994) - could just be collected into a Result<SmallVec, D::Error>
+            for i in 0..len {
+                vec.push(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            }
+            Ok(vec)
+        })
+    }
+}
+
+impl<T: Encodable> Encodable for LinkedList<T> {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
@@ -65,10 +95,10 @@ fn decode<D: Decoder>(d: &mut D) -> Result<VecDeque<T>, D::Error> {
     }
 }
 
-impl<
-    K: Encodable + PartialEq + Ord,
-    V: Encodable
-> Encodable for BTreeMap<K, V> {
+impl<K, V> Encodable for BTreeMap<K, V>
+    where K: Encodable + PartialEq + Ord,
+          V: Encodable
+{
     fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
         e.emit_map(self.len(), |e| {
             let mut i = 0;
@@ -82,10 +112,10 @@ fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<
-    K: Decodable + PartialEq + Ord,
-    V: Decodable
-> Decodable for BTreeMap<K, V> {
+impl<K, V> Decodable for BTreeMap<K, V>
+    where K: Decodable + PartialEq + Ord,
+          V: Decodable
+{
     fn decode<D: Decoder>(d: &mut D) -> Result<BTreeMap<K, V>, D::Error> {
         d.read_map(|d, len| {
             let mut map = BTreeMap::new();
@@ -99,9 +129,9 @@ fn decode<D: Decoder>(d: &mut D) -> Result<BTreeMap<K, V>, D::Error> {
     }
 }
 
-impl<
-    T: Encodable + PartialEq + Ord
-> Encodable for BTreeSet<T> {
+impl<T> Encodable for BTreeSet<T>
+    where T: Encodable + PartialEq + Ord
+{
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             let mut i = 0;
@@ -114,9 +144,9 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<
-    T: Decodable + PartialEq + Ord
-> Decodable for BTreeSet<T> {
+impl<T> Decodable for BTreeSet<T>
+    where T: Decodable + PartialEq + Ord
+{
     fn decode<D: Decoder>(d: &mut D) -> Result<BTreeSet<T>, D::Error> {
         d.read_seq(|d, len| {
             let mut set = BTreeSet::new();
index eee95d9fa67774406bb3569ab95fb9a0a8672621..e02bc5e1025fd6d9ceffaaff3aaa4d0101ea27b3 100644 (file)
@@ -118,6 +118,7 @@ pub fn write_signed_leb128_to<W>(mut value: i128, mut write: W)
     }
 }
 
+#[inline]
 pub fn write_signed_leb128(out: &mut Vec<u8>, value: i128) {
     write_signed_leb128_to(value, |v| write_to_vec(out, v))
 }
index 794fc095096a479c754f07e26562fc8ae6989ca7..e87c2793ee86701ab2d5b88d2a3bf9e2f6ad07e6 100644 (file)
@@ -25,6 +25,7 @@
 #![feature(specialization)]
 #![feature(never_type)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![cfg_attr(test, feature(test))]
 
 pub use self::serialize::{Decoder, Encoder, Decodable, Encodable};
@@ -32,6 +33,8 @@
 pub use self::serialize::{SpecializationError, SpecializedEncoder, SpecializedDecoder};
 pub use self::serialize::{UseSpecializedEncodable, UseSpecializedDecodable};
 
+extern crate smallvec;
+
 mod serialize;
 mod collection_impls;
 
index a77d1d9b88b89a0e048c6f8123de8386ef727a98..c71f474891131dede6617e443b15b3efd4da1e17 100644 (file)
@@ -31,6 +31,7 @@ pub fn into_inner(self) -> Vec<u8> {
         self.data
     }
 
+    #[inline]
     pub fn emit_raw_bytes(&mut self, s: &[u8]) {
         self.data.extend_from_slice(s);
     }
@@ -193,6 +194,7 @@ pub fn advance(&mut self, bytes: usize) {
         self.position += bytes;
     }
 
+    #[inline]
     pub fn read_raw_bytes(&mut self, s: &mut [u8]) -> Result<(), String> {
         let start = self.position;
         let end = start + s.len();
@@ -326,6 +328,7 @@ fn read_str(&mut self) -> Result<Cow<str>, Self::Error> {
         Ok(Cow::Borrowed(s))
     }
 
+    #[inline]
     fn error(&mut self, err: &str) -> Self::Error {
         err.to_string()
     }
index ed94194ffcc05be5411eb9ca3cd5fb397e4f8fab..60bb5a0fec2cdba8f5b8822af8631cd5f6113205 100644 (file)
@@ -119,6 +119,7 @@ fn emit_option<F>(&mut self, f: F) -> Result<(), Self::Error>
         self.emit_enum("Option", f)
     }
 
+    #[inline]
     fn emit_option_none(&mut self) -> Result<(), Self::Error> {
         self.emit_enum_variant("None", 0, 0, |_| Ok(()))
     }
@@ -560,14 +561,12 @@ fn decode<D: Decoder>(d: &mut D) -> Result<Box<[T]>, D::Error> {
 }
 
 impl<T:Encodable> Encodable for Rc<T> {
-    #[inline]
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         (**self).encode(s)
     }
 }
 
 impl<T:Decodable> Decodable for Rc<T> {
-    #[inline]
     fn decode<D: Decoder>(d: &mut D) -> Result<Rc<T>, D::Error> {
         Ok(Rc::new(Decodable::decode(d)?))
     }
@@ -618,7 +617,9 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<T:Decodable+ToOwned> Decodable for Cow<'static, [T]> where [T]: ToOwned<Owned = Vec<T>> {
+impl<T:Decodable+ToOwned> Decodable for Cow<'static, [T]>
+    where [T]: ToOwned<Owned = Vec<T>>
+{
     fn decode<D: Decoder>(d: &mut D) -> Result<Cow<'static, [T]>, D::Error> {
         d.read_seq(|d, len| {
             let mut v = Vec::with_capacity(len);
index b9aba1e9cab321d979430c921d3960cfacf38ac3..6753ed4a3df6d03d50287427d2aa4a485884d40e 100644 (file)
@@ -150,23 +150,23 @@ pub mod __default_lib_allocator {
     // linkage directives are provided as part of the current compiler allocator
     // ABI
 
-    #[no_mangle]
     #[rustc_std_internal_symbol]
+    #[cfg_attr(stage0, no_mangle)]
     pub unsafe extern fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
         let layout = Layout::from_size_align_unchecked(size, align);
         System.alloc(layout)
     }
 
-    #[no_mangle]
     #[rustc_std_internal_symbol]
+    #[cfg_attr(stage0, no_mangle)]
     pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
                                        size: usize,
                                        align: usize) {
         System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
     }
 
-    #[no_mangle]
     #[rustc_std_internal_symbol]
+    #[cfg_attr(stage0, no_mangle)]
     pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
                                        old_size: usize,
                                        align: usize,
@@ -175,8 +175,8 @@ pub mod __default_lib_allocator {
         System.realloc(ptr, old_layout, new_size)
     }
 
-    #[no_mangle]
     #[rustc_std_internal_symbol]
+    #[cfg_attr(stage0, no_mangle)]
     pub unsafe extern fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
         let layout = Layout::from_size_align_unchecked(size, align);
         System.alloc_zeroed(layout)
index 2b319186a8db2ffdb9b997ccdc54140e319e861f..768357ec8dc417e7ea1fedfa4e522dbc2a480009 100644 (file)
@@ -234,10 +234,10 @@ fn can_alias_safehash_as_hash() {
 // make a RawBucket point to invalid memory using safe code.
 impl<K, V> RawBucket<K, V> {
     unsafe fn hash(&self) -> *mut HashUint {
-        self.hash_start.offset(self.idx as isize)
+        self.hash_start.add(self.idx)
     }
     unsafe fn pair(&self) -> *mut (K, V) {
-        self.pair_start.offset(self.idx as isize) as *mut (K, V)
+        self.pair_start.add(self.idx) as *mut (K, V)
     }
     unsafe fn hash_pair(&self) -> (*mut HashUint, *mut (K, V)) {
         (self.hash(), self.pair())
index 29534696abc5be232de994c97448fe71c6e3b398..3de4a1bd4170b62a454a5091fe05a6e4cdec29ed 100644 (file)
@@ -138,7 +138,72 @@ fn description(&self) -> &str {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn cause(&self) -> Option<&dyn Error> { None }
+    #[rustc_deprecated(since = "1.33.0", reason = "replaced by Error::source, which can support \
+                                                   downcasting")]
+    fn cause(&self) -> Option<&dyn Error> {
+        self.source()
+    }
+
+    /// The lower-level source of this error, if any.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::fmt;
+    ///
+    /// #[derive(Debug)]
+    /// struct SuperError {
+    ///     side: SuperErrorSideKick,
+    /// }
+    ///
+    /// impl fmt::Display for SuperError {
+    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///         write!(f, "SuperError is here!")
+    ///     }
+    /// }
+    ///
+    /// impl Error for SuperError {
+    ///     fn description(&self) -> &str {
+    ///         "I'm the superhero of errors"
+    ///     }
+    ///
+    ///     fn source(&self) -> Option<&(dyn Error + 'static)> {
+    ///         Some(&self.side)
+    ///     }
+    /// }
+    ///
+    /// #[derive(Debug)]
+    /// struct SuperErrorSideKick;
+    ///
+    /// impl fmt::Display for SuperErrorSideKick {
+    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///         write!(f, "SuperErrorSideKick is here!")
+    ///     }
+    /// }
+    ///
+    /// impl Error for SuperErrorSideKick {
+    ///     fn description(&self) -> &str {
+    ///         "I'm SuperError side kick"
+    ///     }
+    /// }
+    ///
+    /// fn get_super_error() -> Result<(), SuperError> {
+    ///     Err(SuperError { side: SuperErrorSideKick })
+    /// }
+    ///
+    /// fn main() {
+    ///     match get_super_error() {
+    ///         Err(e) => {
+    ///             println!("Error: {}", e.description());
+    ///             println!("Caused by: {}", e.source().unwrap());
+    ///         }
+    ///         _ => println!("No error"),
+    ///     }
+    /// }
+    /// ```
+    #[stable(feature = "error_source", since = "1.30.0")]
+    fn source(&self) -> Option<&(dyn Error + 'static)> { None }
 
     /// Get the `TypeId` of `self`
     #[doc(hidden)]
index 12ea1ea9f9d49cc56a0ef0c4b3890647cd6a5013..d9657f691c79fdc59a4b07445cd3c79876494423 100644 (file)
@@ -12,7 +12,7 @@
 
 use core::cell::Cell;
 use core::marker::Unpin;
-use core::mem::PinMut;
+use core::pin::PinMut;
 use core::option::Option;
 use core::ptr::NonNull;
 use core::task::{self, Poll};
@@ -88,7 +88,7 @@ pub fn set_task_cx<F, R>(cx: &mut task::Context, f: F) -> R
 /// This function acquires exclusive access to the task context.
 ///
 /// Panics if no task has been set or if the task context has already been
-/// retrived by a surrounding call to get_task_cx.
+/// retrieved by a surrounding call to get_task_cx.
 pub fn get_task_cx<F, R>(f: F) -> R
 where
     F: FnOnce(&mut task::Context) -> R
index 03c97de6ec1e9b8418c9da79ded78dca8777d2d0..77bc7e946eb41bfd4419ec704c1859c14eced5b8 100644 (file)
@@ -889,7 +889,7 @@ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
 
         // 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.
+        // otherwise 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),
index 4fb367fb6ba524147e9a1806d02eab4759a8d0b6..24965ff69318435e874eaad52f9dc8a1b58edcc3 100644 (file)
@@ -18,7 +18,6 @@ pub struct Lazy<T> {
     // We never call `lock.init()`, so it is UB to attempt to acquire this mutex reentrantly!
     lock: Mutex,
     ptr: Cell<*mut Arc<T>>,
-    init: fn() -> Arc<T>,
 }
 
 #[inline]
@@ -26,33 +25,32 @@ const fn done<T>() -> *mut Arc<T> { 1_usize as *mut _ }
 
 unsafe impl<T> Sync for Lazy<T> {}
 
-impl<T: Send + Sync + 'static> Lazy<T> {
-    /// Safety: `init` must not call `get` on the variable that is being
-    /// initialized.
-    pub const unsafe fn new(init: fn() -> Arc<T>) -> Lazy<T> {
+impl<T> Lazy<T> {
+    pub const fn new() -> Lazy<T> {
         Lazy {
             lock: Mutex::new(),
             ptr: Cell::new(ptr::null_mut()),
-            init,
         }
     }
+}
 
-    pub fn get(&'static self) -> Option<Arc<T>> {
-        unsafe {
-            let _guard = self.lock.lock();
-            let ptr = self.ptr.get();
-            if ptr.is_null() {
-                Some(self.init())
-            } else if ptr == done() {
-                None
-            } else {
-                Some((*ptr).clone())
-            }
+impl<T: Send + Sync + 'static> Lazy<T> {
+    /// Safety: `init` must not call `get` on the variable that is being
+    /// initialized.
+    pub unsafe fn get(&'static self, init: fn() -> Arc<T>) -> Option<Arc<T>> {
+        let _guard = self.lock.lock();
+        let ptr = self.ptr.get();
+        if ptr.is_null() {
+            Some(self.init(init))
+        } else if ptr == done() {
+            None
+        } else {
+            Some((*ptr).clone())
         }
     }
 
     // Must only be called with `lock` held
-    unsafe fn init(&'static self) -> Arc<T> {
+    unsafe fn init(&'static self, init: fn() -> Arc<T>) -> Arc<T> {
         // If we successfully register an at exit handler, then we cache the
         // `Arc` allocation in our own internal box (it will get deallocated by
         // the at exit handler). Otherwise we just return the freshly allocated
@@ -66,8 +64,8 @@ unsafe fn init(&'static self) -> Arc<T> {
         });
         // This could reentrantly call `init` again, which is a problem
         // because our `lock` allows reentrancy!
-        // That's why `new` is unsafe and requires the caller to ensure no reentrancy happens.
-        let ret = (self.init)();
+        // That's why `get` is unsafe and requires the caller to ensure no reentrancy happens.
+        let ret = init();
         if registered.is_ok() {
             self.ptr.set(Box::into_raw(Box::new(ret.clone())));
         }
index 1f256f518c7ce083585f57b74ddccbfb95912b04..a413432cdaabc6ba2b0075a2e10e161379ec7578 100644 (file)
@@ -197,9 +197,11 @@ pub struct StdinLock<'a> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdin() -> Stdin {
-    static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = unsafe { Lazy::new(stdin_init) };
+    static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new();
     return Stdin {
-        inner: INSTANCE.get().expect("cannot access stdin during shutdown"),
+        inner: unsafe {
+            INSTANCE.get(stdin_init).expect("cannot access stdin during shutdown")
+        },
     };
 
     fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> {
@@ -396,10 +398,11 @@ pub struct StdoutLock<'a> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdout() -> Stdout {
-    static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>
-        = unsafe { Lazy::new(stdout_init) };
+    static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> = Lazy::new();
     return Stdout {
-        inner: INSTANCE.get().expect("cannot access stdout during shutdown"),
+        inner: unsafe {
+            INSTANCE.get(stdout_init).expect("cannot access stdout during shutdown")
+        },
     };
 
     fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> {
@@ -533,10 +536,11 @@ pub struct StderrLock<'a> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stderr() -> Stderr {
-    static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> =
-        unsafe { Lazy::new(stderr_init) };
+    static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = Lazy::new();
     return Stderr {
-        inner: INSTANCE.get().expect("cannot access stderr during shutdown"),
+        inner: unsafe {
+            INSTANCE.get(stderr_init).expect("cannot access stderr during shutdown")
+        },
     };
 
     fn stderr_init() -> Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> {
index 4f6bda6cfe3798337bcf44c79f9b4fba54208684..d70cf132b3c3a83df35cf295df7bc68736429bd2 100644 (file)
@@ -56,3 +56,24 @@ mod fn_keyword { }
 ///
 /// [book]: https://doc.rust-lang.org/book/second-edition/ch03-01-variables-and-mutability.html
 mod let_keyword { }
+
+#[doc(keyword = "struct")]
+//
+/// The `struct` keyword.
+///
+/// The `struct` keyword is used to define a struct type.
+///
+/// Example:
+///
+/// ```
+/// struct Foo {
+///     field1: u32,
+///     field2: String,
+/// }
+/// ```
+///
+/// There are different kinds of structs. For more information, take a look at the
+/// [Rust Book][book].
+///
+/// [book]: https://doc.rust-lang.org/book/second-edition/ch05-01-defining-structs.html
+mod struct_keyword { }
index b0069f826eefa68bb5b468ea41e1aae13912d71e..e7195b3e21ee37c4ca3c60db1574bbd9be82ff57 100644 (file)
 #![feature(arbitrary_self_types)]
 #![feature(array_error_internals)]
 #![feature(asm)]
-#![feature(attr_literals)]
 #![feature(box_syntax)]
 #![feature(cfg_target_has_atomic)]
 #![feature(cfg_target_thread_local)]
 #![feature(cfg_target_vendor)]
 #![feature(char_error_internals)]
 #![feature(compiler_builtins_lib)]
-#![feature(const_fn)]
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(min_const_fn))]
 #![feature(const_int_ops)]
 #![feature(const_ip)]
 #![feature(core_intrinsics)]
 #![feature(libc)]
 #![feature(link_args)]
 #![feature(linkage)]
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 #![feature(needs_panic_runtime)]
 #![feature(never_type)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(exhaustive_patterns)]
 #![feature(on_unimplemented)]
 #![feature(optin_builtin_traits)]
 #![feature(doc_alias)]
 #![feature(doc_keyword)]
 #![feature(panic_info_message)]
-#![feature(panic_implementation)]
+#![cfg_attr(stage0, feature(panic_implementation))]
+#![cfg_attr(not(stage0), feature(panic_handler))]
 #![feature(non_exhaustive)]
 
 #![default_lib_allocator]
 pub use alloc_crate::fmt;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use alloc_crate::format;
+#[unstable(feature = "pin", issue = "49150")]
+pub use alloc_crate::pin;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use alloc_crate::slice;
 #[stable(feature = "rust1", since = "1.0.0")]
index f15494c5fd7f59beeab250014135eeb81f1ef5da..b649ec2340e93df33e87121b1143dff8c780e840 100644 (file)
@@ -230,7 +230,7 @@ macro_rules! await {
         loop {
             if let $crate::task::Poll::Ready(x) =
                 $crate::future::poll_in_task_cx(unsafe {
-                    $crate::mem::PinMut::new_unchecked(&mut pinned)
+                    $crate::pin::PinMut::new_unchecked(&mut pinned)
                 })
             {
                 break x;
@@ -309,7 +309,7 @@ macro_rules! assert_approx_eq {
 /// These macros do not have any corresponding definition with a `macro_rules!`
 /// macro, but are documented here. Their implementations can be found hardcoded
 /// into libsyntax itself.
-#[cfg(dox)]
+#[cfg(rustdoc)]
 mod builtin {
 
     /// Unconditionally causes compilation to fail with the given error message when encountered.
index 240e82069ff4d64fbb0c72a33eb7a2fdd49d7672..c28f3da98cea95952d5d94c7cf2a6ba1d1e2c9c7 100644 (file)
@@ -57,7 +57,7 @@ pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
 
 #[cfg(test)]
 mod tests {
-    // test the implementations for the current plattform
+    // test the implementations for the current platform
     use super::{memchr, memrchr};
 
     #[test]
index 9a610cd7d6ba3978df157f3209a7d5d98d865ff1..d45a66ef6653257455594c7239fe002bc91acbb9 100644 (file)
@@ -357,15 +357,12 @@ pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
     /// # Examples
     ///
     /// ```
-    /// #![feature(ip_constructors)]
     /// use std::net::Ipv4Addr;
     ///
     /// let addr = Ipv4Addr::LOCALHOST;
     /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1));
     /// ```
-    #[unstable(feature = "ip_constructors",
-               reason = "requires greater scrutiny before stabilization",
-               issue = "44582")]
+    #[stable(feature = "ip_constructors", since = "1.30.0")]
     pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
 
     /// An IPv4 address representing an unspecified address: 0.0.0.0
@@ -373,15 +370,12 @@ pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
     /// # Examples
     ///
     /// ```
-    /// #![feature(ip_constructors)]
     /// use std::net::Ipv4Addr;
     ///
     /// let addr = Ipv4Addr::UNSPECIFIED;
     /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0));
     /// ```
-    #[unstable(feature = "ip_constructors",
-               reason = "requires greater scrutiny before stabilization",
-               issue = "44582")]
+    #[stable(feature = "ip_constructors", since = "1.30.0")]
     pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
 
     /// An IPv4 address representing the broadcast address: 255.255.255.255
@@ -389,15 +383,12 @@ pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
     /// # Examples
     ///
     /// ```
-    /// #![feature(ip_constructors)]
     /// use std::net::Ipv4Addr;
     ///
     /// let addr = Ipv4Addr::BROADCAST;
     /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255));
     /// ```
-    #[unstable(feature = "ip_constructors",
-               reason = "requires greater scrutiny before stabilization",
-               issue = "44582")]
+    #[stable(feature = "ip_constructors", since = "1.30.0")]
     pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
 
     /// Returns the four eight-bit integers that make up this address.
@@ -896,15 +887,12 @@ pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16,
     /// # Examples
     ///
     /// ```
-    /// #![feature(ip_constructors)]
     /// use std::net::Ipv6Addr;
     ///
     /// let addr = Ipv6Addr::LOCALHOST;
     /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
     /// ```
-    #[unstable(feature = "ip_constructors",
-               reason = "requires greater scrutiny before stabilization",
-               issue = "44582")]
+    #[stable(feature = "ip_constructors", since = "1.30.0")]
     pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
 
     /// An IPv6 address representing the unspecified address: `::`
@@ -912,15 +900,12 @@ pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16,
     /// # Examples
     ///
     /// ```
-    /// #![feature(ip_constructors)]
     /// use std::net::Ipv6Addr;
     ///
     /// let addr = Ipv6Addr::UNSPECIFIED;
     /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
     /// ```
-    #[unstable(feature = "ip_constructors",
-               reason = "requires greater scrutiny before stabilization",
-               issue = "44582")]
+    #[stable(feature = "ip_constructors", since = "1.30.0")]
     pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
 
     /// Returns the eight 16-bit segments that make up this address.
index c384ec9168ac4428889fd2ea5df4760f3f1ddd65..1cb9799ff3c22562bcdbcf6b23318c725ac17472 100644 (file)
 //! OS-specific functionality.
 
 #![stable(feature = "os", since = "1.0.0")]
-#![allow(missing_docs, bad_style, missing_debug_implementations)]
+#![allow(missing_docs, nonstandard_style, missing_debug_implementations)]
 
 cfg_if! {
-    if #[cfg(dox)] {
+    if #[cfg(rustdoc)] {
 
         // When documenting libstd we want to show unix/windows/linux modules as
         // these are the "main modules" that are used across platforms. This
index b8c1c4f9e68e7602ad5ab3b78679abf3f84e7988..47547aedcbdec8e0269d5a5d716ef7f1f475f911 100644 (file)
@@ -16,7 +16,7 @@
 use cell::UnsafeCell;
 use fmt;
 use future::Future;
-use mem::PinMut;
+use pin::PinMut;
 use ops::{Deref, DerefMut};
 use panicking;
 use ptr::{Unique, NonNull};
index 283fd36af41ff4976ca69b7896856a157492077b..6eb2db8e63bfed7567ad11a842c4d13fde6292fa 100644 (file)
@@ -319,7 +319,8 @@ pub fn panicking() -> bool {
 
 /// Entry point of panic from the libcore crate.
 #[cfg(not(test))]
-#[panic_implementation]
+#[cfg_attr(stage0, panic_implementation)]
+#[cfg_attr(not(stage0), panic_handler)]
 #[unwind(allowed)]
 pub fn rust_begin_panic(info: &PanicInfo) -> ! {
     continue_panic_fmt(&info)
@@ -397,6 +398,7 @@ fn get(&mut self) -> &(dyn Any + Send) {
 #[unstable(feature = "libstd_sys_internals",
            reason = "used by the panic! macro",
            issue = "0")]
+#[cfg_attr(not(any(stage0, test)), lang = "begin_panic")]
 #[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
 pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u32)) -> ! {
     // Note that this should be the only allocation performed in this code path.
index 53babd449a992fbfe5653a67b1e3d36525cafdd3..58ac4e944087ee7416e2ed36e4a832f9497545b2 100644 (file)
@@ -626,6 +626,14 @@ pub fn env_clear(&mut self) -> &mut Command {
 
     /// Sets the working directory for the child process.
     ///
+    /// # Platform-specific behavior
+    ///
+    /// If the program path is relative (e.g. `"./script.sh"`), it's ambiguous
+    /// whether it should be interpreted relative to the parent's working
+    /// directory or relative to `current_dir`. The behavior in this case is
+    /// platform specific and unstable, and it's recommended to use
+    /// [`canonicalize`] to get an absolute program path instead.
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -638,6 +646,8 @@ pub fn env_clear(&mut self) -> &mut Command {
     ///         .spawn()
     ///         .expect("ls command failed to start");
     /// ```
+    ///
+    /// [`canonicalize`]: ../fs/fn.canonicalize.html
     #[stable(feature = "process", since = "1.0.0")]
     pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
         self.inner.cwd(dir.as_ref().as_ref());
index f6cb8beae84158e6fe6715676c16d60d420b2794..f258ff073e2a7fa390b554bf87c18f317e1e9f93 100644 (file)
@@ -176,7 +176,7 @@ pub const fn new() -> Once {
     /// happens-before relation between the closure and code executing after the
     /// return).
     ///
-    /// If the given closure recusively invokes `call_once` on the same `Once`
+    /// If the given closure recursively invokes `call_once` on the same `Once`
     /// instance the exact behavior is not specified, allowed outcomes are
     /// a panic or a deadlock.
     ///
index c05c837ade27498fef4e2d144e8a378535aa789b..ccf848a9be42057bff8cc695a62fb61bd565c04d 100644 (file)
@@ -28,11 +28,13 @@ pub struct Condvar {
 unsafe impl Send for Condvar {}
 unsafe impl Sync for Condvar {}
 
+const NEW: Condvar = Condvar {
+    condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)),
+};
+
 impl Condvar {
     pub const fn new() -> Condvar {
-        Condvar {
-            condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)),
-        }
+        NEW
     }
 
     pub unsafe fn init(&mut self) {}
index 8539aec5e2c07a1cb5ae8427701abb35b7ce0115..dc8624ec8a1b82800e2eb0dfa754007bec729635 100644 (file)
@@ -32,11 +32,13 @@ pub unsafe fn raw(r: &RWLock) -> *mut AtomicU32 {
 unsafe impl Send for RWLock {}
 unsafe impl Sync for RWLock {}
 
+const NEW: RWLock = RWLock {
+    lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)),
+};
+
 impl RWLock {
     pub const fn new() -> RWLock {
-        RWLock {
-            lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)),
-        }
+        NEW
     }
 
     pub unsafe fn try_read(&self) -> bool {
index c44db3b10722494e4e925987dff53a206bd378b8..61e4ce66eec0fe636e911d6a00f10f5aa3d82f9a 100644 (file)
@@ -57,7 +57,7 @@
 // then later used in the `std::os` module when documenting, for example,
 // Windows when we're compiling for Linux.
 
-#[cfg(dox)]
+#[cfg(rustdoc)]
 cfg_if! {
     if #[cfg(any(unix, target_os = "redox"))] {
         // On unix we'll document what's already available
@@ -77,7 +77,7 @@ pub mod unix_ext {}
     }
 }
 
-#[cfg(dox)]
+#[cfg(rustdoc)]
 cfg_if! {
     if #[cfg(windows)] {
         // On windows we'll just be documenting what's already available
index 4352b72c307735b40d55f4d8da879c706f325e89..f943257c687330c368622f087e42bde74c625f45 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(dead_code, missing_docs, bad_style)]
+#![allow(dead_code, missing_docs, nonstandard_style)]
 
 use io::{self, ErrorKind};
 
index 4830e38d6a92fd8c4c2b337e54b97c1af0a848cc..12e14734ff515edbcc7ee43d51916e9ea7bb182e 100644 (file)
@@ -282,7 +282,7 @@ fn drop(&mut self) {
         // reason for this is that if an error occurs we don't actually know if
         // the file descriptor was closed or not, and if we retried (for
         // something like EINTR), we might close another valid file descriptor
-        // (opened after we closed ours.
+        // opened after we closed ours.
         let _ = unsafe { libc::close(self.fd) };
     }
 }
index 7a89d9857bbcf341c95c3a8955b82933e6c26560..1d5b0cfa94ad549e9252ed00b7fe2a5d9e812b57 100644 (file)
@@ -857,7 +857,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     use sync::atomic::{AtomicBool, Ordering};
 
     // Kernel prior to 4.5 don't have copy_file_range
-    // We store the availability in a global to avoid unneccessary syscalls
+    // We store the availability in a global to avoid unnecessary syscalls
     static HAS_COPY_FILE_RANGE: AtomicBool = AtomicBool::new(true);
 
     unsafe fn copy_file_range(
index c738003caf1d9b220a980c1006b79f7ce6eeeb5d..17214be5b054957da532e8d555f447bf252b349e 100644 (file)
@@ -8,27 +8,27 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(missing_docs, bad_style)]
+#![allow(missing_docs, nonstandard_style)]
 
 use io::{self, ErrorKind};
 use libc;
 
-#[cfg(any(dox, target_os = "linux"))] pub use os::linux as platform;
-
-#[cfg(all(not(dox), target_os = "android"))]   pub use os::android as platform;
-#[cfg(all(not(dox), target_os = "bitrig"))]    pub use os::bitrig as platform;
-#[cfg(all(not(dox), target_os = "dragonfly"))] pub use os::dragonfly as platform;
-#[cfg(all(not(dox), target_os = "freebsd"))]   pub use os::freebsd as platform;
-#[cfg(all(not(dox), target_os = "haiku"))]     pub use os::haiku as platform;
-#[cfg(all(not(dox), target_os = "ios"))]       pub use os::ios as platform;
-#[cfg(all(not(dox), target_os = "macos"))]     pub use os::macos as platform;
-#[cfg(all(not(dox), target_os = "netbsd"))]    pub use os::netbsd as platform;
-#[cfg(all(not(dox), target_os = "openbsd"))]   pub use os::openbsd as platform;
-#[cfg(all(not(dox), target_os = "solaris"))]   pub use os::solaris as platform;
-#[cfg(all(not(dox), target_os = "emscripten"))] pub use os::emscripten as platform;
-#[cfg(all(not(dox), target_os = "fuchsia"))]   pub use os::fuchsia as platform;
-#[cfg(all(not(dox), target_os = "l4re"))]      pub use os::linux as platform;
-#[cfg(all(not(dox), target_os = "hermit"))]    pub use os::hermit as platform;
+#[cfg(any(rustdoc, target_os = "linux"))] pub use os::linux as platform;
+
+#[cfg(all(not(rustdoc), target_os = "android"))]   pub use os::android as platform;
+#[cfg(all(not(rustdoc), target_os = "bitrig"))]    pub use os::bitrig as platform;
+#[cfg(all(not(rustdoc), target_os = "dragonfly"))] pub use os::dragonfly as platform;
+#[cfg(all(not(rustdoc), target_os = "freebsd"))]   pub use os::freebsd as platform;
+#[cfg(all(not(rustdoc), target_os = "haiku"))]     pub use os::haiku as platform;
+#[cfg(all(not(rustdoc), target_os = "ios"))]       pub use os::ios as platform;
+#[cfg(all(not(rustdoc), target_os = "macos"))]     pub use os::macos as platform;
+#[cfg(all(not(rustdoc), target_os = "netbsd"))]    pub use os::netbsd as platform;
+#[cfg(all(not(rustdoc), target_os = "openbsd"))]   pub use os::openbsd as platform;
+#[cfg(all(not(rustdoc), target_os = "solaris"))]   pub use os::solaris as platform;
+#[cfg(all(not(rustdoc), target_os = "emscripten"))] pub use os::emscripten as platform;
+#[cfg(all(not(rustdoc), target_os = "fuchsia"))]   pub use os::fuchsia as platform;
+#[cfg(all(not(rustdoc), target_os = "l4re"))]      pub use os::linux as platform;
+#[cfg(all(not(rustdoc), target_os = "hermit"))]    pub use os::hermit as platform;
 
 pub use self::rand::hashmap_random_keys;
 pub use libc::strlen;
index 04d9f0b06d344efbda8cce7bebdcd6bdd835c983..2d10541752c83b3ca21b1ab5cfdfebf91d340250 100644 (file)
@@ -35,7 +35,7 @@
 #[cfg(not(target_os = "linux"))]
 const SOCK_CLOEXEC: c_int = 0;
 
-// Another conditional contant for name resolution: Macos et iOS use
+// Another conditional constant for name resolution: Macos et iOS use
 // SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket.
 // Other platforms do otherwise.
 #[cfg(target_vendor = "apple")]
@@ -395,30 +395,3 @@ fn on_resolver_failure() {
 
 #[cfg(not(target_env = "gnu"))]
 fn on_resolver_failure() {}
-
-#[cfg(all(test, taget_env = "gnu"))]
-mod test {
-    use super::*;
-
-    #[test]
-    fn test_res_init() {
-        // This mostly just tests that the weak linkage doesn't panic wildly...
-        res_init_if_glibc_before_2_26().unwrap();
-    }
-
-    #[test]
-    fn test_parse_glibc_version() {
-        let cases = [
-            ("0.0", Some((0, 0))),
-            ("01.+2", Some((1, 2))),
-            ("3.4.5.six", Some((3, 4))),
-            ("1", None),
-            ("1.-2", None),
-            ("1.foo", None),
-            ("foo.1", None),
-        ];
-        for &(version_str, parsed) in cases.iter() {
-            assert_eq!(parsed, parse_glibc_version(version_str));
-        }
-    }
-}
index f8f0bbd5bc25070cb042394e56ba9ead29009e34..971e6501c2c2a6088beacceee6c22c6f3ae06893 100644 (file)
@@ -569,3 +569,30 @@ fn parse_glibc_version(version: &str) -> Option<(usize, usize)> {
         _ => None
     }
 }
+
+#[cfg(all(test, target_env = "gnu"))]
+mod test {
+    use super::*;
+
+    #[test]
+    fn test_glibc_version() {
+        // This mostly just tests that the weak linkage doesn't panic wildly...
+        glibc_version();
+    }
+
+    #[test]
+    fn test_parse_glibc_version() {
+        let cases = [
+            ("0.0", Some((0, 0))),
+            ("01.+2", Some((1, 2))),
+            ("3.4.5.six", Some((3, 4))),
+            ("1", None),
+            ("1.-2", None),
+            ("1.foo", None),
+            ("foo.1", None),
+        ];
+        for &(version_str, parsed) in cases.iter() {
+            assert_eq!(parsed, parse_glibc_version(version_str));
+        }
+    }
+}
index e7476ab37f7c86710a2a7959974b6e104203e41c..03a5b2d779e1f633420f0f85e00f8bb29acb0250 100644 (file)
@@ -297,7 +297,7 @@ pub fn lookup_host(_: &str) -> io::Result<LookupHost> {
     unsupported()
 }
 
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 pub mod netc {
     pub const AF_INET: u8 = 0;
     pub const AF_INET6: u8 = 1;
index f64cae810b9ac76bf5a54b317e1bf0df1a6b9b1e..70de4a6f2b6173b2fce64eb5f5a7bd50b53c4db0 100644 (file)
@@ -152,7 +152,14 @@ fn set_frames<W: StackWalker>(StackWalk: W, frames: &mut [Frame]) -> io::Result<
 trait StackWalker {
     type Item: StackFrame;
 
-    fn walk(&self, c::DWORD, c::HANDLE, c::HANDLE, &mut Self::Item, &mut c::CONTEXT) -> c::BOOL;
+    fn walk(
+        &self,
+        _: c::DWORD,
+        _: c::HANDLE,
+        _: c::HANDLE,
+        _: &mut Self::Item,
+        _: &mut c::CONTEXT
+    ) -> c::BOOL;
 }
 
 impl StackWalker for StackWalkExFn {
index e514a56dcc43681dcb3fd8875e0b900402fa3d9f..4c64322a6dce398c1b3d0065597e4a12c57c613c 100644 (file)
@@ -10,7 +10,7 @@
 
 //! C definitions used by libnative that don't belong in liblibc
 
-#![allow(bad_style)]
+#![allow(nonstandard_style)]
 #![cfg_attr(test, allow(dead_code))]
 #![unstable(issue = "0", feature = "windows_c")]
 
@@ -794,7 +794,7 @@ pub struct FLOATING_SAVE_AREA {
 // will not appear in the final documentation. This should be also defined for
 // other architectures supported by Windows such as ARM, and for historical
 // interest, maybe MIPS and PowerPC as well.
-#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))))]
+#[cfg(all(rustdoc, not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))))]
 pub enum CONTEXT {}
 
 #[cfg(target_arch = "aarch64")]
index ccf79de909fa9dd4ca6b51ecafa0f53dce4e8918..31ef9fa2bedfd4a4a0091c661a19db158ae75c0c 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(missing_docs, bad_style)]
+#![allow(missing_docs, nonstandard_style)]
 
 use ptr;
 use ffi::{OsStr, OsString};
index 9bf9f749d4df252c89182265ccb7fc3d80290631..b0e7331e2b6513a20a55623300836c9303b19001 100644 (file)
@@ -58,6 +58,8 @@ pub unsafe fn raw(m: &Mutex) -> c::PSRWLOCK {
 impl Mutex {
     pub const fn new() -> Mutex {
         Mutex {
+            // This works because SRWLOCK_INIT is 0 (wrapped in a struct), so we are also properly
+            // initializing an SRWLOCK here.
             lock: AtomicUsize::new(0),
             held: UnsafeCell::new(false),
         }
index b94482435597e4be2b8ceea0fc7914ea16cd7d12..29ea82c2053cdb08df0e6f8de9efc5f96787c82e 100644 (file)
@@ -10,7 +10,7 @@
 
 //! Implementation of `std::os` functionality for Windows
 
-#![allow(bad_style)]
+#![allow(nonstandard_style)]
 
 use os::windows::prelude::*;
 
index df1dd7401af619476582db504075646df2ea6109..4b19519a57a876cc94ed430e640e89544833aa46 100644 (file)
@@ -359,6 +359,6 @@ unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
     if v.capacity() == v.len() {
         v.reserve(1);
     }
-    slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize),
+    slice::from_raw_parts_mut(v.as_mut_ptr().add(v.len()),
                               v.capacity() - v.len())
 }
index 45204b56ead3631733a2c712061d25586c9eafa2..8725abe741679a50da912a28021ba9be6800986d 100644 (file)
@@ -772,7 +772,7 @@ pub fn is_code_point_boundary(slice: &Wtf8, index: usize) -> bool {
 pub unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 {
     // memory layout of an &[u8] and &Wtf8 are the same
     Wtf8::from_bytes_unchecked(slice::from_raw_parts(
-        s.bytes.as_ptr().offset(begin as isize),
+        s.bytes.as_ptr().add(begin),
         end - begin
     ))
 }
index 61c6084a25023897c4aa27fec6d6745cc4982e6c..a7c7dbb1b402762b9c59fae8304070a51ce823cb 100644 (file)
@@ -1310,11 +1310,17 @@ pub fn thread(&self) -> &Thread {
 
     /// Waits for the associated thread to finish.
     ///
+    /// In terms of [atomic memory orderings],  the completion of the associated
+    /// thread synchronizes with this function returning. In other words, all
+    /// operations performed by that thread are ordered before all
+    /// operations that happen after `join` returns.
+    ///
     /// 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
+    /// [atomic memory orderings]: ../../std/sync/atomic/index.html
     ///
     /// # Panics
     ///
index d1a5ab0211b3b08f57c02c3a5e686e838fd011db..519cc7aa92c556e135423cc15780e1766ef90951 100644 (file)
@@ -17,3 +17,4 @@ syntax_pos = { path = "../libsyntax_pos" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_target = { path = "../librustc_target" }
+smallvec = { version = "0.6.5", features = ["union"] }
index 63aaa487bf8989495efedf9292dfc7a3b4d0e6e5..72f1791ef7c0f995d285a3502a9cb4d230820fd8 100644 (file)
@@ -28,8 +28,8 @@
 use tokenstream::{ThinTokenStream, TokenStream};
 
 use serialize::{self, Encoder, Decoder};
-use std::collections::HashSet;
 use std::fmt;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use std::u32;
 
@@ -407,7 +407,7 @@ pub struct WhereEqPredicate {
 
 /// The set of MetaItems that define the compilation environment of the crate,
 /// used to drive conditional compilation
-pub type CrateConfig = HashSet<(Name, Option<Symbol>)>;
+pub type CrateConfig = FxHashSet<(Name, Option<Symbol>)>;
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Crate {
@@ -992,7 +992,7 @@ pub fn precedence(&self) -> ExprPrecedence {
             ExprKind::Match(..) => ExprPrecedence::Match,
             ExprKind::Closure(..) => ExprPrecedence::Closure,
             ExprKind::Block(..) => ExprPrecedence::Block,
-            ExprKind::Catch(..) => ExprPrecedence::Catch,
+            ExprKind::TryBlock(..) => ExprPrecedence::TryBlock,
             ExprKind::Async(..) => ExprPrecedence::Async,
             ExprKind::Assign(..) => ExprPrecedence::Assign,
             ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
@@ -1113,8 +1113,8 @@ pub enum ExprKind {
     /// created during lowering cannot be made the parent of any other
     /// preexisting defs.
     Async(CaptureBy, NodeId, P<Block>),
-    /// A catch block (`catch { ... }`)
-    Catch(P<Block>),
+    /// A try block (`try { ... }`)
+    TryBlock(P<Block>),
 
     /// An assignment (`a = foo()`)
     Assign(P<Expr>, P<Expr>),
index ecd52a62eab2692601254ed5d9b17ce30593b293..3eecdf14a4e50029eb62d7a161e310bcbd71f905 100644 (file)
@@ -107,7 +107,11 @@ pub struct Stability {
     pub level: StabilityLevel,
     pub feature: Symbol,
     pub rustc_depr: Option<RustcDeprecation>,
-    pub rustc_const_unstable: Option<RustcConstUnstable>,
+    /// `None` means the function is stable but needs to be allowed by the
+    /// `min_const_fn` feature
+    /// `Some` contains the feature gate required to be able to use the function
+    /// as const fn
+    pub const_stability: Option<Symbol>,
 }
 
 /// The available stability levels.
@@ -141,11 +145,6 @@ pub struct RustcDeprecation {
     pub reason: Symbol,
 }
 
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
-pub struct RustcConstUnstable {
-    pub feature: Symbol,
-}
-
 /// Check if `attrs` contains an attribute like `#![feature(feature_name)]`.
 /// This will not perform any "sanity checks" on the form of the attributes.
 pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool {
@@ -176,7 +175,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
 
     let mut stab: Option<Stability> = None;
     let mut rustc_depr: Option<RustcDeprecation> = None;
-    let mut rustc_const_unstable: Option<RustcConstUnstable> = None;
+    let mut rustc_const_unstable: Option<Symbol> = None;
 
     'outer: for attr in attrs_iter {
         if ![
@@ -191,6 +190,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
         mark_used(attr);
 
         let meta = attr.meta();
+        // attributes with data
         if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta {
             let meta = meta.as_ref().unwrap();
             let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
@@ -272,9 +272,7 @@ macro_rules! get_meta {
 
                     get_meta!(feature);
                     if let Some(feature) = feature {
-                        rustc_const_unstable = Some(RustcConstUnstable {
-                            feature
-                        });
+                        rustc_const_unstable = Some(feature);
                     } else {
                         span_err!(diagnostic, attr.span(), E0629, "missing 'feature'");
                         continue
@@ -330,7 +328,7 @@ macro_rules! get_meta {
                                 },
                                 feature,
                                 rustc_depr: None,
-                                rustc_const_unstable: None,
+                                const_stability: None,
                             })
                         }
                         (None, _, _) => {
@@ -379,7 +377,7 @@ macro_rules! get_meta {
                                 },
                                 feature,
                                 rustc_depr: None,
-                                rustc_const_unstable: None,
+                                const_stability: None,
                             })
                         }
                         (None, _) => {
@@ -412,9 +410,9 @@ macro_rules! get_meta {
     }
 
     // Merge the const-unstable info into the stability info
-    if let Some(rustc_const_unstable) = rustc_const_unstable {
+    if let Some(feature) = rustc_const_unstable {
         if let Some(ref mut stab) = stab {
-            stab.rustc_const_unstable = Some(rustc_const_unstable);
+            stab.const_stability = Some(feature);
         } else {
             span_err!(diagnostic, item_sp, E0630,
                       "rustc_const_unstable attribute must be paired with \
index cd9d76822106c431cd07254805310e7e8b1e1227..19bbbceff5fc02f3d6ef9d8e5f7d8421efc3b0f5 100644 (file)
@@ -15,7 +15,7 @@
 pub use self::builtin::{
     cfg_matches, contains_feature_attr, eval_condition, find_crate_name, find_deprecation,
     find_repr_attrs, find_stability, find_unwind_attr, Deprecation, InlineAttr, IntType, ReprAttr,
-    RustcConstUnstable, RustcDeprecation, Stability, StabilityLevel, UnwindAttr,
+    RustcDeprecation, Stability, StabilityLevel, UnwindAttr,
 };
 pub use self::IntType::*;
 pub use self::ReprAttr::*;
index 15abad555f4b65c05dde873d7458f0e072356635..23ce7fc6a65681bb10a90238a94410bae474839b 100644 (file)
@@ -213,19 +213,18 @@ struct MyStruct {
 "##,
 
 E0565: r##"
-A literal was used in an attribute that doesn't support literals.
+A literal was used in a built-in attribute that doesn't support literals.
 
 Erroneous code example:
 
 ```ignore (compile_fail not working here; see Issue #43707)
-#![feature(attr_literals)]
-
 #[inline("always")] // error: unsupported literal
 pub fn something() {}
 ```
 
-Literals in attributes are new and largely unsupported. Work to support literals
-where appropriate is ongoing. Try using an unquoted name instead:
+Literals in attributes are new and largely unsupported in built-in attributes.
+Work to support literals where appropriate is ongoing. Try using an unquoted
+name instead:
 
 ```
 #[inline(always)]
@@ -382,8 +381,9 @@ fn main() {}
 
 ```ignore (limited to a warning during 2018 edition development)
 #![feature(rust_2018_preview)]
-#![feature(raw_identifiers)] // error: the feature `raw_identifiers` is
-                             // included in the Rust 2018 edition
+#![feature(impl_header_lifetime_elision)] // error: the feature
+                                          // `impl_header_lifetime_elision` is
+                                          // included in the Rust 2018 edition
 ```
 
 "##,
index d044efa3c38af20be7fcca1f01ad125520c4aaf4..c5a2cd5ac0b439f03d22ad39f9b44c488c612cbc 100644 (file)
@@ -131,7 +131,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
     let sym = Ident::with_empty_ctxt(Symbol::gensym(&format!(
         "__register_diagnostic_{}", code
     )));
-    MacEager::items(OneVector::many(vec![
+    MacEager::items(OneVector::from_vec(vec![
         ecx.item_mod(
             span,
             span,
@@ -214,7 +214,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
         ),
     );
 
-    MacEager::items(OneVector::many(vec![
+    MacEager::items(OneVector::from_vec(vec![
         P(ast::Item {
             ident: *name,
             attrs: Vec::new(),
index 154fe11dd352c45882a15fe65001ddcac8558044..e8a68b6d7676c5640803e2bf50dcbd9c0eadc949 100644 (file)
@@ -26,7 +26,7 @@
 use symbol::{keywords, Ident, Symbol};
 use ThinVec;
 
-use std::collections::HashMap;
+use rustc_data_structures::fx::FxHashMap;
 use std::iter;
 use std::path::PathBuf;
 use std::rc::Rc;
@@ -316,11 +316,11 @@ fn expand<'cx>(&self,
 // Use a macro because forwarding to a simple function has type system issues
 macro_rules! make_stmts_default {
     ($me:expr) => {
-        $me.make_expr().map(|e| OneVector::one(ast::Stmt {
+        $me.make_expr().map(|e| smallvec![ast::Stmt {
             id: ast::DUMMY_NODE_ID,
             span: e.span,
             node: ast::StmtKind::Expr(e),
-        }))
+        }])
     }
 }
 
@@ -548,11 +548,11 @@ fn make_foreign_items(self: Box<Self>) -> Option<OneVector<ast::ForeignItem>> {
     }
 
     fn make_stmts(self: Box<DummyResult>) -> Option<OneVector<ast::Stmt>> {
-        Some(OneVector::one(ast::Stmt {
+        Some(smallvec![ast::Stmt {
             id: ast::DUMMY_NODE_ID,
             node: ast::StmtKind::Expr(DummyResult::raw_expr(self.span)),
             span: self.span,
-        }))
+        }])
     }
 
     fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
@@ -727,10 +727,12 @@ fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFra
     fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<Attribute>, allow_derive: bool)
                               -> Option<Attribute>;
 
-    fn resolve_invoc(&mut self, invoc: &Invocation, scope: Mark, force: bool)
-                     -> Result<Option<Lrc<SyntaxExtension>>, Determinacy>;
-    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
-                     -> Result<Lrc<SyntaxExtension>, Determinacy>;
+    fn resolve_macro_invocation(&mut self, invoc: &Invocation, scope: Mark, force: bool)
+                                -> Result<Option<Lrc<SyntaxExtension>>, Determinacy>;
+    fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark,
+                          derives_in_scope: &[ast::Path], force: bool)
+                          -> Result<Lrc<SyntaxExtension>, Determinacy>;
+
     fn check_unused_macros(&self);
 }
 
@@ -761,12 +763,13 @@ fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
     fn resolve_imports(&mut self) {}
     fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>, _allow_derive: bool)
                               -> Option<Attribute> { None }
-    fn resolve_invoc(&mut self, _invoc: &Invocation, _scope: Mark, _force: bool)
-                     -> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
+    fn resolve_macro_invocation(&mut self, _invoc: &Invocation, _scope: Mark, _force: bool)
+                                -> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
         Err(Determinacy::Determined)
     }
-    fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _kind: MacroKind,
-                     _force: bool) -> Result<Lrc<SyntaxExtension>, Determinacy> {
+    fn resolve_macro_path(&mut self, _path: &ast::Path, _kind: MacroKind, _scope: Mark,
+                          _derives_in_scope: &[ast::Path], _force: bool)
+                          -> Result<Lrc<SyntaxExtension>, Determinacy> {
         Err(Determinacy::Determined)
     }
     fn check_unused_macros(&self) {}
@@ -797,7 +800,7 @@ pub struct ExtCtxt<'a> {
     pub resolver: &'a mut dyn Resolver,
     pub resolve_err_count: usize,
     pub current_expansion: ExpansionData,
-    pub expansions: HashMap<Span, Vec<String>>,
+    pub expansions: FxHashMap<Span, Vec<String>>,
 }
 
 impl<'a> ExtCtxt<'a> {
@@ -818,7 +821,7 @@ pub fn new(parse_sess: &'a parse::ParseSess,
                 directory_ownership: DirectoryOwnership::Owned { relative: None },
                 crate_span: None,
             },
-            expansions: HashMap::new(),
+            expansions: FxHashMap::default(),
         }
     }
 
index 80bbc618932ef7f89613e9ff82e4527a42e96a04..684cee38874630fa7d0f311cd34d1b729c9177d8 100644 (file)
@@ -17,7 +17,7 @@
 use symbol::Symbol;
 use syntax_pos::Span;
 
-use std::collections::HashSet;
+use rustc_data_structures::fx::FxHashSet;
 
 pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>) -> Vec<ast::Path> {
     let mut result = Vec::new();
@@ -48,7 +48,7 @@ pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>) -> Vec
 pub fn add_derived_markers<T>(cx: &mut ExtCtxt, span: Span, traits: &[ast::Path], item: T) -> T
     where T: HasAttrs,
 {
-    let (mut names, mut pretty_name) = (HashSet::new(), "derive(".to_owned());
+    let (mut names, mut pretty_name) = (FxHashSet::default(), "derive(".to_owned());
     for (i, path) in traits.iter().enumerate() {
         if i > 0 {
             pretty_name.push_str(", ");
index b12b2c49caa58608c737675bb1565e610f58ef61..6e38f820586ffaea612ff38ddbab17eff5011d21 100644 (file)
 use tokenstream::{TokenStream, TokenTree};
 use visit::{self, Visitor};
 
-use std::collections::HashMap;
+use rustc_data_structures::fx::FxHashMap;
 use std::fs::File;
 use std::io::Read;
+use std::iter::FromIterator;
 use std::{iter, mem};
 use std::rc::Rc;
 use std::path::PathBuf;
@@ -131,7 +132,7 @@ fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
                 self.expand_fragment(AstFragment::$Kind(ast)).$make_ast()
             })*)*
             $($(fn $fold_ast_elt(&mut self, ast_elt: <$AstTy as IntoIterator>::Item) -> $AstTy {
-                self.expand_fragment(AstFragment::$Kind(OneVector::one(ast_elt))).$make_ast()
+                self.expand_fragment(AstFragment::$Kind(smallvec![ast_elt])).$make_ast()
             })*)*
         }
 
@@ -243,15 +244,6 @@ pub fn span(&self) -> Span {
             InvocationKind::Derive { ref path, .. } => path.span,
         }
     }
-
-    pub fn path(&self) -> Option<&Path> {
-        match self.kind {
-            InvocationKind::Bang { ref mac, .. } => Some(&mac.node.path),
-            InvocationKind::Attr { attr: Some(ref attr), .. } => Some(&attr.path),
-            InvocationKind::Attr { attr: None, .. } => None,
-            InvocationKind::Derive { ref path, .. } => Some(path),
-        }
-    }
 }
 
 pub struct MacroExpander<'a, 'b:'a> {
@@ -279,7 +271,7 @@ pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
 
         let orig_mod_span = krate.module.inner;
 
-        let krate_item = AstFragment::Items(OneVector::one(P(ast::Item {
+        let krate_item = AstFragment::Items(smallvec![P(ast::Item {
             attrs: krate.attrs,
             span: krate.span,
             node: ast::ItemKind::Mod(krate.module),
@@ -287,7 +279,7 @@ pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
             id: ast::DUMMY_NODE_ID,
             vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public),
             tokens: None,
-        })));
+        })]);
 
         match self.expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
             Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => {
@@ -321,13 +313,13 @@ fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
         // we'll be able to immediately resolve most of imported macros.
         self.resolve_imports();
 
-        // Resolve paths in all invocations and produce ouput expanded fragments for them, but
+        // Resolve paths in all invocations and produce output expanded fragments for them, but
         // do not insert them into our input AST fragment yet, only store in `expanded_fragments`.
         // The output fragments also go through expansion recursively until no invocations are left.
         // Unresolved macros produce dummy outputs as a recovery measure.
         invocations.reverse();
         let mut expanded_fragments = Vec::new();
-        let mut derives: HashMap<Mark, Vec<_>> = HashMap::new();
+        let mut derives: FxHashMap<Mark, Vec<_>> = FxHashMap::default();
         let mut undetermined_invocations = Vec::new();
         let (mut progress, mut force) = (false, !self.monotonic);
         loop {
@@ -343,7 +335,7 @@ fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
 
             let scope =
                 if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
-            let ext = match self.cx.resolver.resolve_invoc(&invoc, scope, force) {
+            let ext = match self.cx.resolver.resolve_macro_invocation(&invoc, scope, force) {
                 Ok(ext) => Some(ext),
                 Err(Determinacy::Determined) => None,
                 Err(Determinacy::Undetermined) => {
@@ -393,8 +385,8 @@ fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
                     for path in &traits {
                         let mark = Mark::fresh(self.cx.current_expansion.mark);
                         derives.push(mark);
-                        let item = match self.cx.resolver.resolve_macro(
-                                Mark::root(), path, MacroKind::Derive, false) {
+                        let item = match self.cx.resolver.resolve_macro_path(
+                                path, MacroKind::Derive, Mark::root(), &[], false) {
                             Ok(ext) => match *ext {
                                 BuiltinDerive(..) => item_with_markers.clone(),
                                 _ => item.clone(),
@@ -675,30 +667,25 @@ fn gate_proc_macro_expansion(&self, span: Span, fragment: &Option<AstFragment>)
             None => return,
         };
 
-        fragment.visit_with(&mut DisallowModules {
+        fragment.visit_with(&mut DisallowMacros {
             span,
             parse_sess: self.cx.parse_sess,
         });
 
-        struct DisallowModules<'a> {
+        struct DisallowMacros<'a> {
             span: Span,
             parse_sess: &'a ParseSess,
         }
 
-        impl<'ast, 'a> Visitor<'ast> for DisallowModules<'a> {
+        impl<'ast, 'a> Visitor<'ast> for DisallowMacros<'a> {
             fn visit_item(&mut self, i: &'ast ast::Item) {
-                let name = match i.node {
-                    ast::ItemKind::Mod(_) => Some("modules"),
-                    ast::ItemKind::MacroDef(_) => Some("macro definitions"),
-                    _ => None,
-                };
-                if let Some(name) = name {
+                if let ast::ItemKind::MacroDef(_) = i.node {
                     emit_feature_err(
                         self.parse_sess,
                         "proc_macro_gen",
                         self.span,
                         GateIssue::Language,
-                        &format!("procedural macros cannot expand to {}", name),
+                        &format!("procedural macros cannot expand to macro definitions"),
                     );
                 }
                 visit::walk_item(self, i);
@@ -1418,7 +1405,7 @@ fn fold_item(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
                         ui
                     });
 
-                    OneVector::many(
+                    OneVector::from_iter(
                         self.fold_unnameable(item).into_iter()
                             .chain(self.fold_unnameable(use_item)))
                 } else {
index 18b4119fde8e49767d270bff3c14ce3cfece17fc..5906412883ad0c0356091004cbbe261a8a5e63c6 100644 (file)
@@ -21,7 +21,7 @@
 use ThinVec;
 use util::move_map::MoveMap;
 
-use std::collections::HashMap;
+use rustc_data_structures::fx::FxHashMap;
 
 pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
     fn mac_placeholder() -> ast::Mac {
@@ -46,42 +46,42 @@ fn mac_placeholder() -> ast::Mac {
     match kind {
         AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
         AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
-        AstFragmentKind::Items => AstFragment::Items(OneVector::one(P(ast::Item {
+        AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
             id, span, ident, vis, attrs,
             node: ast::ItemKind::Mac(mac_placeholder()),
             tokens: None,
-        }))),
-        AstFragmentKind::TraitItems => AstFragment::TraitItems(OneVector::one(ast::TraitItem {
+        })]),
+        AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::TraitItem {
             id, span, ident, attrs, generics,
             node: ast::TraitItemKind::Macro(mac_placeholder()),
             tokens: None,
-        })),
-        AstFragmentKind::ImplItems => AstFragment::ImplItems(OneVector::one(ast::ImplItem {
+        }]),
+        AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::ImplItem {
             id, span, ident, vis, attrs, generics,
             node: ast::ImplItemKind::Macro(mac_placeholder()),
             defaultness: ast::Defaultness::Final,
             tokens: None,
-        })),
+        }]),
         AstFragmentKind::ForeignItems =>
-            AstFragment::ForeignItems(OneVector::one(ast::ForeignItem {
+            AstFragment::ForeignItems(smallvec![ast::ForeignItem {
                 id, span, ident, vis, attrs,
                 node: ast::ForeignItemKind::Macro(mac_placeholder()),
-            })),
+            }]),
         AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
             id, span, node: ast::PatKind::Mac(mac_placeholder()),
         })),
         AstFragmentKind::Ty => AstFragment::Ty(P(ast::Ty {
             id, span, node: ast::TyKind::Mac(mac_placeholder()),
         })),
-        AstFragmentKind::Stmts => AstFragment::Stmts(OneVector::one({
+        AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{
             let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ThinVec::new()));
             ast::Stmt { id, span, node: ast::StmtKind::Mac(mac) }
-        })),
+        }]),
     }
 }
 
 pub struct PlaceholderExpander<'a, 'b: 'a> {
-    expanded_fragments: HashMap<ast::NodeId, AstFragment>,
+    expanded_fragments: FxHashMap<ast::NodeId, AstFragment>,
     cx: &'a mut ExtCtxt<'b>,
     monotonic: bool,
 }
@@ -90,7 +90,7 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> {
     pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
         PlaceholderExpander {
             cx,
-            expanded_fragments: HashMap::new(),
+            expanded_fragments: FxHashMap::default(),
             monotonic,
         }
     }
@@ -118,7 +118,7 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
     fn fold_item(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
         match item.node {
             ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(),
-            ast::ItemKind::MacroDef(_) => return OneVector::one(item),
+            ast::ItemKind::MacroDef(_) => return smallvec![item],
             _ => {}
         }
 
index 19a204cc989bfeb9f05dbdf775a08ca78f32d6ce..e4b9e3216b13b7cf06c064a1d0276a5e2ca9be4e 100644 (file)
@@ -184,7 +184,7 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::Toke
         Ok(..) => {
             // Add this input file to the code map to make it available as
             // dependency information, but don't enter it's contents
-            cx.source_map().new_source_file(file.into(), "".to_string());
+            cx.source_map().new_source_file(file.into(), String::new());
 
             base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(bytes))))
         }
index 82f88d1d8643eff41d574090b3e57a7d3fa890e0..c962e7fcbb4cfce003da8e7f43c0b8eae534cfab 100644 (file)
 use symbol::keywords;
 use tokenstream::TokenStream;
 
+use rustc_data_structures::fx::FxHashMap;
+use std::collections::hash_map::Entry::{Occupied, Vacant};
 use std::mem;
 use std::ops::{Deref, DerefMut};
 use std::rc::Rc;
-use std::collections::HashMap;
-use std::collections::hash_map::Entry::{Occupied, Vacant};
 
 // To avoid costly uniqueness checks, we require that `MatchSeq` always has a nonempty body.
 
@@ -263,7 +263,7 @@ pub enum ParseResult<T> {
 
 /// A `ParseResult` where the `Success` variant contains a mapping of `Ident`s to `NamedMatch`es.
 /// This represents the mapping of metavars to the token trees they bind to.
-pub type NamedParseResult = ParseResult<HashMap<Ident, Rc<NamedMatch>>>;
+pub type NamedParseResult = ParseResult<FxHashMap<Ident, Rc<NamedMatch>>>;
 
 /// Count how many metavars are named in the given matcher `ms`.
 pub fn count_names(ms: &[TokenTree]) -> usize {
@@ -351,7 +351,7 @@ fn n_rec<I: Iterator<Item = NamedMatch>>(
         sess: &ParseSess,
         m: &TokenTree,
         res: &mut I,
-        ret_val: &mut HashMap<Ident, Rc<NamedMatch>>,
+        ret_val: &mut FxHashMap<Ident, Rc<NamedMatch>>,
     ) -> Result<(), (syntax_pos::Span, String)> {
         match *m {
             TokenTree::Sequence(_, ref seq) => for next_m in &seq.tts {
@@ -382,7 +382,7 @@ fn n_rec<I: Iterator<Item = NamedMatch>>(
         Ok(())
     }
 
-    let mut ret_val = HashMap::new();
+    let mut ret_val = FxHashMap::default();
     for m in ms {
         match n_rec(sess, m, res.by_ref(), &mut ret_val) {
             Ok(_) => {}
@@ -637,14 +637,14 @@ pub fn parse(
 
     // A queue of possible matcher positions. We initialize it with the matcher position in which
     // the "dot" is before the first token of the first token tree in `ms`. `inner_parse_loop` then
-    // processes all of these possible matcher positions and produces posible next positions into
+    // processes all of these possible matcher positions and produces possible next positions into
     // `next_items`. After some post-processing, the contents of `next_items` replenish `cur_items`
     // and we start over again.
     //
     // This MatcherPos instance is allocated on the stack. All others -- and
     // there are frequently *no* others! -- are allocated on the heap.
     let mut initial = initial_matcher_pos(ms, parser.span.lo());
-    let mut cur_items = OneVector::one(MatcherPosHandle::Ref(&mut initial));
+    let mut cur_items = smallvec![MatcherPosHandle::Ref(&mut initial)];
     let mut next_items = Vec::new();
 
     loop {
@@ -726,7 +726,7 @@ pub fn parse(
                 ),
             );
         }
-        // If there are no posible next positions AND we aren't waiting for the black-box parser,
+        // If there are no possible next positions AND we aren't waiting for the black-box parser,
         // then their is a syntax error.
         else if bb_items.is_empty() && next_items.is_empty() {
             return Failure(parser.span, parser.token);
index 770561fe3269a3d8228ad9f7167cf566614db4fc..d09127d6b08b7a303ffd729c22727f21b798ea0f 100644 (file)
@@ -27,8 +27,8 @@
 use symbol::Symbol;
 use tokenstream::{TokenStream, TokenTree};
 
+use rustc_data_structures::fx::FxHashMap;
 use std::borrow::Cow;
-use std::collections::HashMap;
 use std::collections::hash_map::Entry;
 
 use rustc_data_structures::sync::Lrc;
@@ -451,14 +451,14 @@ struct FirstSets {
     // If two sequences have the same span in a matcher, then map that
     // span to None (invalidating the mapping here and forcing the code to
     // use a slow path).
-    first: HashMap<Span, Option<TokenSet>>,
+    first: FxHashMap<Span, Option<TokenSet>>,
 }
 
 impl FirstSets {
     fn new(tts: &[quoted::TokenTree]) -> FirstSets {
         use self::quoted::TokenTree;
 
-        let mut sets = FirstSets { first: HashMap::new() };
+        let mut sets = FirstSets { first: FxHashMap::default() };
         build_recur(&mut sets, tts);
         return sets;
 
@@ -964,7 +964,7 @@ fn is_legal_fragment_specifier(sess: &ParseSess,
                                frag_span: Span) -> bool {
     match frag_name {
         "item" | "block" | "stmt" | "expr" | "pat" | "lifetime" |
-        "path" | "ty" | "ident" | "meta" | "tt" | "" => true,
+        "path" | "ty" | "ident" | "meta" | "tt" | "vis" | "" => true,
         "literal" => {
             if !features.macro_literal_matcher &&
                !attr::contains_name(attrs, "allow_internal_unstable") {
@@ -977,18 +977,6 @@ fn is_legal_fragment_specifier(sess: &ParseSess,
             }
             true
         },
-        "vis" => {
-            if !features.macro_vis_matcher &&
-               !attr::contains_name(attrs, "allow_internal_unstable") {
-                let explain = feature_gate::EXPLAIN_VIS_MATCHER;
-                emit_feature_err(sess,
-                                 "macro_vis_matcher",
-                                 frag_span,
-                                 GateIssue::Language,
-                                 explain);
-            }
-            true
-        },
         _ => false,
     }
 }
index 357fc77a3a79d8c7f8a3df5f72a004132a7131a9..cc635a29275fabaae849e8b23bb0c44b469add54 100644 (file)
@@ -323,7 +323,7 @@ fn parse_tree<I>(
             }
 
             // `tree` is followed by an `ident`. This could be `$meta_var` or the `$crate` special
-            // metavariable that names the crate of the invokation.
+            // metavariable that names the crate of the invocation.
             Some(tokenstream::TokenTree::Token(ident_span, ref token)) if token.is_ident() => {
                 let (ident, is_raw) = token.ident().unwrap();
                 let span = ident_span.with_lo(span.lo());
index d451227e77cf3d7ffac51dc2cea844fbf1c7f5a7..549e5f00dcec4cbe8cc7478f673140fadc4f0aa6 100644 (file)
 use syntax_pos::{Span, DUMMY_SP};
 use tokenstream::{TokenStream, TokenTree, Delimited};
 
-use std::rc::Rc;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use std::mem;
 use std::ops::Add;
-use std::collections::HashMap;
+use std::rc::Rc;
 
 // An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`).
 enum Frame {
@@ -67,11 +67,11 @@ fn next(&mut self) -> Option<quoted::TokenTree> {
 /// `src` contains no `TokenTree::{Sequence, MetaVar, MetaVarDecl}`s, `interp` can
 /// (and should) be None.
 pub fn transcribe(cx: &ExtCtxt,
-                  interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
+                  interp: Option<FxHashMap<Ident, Rc<NamedMatch>>>,
                   src: Vec<quoted::TokenTree>)
                   -> TokenStream {
-    let mut stack = OneVector::one(Frame::new(src));
-    let interpolations = interp.unwrap_or_else(HashMap::new); /* just a convenience */
+    let mut stack: OneVector<Frame> = smallvec![Frame::new(src)];
+    let interpolations = interp.unwrap_or_else(FxHashMap::default); /* just a convenience */
     let mut repeats = Vec::new();
     let mut result: Vec<TokenStream> = Vec::new();
     let mut result_stack = Vec::new();
@@ -187,7 +187,7 @@ pub fn transcribe(cx: &ExtCtxt,
 }
 
 fn lookup_cur_matched(ident: Ident,
-                      interpolations: &HashMap<Ident, Rc<NamedMatch>>,
+                      interpolations: &FxHashMap<Ident, Rc<NamedMatch>>,
                       repeats: &[(usize, usize)])
                       -> Option<Rc<NamedMatch>> {
     interpolations.get(&ident).map(|matched| {
@@ -234,7 +234,7 @@ fn add(self, other: LockstepIterSize) -> LockstepIterSize {
 }
 
 fn lockstep_iter_size(tree: &quoted::TokenTree,
-                      interpolations: &HashMap<Ident, Rc<NamedMatch>>,
+                      interpolations: &FxHashMap<Ident, Rc<NamedMatch>>,
                       repeats: &[(usize, usize)])
                       -> LockstepIterSize {
     use self::quoted::TokenTree;
index 74f573fceba813eb5ee404fc7df061e3ce46e333..14781dd8e24d3812c06d55137378e66b3fc6e6cd 100644 (file)
 use std::{env, path};
 
 macro_rules! set {
+    // The const_fn feature also enables the min_const_fn feature, because `min_const_fn` allows
+    // the declaration `const fn`, but the `const_fn` feature gate enables things inside those
+    // functions that we do not want to expose to the user for now.
+    (const_fn) => {{
+        fn f(features: &mut Features, _: Span) {
+            features.const_fn = true;
+            features.min_const_fn = true;
+        }
+        f as fn(&mut Features, Span)
+    }};
     ($field: ident) => {{
         fn f(features: &mut Features, _: Span) {
             features.$field = true;
@@ -206,24 +216,33 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // #23121. Array patterns have some hazards yet.
     (active, slice_patterns, "1.0.0", Some(23121), None),
 
-    // Allows the definition of `const fn` functions.
+    // Allows the definition of `const fn` functions with some advanced features.
     (active, const_fn, "1.2.0", Some(24111), None),
 
+    // Allows the definition of `const fn` functions.
+    (active, min_const_fn, "1.30.0", Some(53555), None),
+
     // Allows let bindings and destructuring in `const fn` functions and constants.
     (active, const_let, "1.22.1", Some(48821), None),
 
-    // Allows accessing fields of unions inside const fn
+    // Allows accessing fields of unions inside const fn.
     (active, const_fn_union, "1.27.0", Some(51909), None),
 
-    // Allows casting raw pointers to `usize` during const eval
+    // Allows casting raw pointers to `usize` during const eval.
     (active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None),
 
-    // Allows dereferencing raw pointers during const eval
+    // Allows dereferencing raw pointers during const eval.
     (active, const_raw_ptr_deref, "1.27.0", Some(51911), None),
 
-    // Allows comparing raw pointers during const eval
+    // Allows reinterpretation of the bits of a value of one type as another type during const eval.
+    (active, const_transmute, "1.29.0", Some(53605), None),
+
+    // Allows comparing raw pointers during const eval.
     (active, const_compare_raw_pointers, "1.27.0", Some(53020), None),
 
+    // Allows panicking during const eval (produces compile-time errors)
+    (active, const_panic, "1.30.0", Some(51999), None),
+
     // Allows using #[prelude_import] on glob `use` items.
     //
     // rustc internal
@@ -286,9 +305,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // Allows exhaustive pattern matching on types that contain uninhabited types
     (active, exhaustive_patterns, "1.13.0", Some(51085), None),
 
-    // Allows all literals in attribute lists and values of key-value pairs
-    (active, attr_literals, "1.13.0", Some(34981), None),
-
     // Allows untagged unions `union U { ... }`
     (active, untagged_unions, "1.13.0", Some(32836), None),
 
@@ -330,8 +346,8 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // `extern "x86-interrupt" fn()`
     (active, abi_x86_interrupt, "1.17.0", Some(40180), None),
 
-    // Allows the `catch {...}` expression
-    (active, catch_expr, "1.17.0", Some(31436), None),
+    // Allows the `try {...}` expression
+    (active, try_blocks, "1.29.0", Some(31436), None),
 
     // Used to preserve symbols (see llvm.used)
     (active, used, "1.18.0", Some(40289), None),
@@ -342,9 +358,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // Allows overlapping impls of marker traits
     (active, overlapping_marker_traits, "1.18.0", Some(29864), None),
 
-    // Allows use of the :vis macro fragment specifier
-    (active, macro_vis_matcher, "1.18.0", Some(41022), None),
-
     // rustc internal
     (active, abi_thiscall, "1.19.0", None, None),
 
@@ -423,9 +436,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // `use path as _;` and `extern crate c as _;`
     (active, underscore_imports, "1.26.0", Some(48216), None),
 
-    // Allows keywords to be escaped for use as identifiers
-    (active, raw_identifiers, "1.26.0", Some(48589), Some(Edition::Edition2018)),
-
     // Allows macro invocations in `extern {}` blocks
     (active, macros_in_extern, "1.27.0", Some(49476), None),
 
@@ -444,9 +454,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     (active, tbm_target_feature, "1.27.0", Some(44839), None),
     (active, wasm_target_feature, "1.30.0", Some(44839), None),
 
-    // Allows macro invocations of the form `#[foo::bar]`
-    (active, proc_macro_path_invoc, "1.27.0", Some(38356), None),
-
     // Allows macro invocations on modules expressions and statements and
     // procedural macros to expand to non-items.
     (active, proc_macro_mod, "1.27.0", Some(38356), None),
@@ -460,8 +467,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // Access to crate names passed via `--extern` through prelude
     (active, extern_prelude, "1.27.0", Some(44660), Some(Edition::Edition2018)),
 
-    // Scoped attributes
-    (active, tool_attributes, "1.25.0", Some(44690), None),
     // Scoped lints
     (active, tool_lints, "1.28.0", Some(44690), None),
 
@@ -477,8 +482,12 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // 'a: { break 'a; }
     (active, label_break_value, "1.28.0", Some(48594), None),
 
-    // #[panic_implementation]
+    // Integer match exhaustiveness checking
+    (active, exhaustive_integer_patterns, "1.30.0", Some(50907), None),
+
+    // RFC 2070: #[panic_implementation] / #[panic_handler]
     (active, panic_implementation, "1.28.0", Some(44489), None),
+    (active, panic_handler, "1.30.0", Some(44489), None),
 
     // #[doc(keyword = "...")]
     (active, doc_keyword, "1.28.0", Some(51315), None),
@@ -648,9 +657,19 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     (accepted, repr_transparent, "1.28.0", Some(43036), None),
     // Defining procedural macros in `proc-macro` crates
     (accepted, proc_macro, "1.29.0", Some(38356), None),
+    // Allows use of the :vis macro fragment specifier
+    (accepted, macro_vis_matcher, "1.30.0", Some(41022), None),
     // Allows importing and reexporting macros with `use`,
     // enables macro modularization in general.
     (accepted, use_extern_macros, "1.30.0", Some(35896), None),
+    // Allows keywords to be escaped for use as identifiers
+    (accepted, raw_identifiers, "1.30.0", Some(48589), None),
+    // Attributes scoped to tools
+    (accepted, tool_attributes, "1.30.0", Some(44690), None),
+    // Allows multi-segment paths in attributes and derives
+    (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None),
+    // Allows all literals in attribute lists and values of key-value pairs.
+    (accepted, attr_literals, "1.30.0", Some(34981), None),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must
@@ -863,6 +882,12 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                         is just used for rustc unit tests \
                                         and will never be stable",
                                        cfg_fn!(rustc_attrs))),
+    ("rustc_dump_user_substs", Whitelisted, Gated(Stability::Unstable,
+                                       "rustc_attrs",
+                                       "this attribute \
+                                        is just used for rustc unit tests \
+                                        and will never be stable",
+                                       cfg_fn!(rustc_attrs))),
     ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
                                                  "rustc_attrs",
                                                  "the `#[rustc_if_this_changed]` attribute \
@@ -1101,11 +1126,20 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                    "infer 'static lifetime requirements",
                                    cfg_fn!(infer_static_outlives_requirements))),
 
+    // RFC 2070 (deprecated attribute name)
+    ("panic_implementation",
+     Normal,
+     Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/44489\
+                                  #issuecomment-415140224"),
+           "panic_implementation",
+           "This attribute was renamed to `panic_handler`",
+           cfg_fn!(panic_implementation))),
+
     // RFC 2070
-    ("panic_implementation", Normal, Gated(Stability::Unstable,
-                           "panic_implementation",
-                           "#[panic_implementation] is an unstable feature",
-                           cfg_fn!(panic_implementation))),
+    ("panic_handler", Normal, Gated(Stability::Unstable,
+                                    "panic_handler",
+                                    "#[panic_handler] is an unstable feature",
+                                    cfg_fn!(panic_handler))),
 
     ("alloc_error_handler", Normal, Gated(Stability::Unstable,
                            "alloc_error_handler",
@@ -1130,6 +1164,7 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
     ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
     ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
     ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
+    ("rustdoc", "doc_cfg", cfg_fn!(doc_cfg)),
 ];
 
 #[derive(Debug)]
@@ -1363,9 +1398,6 @@ fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue
 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
     "attributes of the form `#[derive_*]` are reserved for the compiler";
 
-pub const EXPLAIN_VIS_MATCHER: &'static str =
-    ":vis fragment specifier is experimental and subject to change";
-
 pub const EXPLAIN_LITERAL_MATCHER: &'static str =
     ":literal fragment specifier is experimental and subject to change";
 
@@ -1451,22 +1483,6 @@ fn check_abi(&self, abi: Abi, span: Span) {
     }
 }
 
-fn contains_novel_literal(item: &ast::MetaItem) -> bool {
-    use ast::MetaItemKind::*;
-    use ast::NestedMetaItemKind::*;
-
-    match item.node {
-        Word => false,
-        NameValue(ref lit) => !lit.node.is_str(),
-        List(ref list) => list.iter().any(|li| {
-            match li.node {
-                MetaItem(ref mi) => contains_novel_literal(mi),
-                Literal(_) => true,
-            }
-        }),
-    }
-}
-
 impl<'a> PostExpansionVisitor<'a> {
     fn whole_crate_feature_gates(&mut self, _krate: &ast::Crate) {
         for &(ident, span) in &*self.context.parse_sess.non_modrs_mods.borrow() {
@@ -1526,28 +1542,11 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
         }
 
         if !self.context.features.unrestricted_attribute_tokens {
-            // Unfortunately, `parse_meta` cannot be called speculatively because it can report
-            // errors by itself, so we have to call it only if the feature is disabled.
-            match attr.parse_meta(self.context.parse_sess) {
-                Ok(meta) => {
-                    // allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
-                    let mut allow_attr_literal = false;
-                    if attr.path == "repr" {
-                        if let Some(content) = meta.meta_item_list() {
-                            allow_attr_literal = content.iter().any(
-                                |c| c.check_name("align") || c.check_name("packed"));
-                        }
-                    }
-
-                    if !allow_attr_literal && contains_novel_literal(&meta) {
-                        gate_feature_post!(&self, attr_literals, attr.span,
-                                        "non-string literals in attributes, or string \
-                                        literals in top-level positions, are experimental");
-                    }
-                }
-                Err(mut err) => {
-                    err.help("try enabling `#![feature(unrestricted_attribute_tokens)]`").emit()
-                }
+            // Unfortunately, `parse_meta` cannot be called speculatively
+            // because it can report errors by itself, so we have to call it
+            // only if the feature is disabled.
+            if let Err(mut err) = attr.parse_meta(self.context.parse_sess) {
+                err.help("try enabling `#![feature(unrestricted_attribute_tokens)]`").emit()
             }
         }
     }
@@ -1734,8 +1733,8 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
                                   e.span,
                                   "yield syntax is experimental");
             }
-            ast::ExprKind::Catch(_) => {
-                gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
+            ast::ExprKind::TryBlock(_) => {
+                gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
             }
             ast::ExprKind::IfLet(ref pats, ..) | ast::ExprKind::WhileLet(ref pats, ..) => {
                 if pats.len() > 1 {
@@ -1801,7 +1800,7 @@ fn visit_fn(&mut self,
                     gate_feature_post!(&self, async_await, span, "async fn is unstable");
                 }
                 if header.constness.node == ast::Constness::Const {
-                    gate_feature_post!(&self, const_fn, span, "const fn is unstable");
+                    gate_feature_post!(&self, min_const_fn, span, "const fn is unstable");
                 }
                 // stability of const fn methods are covered in
                 // visit_trait_item and visit_impl_item below; this is
@@ -1859,7 +1858,7 @@ fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
         match ii.node {
             ast::ImplItemKind::Method(ref sig, _) => {
                 if sig.header.constness.node == ast::Constness::Const {
-                    gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
+                    gate_feature_post!(&self, min_const_fn, ii.span, "const fn is unstable");
                 }
             }
             ast::ImplItemKind::Existential(..) => {
@@ -1870,10 +1869,15 @@ fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
                     "existential types are unstable"
                 );
             }
-
-            ast::ImplItemKind::Type(_) if !ii.generics.params.is_empty() => {
-                gate_feature_post!(&self, generic_associated_types, ii.span,
-                                   "generic associated types are unstable");
+            ast::ImplItemKind::Type(_) => {
+                if !ii.generics.params.is_empty() {
+                    gate_feature_post!(&self, generic_associated_types, ii.span,
+                                       "generic associated types are unstable");
+                }
+                if !ii.generics.where_clause.predicates.is_empty() {
+                    gate_feature_post!(&self, generic_associated_types, ii.span,
+                                       "where clauses on associated types are unstable");
+                }
             }
             _ => {}
         }
@@ -2072,16 +2076,6 @@ pub fn check_crate(krate: &ast::Crate,
         plugin_attributes,
     };
 
-    if !features.raw_identifiers {
-        for &span in sess.raw_identifier_spans.borrow().iter() {
-            if !span.allows_unstable() {
-                gate_feature!(&ctx, raw_identifiers, span,
-                    "raw identifiers are experimental and subject to change"
-                );
-            }
-        }
-    }
-
     let visitor = &mut PostExpansionVisitor { context: &ctx };
     visitor.whole_crate_feature_gates(krate);
     visit::walk_crate(visitor, krate);
index 82dae3bc973240c74350dcf5e9b3c4de6f9fd989..dff408d233977b559c99dce845735fba927c8956 100644 (file)
@@ -31,6 +31,7 @@
 use util::move_map::MoveMap;
 
 use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::small_vec::ExpectOne;
 
 pub trait Folder : Sized {
     // Any additions to this trait should happen in form
@@ -972,7 +973,7 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
 
 pub fn noop_fold_trait_item<T: Folder>(i: TraitItem, folder: &mut T)
                                        -> OneVector<TraitItem> {
-    OneVector::one(TraitItem {
+    smallvec![TraitItem {
         id: folder.new_id(i.id),
         ident: folder.fold_ident(i.ident),
         attrs: fold_attrs(i.attrs, folder),
@@ -996,12 +997,12 @@ pub fn noop_fold_trait_item<T: Folder>(i: TraitItem, folder: &mut T)
         },
         span: folder.new_span(i.span),
         tokens: i.tokens,
-    })
+    }]
 }
 
 pub fn noop_fold_impl_item<T: Folder>(i: ImplItem, folder: &mut T)
                                       -> OneVector<ImplItem> {
-    OneVector::one(ImplItem {
+    smallvec![ImplItem {
         id: folder.new_id(i.id),
         vis: folder.fold_vis(i.vis),
         ident: folder.fold_ident(i.ident),
@@ -1024,7 +1025,7 @@ pub fn noop_fold_impl_item<T: Folder>(i: ImplItem, folder: &mut T)
         },
         span: folder.new_span(i.span),
         tokens: i.tokens,
-    })
+    }]
 }
 
 pub fn noop_fold_fn_header<T: Folder>(mut header: FnHeader, folder: &mut T) -> FnHeader {
@@ -1077,7 +1078,7 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, span}: Crate,
 
 // fold one item into possibly many items
 pub fn noop_fold_item<T: Folder>(i: P<Item>, folder: &mut T) -> OneVector<P<Item>> {
-    OneVector::one(i.map(|i| folder.fold_item_simple(i)))
+    smallvec![i.map(|i| folder.fold_item_simple(i))]
 }
 
 // fold one item into exactly one item
@@ -1099,7 +1100,7 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span,
 
 pub fn noop_fold_foreign_item<T: Folder>(ni: ForeignItem, folder: &mut T)
 -> OneVector<ForeignItem> {
-    OneVector::one(folder.fold_foreign_item_simple(ni))
+    smallvec![folder.fold_foreign_item_simple(ni)]
 }
 
 pub fn noop_fold_foreign_item_simple<T: Folder>(ni: ForeignItem, folder: &mut T) -> ForeignItem {
@@ -1361,7 +1362,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
             }
             ExprKind::Yield(ex) => ExprKind::Yield(ex.map(|x| folder.fold_expr(x))),
             ExprKind::Try(ex) => ExprKind::Try(folder.fold_expr(ex)),
-            ExprKind::Catch(body) => ExprKind::Catch(folder.fold_block(body)),
+            ExprKind::TryBlock(body) => ExprKind::TryBlock(folder.fold_block(body)),
         },
         id: folder.new_id(id),
         span: folder.new_span(span),
@@ -1387,7 +1388,7 @@ pub fn noop_fold_stmt<T: Folder>(Stmt {node, span, id}: Stmt, folder: &mut T) ->
 
 pub fn noop_fold_stmt_kind<T: Folder>(node: StmtKind, folder: &mut T) -> OneVector<StmtKind> {
     match node {
-        StmtKind::Local(local) => OneVector::one(StmtKind::Local(folder.fold_local(local))),
+        StmtKind::Local(local) => smallvec![StmtKind::Local(folder.fold_local(local))],
         StmtKind::Item(item) => folder.fold_item(item).into_iter().map(StmtKind::Item).collect(),
         StmtKind::Expr(expr) => {
             folder.fold_opt_expr(expr).into_iter().map(StmtKind::Expr).collect()
@@ -1395,9 +1396,9 @@ pub fn noop_fold_stmt_kind<T: Folder>(node: StmtKind, folder: &mut T) -> OneVect
         StmtKind::Semi(expr) => {
             folder.fold_opt_expr(expr).into_iter().map(StmtKind::Semi).collect()
         }
-        StmtKind::Mac(mac) => OneVector::one(StmtKind::Mac(mac.map(|(mac, semi, attrs)| {
+        StmtKind::Mac(mac) => smallvec![StmtKind::Mac(mac.map(|(mac, semi, attrs)| {
             (folder.fold_mac(mac), semi, fold_attrs(attrs.into(), folder).into())
-        }))),
+        }))],
     }
 }
 
index 289f023cefae390fca0b112cc6a0cb776bff7011..c8ec273a03f2866e4fd77bb57cb02e8c2fff7a04 100644 (file)
 #![feature(crate_visibility_modifier)]
 #![feature(macro_at_most_once_rep)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(rustc_attrs)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
 #![feature(str_escape)]
+#![feature(try_trait)]
 #![feature(unicode_internals)]
-#![feature(catch_expr)]
 
 #![recursion_limit="256"]
 
@@ -40,6 +41,8 @@
 extern crate rustc_data_structures;
 extern crate rustc_target;
 #[macro_use] extern crate scoped_tls;
+#[macro_use]
+extern crate smallvec;
 
 extern crate serialize as rustc_serialize; // used by deriving
 
index 531483e7de120efd0fa8c06d554d0621d3a874b1..99f9d0511fe5e406046be5588594818d66c36089 100644 (file)
@@ -31,7 +31,7 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
         ast::ExprKind::WhileLet(..) |
         ast::ExprKind::Loop(..) |
         ast::ExprKind::ForLoop(..) |
-        ast::ExprKind::Catch(..) => false,
+        ast::ExprKind::TryBlock(..) => false,
         _ => true,
     }
 }
index dde0466f43c2d4cb540094f302327a3bc91cfa78..172a48ddba2d94382e011d6e4488c3b6addc2c85 100644 (file)
@@ -230,7 +230,7 @@ fn trim_whitespace_prefix_and_push_line(lines: &mut Vec<String>, s: String, col:
             if col < len {
                 (&s[col..len]).to_string()
             } else {
-                "".to_string()
+                String::new()
             }
         }
         None => s,
index 448ff9676c927492791e6ac08ec42391fdecfc0f..96584a580f1758d72e5797aee7bb11255362dae1 100644 (file)
@@ -1831,10 +1831,10 @@ mod tests {
     use errors;
     use feature_gate::UnstableFeatures;
     use parse::token;
-    use std::collections::HashSet;
     use std::io;
     use std::path::PathBuf;
     use diagnostics::plugin::ErrorMap;
+    use rustc_data_structures::fx::FxHashSet;
     use rustc_data_structures::sync::Lock;
     use with_globals;
     fn mk_sess(cm: Lrc<SourceMap>) -> ParseSess {
@@ -1845,10 +1845,10 @@ fn mk_sess(cm: Lrc<SourceMap>) -> ParseSess {
         ParseSess {
             span_diagnostic: errors::Handler::with_emitter(true, false, Box::new(emitter)),
             unstable_features: UnstableFeatures::from_environment(),
-            config: CrateConfig::new(),
+            config: CrateConfig::default(),
             included_mod_stack: Lock::new(Vec::new()),
             code_map: cm,
-            missing_fragment_specifiers: Lock::new(HashSet::new()),
+            missing_fragment_specifiers: Lock::new(FxHashSet::default()),
             raw_identifier_spans: Lock::new(Vec::new()),
             registered_diagnostics: Lock::new(ErrorMap::new()),
             non_modrs_mods: Lock::new(vec![]),
index 88ff8582da80194ec0c24936970cf8517f9f350b..03bf1b5a4e1ed53069e3ddc118a04e1bc8ce9007 100644 (file)
@@ -12,7 +12,7 @@
 // http://www.unicode.org/Public/security/10.0.0/confusables.txt
 
 use syntax_pos::{Span, NO_EXPANSION};
-use errors::DiagnosticBuilder;
+use errors::{Applicability, DiagnosticBuilder};
 use super::StringReader;
 
 const UNICODE_ARRAY: &[(char, &str, char)] = &[
                 let msg =
                     format!("Unicode character '{}' ({}) looks like '{}' ({}), but it is not",
                             ch, u_name, ascii_char, ascii_name);
-                err.span_suggestion(span, &msg, ascii_char.to_string());
+                err.span_suggestion_with_applicability(
+                    span,
+                    &msg,
+                    ascii_char.to_string(),
+                    Applicability::MaybeIncorrect);
                 true
             },
             None => {
index adf01197c6d9f3f6b43586763fc6cdb250d06515..28d63399b4461f3c024a30820fb3a43ff2d3b757 100644 (file)
@@ -24,8 +24,8 @@
 use tokenstream::{TokenStream, TokenTree};
 use diagnostics::plugin::ErrorMap;
 
+use rustc_data_structures::fx::FxHashSet;
 use std::borrow::Cow;
-use std::collections::HashSet;
 use std::iter;
 use std::path::{Path, PathBuf};
 use std::str;
@@ -46,7 +46,7 @@ pub struct ParseSess {
     pub span_diagnostic: Handler,
     pub unstable_features: UnstableFeatures,
     pub config: CrateConfig,
-    pub missing_fragment_specifiers: Lock<HashSet<Span>>,
+    pub missing_fragment_specifiers: Lock<FxHashSet<Span>>,
     /// Places where raw identifiers were used. This is used for feature gating
     /// raw identifiers
     pub raw_identifier_spans: Lock<Vec<Span>>,
@@ -75,8 +75,8 @@ pub fn with_span_handler(handler: Handler, code_map: Lrc<SourceMap>) -> ParseSes
         ParseSess {
             span_diagnostic: handler,
             unstable_features: UnstableFeatures::from_environment(),
-            config: HashSet::new(),
-            missing_fragment_specifiers: Lock::new(HashSet::new()),
+            config: FxHashSet::default(),
+            missing_fragment_specifiers: Lock::new(FxHashSet::default()),
             raw_identifier_spans: Lock::new(Vec::new()),
             registered_diagnostics: Lock::new(ErrorMap::new()),
             included_mod_stack: Lock::new(vec![]),
@@ -533,7 +533,7 @@ fn byte_lit(lit: &str) -> (u8, usize) {
 fn byte_str_lit(lit: &str) -> Lrc<Vec<u8>> {
     let mut res = Vec::with_capacity(lit.len());
 
-    let error = |i| format!("lexer should have rejected {} at {}", lit, i);
+    let error = |i| panic!("lexer should have rejected {} at {}", lit, i);
 
     /// Eat everything up to a non-whitespace
     fn eat<I: Iterator<Item=(usize, u8)>>(it: &mut iter::Peekable<I>) {
@@ -552,12 +552,11 @@ fn eat<I: Iterator<Item=(usize, u8)>>(it: &mut iter::Peekable<I>) {
     loop {
         match chars.next() {
             Some((i, b'\\')) => {
-                let em = error(i);
-                match chars.peek().expect(&em).1 {
+                match chars.peek().unwrap_or_else(|| error(i)).1 {
                     b'\n' => eat(&mut chars),
                     b'\r' => {
                         chars.next();
-                        if chars.peek().expect(&em).1 != b'\n' {
+                        if chars.peek().unwrap_or_else(|| error(i)).1 != b'\n' {
                             panic!("lexer accepted bare CR");
                         }
                         eat(&mut chars);
@@ -574,8 +573,7 @@ fn eat<I: Iterator<Item=(usize, u8)>>(it: &mut iter::Peekable<I>) {
                 }
             },
             Some((i, b'\r')) => {
-                let em = error(i);
-                if chars.peek().expect(&em).1 != b'\n' {
+                if chars.peek().unwrap_or_else(|| error(i)).1 != b'\n' {
                     panic!("lexer accepted bare CR");
                 }
                 chars.next();
index ceef03bb6536ec74e09a1638ae1663eff78b2da4..c741bde7c5f24f7d1b4dee695d908ad3f028c4b4 100644 (file)
@@ -684,7 +684,7 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
             let mut i = tokens.iter();
             // This might be a sign we need a connect method on Iterator.
             let b = i.next()
-                     .map_or("".to_string(), |t| t.to_string());
+                     .map_or(String::new(), |t| t.to_string());
             i.enumerate().fold(b, |mut b, (i, a)| {
                 if tokens.len() > 2 && i == tokens.len() - 2 {
                     b.push_str(", or ");
@@ -786,7 +786,12 @@ fn expected_ident_found(&self) -> DiagnosticBuilder<'a> {
         } else {
             err.span_label(self.span, "expected identifier");
             if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
-                err.span_suggestion(self.span, "remove this comma", "".into());
+                err.span_suggestion_with_applicability(
+                    self.span,
+                    "remove this comma",
+                    String::new(),
+                    Applicability::MachineApplicable,
+                );
             }
         }
         err
@@ -1079,12 +1084,13 @@ pub fn parse_seq_to_before_end<T, F>(&mut self,
         self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f)
     }
 
-    fn parse_seq_to_before_tokens<T, F>(&mut self,
-                                            kets: &[&token::Token],
-                                            sep: SeqSep,
-                                            expect: TokenExpectType,
-                                            mut f: F)
-                                            -> PResult<'a, Vec<T>>
+    fn parse_seq_to_before_tokens<T, F>(
+        &mut self,
+        kets: &[&token::Token],
+        sep: SeqSep,
+        expect: TokenExpectType,
+        mut f: F,
+    ) -> PResult<'a, Vec<T>>
         where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
     {
         let mut first: bool = true;
@@ -1375,7 +1381,13 @@ fn parse_trait_item_(&mut self,
                 // This is somewhat dubious; We don't want to allow
                 // argument names to be left off if there is a
                 // definition...
-                p.parse_arg_general(false)
+
+                // We don't allow argument names to be left off in edition 2018.
+                if p.span.edition() >= Edition::Edition2018 {
+                    p.parse_arg_general(true)
+                } else {
+                    p.parse_arg_general(false)
+                }
             })?;
             generics.where_clause = self.parse_where_clause()?;
 
@@ -1756,9 +1768,17 @@ fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> {
 
             let parser_snapshot_before_pat = self.clone();
 
+            // Once we can use edition 2018 in the compiler,
+            // replace this with real try blocks.
+            macro_rules! try_block {
+                ($($inside:tt)*) => (
+                    (||{ ::std::ops::Try::from_ok({ $($inside)* }) })()
+                )
+            }
+
             // We're going to try parsing the argument as a pattern (even though it's not
             // allowed). This way we can provide better errors to the user.
-            let pat_arg: PResult<'a, _> = do catch {
+            let pat_arg: PResult<'a, _> = try_block! {
                 let pat = self.parse_pat()?;
                 self.expect(&token::Colon)?;
                 (pat, self.parse_ty()?)
@@ -2058,12 +2078,12 @@ fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool)
                     TokenExpectType::Expect,
                     |p| p.parse_ty())?;
                 self.bump(); // `)`
+                let span = lo.to(self.prev_span);
                 let output = if self.eat(&token::RArrow) {
                     Some(self.parse_ty_common(false, false)?)
                 } else {
                     None
                 };
-                let span = lo.to(self.prev_span);
                 ParenthesisedArgs { inputs, output, span }.into()
             };
 
@@ -2386,11 +2406,15 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                         BlockCheckMode::Unsafe(ast::UserProvided),
                         attrs);
                 }
-                if self.is_catch_expr() {
+                if self.is_do_catch_block() {
+                    let mut db = self.fatal("found removed `do catch` syntax");
+                    db.help("Following RFC #2388, the new non-placeholder syntax is `try`");
+                    return Err(db);
+                }
+                if self.is_try_block() {
                     let lo = self.span;
-                    assert!(self.eat_keyword(keywords::Do));
-                    assert!(self.eat_keyword(keywords::Catch));
-                    return self.parse_catch_expr(lo, attrs);
+                    assert!(self.eat_keyword(keywords::Try));
+                    return self.parse_try_block(lo, attrs);
                 }
                 if self.eat_keyword(keywords::Return) {
                     if self.token.can_begin_expr() {
@@ -2505,7 +2529,7 @@ fn parse_struct_expr(&mut self, lo: Span, pth: ast::Path, mut attrs: ThinVec<Att
                     err.span_suggestion_short_with_applicability(
                         self.span,
                         "remove this comma",
-                        "".to_owned(),
+                        String::new(),
                         Applicability::MachineApplicable
                     );
                     err.note("the base struct must always be the last field");
@@ -3452,13 +3476,13 @@ pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>)
             ExprKind::Async(capture_clause, ast::DUMMY_NODE_ID, body), attrs))
     }
 
-    /// Parse a `do catch {...}` expression (`do catch` token already eaten)
-    fn parse_catch_expr(&mut self, span_lo: Span, mut attrs: ThinVec<Attribute>)
+    /// Parse a `try {...}` expression (`try` token already eaten)
+    fn parse_try_block(&mut self, span_lo: Span, mut attrs: ThinVec<Attribute>)
         -> PResult<'a, P<Expr>>
     {
         let (iattrs, body) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
-        Ok(self.mk_expr(span_lo.to(body.span), ExprKind::Catch(body), attrs))
+        Ok(self.mk_expr(span_lo.to(body.span), ExprKind::TryBlock(body), attrs))
     }
 
     // `match` token already eaten
@@ -3472,7 +3496,7 @@ fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<E
                 e.span_suggestion_short_with_applicability(
                     match_span,
                     "try removing this `match`",
-                    "".to_owned(),
+                    String::new(),
                     Applicability::MaybeIncorrect // speculative
                 );
             }
@@ -3535,8 +3559,8 @@ fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<E
                         if arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col
                             && expr_lines.lines.len() == 2
                             && self.token == token::FatArrow => {
-                            // We check wether there's any trailing code in the parse span, if there
-                            // isn't, we very likely have the following:
+                            // We check whether there's any trailing code in the parse span,
+                            // if there isn't, we very likely have the following:
                             //
                             // X |     &Y => "y"
                             //   |        --    - missing comma
@@ -3849,7 +3873,7 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<source_map::Spanned<ast::Fiel
                 if self.token == token::CloseDelim(token::Brace) {
                     // If the struct looks otherwise well formed, recover and continue.
                     if let Some(sp) = comma_sp {
-                        err.span_suggestion_short(sp, "remove this comma", "".into());
+                        err.span_suggestion_short(sp, "remove this comma", String::new());
                     }
                     err.emit();
                     break;
@@ -3889,7 +3913,7 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<source_map::Spanned<ast::Fiel
                 err.multipart_suggestion(
                     "move the `..` to the end of the field list",
                     vec![
-                        (etc_span, "".into()),
+                        (etc_span, String::new()),
                         (self.span, format!("{}.. }}", if ate_comma { "" } else { ", " })),
                     ],
                 );
@@ -3934,7 +3958,7 @@ fn parse_as_ident(&mut self) -> bool {
     }
 
     /// A wrapper around `parse_pat` with some special error handling for the
-    /// "top-level" patterns in a match arm, `for` loop, `let`, &c. (in contast
+    /// "top-level" patterns in a match arm, `for` loop, `let`, &c. (in contrast
     /// to subpatterns within such).
     fn parse_top_level_pat(&mut self) -> PResult<'a, P<Pat>> {
         let pat = self.parse_pat()?;
@@ -4322,7 +4346,7 @@ fn recover_stmt(&mut self) {
     // If `break_on_semi` is `Break`, then we will stop consuming tokens after
     // finding (and consuming) a `;` outside of `{}` or `[]` (note that this is
     // approximate - it can mean we break too early due to macros, but that
-    // shoud only lead to sub-optimal recovery, not inaccurate parsing).
+    // should only lead to sub-optimal recovery, not inaccurate parsing).
     //
     // If `break_on_block` is `Break`, then we will stop consuming tokens
     // after finding (and consuming) a brace-delimited block.
@@ -4407,12 +4431,20 @@ fn is_async_block(&mut self) -> bool {
         )
     }
 
-    fn is_catch_expr(&mut self) -> bool {
+    fn is_do_catch_block(&mut self) -> bool {
         self.token.is_keyword(keywords::Do) &&
         self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) &&
         self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace)) &&
+        !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
+    }
+
+    fn is_try_block(&mut self) -> bool {
+        self.token.is_keyword(keywords::Try) &&
+        self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) &&
 
-        // prevent `while catch {} {}`, `if catch {} {} else {}`, etc.
+        self.span.edition() >= Edition::Edition2018 &&
+
+        // prevent `while try {} {}`, `if try {} {} else {}`, etc.
         !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
     }
 
@@ -4887,7 +4919,7 @@ fn err_dotdotdot_syntax(&self, span: Span) {
     fn parse_generic_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, GenericBounds> {
         let mut bounds = Vec::new();
         loop {
-            // This needs to be syncronized with `Token::can_begin_bound`.
+            // This needs to be synchronized with `Token::can_begin_bound`.
             let is_bound_start = self.check_path() || self.check_lifetime() ||
                                  self.check(&token::Question) ||
                                  self.check_keyword(keywords::For) ||
@@ -6056,7 +6088,12 @@ fn parse_single_struct_field(&mut self,
                                                                 self.this_token_to_string()));
                 if self.token.is_ident() {
                     // This is likely another field; emit the diagnostic and keep going
-                    err.span_suggestion(sp, "try adding a comma", ",".into());
+                    err.span_suggestion_with_applicability(
+                        sp,
+                        "try adding a comma",
+                        ",".into(),
+                        Applicability::MachineApplicable,
+                    );
                     err.emit();
                 } else {
                     return Err(err)
@@ -6189,7 +6226,7 @@ fn parse_mod_items(&mut self, term: &token::Token, inner_lo: Span) -> PResult<'a
             if token_str == ";" {
                 let msg = "consider removing this semicolon";
                 err.span_suggestion_short_with_applicability(
-                    self.span, msg, "".to_string(), Applicability::MachineApplicable
+                    self.span, msg, String::new(), Applicability::MachineApplicable
                 );
                 if !items.is_empty() {  // Issue #51603
                     let previous_item = &items[items.len()-1];
@@ -6842,8 +6879,6 @@ fn parse_item_(
     }
 
     /// Parse one of the items allowed by the flags.
-    /// NB: this function no longer parses the items inside an
-    /// extern crate.
     fn parse_item_implementation(
         &mut self,
         attrs: Vec<Attribute>,
index da3ba928effd776a623bab0242a8754428575433..85d29a5be89db03b1e8303e55d3f9907f41a503f 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::AnnNode::*;
-
 use rustc_target::spec::abi::{self, Abi};
 use ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
 use ast::{SelfKind, GenericBound, TraitBoundModifier};
 use std::vec;
 
 pub enum AnnNode<'a> {
-    NodeIdent(&'a ast::Ident),
-    NodeName(&'a ast::Name),
-    NodeBlock(&'a ast::Block),
-    NodeItem(&'a ast::Item),
-    NodeSubItem(ast::NodeId),
-    NodeExpr(&'a ast::Expr),
-    NodePat(&'a ast::Pat),
+    Ident(&'a ast::Ident),
+    Name(&'a ast::Name),
+    Block(&'a ast::Block),
+    Item(&'a ast::Item),
+    SubItem(ast::NodeId),
+    Expr(&'a ast::Expr),
+    Pat(&'a ast::Pat),
 }
 
 pub trait PpAnn {
@@ -1196,7 +1194,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
         self.hardbreak_if_not_bol()?;
         self.maybe_print_comment(item.span.lo())?;
         self.print_outer_attributes(&item.attrs)?;
-        self.ann.pre(self, NodeItem(item))?;
+        self.ann.pre(self, AnnNode::Item(item))?;
         match item.node {
             ast::ItemKind::ExternCrate(orig_name) => {
                 self.head(&visibility_qualified(&item.vis, "extern crate"))?;
@@ -1439,7 +1437,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 self.end()?;
             }
         }
-        self.ann.post(self, NodeItem(item))
+        self.ann.post(self, AnnNode::Item(item))
     }
 
     fn print_trait_ref(&mut self, t: &ast::TraitRef) -> io::Result<()> {
@@ -1596,7 +1594,7 @@ pub fn print_method_sig(&mut self,
 
     pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
                             -> io::Result<()> {
-        self.ann.pre(self, NodeSubItem(ti.id))?;
+        self.ann.pre(self, AnnNode::SubItem(ti.id))?;
         self.hardbreak_if_not_bol()?;
         self.maybe_print_comment(ti.span.lo())?;
         self.print_outer_attributes(&ti.attrs)?;
@@ -1638,11 +1636,11 @@ pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
                 }
             }
         }
-        self.ann.post(self, NodeSubItem(ti.id))
+        self.ann.post(self, AnnNode::SubItem(ti.id))
     }
 
     pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
-        self.ann.pre(self, NodeSubItem(ii.id))?;
+        self.ann.pre(self, AnnNode::SubItem(ii.id))?;
         self.hardbreak_if_not_bol()?;
         self.maybe_print_comment(ii.span.lo())?;
         self.print_outer_attributes(&ii.attrs)?;
@@ -1672,7 +1670,7 @@ pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
                 }
             }
         }
-        self.ann.post(self, NodeSubItem(ii.id))
+        self.ann.post(self, AnnNode::SubItem(ii.id))
     }
 
     pub fn print_stmt(&mut self, st: &ast::Stmt) -> io::Result<()> {
@@ -1756,7 +1754,7 @@ pub fn print_block_maybe_unclosed(&mut self,
             BlockCheckMode::Default => ()
         }
         self.maybe_print_comment(blk.span.lo())?;
-        self.ann.pre(self, NodeBlock(blk))?;
+        self.ann.pre(self, AnnNode::Block(blk))?;
         self.bopen()?;
 
         self.print_inner_attributes(attrs)?;
@@ -1774,7 +1772,7 @@ pub fn print_block_maybe_unclosed(&mut self,
         }
 
         self.bclose_maybe_open(blk.span, indented, close_box)?;
-        self.ann.post(self, NodeBlock(blk))
+        self.ann.post(self, AnnNode::Block(blk))
     }
 
     fn print_else(&mut self, els: Option<&ast::Expr>) -> io::Result<()> {
@@ -2065,7 +2063,7 @@ fn print_expr_outer_attr_style(&mut self,
         }
 
         self.ibox(INDENT_UNIT)?;
-        self.ann.pre(self, NodeExpr(expr))?;
+        self.ann.pre(self, AnnNode::Expr(expr))?;
         match expr.node {
             ast::ExprKind::Box(ref expr) => {
                 self.word_space("box")?;
@@ -2379,13 +2377,13 @@ fn print_expr_outer_attr_style(&mut self,
                 self.print_expr_maybe_paren(e, parser::PREC_POSTFIX)?;
                 self.s.word("?")?
             }
-            ast::ExprKind::Catch(ref blk) => {
-                self.head("do catch")?;
+            ast::ExprKind::TryBlock(ref blk) => {
+                self.head("try")?;
                 self.s.space()?;
                 self.print_block_with_attrs(blk, attrs)?
             }
         }
-        self.ann.post(self, NodeExpr(expr))?;
+        self.ann.post(self, AnnNode::Expr(expr))?;
         self.end()
     }
 
@@ -2404,7 +2402,7 @@ pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
         } else {
             self.s.word(&ident.as_str())?;
         }
-        self.ann.post(self, NodeIdent(&ident))
+        self.ann.post(self, AnnNode::Ident(&ident))
     }
 
     pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
@@ -2413,7 +2411,7 @@ pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
 
     pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> {
         self.s.word(&name.as_str())?;
-        self.ann.post(self, NodeName(&name))
+        self.ann.post(self, AnnNode::Name(&name))
     }
 
     pub fn print_for_decl(&mut self, loc: &ast::Local,
@@ -2537,7 +2535,7 @@ fn print_generic_args(&mut self,
 
     pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
         self.maybe_print_comment(pat.span.lo())?;
-        self.ann.pre(self, NodePat(pat))?;
+        self.ann.pre(self, AnnNode::Pat(pat))?;
         /* Pat isn't normalized, but the beauty of it
          is that it doesn't matter */
         match pat.node {
@@ -2675,7 +2673,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
             }
             PatKind::Mac(ref m) => self.print_mac(m)?,
         }
-        self.ann.post(self, NodePat(pat))
+        self.ann.post(self, AnnNode::Pat(pat))
     }
 
     fn print_pats(&mut self, pats: &[P<ast::Pat>]) -> io::Result<()> {
index c65931a8577183452e063f0019edb2c7f46463bd..8f91db8efa71a66a9096560dd73557040a29f0a3 100644 (file)
@@ -1030,7 +1030,7 @@ fn init_code_map() -> SourceMap {
         cm.new_source_file(PathBuf::from("blork.rs").into(),
                        "first line.\nsecond line".to_string());
         cm.new_source_file(PathBuf::from("empty.rs").into(),
-                       "".to_string());
+                       String::new());
         cm.new_source_file(PathBuf::from("blork2.rs").into(),
                        "first line.\nsecond line".to_string());
         cm
index 988f50b4f0c9ed845d7d5d3ac0cd8386e06ea966..49ab0c2256e89674c3e983217f79daad314345bf 100644 (file)
@@ -41,6 +41,7 @@
 use OneVector;
 use symbol::{self, Symbol, keywords};
 use ThinVec;
+use rustc_data_structures::small_vec::ExpectOne;
 
 enum ShouldPanic {
     No,
@@ -183,7 +184,7 @@ fn fold_item(&mut self, i: P<ast::Item>) -> OneVector<P<ast::Item>> {
         if ident.name != keywords::Invalid.name() {
             self.cx.path.pop();
         }
-        OneVector::one(P(item))
+        smallvec![P(item)]
     }
 
     fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { mac }
@@ -235,7 +236,7 @@ fn fold_item(&mut self, i: P<ast::Item>) -> OneVector<P<ast::Item>> {
             EntryPointType::OtherMain => folded,
         };
 
-        OneVector::one(folded)
+        smallvec![folded]
     }
 
     fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { mac }
index 67bc6f947b59a52c0132efe402ec302eaed3513c..6866806cd7c669d0f19af0ce25c8efb3855cfed1 100644 (file)
@@ -273,7 +273,7 @@ pub enum ExprPrecedence {
     Loop,
     Match,
     Block,
-    Catch,
+    TryBlock,
     Struct,
     Async,
 }
@@ -332,7 +332,7 @@ pub fn order(self) -> i8 {
             ExprPrecedence::Loop |
             ExprPrecedence::Match |
             ExprPrecedence::Block |
-            ExprPrecedence::Catch |
+            ExprPrecedence::TryBlock |
             ExprPrecedence::Async |
             ExprPrecedence::Struct => PREC_PAREN,
         }
index fccc80b668f3e25fe61f0ab1f7e51f0a9164e67a..77311bf53fd1e84e5c0b1e5f9fc190993e0ed133 100644 (file)
@@ -809,7 +809,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
         ExprKind::Try(ref subexpression) => {
             visitor.visit_expr(subexpression)
         }
-        ExprKind::Catch(ref body) => {
+        ExprKind::TryBlock(ref body) => {
             visitor.visit_block(body)
         }
     }
index 1676757d9b89da186cae413333749efe3a85f9fa..8dba34583bef3ff25b1d8045a77dfc1a938f8285 100644 (file)
@@ -15,4 +15,5 @@ rustc_errors = { path = "../librustc_errors" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 rustc_data_structures = { path = "../librustc_data_structures" }
-rustc_target = { path = "../librustc_target" }
\ No newline at end of file
+rustc_target = { path = "../librustc_target" }
+smallvec = { version = "0.6.5", features = ["union"] }
index d97c0b14f797a998fa8bff2701b97f412d749b32..efe9c2cefdebe93b3e1e4f646e2b2093061ae5b3 100644 (file)
 use syntax::symbol::Symbol;
 use syntax::tokenstream;
 use syntax_pos::{MultiSpan, Span, DUMMY_SP};
+use errors::Applicability;
 
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use std::borrow::Cow;
 use std::collections::hash_map::Entry;
-use std::collections::{HashMap, HashSet};
 
 #[derive(PartialEq)]
 enum ArgumentType {
@@ -64,7 +65,7 @@ struct Context<'a, 'b: 'a> {
     /// Unique format specs seen for each argument.
     arg_unique_types: Vec<Vec<ArgumentType>>,
     /// Map from named arguments to their resolved indices.
-    names: HashMap<String, usize>,
+    names: FxHashMap<String, usize>,
 
     /// The latest consecutive literal strings, or empty if there weren't any.
     literal: String,
@@ -103,7 +104,7 @@ struct Context<'a, 'b: 'a> {
     /// * `count_args`: `vec![Exact(0), Exact(5), Exact(3)]`
     count_args: Vec<Position>,
     /// Relative slot numbers for count arguments.
-    count_positions: HashMap<usize, usize>,
+    count_positions: FxHashMap<usize, usize>,
     /// Number of count slots assigned.
     count_positions_count: usize,
 
@@ -117,7 +118,7 @@ struct Context<'a, 'b: 'a> {
     invalid_refs: Vec<(usize, usize)>,
     /// Spans of all the formatting arguments, in order.
     arg_spans: Vec<Span>,
-    /// Wether this formatting string is a literal or it comes from a macro.
+    /// Whether this formatting string is a literal or it comes from a macro.
     is_literal: bool,
 }
 
@@ -133,9 +134,9 @@ struct Context<'a, 'b: 'a> {
 fn parse_args(ecx: &mut ExtCtxt,
               sp: Span,
               tts: &[tokenstream::TokenTree])
-              -> Option<(P<ast::Expr>, Vec<P<ast::Expr>>, HashMap<String, usize>)> {
+              -> Option<(P<ast::Expr>, Vec<P<ast::Expr>>, FxHashMap<String, usize>)> {
     let mut args = Vec::<P<ast::Expr>>::new();
-    let mut names = HashMap::<String, usize>::new();
+    let mut names = FxHashMap::<String, usize>::default();
 
     let mut p = ecx.new_parser_from_tts(tts);
 
@@ -767,7 +768,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
                                     sp: Span,
                                     efmt: P<ast::Expr>,
                                     args: Vec<P<ast::Expr>>,
-                                    names: HashMap<String, usize>,
+                                    names: FxHashMap<String, usize>,
                                     append_newline: bool)
                                     -> P<ast::Expr> {
     // NOTE: this verbose way of initializing `Vec<Vec<ArgumentType>>` is because
@@ -791,10 +792,11 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
                 0 => "{}".to_string(),
                 _ => format!("{}{{}}", "{} ".repeat(args.len())),
             };
-            err.span_suggestion(
+            err.span_suggestion_with_applicability(
                 fmt_sp.shrink_to_lo(),
                 "you might be missing a string literal to format with",
                 format!("\"{}\", ", sugg_fmt),
+                Applicability::MaybeIncorrect,
             );
             err.emit();
             return DummyResult::raw_expr(sp);
@@ -850,7 +852,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
         curpiece: 0,
         arg_index_map: Vec::new(),
         count_args: Vec::new(),
-        count_positions: HashMap::new(),
+        count_positions: FxHashMap::default(),
         count_positions_count: 0,
         count_args_index_offset: 0,
         literal: String::new(),
@@ -950,7 +952,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
 
             // The set of foreign substitutions we've explained.  This prevents spamming the user
             // with `%d should be written as {}` over and over again.
-            let mut explained = HashSet::new();
+            let mut explained = FxHashSet::default();
 
             macro_rules! check_foreign {
                 ($kind:ident) => {{
index 56f28d04e9d5c4bd8bc8f09eb79cbcd851df2867..1130a50537d017150d48e7e8e761d51522ee91da 100644 (file)
@@ -18,8 +18,6 @@
 /// LLVM's `module asm "some assembly here"`. All of LLVM's caveats
 /// therefore apply.
 
-use rustc_data_structures::small_vec::OneVector;
-
 use syntax::ast;
 use syntax::source_map::respan;
 use syntax::ext::base;
@@ -52,7 +50,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt,
         None => return DummyResult::any(sp),
     };
 
-    MacEager::items(OneVector::one(P(ast::Item {
+    MacEager::items(smallvec![P(ast::Item {
         ident: ast::Ident::with_empty_ctxt(Symbol::intern("")),
         attrs: Vec::new(),
         id: ast::DUMMY_NODE_ID,
@@ -63,5 +61,5 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt,
         vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
         span: sp,
         tokens: None,
-    })))
+    })])
 }
index 1ba4ab474258c76939a18a9ee8e6d0c81b78a667..84436b4e4eacf84cfcfc0d2bb8d535abb3a2a558 100644 (file)
@@ -17,6 +17,7 @@
 #![feature(proc_macro_internals)]
 #![feature(decl_macro)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(str_escape)]
 
 #![feature(rustc_diagnostic_macros)]
@@ -29,6 +30,8 @@
 extern crate rustc_data_structures;
 extern crate rustc_errors as errors;
 extern crate rustc_target;
+#[macro_use]
+extern crate smallvec;
 
 mod diagnostics;
 
index 670fd5b872d92f96b5736378399c87333e14de0a..7e985cf52f550d1aa1f8c95cd5ba9fbdd0dad2b6 100644 (file)
@@ -21,8 +21,7 @@
 use symbol::Symbol;
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
-use std::collections::HashMap;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use std::fmt;
 
 /// A SyntaxContext represents a chain of macro expansions (represented by marks).
@@ -108,14 +107,7 @@ pub fn expn_info(self) -> Option<ExpnInfo> {
 
     #[inline]
     pub fn set_expn_info(self, info: ExpnInfo) {
-        HygieneData::with(|data| {
-            let old_info = &mut data.marks[self.0 as usize].expn_info;
-            if let Some(old_info) = old_info {
-                panic!("expansion info is reset for the mark {}\nold: {:#?}\nnew: {:#?}",
-                       self.0, old_info, info);
-            }
-            *old_info = Some(info);
-        })
+        HygieneData::with(|data| data.marks[self.0 as usize].expn_info = Some(info))
     }
 
     #[inline]
@@ -197,7 +189,7 @@ pub fn looks_like_proc_macro_derive(self) -> bool {
 crate struct HygieneData {
     marks: Vec<MarkData>,
     syntax_contexts: Vec<SyntaxContextData>,
-    markings: HashMap<(SyntaxContext, Mark, Transparency), SyntaxContext>,
+    markings: FxHashMap<(SyntaxContext, Mark, Transparency), SyntaxContext>,
     default_edition: Edition,
 }
 
@@ -219,7 +211,7 @@ impl HygieneData {
                 opaque: SyntaxContext(0),
                 opaque_and_semitransparent: SyntaxContext(0),
             }],
-            markings: HashMap::new(),
+            markings: FxHashMap::default(),
             default_edition: Edition::Edition2015,
         }
     }
@@ -238,7 +230,7 @@ pub fn set_default_edition(edition: Edition) {
 }
 
 pub fn clear_markings() {
-    HygieneData::with(|data| data.markings = HashMap::new());
+    HygieneData::with(|data| data.markings = FxHashMap::default());
 }
 
 impl SyntaxContext {
@@ -595,7 +587,7 @@ pub fn name(&self) -> Symbol {
 #[derive(Clone, Copy, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
 pub enum CompilerDesugaringKind {
     QuestionMark,
-    Catch,
+    TryBlock,
     /// Desugaring of an `impl Trait` in return type position
     /// to an `existential type Foo: Trait;` + replacing the
     /// `impl Trait` with `Foo`.
@@ -609,7 +601,7 @@ pub fn name(self) -> Symbol {
         Symbol::intern(match self {
             CompilerDesugaringKind::Async => "async",
             CompilerDesugaringKind::QuestionMark => "?",
-            CompilerDesugaringKind::Catch => "do catch",
+            CompilerDesugaringKind::TryBlock => "try block",
             CompilerDesugaringKind::ExistentialReturnType => "existential type",
             CompilerDesugaringKind::ForLoop => "for loop",
         })
index bd70344b018127992879e1f0684868c91cad8035..a493ea4f565ea92139e26680770781557ad79818 100644 (file)
@@ -22,6 +22,7 @@
 #![feature(crate_visibility_modifier)]
 #![feature(custom_attribute)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(non_exhaustive)]
 #![feature(optin_builtin_traits)]
 #![feature(specialization)]
index 62f22475e7de750cdd0179eb564f83fb681960a1..defdca9abd15ae89ab057f20b2cb057ec759ecd3 100644 (file)
@@ -415,23 +415,25 @@ pub fn fresh() -> Self {
 
     // Edition-specific keywords reserved for future use.
     (51, Async,              "async") // >= 2018 Edition Only
+    (52, Try,                "try") // >= 2018 Edition Only
 
     // Special lifetime names
-    (52, UnderscoreLifetime, "'_")
-    (53, StaticLifetime,     "'static")
+    (53, UnderscoreLifetime, "'_")
+    (54, StaticLifetime,     "'static")
 
     // Weak keywords, have special meaning only in specific contexts.
-    (54, Auto,               "auto")
-    (55, Catch,              "catch")
-    (56, Default,            "default")
-    (57, Dyn,                "dyn")
-    (58, Union,              "union")
-    (59, Existential,        "existential")
+    (55, Auto,               "auto")
+    (56, Catch,              "catch")
+    (57, Default,            "default")
+    (58, Dyn,                "dyn")
+    (59, Union,              "union")
+    (60, Existential,        "existential")
 }
 
 impl Symbol {
     fn is_unused_keyword_2018(self) -> bool {
-        self == keywords::Async.name()
+        self >= keywords::Async.name() &&
+        self <= keywords::Try.name()
     }
 }
 
@@ -586,7 +588,7 @@ pub fn with<F: FnOnce(&str) -> R, R>(self, f: F) -> R {
         });
         // This is safe because the interner keeps string alive until it is dropped.
         // We can access it because we know the interner is still alive since we use a
-        // scoped thread local to access it, and it was alive at the begining of this scope
+        // scoped thread local to access it, and it was alive at the beginning of this scope
         unsafe { f(&*str) }
     }
 
index a49fd67639dbe5210fe1118a2f1e672f8958f7b5..df90be6393743a75dfc058d41c556c3116a1e580 100644 (file)
@@ -51,6 +51,7 @@
 // Handle rustfmt skips
 #![feature(custom_attribute)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![allow(unused_attributes)]
 
 use std::io::prelude::*;
index 89235d897bde6bc218e2e95766506cd598d38fd7..f7e0788a884c3a60586decd5d7e2d67c4db16344 100644 (file)
@@ -102,7 +102,7 @@ fn write_result(
                 let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize;
 
                 let mbps = if bs.mb_s == 0 {
-                    "".into()
+                    String::new()
                 } else {
                     format!(r#", "mib_per_second": {}"#, bs.mb_s)
                 };
index 22a06b9f605dbdc66f5b70bdfb2fd84b5b079141..6f7dfee53facc423fa5919c854be3c9c00a26043 100644 (file)
@@ -18,6 +18,7 @@ pub(crate) struct TerseFormatter<T> {
     max_name_len: usize,
 
     test_count: usize,
+    total_test_count: usize,
 }
 
 impl<T: Write> TerseFormatter<T> {
@@ -33,6 +34,7 @@ pub fn new(
             max_name_len,
             is_multithreaded,
             test_count: 0,
+            total_test_count: 0, // initialized later, when write_run_start is called
         }
     }
 
@@ -66,7 +68,8 @@ pub fn write_short_result(
             // we insert a new line every 100 dots in order to flush the
             // screen when dealing with line-buffered output (e.g. piping to
             // `stamp` in the rust CI).
-            self.write_plain("\n")?;
+            let out = format!(" {}/{}\n", self.test_count+1, self.total_test_count);
+            self.write_plain(&out)?;
         }
 
         self.test_count += 1;
@@ -160,6 +163,7 @@ fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> {
 
 impl<T: Write> OutputFormatter for TerseFormatter<T> {
     fn write_run_start(&mut self, test_count: usize) -> io::Result<()> {
+        self.total_test_count = test_count;
         let noun = if test_count != 1 { "tests" } else { "test" };
         self.write_plain(&format!("\nrunning {} {}\n", test_count, noun))
     }
index 060ea1ea9b1329634d2ab6281b467c302563a1d9..d993c6244fc163d7241095a4ff62200d81922ae2 100644 (file)
@@ -36,6 +36,7 @@
 #![feature(fnbox)]
 #![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(set_stdio)]
 #![feature(panic_unwind)]
 #![feature(staged_api)]
@@ -1183,7 +1184,7 @@ fn get_concurrency() -> usize {
     };
 
     #[cfg(windows)]
-    #[allow(bad_style)]
+    #[allow(nonstandard_style)]
     fn num_cpus() -> usize {
         #[repr(C)]
         struct SYSTEM_INFO {
index 424a7e3d009ecaa6c930c200c7819552b7609e89..3b94dc238d91cf9aab3686fc3671bb4caa4b9e11 100644 (file)
@@ -14,6 +14,7 @@
 #![feature(cfg_target_vendor)]
 #![feature(link_cfg)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(staged_api)]
 #![feature(unwind_attributes)]
 #![feature(static_nobundle)]
index 73a259bd4438e90edf46788f7be470412d4e0ec8..43c3e1e7666239568d219c4dd2299e8ae8521132 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(bad_style)]
+#![allow(nonstandard_style)]
 
 macro_rules! cfg_if {
     ( $( if #[cfg( $meta:meta )] { $($it1:item)* } else { $($it2:item)* } )* ) =>
index e19f07f5a6e5546ab4f6ea951e3c6b8627edeaa7..2a1cdeadd3ea8e1eba9cc681037b83f07332763b 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit e19f07f5a6e5546ab4f6ea951e3c6b8627edeaa7
+Subproject commit 2a1cdeadd3ea8e1eba9cc681037b83f07332763b
index d9fbd494ab3484ed3f4ae519eb08380291479895..09befdaae37c5971a331f2c19376876c1d21491c 100644 (file)
@@ -359,6 +359,12 @@ extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) {
 }
 #endif
 
+extern "C" const char* LLVMRustGetHostCPUName(size_t *len) {
+  StringRef Name = sys::getHostCPUName();
+  *len = Name.size();
+  return Name.data();
+}
+
 extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
     const char *TripleStr, const char *CPU, const char *Feature,
     LLVMRustCodeModel RustCM, LLVMRustRelocMode RustReloc,
@@ -381,11 +387,6 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
     return nullptr;
   }
 
-  StringRef RealCPU = CPU;
-  if (RealCPU == "native") {
-    RealCPU = sys::getHostCPUName();
-  }
-
   TargetOptions Options;
 
   Options.FloatABIType = FloatABI::Default;
@@ -417,7 +418,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
   if (RustCM != LLVMRustCodeModel::None)
     CM = fromRust(RustCM);
   TargetMachine *TM = TheTarget->createTargetMachine(
-      Trip.getTriple(), RealCPU, Feature, Options, RM, CM, OptLevel);
+      Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel);
   return wrap(TM);
 }
 
@@ -556,7 +557,8 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
   }
 
 #if LLVM_VERSION_GE(7, 0)
-  unwrap(Target)->addPassesToEmitFile(*PM, OS, nullptr, FileType, false);
+  buffer_ostream BOS(OS);
+  unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, false);
 #else
   unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
 #endif
index 7da830e1125bab2f7e2788ab8a4546d7b7584d05..24a384fceb857fe17e5c2553dff5df6a5396d5b9 100644 (file)
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2018-08-02
+2018-08-22
index 7a16b22a023c44e3728e80503f3f74ae7308f467..2951ee4f6c94bf7f56b8efea7df0dd9f9cf58ec4 100644 (file)
@@ -28,7 +28,7 @@ fn start(_: isize, _: *const *const u8) -> isize {
     let _: (char, u32) = Trait::without_default_impl(0);
 
     // Currently, no object code is generated for trait methods with default
-    // implemenations, unless they are actually called from somewhere. Therefore
+    // implementations, unless they are actually called from somewhere. Therefore
     // we cannot import the implementations and have to create our own inline.
     //~ MONO_ITEM fn cgu_export_trait_method::Trait[0]::with_default_impl[0]<u32>
     let _ = Trait::with_default_impl(0u32);
index c2ff846721c5f87584197f6bd1f8b99f88cea85c..14624176436000dbd682ee8d1b1aa564a70a92d9 100644 (file)
@@ -13,7 +13,7 @@
 
 // NB: We do not expect *any* monomorphization to be generated here.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 #![deny(dead_code)]
 #![crate_type = "rlib"]
 
index 09031508da1f709e6a2fee06854b163974a79169..0bd021f8ae2d68a90127754ec2a9e1719a339e27 100644 (file)
@@ -120,13 +120,13 @@ pub fn unsafe_slice(_: &[UnsafeInner]) {
 pub fn str(_: &[u8]) {
 }
 
-// CHECK: @trait_borrow({}* nonnull %arg0.0, [4 x [[USIZE]]]* noalias readonly dereferenceable({{.*}}) %arg0.1)
+// CHECK: @trait_borrow({}* nonnull %arg0.0, [3 x [[USIZE]]]* noalias readonly dereferenceable({{.*}}) %arg0.1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn trait_borrow(_: &Drop) {
 }
 
-// CHECK: @trait_box({}* noalias nonnull, [4 x [[USIZE]]]* noalias readonly dereferenceable({{.*}}))
+// CHECK: @trait_box({}* noalias nonnull, [3 x [[USIZE]]]* noalias readonly dereferenceable({{.*}}))
 #[no_mangle]
 pub fn trait_box(_: Box<Drop>) {
 }
index 9cabcd9157a6acdb78fcb3b2233aa497477d690e..3ea20aa921e1bf6f6646bf9aa3a7dceae2432da3 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-flags:-Clink-dead-code
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 #![crate_type = "rlib"]
 
 // This test makes sure that, when -Clink-dead-code is specified, we generate
index 7303af73cac9ef9b17112311e519b64287230e76..c965a3ed86c82d7336d47961b9a95f69935d4f84 100644 (file)
@@ -12,7 +12,7 @@
 
 #![feature(plugin_registrar, rustc_private)]
 #![feature(box_syntax)]
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 #![feature(macro_at_most_once_rep)]
 
 #[macro_use] extern crate rustc;
index 3f3997726c93996e6846bfa3a73c69ef36a2e9f2..082f15a39dd955254c7b94b62ef41ef0eeb9f295 100644 (file)
@@ -12,7 +12,7 @@
 
 #![feature(plugin_registrar)]
 #![feature(box_syntax, rustc_private)]
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 #![feature(macro_at_most_once_rep)]
 
 // Load rustc as a plugin to get macros
@@ -49,5 +49,5 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_late_lint_pass(box Pass);
-    reg.register_lint_group("lint_me", vec![TEST_LINT, PLEASE_LINT]);
+    reg.register_lint_group("lint_me", None, vec![TEST_LINT, PLEASE_LINT]);
 }
index ab39709c529dcd3298361937db77ad02f761c942..315dad7eea515279f0aa1d06b15ba5ea2ded568b 100644 (file)
@@ -12,7 +12,7 @@
 
 #![feature(plugin_registrar)]
 #![feature(box_syntax, rustc_private)]
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 #![feature(macro_at_most_once_rep)]
 
 extern crate syntax;
index eedc1e745e270c15d883ce060277aac5f767e734..f46d906d865a8bccdeb87282d2610b0fd47d7b0b 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // This crate attempts to enumerate the various scenarios for how a
-// type can define fields and methods with various visiblities and
+// type can define fields and methods with various visibilities and
 // stabilities.
 //
 // The basic stability pattern in this file has four cases:
@@ -23,7 +23,7 @@
 //
 // However, since stability attributes can only be observed in
 // cross-crate linkage scenarios, there is little reason to take the
-// cross-product (4 stability cases * 4 visiblity cases), because the
+// cross-product (4 stability cases * 4 visibility cases), because the
 // first three visibility cases cannot be accessed outside this crate,
 // and therefore stability is only relevant when the visibility is pub
 // to the whole universe.
index 4d89384137b8006c5d38a9eb20b8c3fd80ed627f..67fe93058aa8936270017b6c3eeee0b72c2c415d 100644 (file)
 
 use proc_macro::*;
 
-#[proc_macro_attribute]
-pub fn attr2mod(_: TokenStream, _: TokenStream) -> TokenStream {
-    "mod test {}".parse().unwrap()
-}
-
 #[proc_macro_attribute]
 pub fn attr2mac1(_: TokenStream, _: TokenStream) -> TokenStream {
     "macro_rules! foo1 { (a) => (a) }".parse().unwrap()
@@ -31,11 +26,6 @@ pub fn attr2mac2(_: TokenStream, _: TokenStream) -> TokenStream {
     "macro foo2(a) { a }".parse().unwrap()
 }
 
-#[proc_macro]
-pub fn mac2mod(_: TokenStream) -> TokenStream {
-    "mod test2 {}".parse().unwrap()
-}
-
 #[proc_macro]
 pub fn mac2mac1(_: TokenStream) -> TokenStream {
     "macro_rules! foo3 { (a) => (a) }".parse().unwrap()
@@ -49,7 +39,6 @@ pub fn mac2mac2(_: TokenStream) -> TokenStream {
 #[proc_macro]
 pub fn tricky(_: TokenStream) -> TokenStream {
     "fn foo() {
-        mod test {}
         macro_rules! foo { (a) => (a) }
     }".parse().unwrap()
 }
index b7ab978b8ed0a9714eb61008495091faf1702908..4c038179544ffff75f9ca952fbcf82ff8ee43a64 100644 (file)
@@ -14,9 +14,6 @@
 
 use foo::*;
 
-#[attr2mod]
-//~^ ERROR: cannot expand to modules
-pub fn a() {}
 #[attr2mac1]
 //~^ ERROR: cannot expand to macro definitions
 pub fn a() {}
@@ -24,12 +21,10 @@ pub fn a() {}
 //~^ ERROR: cannot expand to macro definitions
 pub fn a() {}
 
-mac2mod!(); //~ ERROR: cannot expand to modules
 mac2mac1!(); //~ ERROR: cannot expand to macro definitions
 mac2mac2!(); //~ ERROR: cannot expand to macro definitions
 
 tricky!();
-//~^ ERROR: cannot expand to modules
-//~| ERROR: cannot expand to macro definitions
+//~^ ERROR: cannot expand to macro definitions
 
 fn main() {}
index 0798aa549f0b2cd4d2a8ac905551509ad165be54..5cf65103ba3ebd61cde98e0737e4617678b29139 100644 (file)
@@ -10,7 +10,6 @@
 
 // aux-build:proc-macro-gates.rs
 // gate-test-proc_macro_non_items
-// gate-test-proc_macro_path_invoc
 // gate-test-proc_macro_mod line
 // gate-test-proc_macro_expr
 // gate-test-proc_macro_mod
 
 use foo::*;
 
-#[foo::a] //~ ERROR: paths of length greater than one
-fn _test() {}
-
 fn _test_inner() {
     #![a] // OK
 }
 
 #[a] //~ ERROR: custom attributes cannot be applied to modules
-//~| ERROR: procedural macros cannot expand to modules
 mod _test2 {}
 
 mod _test2_inner {
     #![a] //~ ERROR: custom attributes cannot be applied to modules
-    //~| ERROR: procedural macros cannot expand to modules
 }
 
 #[a = y] //~ ERROR: must only be followed by a delimiter token
index db16ac325ac595c8d93335623d8e90c67a3859b8..e3b4fba176e3c2be517e4ac7672dbf62a7f36df1 100644 (file)
 // no-prefer-dynamic
 
 #![crate_type = "rlib"]
-#![feature(panic_implementation)]
+#![feature(panic_handler)]
 #![no_std]
 
 use core::panic::PanicInfo;
 
-#[panic_implementation]
+#[panic_handler]
 fn panic(info: &PanicInfo) -> ! {
     loop {}
 }
index a5ba9ef9bd35dd844d1ea5d1ca2a30cd6b572823..fea81f0cc8fa4c6a48f2600646aa58d7caadd19b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 #![feature(cfg_target_thread_local, thread_local_internals)]
 
 // On platforms *without* `#[thread_local]`, use
diff --git a/src/test/compile-fail/panic-handler-missing.rs b/src/test/compile-fail/panic-handler-missing.rs
new file mode 100644 (file)
index 0000000..d17c19b
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern: `#[panic_handler]` function required, but not found
+
+#![feature(lang_items)]
+#![no_main]
+#![no_std]
+
+#[lang = "eh_personality"]
+fn eh() {}
diff --git a/src/test/compile-fail/panic-handler-twice.rs b/src/test/compile-fail/panic-handler-twice.rs
new file mode 100644 (file)
index 0000000..6c9515c
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:some-panic-impl.rs
+
+#![feature(panic_handler)]
+#![feature(lang_items)]
+#![no_std]
+#![no_main]
+
+extern crate some_panic_impl;
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+    //~^ error duplicate lang item found: `panic_impl`
+    loop {}
+}
+
+#[lang = "eh_personality"]
+fn eh() {}
diff --git a/src/test/compile-fail/panic-implementation-missing.rs b/src/test/compile-fail/panic-implementation-missing.rs
deleted file mode 100644 (file)
index b11081a..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern: `#[panic_implementation]` function required, but not found
-
-#![feature(lang_items)]
-#![no_main]
-#![no_std]
-
-#[lang = "eh_personality"]
-fn eh() {}
diff --git a/src/test/compile-fail/panic-implementation-twice.rs b/src/test/compile-fail/panic-implementation-twice.rs
deleted file mode 100644 (file)
index 78dc545..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:some-panic-impl.rs
-
-#![feature(panic_implementation)]
-#![feature(lang_items)]
-#![no_std]
-#![no_main]
-
-extern crate some_panic_impl;
-
-use core::panic::PanicInfo;
-
-#[panic_implementation]
-fn panic(info: &PanicInfo) -> ! {
-    //~^ error duplicate lang item found: `panic_impl`
-    loop {}
-}
-
-#[lang = "eh_personality"]
-fn eh() {}
index 42972c40674b68e31e67d93f9fa24c83f59e6ad1..493c708018177e7f9ffb4dfe88f6d04e49eb42a1 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // aux-build:weak-lang-items.rs
-// error-pattern: `#[panic_implementation]` function required, but not found
+// error-pattern: `#[panic_handler]` function required, but not found
 // error-pattern: language item required, but not found: `eh_personality`
 // ignore-wasm32-bare compiled with panic=abort, personality not required
 
diff --git a/src/test/incremental-fulldeps/auxiliary/issue_49482_macro_def.rs b/src/test/incremental-fulldeps/auxiliary/issue_49482_macro_def.rs
new file mode 100644 (file)
index 0000000..763c9eb
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type="proc-macro"]
+#![allow(non_snake_case)]
+
+extern crate proc_macro;
+
+macro_rules! proc_macro_expr_impl {
+    ($(
+        $( #[$attr:meta] )*
+        pub fn $func:ident($input:ident: &str) -> String;
+    )+) => {
+        $(
+            $( #[$attr] )*
+            #[proc_macro_derive($func)]
+            pub fn $func(_input: ::proc_macro::TokenStream) -> ::proc_macro::TokenStream {
+                panic!()
+            }
+        )+
+    };
+}
+
+proc_macro_expr_impl! {
+    pub fn f1(input: &str) -> String;
+    pub fn f2(input: &str) -> String;
+    pub fn f3(input: &str) -> String;
+    pub fn f4(input: &str) -> String;
+    pub fn f5(input: &str) -> String;
+    pub fn f6(input: &str) -> String;
+    pub fn f7(input: &str) -> String;
+    pub fn f8(input: &str) -> String;
+    pub fn f9(input: &str) -> String;
+    pub fn fA(input: &str) -> String;
+    pub fn fB(input: &str) -> String;
+    pub fn fC(input: &str) -> String;
+    pub fn fD(input: &str) -> String;
+    pub fn fE(input: &str) -> String;
+    pub fn fF(input: &str) -> String;
+}
diff --git a/src/test/incremental-fulldeps/auxiliary/issue_49482_reexport.rs b/src/test/incremental-fulldeps/auxiliary/issue_49482_reexport.rs
new file mode 100644 (file)
index 0000000..aa9aa3b
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_use]
+extern crate issue_49482_macro_def;
+
+pub use issue_49482_macro_def::*;
+
+pub fn foo() {}
diff --git a/src/test/incremental-fulldeps/issue-49482.rs b/src/test/incremental-fulldeps/issue-49482.rs
new file mode 100644 (file)
index 0000000..3261b5a
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue_49482_macro_def.rs
+// aux-build:issue_49482_reexport.rs
+// ignore-stage1
+// revisions: rpass1
+
+extern crate issue_49482_reexport;
+
+pub trait KvStorage
+{
+    fn get(&self);
+}
+
+impl<K> KvStorage for Box<K>
+where
+    K: KvStorage + ?Sized,
+{
+    fn get(&self) {
+        (**self).get()
+    }
+}
+
+impl KvStorage for u32 {
+    fn get(&self) {}
+}
+
+fn main() {
+    /* force issue_49482_reexport to be loaded */
+    issue_49482_reexport::foo();
+
+    Box::new(2).get();
+}
index 646c4312fc21f9598197ad5ebf719c735fd11762..1bf740fdec6192beaf4cc5e25ed26d849193f876 100644 (file)
@@ -15,7 +15,7 @@
 
 // compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=yes
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 static TEST_SIGNED: i128 = const_signed(-222);
 static TEST_UNSIGNED: u128 = const_unsigned(200);
index b4b54e13a698ee87d2334ca6a3eae888e1b48ab6..235df8a6785d4d4d100d1d2d3afccaf165e8a845 100644 (file)
@@ -10,9 +10,9 @@
 
 // ignore-emscripten
 
-// compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=no
+// compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=no -O
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 static TEST_SIGNED: i128 = const_signed(-222);
 static TEST_UNSIGNED: u128 = const_unsigned(200);
@@ -63,103 +63,65 @@ fn main() {
 // END RUST SOURCE
 
 // START rustc.const_signed.Lower128Bit.after.mir
-//     _8 = _1;
-//     _9 = const compiler_builtins::int::addsub::rust_i128_addo(move _8, const 1i128) -> bb10;
-//     ...
-//     _7 = move (_9.0: i128);
-//     ...
-//     _10 = const compiler_builtins::int::addsub::rust_i128_subo(move _7, const 2i128) -> bb11;
-//     ...
-//     _6 = move (_10.0: i128);
-//     ...
-//     _11 = const compiler_builtins::int::mul::rust_i128_mulo(move _6, const 3i128) -> bb12;
-//     ...
-//     _5 = move (_11.0: i128);
-//     ...
-//     _12 = Eq(const 4i128, const 0i128);
-//     assert(!move _12, "attempt to divide by zero") -> bb4;
-//     ...
-//     _13 = Eq(const 4i128, const -1i128);
-//     _14 = Eq(_5, const -170141183460469231731687303715884105728i128);
-//     _15 = BitAnd(move _13, move _14);
-//     assert(!move _15, "attempt to divide with overflow") -> bb5;
-//     ...
-//     _4 = const compiler_builtins::int::sdiv::rust_i128_div(move _5, const 4i128) -> bb13;
-//     ...
-//     _17 = Eq(const 5i128, const -1i128);
-//     _18 = Eq(_4, const -170141183460469231731687303715884105728i128);
-//     _19 = BitAnd(move _17, move _18);
-//     assert(!move _19, "attempt to calculate the remainder with overflow") -> bb7;
-//     ...
-//     _3 = const compiler_builtins::int::sdiv::rust_i128_rem(move _4, const 5i128) -> bb15;
-//     ...
-//     _2 = move (_20.0: i128);
-//     ...
-//     _23 = const 7i32 as u128 (Misc);
-//     _21 = const compiler_builtins::int::shift::rust_i128_shro(move _2, move _23) -> bb16;
-//     ...
-//     _0 = move (_21.0: i128);
-//     ...
-//     assert(!move (_9.1: bool), "attempt to add with overflow") -> bb1;
-//     ...
-//     assert(!move (_10.1: bool), "attempt to subtract with overflow") -> bb2;
-//     ...
-//     assert(!move (_11.1: bool), "attempt to multiply with overflow") -> bb3;
-//     ...
-//     _16 = Eq(const 5i128, const 0i128);
-//     assert(!move _16, "attempt to calculate the remainder with a divisor of zero") -> bb6;
-//     ...
-//     assert(!move (_20.1: bool), "attempt to shift left with overflow") -> bb8;
-//     ...
-//     _22 = const 6i32 as u128 (Misc);
-//     _20 = const compiler_builtins::int::shift::rust_i128_shlo(move _3, move _22) -> bb14;
-//     ...
-//     assert(!move (_21.1: bool), "attempt to shift right with overflow") -> bb9;
+// _7 = const compiler_builtins::int::addsub::rust_i128_add(move _8, const 1i128) -> bb7;
+// ...
+// _10 = Eq(const 4i128, const -1i128);
+// _11 = Eq(_5, const -170141183460469231731687303715884105728i128);
+// _12 = BitAnd(move _10, move _11);
+// assert(!move _12, "attempt to divide with overflow") -> bb2;
+// ...
+// _4 = const compiler_builtins::int::sdiv::rust_i128_div(move _5, const 4i128) -> bb8;
+// ...
+// _14 = Eq(const 5i128, const -1i128);
+// _15 = Eq(_4, const -170141183460469231731687303715884105728i128);
+// _16 = BitAnd(move _14, move _15);
+// assert(!move _16, "attempt to calculate the remainder with overflow") -> bb4;
+// ...
+// _3 = const compiler_builtins::int::sdiv::rust_i128_rem(move _4, const 5i128) -> bb11;
+// ...
+// _9 = Eq(const 4i128, const 0i128);
+// assert(!move _9, "attempt to divide by zero") -> bb1;
+// ...
+// _5 = const compiler_builtins::int::mul::rust_i128_mul(move _6, const 3i128) -> bb5;
+// ...
+// _6 = const compiler_builtins::int::addsub::rust_i128_sub(move _7, const 2i128) -> bb6;
+// ...
+// _13 = Eq(const 5i128, const 0i128);
+// assert(!move _13, "attempt to calculate the remainder with a divisor of zero") -> bb3;
+// ...
+// _17 = const 7i32 as u32 (Misc);
+// _0 = const compiler_builtins::int::shift::rust_i128_shr(move _2, move _17) -> bb9;
+// ...
+// _18 = const 6i32 as u32 (Misc);
+// _2 = const compiler_builtins::int::shift::rust_i128_shl(move _3, move _18) -> bb10;
 // END rustc.const_signed.Lower128Bit.after.mir
 
 // START rustc.const_unsigned.Lower128Bit.after.mir
-//     _8 = _1;
-//     _9 = const compiler_builtins::int::addsub::rust_u128_addo(move _8, const 1u128) -> bb8;
-//     ...
-//     _7 = move (_9.0: u128);
-//     ...
-//     _10 = const compiler_builtins::int::addsub::rust_u128_subo(move _7, const 2u128) -> bb9;
-//     ...
-//     _6 = move (_10.0: u128);
-//     ...
-//     _11 = const compiler_builtins::int::mul::rust_u128_mulo(move _6, const 3u128) -> bb10;
-//     ...
-//     _5 = move (_11.0: u128);
-//     ...
-//     _12 = Eq(const 4u128, const 0u128);
-//     assert(!move _12, "attempt to divide by zero") -> bb4;
-//     ...
-//     _4 = const compiler_builtins::int::udiv::rust_u128_div(move _5, const 4u128) -> bb11;
-//     ...
-//     _3 = const compiler_builtins::int::udiv::rust_u128_rem(move _4, const 5u128) -> bb13;
-//     ...
-//     _2 = move (_14.0: u128);
-//     ...
-//     _17 = const 7i32 as u128 (Misc);
-//     _15 = const compiler_builtins::int::shift::rust_u128_shro(move _2, move _17) -> bb14;
-//     ...
-//     _0 = move (_15.0: u128);
-//     ...
-//     assert(!move (_9.1: bool), "attempt to add with overflow") -> bb1;
-//     ...
-//     assert(!move (_10.1: bool), "attempt to subtract with overflow") -> bb2;
-//     ...
-//     assert(!move (_11.1: bool), "attempt to multiply with overflow") -> bb3;
-//     ...
-//     _13 = Eq(const 5u128, const 0u128);
-//     assert(!move _13, "attempt to calculate the remainder with a divisor of zero") -> bb5;
-//     ...
-//     assert(!move (_14.1: bool), "attempt to shift left with overflow") -> bb6;
-//     ...
-//     _16 = const 6i32 as u128 (Misc);
-//     _14 = const compiler_builtins::int::shift::rust_u128_shlo(move _3, move _16) -> bb12;
-//     ...
-//     assert(!move (_15.1: bool), "attempt to shift right with overflow") -> bb7;
+// _8 = _1;
+// _7 = const compiler_builtins::int::addsub::rust_u128_add(move _8, const 1u128) -> bb5;
+// ...
+// _4 = const compiler_builtins::int::udiv::rust_u128_div(move _5, const 4u128) -> bb6;
+// ...
+// _3 = const compiler_builtins::int::udiv::rust_u128_rem(move _4, const 5u128) -> bb9;
+// ...
+// _9 = Eq(const 4u128, const 0u128);
+// assert(!move _9, "attempt to divide by zero") -> bb1;
+// ...
+// _5 = const compiler_builtins::int::mul::rust_u128_mul(move _6, const 3u128) -> bb3;
+// ...
+// _6 = const compiler_builtins::int::addsub::rust_u128_sub(move _7, const 2u128) -> bb4;
+// ...
+// _10 = Eq(const 5u128, const 0u128);
+// assert(!move _10, "attempt to calculate the remainder with a divisor of zero") -> bb2;
+// ...
+// return;
+// ...
+// _11 = const 7i32 as u32 (Misc);
+// _0 = const compiler_builtins::int::shift::rust_u128_shr(move _2, move _11) -> bb7;
+// ...
+// _12 = const 6i32 as u32 (Misc);
+// _2 = const compiler_builtins::int::shift::rust_u128_shl(move _3, move _12) -> bb8;
+
 // END rustc.const_unsigned.Lower128Bit.after.mir
 
 // START rustc.test_signed.Lower128Bit.after.mir
index adc0249a40cfcac3bb7e37e82a9b10c32dee8b9c..ffc5603bb1670d68173307baae418846d7eb86d6 100644 (file)
@@ -34,15 +34,15 @@ fn main() {
 // | '_#4r    | Local    | ['_#4r]
 // |
 // | Inferred Region Values
-// | '_#0r    | U0 | {bb0[0..=127], '_#0r}
-// | '_#1r    | U0 | {bb0[0..=127], '_#1r}
-// | '_#2r    | U0 | {bb0[0..=127], '_#2r}
-// | '_#3r    | U0 | {bb0[0..=127], '_#3r}
-// | '_#4r    | U0 | {bb0[0..=127], '_#4r}
-// | '_#5r    | U0 | {bb0[0..=127], '_#1r}
-// | '_#6r    | U0 | {bb0[0..=127], '_#2r}
-// | '_#7r    | U0 | {bb0[0..=127], '_#1r}
-// | '_#8r    | U0 | {bb0[0..=127], '_#3r}
+// | '_#0r    | U0 | {bb0[0..=1], '_#0r}
+// | '_#1r    | U0 | {bb0[0..=1], '_#1r}
+// | '_#2r    | U0 | {bb0[0..=1], '_#2r}
+// | '_#3r    | U0 | {bb0[0..=1], '_#3r}
+// | '_#4r    | U0 | {bb0[0..=1], '_#4r}
+// | '_#5r    | U0 | {bb0[0..=1], '_#1r}
+// | '_#6r    | U0 | {bb0[0..=1], '_#2r}
+// | '_#7r    | U0 | {bb0[0..=1], '_#1r}
+// | '_#8r    | U0 | {bb0[0..=1], '_#3r}
 // |
 // ...
 // fn use_x(_1: &'_#5r mut i32, _2: &'_#6r u32, _3: &'_#7r u32, _4: &'_#8r u32) -> bool {
diff --git a/src/test/parse-fail/do-catch-suggests-try.rs b/src/test/parse-fail/do-catch-suggests-try.rs
new file mode 100644 (file)
index 0000000..449135e
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z parse-only
+
+fn main() {
+    let _: Option<()> = do catch {};
+    //~^ ERROR found removed `do catch` syntax
+    //~^^ HELP Following RFC #2388, the new non-placeholder syntax is `try`
+}
diff --git a/src/test/parse-fail/keyword-try-as-identifier-edition2018.rs b/src/test/parse-fail/keyword-try-as-identifier-edition2018.rs
new file mode 100644 (file)
index 0000000..1e4f85c
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z parse-only --edition 2018
+
+fn main() {
+    let try = "foo"; //~ error: expected pattern, found reserved keyword `try`
+}
index ce157e3632c70a5f67f07331e0f9ad23e43fc3a3..73aa31699630c8f1ea8a669db52c4af8557046cf 100644 (file)
@@ -11,7 +11,7 @@
 // pp-exact
 // Tests literals in attributes.
 
-#![feature(custom_attribute, attr_literals)]
+#![feature(custom_attribute)]
 
 fn main() {
     #![hello("hi", 1, 2, 1.012, pi = 3.14, bye, name("John"))]
index a77175975f9412ed3d7057f8da719e89e970d7a9..30efe3b9ab2c48cd0fceaf3007e3a83b072f5b31 100644 (file)
@@ -10,7 +10,7 @@
 
 // error-pattern:index out of bounds: the len is 5 but the index is 5
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 const fn test(x: usize) -> i32 {
     [42;5][x]
 }
index 3f75229948df0782c03cdb6a0163efe8c6206d5d..c7d5574f909f208f3a959a24a04b881ea6e347c1 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:runned an unexported test
+// error-pattern:ran an unexported test
 // compile-flags:--test
 // check-stdout
 
@@ -17,6 +17,6 @@ pub fn exported() {}
 
     #[test]
     fn unexported() {
-        panic!("runned an unexported test");
+        panic!("ran an unexported test");
     }
 }
index 2e100b269e14bfa440f429d84050a3ad0be50256..3412c8ce1f5820b3d5e7c9ecf6b230d300c9ef68 100644 (file)
@@ -1,6 +1,6 @@
 -include ../tools.mk
 
-# Test that hir-tree output doens't crash and includes
+# Test that hir-tree output doesn't crash and includes
 # the string constant we would expect to see.
 
 all:
index 453602b800b5e546d7cecb9d7e4069885a04a8dd..e980b12039e96d35ba674b0a437b8469570b37b6 100644 (file)
 
 #![crate_type = "bin"]
 #![feature(lang_items)]
-#![feature(panic_implementation)]
+#![feature(panic_handler)]
 #![no_main]
 #![no_std]
 
 use core::alloc::Layout;
 use core::panic::PanicInfo;
 
-#[panic_implementation]
+#[panic_handler]
 fn panic(_: &PanicInfo) -> ! {
     loop {}
 }
index 46cdf2e2fa55e5397fb4d60ccdc436acebbbec8d..065b2b6bf18faf70de11bf0123470bc092718492 100644 (file)
@@ -9,12 +9,12 @@
 // except according to those terms.
 
 #![crate_type = "rlib"]
-#![feature(panic_implementation)]
+#![feature(panic_handler)]
 #![no_std]
 
 use core::panic::PanicInfo;
 
-#[panic_implementation]
+#[panic_handler]
 fn panic(info: &PanicInfo) -> ! {
     loop {}
 }
index 0019e5ee7943b8c3d7f1256c88bf536331a64bfd..b669f9cedc1e9d485fb40429dc869a04e9c7a8ce 100644 (file)
@@ -1,6 +1,6 @@
 -include ../tools.mk
 
-# Test that hir-tree output doens't crash and includes
+# Test that hir-tree output doesn't crash and includes
 # the string constant we would expect to see.
 
 all:
index bea5519ec5f70889f4122cc60800c89060af4b1d..4b7fece36d92a9e386ce14707ec2657b7a1a7688 100644 (file)
@@ -3,7 +3,7 @@
 LOG := $(TMPDIR)/log.txt
 
 # This test builds a shared object, then an executable that links it as a native
-# rust library (constrast to an rlib). The shared library and executable both
+# rust library (contrast to an rlib). The shared library and executable both
 # are compiled with address sanitizer, and we assert that a fault in the cdylib
 # is correctly detected.
 
index 0cc8f73da8b56cf6b594e948d44b5d32cd85209d..97f617214222427b86312ac3105a38c544af6fe1 100644 (file)
@@ -3,7 +3,7 @@
 LOG := $(TMPDIR)/log.txt
 
 # This test builds a shared object, then an executable that links it as a native
-# rust library (constrast to an rlib). The shared library and executable both
+# rust library (contrast to an rlib). The shared library and executable both
 # are compiled with address sanitizer, and we assert that a fault in the dylib
 # is correctly detected.
 
index 0c9d93ecb2af7579829e886280f0bd6848056162..fee41461612dbdc72ce984189bb5c1c27452e82a 100644 (file)
@@ -1,5 +1,20 @@
 -include ../tools.mk
 
-all:
-       $(RUSTC) foo.rs -C target-cpu=native
+# I *really* don't want to deal with a cross-platform way to compare file sizes,
+# tests in `make` sort of are awful
+ifeq ($(TARGET),x86_64-unknown-linux-gnu)
+all: $(TMPDIR)/out.log
+       # Make sure no warnings about "unknown CPU `native`" were emitted
+       if [ "$$(wc -c $(TMPDIR)/out.log | cut -d' ' -f 1)" = "0" ]; then \
+         echo no warnings generated; \
+       else \
+         exit 1; \
+       fi
+else
+all: $(TMPDIR)/out.log
+endif
+
+
+$(TMPDIR)/out.log:
+       $(RUSTC) foo.rs -C target-cpu=native 2>&1 | tee $(TMPDIR)/out.log
        $(call RUN,foo)
diff --git a/src/test/run-make-fulldeps/use-suggestions-rust-2018/Makefile b/src/test/run-make-fulldeps/use-suggestions-rust-2018/Makefile
new file mode 100644 (file)
index 0000000..fc39691
--- /dev/null
@@ -0,0 +1,7 @@
+-include ../tools.mk
+
+all:
+       $(RUSTC) ep-nested-lib.rs
+
+       $(RUSTC) use-suggestions.rs --edition=2018 --extern ep_nested_lib=$(TMPDIR)/libep_nested_lib.rlib 2>&1 | $(CGREP) "use ep_nested_lib::foo::bar::Baz"
+
diff --git a/src/test/run-make-fulldeps/use-suggestions-rust-2018/ep-nested-lib.rs b/src/test/run-make-fulldeps/use-suggestions-rust-2018/ep-nested-lib.rs
new file mode 100644 (file)
index 0000000..c0bce6e
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "rlib"]
+
+pub mod foo {
+    pub mod bar {
+        pub struct Baz;
+    }
+}
diff --git a/src/test/run-make-fulldeps/use-suggestions-rust-2018/use-suggestions.rs b/src/test/run-make-fulldeps/use-suggestions-rust-2018/use-suggestions.rs
new file mode 100644 (file)
index 0000000..62730a5
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let x = Baz{};
+}
index 979ec44b040776407dd955a1b5a5cf4ade1e057c..061280779b0cf633fc2584527bc8a496033aaec7 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(panic_implementation, alloc_error_handler)]
+#![feature(panic_handler, alloc_error_handler)]
 #![crate_type = "cdylib"]
 #![no_std]
 
@@ -39,7 +39,7 @@ fn a(_: core::alloc::Layout) -> ! {
     loop {}
 }
 
-#[panic_implementation]
+#[panic_handler]
 fn b(_: &core::panic::PanicInfo) -> ! {
     loop {}
 }
diff --git a/src/test/run-make/wasm-symbols-not-imported/Makefile b/src/test/run-make/wasm-symbols-not-imported/Makefile
new file mode 100644 (file)
index 0000000..773e32a
--- /dev/null
@@ -0,0 +1,16 @@
+-include ../../run-make-fulldeps/tools.mk
+
+ifeq ($(TARGET),wasm32-unknown-unknown)
+all:
+       $(RUSTC) foo.rs --target wasm32-unknown-unknown
+       $(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
+       $(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto
+       $(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
+       $(RUSTC) foo.rs --target wasm32-unknown-unknown -O
+       $(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
+       $(RUSTC) foo.rs --target wasm32-unknown-unknown -O -C lto
+       $(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
+else
+all:
+endif
+
diff --git a/src/test/run-make/wasm-symbols-not-imported/foo.rs b/src/test/run-make/wasm-symbols-not-imported/foo.rs
new file mode 100644 (file)
index 0000000..156db48
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "cdylib"]
+
+#![feature(panic_implementation)]
+#![no_std]
+
+use core::panic::PanicInfo;
+
+#[no_mangle]
+pub extern fn foo() {
+    panic!()
+}
+
+#[panic_implementation]
+fn panic(_info: &PanicInfo) -> ! {
+    loop {}
+}
diff --git a/src/test/run-make/wasm-symbols-not-imported/verify-no-imports.js b/src/test/run-make/wasm-symbols-not-imported/verify-no-imports.js
new file mode 100644 (file)
index 0000000..28a98b5
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let list = WebAssembly.Module.imports(m);
+console.log('imports', list);
+if (list.length !== 0)
+  throw new Error("there are some imports");
index ff5d9a59bfa0071c497ecf19f07b8a729d034256..533d0ac490c413c5179e50de334c5b1f51100b90 100644 (file)
@@ -31,7 +31,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
 
 fn expand(cx: &mut ExtCtxt, _: syntax_pos::Span, _: &[tokenstream::TokenTree])
           -> Box<MacResult+'static> {
-    MacEager::items(OneVector::many(vec![
+    MacEager::items(OneVector::from_vec(vec![
         quote_item!(cx, struct Struct1;).unwrap(),
         quote_item!(cx, struct Struct2;).unwrap()
     ]))
index fa208e14b7d1c632afb41ef6b26eba6c7eba5de5..601003827c6a287a463e193bda77647ff4274a62 100644 (file)
@@ -12,7 +12,7 @@
 
 #![feature(plugin_registrar, rustc_private)]
 #![feature(box_syntax)]
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 #![feature(macro_at_most_once_rep)]
 
 #[macro_use] extern crate rustc;
index 9faa7366ec5f19fba069c5db92945726f8487a1d..b9c565a9d3c23c590726725405e4f1bbf209aeff 100644 (file)
@@ -19,7 +19,7 @@
 
 #[proc_macro_attribute]
 pub fn attr_tru(_attr: TokenStream, item: TokenStream) -> TokenStream {
-    let name = item.into_iter().skip(1).next().unwrap();
+    let name = item.into_iter().nth(1).unwrap();
     quote!(fn $name() -> bool { true })
 }
 
index baf9e0d5dc5a6165bd06b4b2688cde9c13c921a1..6283d054373c12339bc4920819c8c99cb745f0b7 100644 (file)
@@ -92,7 +92,9 @@ fn main() {
         let tc = TestCalls { count: &mut count };
         // we should never get use this filename, but lets make sure they are valid args.
         let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()];
-        rustc_driver::run_compiler(&args, Box::new(tc), None, None);
+        syntax::with_globals(|| {
+            rustc_driver::run_compiler(&args, Box::new(tc), None, None);
+        });
     }
     assert_eq!(count, 30);
 }
index ce552d3ab7dd67ff8ff04d1cef1db678c121a57d..86d7cd54d973949b9f466e213ac09caca29c90f4 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:macro_crate_test.rs
 // ignore-stage1
 
-#![feature(plugin, rustc_attrs, attr_literals)]
+#![feature(plugin, rustc_attrs)]
 #![plugin(macro_crate_test)]
 
 #[macro_use]
index 7edb3e0f8a08314191df44482ba9a58d53ca9cea..f525e0f082a44b723facd5f3f5aae20274762a8a 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #![feature(box_syntax, plugin, plugin_registrar, rustc_private)]
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 #![feature(macro_at_most_once_rep)]
 #![crate_type = "dylib"]
 
@@ -27,6 +27,7 @@
 use rustc::hir;
 use rustc::hir::intravisit;
 use rustc::hir::map as hir_map;
+use hir::Node;
 use rustc::lint::{LateContext, LintPass, LintArray, LateLintPass, LintContext};
 use rustc::ty;
 use syntax::{ast, source_map};
@@ -58,7 +59,7 @@ fn check_fn(&mut self,
                 id: ast::NodeId) {
 
         let item = match cx.tcx.hir.get(id) {
-            hir_map::Node::NodeItem(item) => item,
+            Node::Item(item) => item,
             _ => cx.tcx.hir.expect_item(cx.tcx.hir.get_parent(id)),
         };
 
index 1de6496e29f8b22fc6a6d8d92bfd7dbb7208b84c..ac9eca38226691a2e33cf68e5db1ede16122423d 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:derive-b.rs
 // ignore-stage1
 
-#![feature(proc_macro_path_invoc, unrestricted_attribute_tokens)]
+#![feature(unrestricted_attribute_tokens)]
 
 extern crate derive_b;
 
index d4af99f97c5c82001c5394169a6530cbce193145..7bbdbc6505db5d40bc2a46dd642306f4a8de3552 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:issue-42708.rs
 // ignore-stage1
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 #![allow(unused)]
 
 extern crate issue_42708;
index 53783e7fedb2929ed865eed6dd49ae66a22e1fc7..410faaeb3eeaccf7d646abcdcfa3797ee346d0a5 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:issue-50061.rs
 // ignore-stage1
 
-#![feature(proc_macro_path_invoc, decl_macro)]
+#![feature(decl_macro)]
 
 extern crate issue_50061;
 
index 15e3b4b03eb27b0a68e01e4708ed67b81cf76d41..6f89c5d377f54511501a1d12fce65cbee058094e 100644 (file)
@@ -11,7 +11,6 @@
 // #45662
 
 #![feature(repr_align)]
-#![feature(attr_literals)]
 
 #[repr(align(16))]
 pub struct A(i64);
index 99b8ad83bf6ccfe44c76d2f25274cbf4da569b6a..46f228459079a25806ebd417e607754e52dac171 100644 (file)
@@ -12,8 +12,8 @@
 
 #![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)]
 
-use std::boxed::PinBox;
-use std::mem::PinMut;
+use std::pin::PinBox;
+use std::pin::PinMut;
 use std::future::Future;
 use std::sync::{
     Arc,
index be06e8dd5700b19e383e01ec50c36204e4b449b7..6985a6527c874eb51562d2a2da695af198692421 100644 (file)
@@ -11,6 +11,6 @@
 // Crate that exports a const fn. Used for testing cross-crate.
 
 #![crate_type="rlib"]
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 pub const fn foo() -> usize { 22 }
index 69952e9f90af6a4949bd9f8f9da2528356c35a02..f8ed2c7f432eb6a52dd1a7386a66c6d87a13aa58 100644 (file)
@@ -10,8 +10,6 @@
 
 // edition:2015
 
-#![feature(raw_identifiers)]
-
 #[macro_export]
 macro_rules! produces_async {
     () => (pub fn async() {})
index 832ee1d7c1b456be5e7a6744518041a400b4bc67..5351a40916b7d44df25f6e7c8bec63a0460fd13a 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 #![crate_type = "lib"]
 
 const fn foo(i: i32) -> i32 {
index dee40b2fc573558641977edcf574eb99b991cfaf..87b01ed990036cae7ad8c85acb429c188d31366b 100644 (file)
@@ -32,43 +32,43 @@ pub fn type_ids() -> Vec<TypeId> {
         ]
     }
 
-    // Tests TyBool
+    // Tests Bool
     pub type FooBool = bool;
 
-    // Tests TyChar
+    // Tests Char
     pub type FooChar = char;
 
-    // Tests TyInt (does not test all variants of IntTy)
+    // Tests Int (does not test all variants of IntTy)
     pub type FooInt = isize;
 
-    // Tests TyUint (does not test all variants of UintTy)
+    // Tests Uint (does not test all variants of UintTy)
     pub type FooUint = usize;
 
-    // Tests TyFloat (does not test all variants of FloatTy)
+    // Tests Float (does not test all variants of FloatTy)
     pub type FooFloat = f64;
 
-    // Tests TyStr
+    // Tests Str
     pub type FooStr = str;
 
-    // Tests TyArray
+    // Tests Array
     pub type FooArray = [u8; 1];
 
-    // Tests TySlice
+    // Tests Slice
     pub type FooSlice = [u8];
 
     // Tests Box (of u8)
     pub type FooBox = Box<u8>;
 
-    // Tests TyRawPtr
+    // Tests RawPtr
     pub type FooPtr = *const u8;
 
-    // Tests TyRef
+    // Tests Ref
     pub type FooRef = &'static u8;
 
-    // Tests TyFnPtr
+    // Tests FnPtr
     pub type FooFnPtr = fn(u8) -> bool;
 
-    // Tests TyDynamic
+    // Tests Dynamic
     pub trait FooTrait {
         fn foo_method(&self) -> usize;
     }
@@ -85,13 +85,13 @@ pub enum FooEnum {
         VarB(usize, usize)
     }
 
-    // Tests TyTuple
+    // Tests Tuple
     pub type FooNil = ();
     pub type FooTuple = (u8, i8, bool);
 
-    // Skipping TyParam
+    // Skipping Param
 
-    // Skipping TyInfer
+    // Skipping Infer
 
-    // Skipping TyError
+    // Skipping Error
 }
diff --git a/src/test/run-pass/catch-expr.rs b/src/test/run-pass/catch-expr.rs
deleted file mode 100644 (file)
index c23bca7..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(catch_expr)]
-
-struct catch {}
-
-pub fn main() {
-    let catch_result: Option<_> = do catch {
-        let x = 5;
-        x
-    };
-    assert_eq!(catch_result, Some(5));
-
-    let mut catch = true;
-    while catch { catch = false; }
-    assert_eq!(catch, false);
-
-    catch = if catch { false } else { true };
-    assert_eq!(catch, true);
-
-    match catch {
-        _ => {}
-    };
-
-    let catch_err: Result<_, i32> = do catch {
-        Err(22)?;
-        1
-    };
-    assert_eq!(catch_err, Err(22));
-
-    let catch_okay: Result<i32, i32> = do catch {
-        if false { Err(25)?; }
-        Ok::<(), i32>(())?;
-        28
-    };
-    assert_eq!(catch_okay, Ok(28));
-
-    let catch_from_loop: Result<i32, i32> = do catch {
-        for i in 0..10 {
-            if i < 5 { Ok::<i32, i32>(i)?; } else { Err(i)?; }
-        }
-        22
-    };
-    assert_eq!(catch_from_loop, Err(5));
-
-    let cfg_init;
-    let _res: Result<(), ()> = do catch {
-        cfg_init = 5;
-    };
-    assert_eq!(cfg_init, 5);
-
-    let cfg_init_2;
-    let _res: Result<(), ()> = do catch {
-        cfg_init_2 = 6;
-        Err(())?;
-    };
-    assert_eq!(cfg_init_2, 6);
-
-    let my_string = "test".to_string();
-    let res: Result<&str, ()> = do catch {
-        // Unfortunately, deref doesn't fire here (#49356)
-        &my_string[..]
-    };
-    assert_eq!(res, Ok("test"));
-
-    let my_opt: Option<_> = do catch { () };
-    assert_eq!(my_opt, Some(()));
-
-    let my_opt: Option<_> = do catch { };
-    assert_eq!(my_opt, Some(()));
-}
index 9599f65da4eca31de48824d5b0bc58d469234ede..c4fc9ee53fd7fbde976b50d682d728cc48dbd5a5 100644 (file)
@@ -24,7 +24,7 @@
 use std::sync::atomic::{AtomicUsize, Ordering};
 
 fn main() {
-    if let Some(arg) = env::args().skip(1).next() {
+    if let Some(arg) = env::args().nth(1) {
         match &arg[..] {
             "test1" => println!("hello2"),
             "test2" => assert_eq!(env::var("FOO").unwrap(), "BAR"),
index 77c70fe7f63545567d61ac6e49b0eee0054447bf..3fe27ca200cb00d4b300f932d7b959ced146b0f4 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const fn add(x: usize, y: usize) -> usize {
     x + y
index 7d8d941439cf8c953848bdcd29267c6083cc0c71..bed78f1e8978f6dc3c9304c1853432609cce0bd8 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 struct Foo { value: u32 }
 
index 86f5dedc4d1b1fdc5717999ab855fc1bc5d88d9c..d5959a89e51a5bf597dc7a7d248783e409be3859 100644 (file)
@@ -10,7 +10,7 @@
 
 // Test a call whose argument is the result of another call.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const fn sub(x: u32, y: u32) -> u32 {
     x - y
index 3b27987f190cdf5c2a808e0ef02de11f981ee6a4..836716051d2132e1bd9b7f197fde1bb96cb21c80 100644 (file)
@@ -7,7 +7,7 @@
 // <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(const_fn)]
+#![feature(min_const_fn)]
 
 struct A;
 
index 104ab6e19db672db5e51b2bf8001b9a4b821cdf8..689ae19e7d4f4cfa4f09f039ca0bff8052ca5def 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 #[derive(PartialEq, Eq)]
 enum Cake {
index 06fbe9bf4f63958372c055f193e81dd09fe87a97..245dd673b512cff1f465cef0b92f514ecf92de51 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 use std::mem;
 
index 2511cfd042206d1257725f0770985dcc7d0c6d12..b267245b789694770615ba1aa8166c33c047f7ee 100644 (file)
@@ -10,7 +10,7 @@
 
 // A quick test of 'unsafe const fn' functionality
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const unsafe fn dummy(v: u32) -> u32 {
     !v
index eec4c940585c0f75a0e4d2e7c33bd4efb5f05440..574fb29e82c7df08be4371a0019a0ea2e1e64dd1 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const FOO: isize = 10;
 const BAR: isize = 3;
index c435e5fdaab4a108cb3e2c4171abc7303756bb70..f59a6810e3a78f76bea3112c1dc0ba2e883df9ec 100644 (file)
@@ -10,7 +10,7 @@
 
 // https://github.com/rust-lang/rust/issues/48279
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 #[derive(PartialEq, Eq)]
 pub struct NonZeroU32 {
index 0bb253d1a6455d94f97e59cf7a738533bf45e81f..352958f4c6a454f82f0d5219432658e6e377f4da 100644 (file)
@@ -10,7 +10,7 @@
 
 // https://github.com/rust-lang/rust/issues/46114
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 #[derive(Eq, PartialEq)]
 struct A { value: u32 }
index 2d228408254aa687dc5925b62fc20b4b4324a595..28b876c308b64544b2156bb79b5b84138b5b5161 100644 (file)
@@ -8,10 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: -O
+
 fn foo(_: &'static [&'static str]) {}
 fn bar(_: &'static [&'static str; 3]) {}
+fn baz_i32(_: &'static i32) {}
+fn baz_u32(_: &'static u32) {}
 
 fn main() {
     foo(&["a", "b", "c"]);
     bar(&["d", "e", "f"]);
+
+    // make sure that these do not cause trouble despite overflowing
+    baz_u32(&(0-1));
+    baz_i32(&-std::i32::MIN);
 }
index d57d3bcb49aa8d5c7f6de2be81b5865e1fcfc2f9..87fdac4bfb4fe296daa58fd4bc08aa29ededfb79 100644 (file)
@@ -10,7 +10,7 @@
 
 // https://github.com/rust-lang/rust/issues/43754
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 const fn foo(x: usize) -> usize {
     return x;
 }
diff --git a/src/test/run-pass/ctfe/transmute-const.rs b/src/test/run-pass/ctfe/transmute-const.rs
new file mode 100644 (file)
index 0000000..bf9459a
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(const_transmute)]
+
+use std::mem;
+
+#[repr(transparent)]
+struct Foo(u32);
+
+const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
+
+fn main() {
+    assert_eq!(TRANSMUTED_U32, 3);
+}
index b6e640ab5b5b6a62bbb27d28e5d3f3fa59d6c46a..5f915a762d1492e4eecc3582b6c12a50c6f7a79b 100644 (file)
@@ -385,7 +385,7 @@ pub fn main() {
     // RwLock (since we can grab the child pointers in read-only
     // mode), but we cannot lock a std::sync::Mutex to guard reading
     // from each node via the same pattern, since once you hit the
-    // cycle, you'll be trying to acquring the same lock twice.
+    // cycle, you'll be trying to acquiring the same lock twice.
     // (We deal with this by exiting the traversal early if try_lock fails.)
 
     // Cycle 12: { arc0 -> (arc1, arc2), arc1 -> (), arc2 -> arc0 }, refcells
index 73869e63de7c4bfc879ff160230bade1da85bbe3..1751eacc6b7ce42bb90b831fd87870d6aff0d40a 100644 (file)
@@ -11,8 +11,6 @@
 // edition:2015
 // aux-build:edition-kw-macro-2015.rs
 
-#![feature(raw_identifiers)]
-
 #[macro_use]
 extern crate edition_kw_macro_2015;
 
index 0a1c6505854c99cacdf044efed2eed888f0316c3..f2794a4b8d81ab403c2a5007e7e8ac71425e48c4 100644 (file)
@@ -11,8 +11,6 @@
 // edition:2015
 // aux-build:edition-kw-macro-2018.rs
 
-#![feature(raw_identifiers)]
-
 #[macro_use]
 extern crate edition_kw_macro_2018;
 
index 476cb48c0d2ee7af5169b9616a3b425bb83f5f12..69a04437691dd3f0a7e4c8654c0954b46fcf0529 100644 (file)
@@ -11,9 +11,9 @@
 #![feature(arbitrary_self_types, futures_api, pin)]
 #![allow(unused)]
 
-use std::boxed::PinBox;
+use std::pin::PinBox;
 use std::future::Future;
-use std::mem::PinMut;
+use std::pin::PinMut;
 use std::rc::Rc;
 use std::sync::{
     Arc,
index d09376acc84ae82c0862db78f4b1e154e5b559f9..37436d7ae0042cbeda01beabee0e88871dd6234e 100644 (file)
@@ -310,7 +310,7 @@ fn foo() -> isize {
 }
 
 fn test_once() {
-    // Make sure each argument are evaluted only once even though it may be
+    // Make sure each argument are evaluated only once even though it may be
     // formatted multiple times
     fn foo() -> isize {
         static mut FOO: isize = 0;
index 53cb4c4b009e5c870c43f9e13ee76fc30f3dc58c..a18d82fb7a4e7e22c334fe85204ff5b500795ae7 100644 (file)
@@ -11,6 +11,8 @@
 // ignore-wasm32
 // ignore-emscripten
 
+// compile-flags: -C debug_assertions=yes
+
 #![feature(const_fn, libc)]
 #![allow(const_err)]
 
@@ -19,7 +21,7 @@
 use std::env;
 use std::process::{Command, Stdio};
 
-// this will panic in debug mode
+// this will panic in debug mode and overflow in release mode
 const fn bar() -> usize { 0 - 1 }
 
 fn foo() {
index 2ec97e373b29bbf69a653871c6422c078edfea4b..04ffad501b042e406ee2bb75d308c25bb4f64e3e 100644 (file)
@@ -27,7 +27,7 @@ pub fn main() {
     }
     match 'c' {
       'a'...'z' => {}
-      _ => panic!("should suppport char ranges")
+      _ => panic!("should support char ranges")
     }
     match -3_isize {
       -7...5 => {}
index d5b799710941bdb9a5c6aaf4e1e872fd46b9386c..5727f54cd7046db4228cf73d46c6a9079939de36 100644 (file)
@@ -26,7 +26,7 @@
 // trailing comma on lifetime bounds
 type TypeE = TypeA<'static,>;
 
-// normal type arugment
+// normal type argument
 type TypeF<T> = Box<T>;
 
 // type argument with trailing comma
index 5a010f2be7a3425168405669205e59714172887b..10482139a978c49297794d919ada6ddc2eb95666 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 fn main() {}
 
index 6d9adbcd57980354095a0acebcfb5ebd84eae510..3079d9de3c23861af323b2e8e3cb40a1635f4441 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 struct A {
     field: usize,
 }
index 24f4c9f590b11341a74997d5e574989e5385aefe..7be79f3a450974bb6c76b6b93e29c8ff1f5813cc 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const fn foo() -> *const i8 {
     b"foo" as *const _ as *const i8
index ab368537e21c0bfb7a165f757e20c04c9f3384d8..3bc0f7a0fdee8f3eae3b733dbeec64f33a451f13 100644 (file)
@@ -11,7 +11,7 @@
 // Issue 33903:
 // Built-in indexing should be used even when the index is not
 // trivially an integer
-// Only built-in indexing can be used in constant expresssions
+// Only built-in indexing can be used in constant expressions
 
 const FOO: i32 = [12, 34][0 + 1];
 
index 9bdde02d0061ce23b1643b4b34fedc0ef1e0cb83..9b3289e67859a8da0cb2d9c292ba3393b2341227 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const fn foo() -> i64 {
     3
index c65823e460be3a1d1db682f2a50867ea65004070..cb79eda8b07399c3a7b48ea947a013cb787584c7 100644 (file)
@@ -8,12 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(catch_expr)]
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
 
 fn main() {
     let mut a = 0;
     let () = {
-        let _: Result<(), ()> = do catch {
+        let _: Result<(), ()> = try {
             let _ = Err(())?;
             return
         };
diff --git a/src/test/run-pass/issue-48006.rs b/src/test/run-pass/issue-48006.rs
new file mode 100644 (file)
index 0000000..d5887bb
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(step_trait)]
+
+use std::iter::Step;
+
+#[cfg(target_pointer_width = "16")]
+fn main() {
+    assert!(Step::steps_between(&0u32, &::std::u32::MAX).is_none());
+}
+
+#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
+fn main() {
+    assert!(Step::steps_between(&0u32, &::std::u32::MAX).is_some());
+}
index a603dfbfe5fa5fde5e463affda9d566b875f3a56..46aeb329c896babd7e83b4b40b91acc4888541b2 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test that we are able to reinitilize box with moved referent
+// Test that we are able to reinitialize box with moved referent
 #![feature(nll)]
 static mut ORDER: [usize; 3] = [0, 0, 0];
 static mut INDEX: usize = 0;
diff --git a/src/test/run-pass/issue-50865-private-impl-trait/auxiliary/lib.rs b/src/test/run-pass/issue-50865-private-impl-trait/auxiliary/lib.rs
new file mode 100644 (file)
index 0000000..306256d
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "lib"]
+
+pub fn bar<P>( // Error won't happen if "bar" is not generic
+    _baz: P,
+) {
+    hide_foo()();
+}
+
+fn hide_foo() -> impl Fn() { // Error won't happen if "iterate" hasn't impl Trait or has generics
+    foo
+}
+
+fn foo() { // Error won't happen if "foo" isn't used in "iterate" or has generics
+}
diff --git a/src/test/run-pass/issue-50865-private-impl-trait/main.rs b/src/test/run-pass/issue-50865-private-impl-trait/main.rs
new file mode 100644 (file)
index 0000000..bc347ed
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:lib.rs
+
+// Regression test for #50865.
+// When using generics or specifying the type directly, this example
+// codegens `foo` internally. However, when using a private `impl Trait`
+// function which references another private item, `foo` (in this case)
+// wouldn't be codegenned until main.rs used `bar`, as with impl Trait
+// it is not cast to `fn()` automatically to satisfy e.g.
+// `fn foo() -> fn() { ... }`.
+
+extern crate lib;
+
+fn main() {
+    lib::bar(()); // Error won't happen if bar is called from same crate
+}
diff --git a/src/test/run-pass/issue-52705/auxiliary/png.rs b/src/test/run-pass/issue-52705/auxiliary/png.rs
deleted file mode 100644 (file)
index 48d53a2..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![crate_type = "lib"]
-
-pub struct DecodingError;
diff --git a/src/test/run-pass/issue-52705/auxiliary/png2.rs b/src/test/run-pass/issue-52705/auxiliary/png2.rs
new file mode 100644 (file)
index 0000000..48d53a2
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "lib"]
+
+pub struct DecodingError;
index 101f67e3e7b98dfa278b5be1bb3f5fd26e93f1e2..fb7b2f812c3cae4d3d9e93a4e94fc5ce06c2777a 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:png.rs
+// aux-build:png2.rs
 // edition:2018
 
 mod png {
-    use png as png_ext;
+    use png2 as png_ext;
 
     fn foo() -> png_ext::DecodingError { unimplemented!() }
 }
index 68271accb61a2a5514dfd8728bebb2c6eb2ce89d..488bc6e6927a077561ae9153365407aa07f4c8c1 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 const fn f() -> usize {
     5
 }
index c371a33257f4e3fe373e81a9b6b78dd232d8d263..9216040ab6ec892b7c7b5f500aedf768d6c757dd 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 
 //{{{ issue 40569 ==============================================================
 
index 32145277252cb89df22f3283b56cbcc92b405986..db8331358b96e31ddcfd084830f11bfe897f4e9d 100644 (file)
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 #![allow(dead_code, unused_imports)]
-#![feature(macro_vis_matcher, crate_visibility_modifier)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
+#![feature(crate_visibility_modifier)]
 
 /**
 Ensure that `:vis` matches can be captured in existing positions, and passed
index 859edb80a07438ca51be080cba7c18cf2fa01241..efa725321967d20ca603d11fb131fd4ace262ebe 100644 (file)
@@ -34,7 +34,7 @@ pub fn main() {
     }
     match 'c' {
       'a'..='z' => {}
-      _ => panic!("should suppport char ranges")
+      _ => panic!("should support char ranges")
     }
     match -3 {
       -7..=5 => {}
index 759296ad46b877ce7f979404f2b9a1bfcbf67fe0..bedcee43db5ba511a9ff54822257f843198eef7d 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // Regression test for #23698: The reassignment checker only cared
-// about the last assigment in a match arm body
+// about the last assignment in a match arm body
 
 // Use an extra function to make sure no extra assignments
 // are introduced by macros in the match statement
index 4de8f6a7194159dafd8c68d0a0308cd69982a3dc..220482f57eb01052b9f991574cdbdb8bfd9e72b7 100644 (file)
@@ -27,7 +27,7 @@ fn my_write(&mut self, buf: &[u8]) -> Result<(), ()> {
         let write_len = buf.len();
         unsafe {
             *self = slice::from_raw_parts_mut(
-                self.as_mut_ptr().offset(write_len as isize),
+                self.as_mut_ptr().add(write_len),
                 self.len() - write_len
             );
         }
index 7968ae2278ae93a06eba631c4885e39408d52972..9d23a0c71489a8187e19522111d07c585a3f55a0 100644 (file)
@@ -26,7 +26,7 @@ fn sanity_check_size<T: Copy>(one: T) {
 
 fn main() {
     // This can fail if rustc and LLVM disagree on the size of a type.
-    // In this case, `Option<Packed<(&(), u32)>>` was erronously not
+    // In this case, `Option<Packed<(&(), u32)>>` was erroneously not
     // marked as packed despite needing alignment `1` and containing
     // its `&()` discriminant, which has alignment larger than `1`.
     sanity_check_size((Some(Packed((&(), 0))), true));
index 61ef386442bb91da051a77faee29950aa3f1d59e..c4cae1e1d611d6bfa2f132241cf26db3b928bc34 100644 (file)
@@ -37,8 +37,8 @@ unsafe fn sanity_check(ascend: &[*mut u8]) {
         for i in 0..COUNT / 2 {
             let (p0, p1, size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i));
             for j in 0..size {
-                assert_eq!(*p0.offset(j as isize), i as u8);
-                assert_eq!(*p1.offset(j as isize), i as u8);
+                assert_eq!(*p0.add(j), i as u8);
+                assert_eq!(*p1.add(j), i as u8);
             }
         }
     }
@@ -100,8 +100,8 @@ fn idx_to_size(i: usize) -> usize { (i+1) * 10 }
     for i in 0..COUNT / 2 {
         let (p0, p1, size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i));
         for j in 0..size {
-            *p0.offset(j as isize) = i as u8;
-            *p1.offset(j as isize) = i as u8;
+            *p0.add(j) = i as u8;
+            *p1.add(j) = i as u8;
         }
     }
 
index 6cea75cf1d11e9a83daa59481c62a90d8f60d9cf..2ef9fba2076add70307e2be38398a0809f88b1c8 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(raw_identifiers)]
-
 use std::mem;
 
 #[r#repr(r#C, r#packed)]
index 5d495c4e9e557eca33006318ca3ffd6af05b9bd7..eefce3981bec1f64c1a9a25b739c0d825355465f 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(raw_identifiers)]
-
 fn r#fn(r#match: u32) -> u32 {
     r#match
 }
index 256bd263d38d42c1d5c182310ccbdf50c48e4518..4306ffe2042af6d326cfe748f858c967d59a8872 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(raw_identifiers)]
-
 #[derive(Debug, PartialEq, Eq)]
 struct IntWrapper(u32);
 
index 4bd16ded52fbdf6b39ba4e5d86aaa8deadd7207f..9e89b79266cface4c335c39e1a6db9e29108411b 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![feature(decl_macro)]
-#![feature(raw_identifiers)]
 
 r#macro_rules! r#struct {
     ($r#struct:expr) => { $r#struct }
index a0b83ba4c24a5d95c328cc00dfcb2f9ddc70a79f..d349519478ae403891a6308cdda9d7fa95e67fb6 100644 (file)
@@ -36,7 +36,7 @@ fn start(argc: isize, argv: *const *const u8) -> isize {
 
     let args = unsafe {
         (0..argc as usize).map(|i| {
-            let ptr = *argv.offset(i as isize) as *const _;
+            let ptr = *argv.add(i) as *const _;
             CStr::from_ptr(ptr).to_bytes().to_vec()
         }).collect::<Vec<_>>()
     };
index eae431aa4044d2d507aefee2de554e9cedf645f5..ad099f82d13b97ffec795ccb46839952f3ecc040 100644 (file)
@@ -33,7 +33,7 @@
 
 fn main() {
     unsafe {
-        // Install signal hander that runs on alternate signal stack.
+        // Install signal handler that runs on alternate signal stack.
         let mut action: sigaction = std::mem::zeroed();
         action.sa_flags = (SA_ONSTACK | SA_SIGINFO) as _;
         action.sa_sigaction = signal_handler as sighandler_t;
index 139da046452646b77c1193c8f18691b3ae084a6d..a7fd9f299c033bdb8c086e310290ed21678e6cfa 100644 (file)
@@ -52,7 +52,7 @@ fn is_sigill(status: ExitStatus) -> bool {
 }
 
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 mod test {
     // An SSE type
     #[repr(simd)]
index eb13930de403f2877c73e01aa8b37149a3b1c333..9d8e56e44cbb3c71847adc180661fadb6cf4c9a7 100644 (file)
@@ -10,7 +10,6 @@
 
 // Scoped attributes should not trigger an unused attributes lint.
 
-#![feature(tool_attributes)]
 #![deny(unused_attributes)]
 
 fn main() {
diff --git a/src/test/run-pass/try-block.rs b/src/test/run-pass/try-block.rs
new file mode 100644 (file)
index 0000000..a7e7cc2
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+struct catch {}
+
+pub fn main() {
+    let catch_result: Option<_> = try {
+        let x = 5;
+        x
+    };
+    assert_eq!(catch_result, Some(5));
+
+    let mut catch = true;
+    while catch { catch = false; }
+    assert_eq!(catch, false);
+
+    catch = if catch { false } else { true };
+    assert_eq!(catch, true);
+
+    match catch {
+        _ => {}
+    };
+
+    let catch_err: Result<_, i32> = try {
+        Err(22)?;
+        1
+    };
+    assert_eq!(catch_err, Err(22));
+
+    let catch_okay: Result<i32, i32> = try {
+        if false { Err(25)?; }
+        Ok::<(), i32>(())?;
+        28
+    };
+    assert_eq!(catch_okay, Ok(28));
+
+    let catch_from_loop: Result<i32, i32> = try {
+        for i in 0..10 {
+            if i < 5 { Ok::<i32, i32>(i)?; } else { Err(i)?; }
+        }
+        22
+    };
+    assert_eq!(catch_from_loop, Err(5));
+
+    let cfg_init;
+    let _res: Result<(), ()> = try {
+        cfg_init = 5;
+    };
+    assert_eq!(cfg_init, 5);
+
+    let cfg_init_2;
+    let _res: Result<(), ()> = try {
+        cfg_init_2 = 6;
+        Err(())?;
+    };
+    assert_eq!(cfg_init_2, 6);
+
+    let my_string = "test".to_string();
+    let res: Result<&str, ()> = try {
+        // Unfortunately, deref doesn't fire here (#49356)
+        &my_string[..]
+    };
+    assert_eq!(res, Ok("test"));
+
+    let my_opt: Option<_> = try { () };
+    assert_eq!(my_opt, Some(()));
+
+    let my_opt: Option<_> = try { };
+    assert_eq!(my_opt, Some(()));
+}
diff --git a/src/test/run-pass/try-from-int-error-partial-eq.rs b/src/test/run-pass/try-from-int-error-partial-eq.rs
new file mode 100644 (file)
index 0000000..1122f5a
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(try_from)]
+#![allow(unused_must_use)]
+
+use std::convert::TryFrom;
+use std::num::TryFromIntError;
+
+fn main() {
+    let x: u32 = 125;
+    let y: Result<u8, TryFromIntError> = u8::try_from(x);
+    y == Ok(125);
+}
diff --git a/src/test/run-pass/try-is-identifier-edition2015.rs b/src/test/run-pass/try-is-identifier-edition2015.rs
new file mode 100644 (file)
index 0000000..aafb52e
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition 2015
+
+fn main() {
+    let try = 2;
+    struct try { try: u32 };
+    let try: try = try { try };
+    assert_eq!(try.try, 2);
+}
index 40071ec9754e2617bcda034310e6c48b16ca29d6..c95885518ea2f44d7cd83ee98a86e06d27d7e9bd 100644 (file)
@@ -12,7 +12,7 @@
 //
 //    error: internal compiler error: get_unique_type_id_of_type() -
 //    unexpected type: closure,
-//    TyClosure(syntax::ast::DefId{krate: 0, node: 66},
+//    Closure(syntax::ast::DefId{krate: 0, node: 66},
 //    ReScope(63))
 //
 // This is a regression test for issue #17021.
index 061c7b30741d935d1f58e22b87de6575588daca6..55842dc8e45e66d36001e10298f724236b22be0a 100644 (file)
@@ -14,7 +14,7 @@ const QUERY = 'pinbox::new';
 
 const EXPECTED = {
     'others': [
-        { 'path': 'std::boxed::PinBox', 'name': 'new' },
-        { 'path': 'alloc::boxed::PinBox', 'name': 'new' },
+        { 'path': 'std::pin::PinBox', 'name': 'new' },
+        { 'path': 'alloc::pin::PinBox', 'name': 'new' },
     ],
 };
diff --git a/src/test/rustdoc-js/substring.js b/src/test/rustdoc-js/substring.js
new file mode 100644 (file)
index 0000000..49c1c05
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// exact-check
+
+const QUERY = 'waker_from';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std::task', 'name': 'local_waker_from_nonlocal' },
+        { 'path': 'alloc::task', 'name': 'local_waker_from_nonlocal' },
+    ],
+};
index 702953e2e9dd104781f66075b589b4b1dd290855..4a654ccb1350351e13fb47a3579fe7d5b3301a66 100644 (file)
@@ -14,6 +14,6 @@ const EXPECTED = {
     'others': [
         { 'path': 'std::vec::Vec', 'name': 'new' },
         { 'path': 'std::vec::Vec', 'name': 'ne' },
-        { 'path': 'std::boxed::PinBox', 'name': 'new' },
+        { 'path': 'std::pin::PinBox', 'name': 'new' },
     ],
 };
index 25de698cad10e2308f0b1a5c9f2678d48b35159f..0c1eedc86ccfd83cdcd60d6155fc670566cfa77a 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-flags: -Cmetadata=aux
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 pub const fn foo() {}
 pub const unsafe fn bar() {}
diff --git a/src/test/rustdoc/blanket-reexport-item.rs b/src/test/rustdoc/blanket-reexport-item.rs
new file mode 100644 (file)
index 0000000..355bfa0
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+// @has foo/struct.S.html '//h3[@id="impl-Into"]//code' 'impl<T, U> Into for T'
+pub struct S2 {}
+mod m {
+    pub struct S {}
+}
+pub use m::*;
index c323681f60b0a1ac66997faa937c27d22f15721a..dc7a2799b46a911a0c3e92583613ff021e9c0371 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 #![crate_name = "foo"]
 
 // @has foo/fn.bar.html
index 380feb941d6feab4eaaa03f45ff326ba4db8606b..49694e3ae08d1830599ce2d7946d8a8da2e15081 100644 (file)
@@ -10,7 +10,7 @@
 
 #![crate_type="lib"]
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 pub struct Foo;
 
diff --git a/src/test/rustdoc/extern-html-root-url.rs b/src/test/rustdoc/extern-html-root-url.rs
new file mode 100644 (file)
index 0000000..c8a13be
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+// ignore-tidy-linelength
+
+// compile-flags:-Z unstable-options --extern-html-root-url core=https://example.com/core/0.1.0
+
+// @has extern_html_root_url/index.html
+// @has - '//a/@href' 'https://example.com/core/0.1.0/core/iter/index.html'
+#[doc(no_inline)]
+pub use std::iter;
diff --git a/src/test/rustdoc/impl-everywhere.rs b/src/test/rustdoc/impl-everywhere.rs
new file mode 100644 (file)
index 0000000..62da6f1
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+pub trait Foo {}
+pub trait Foo2 {}
+
+pub struct Bar;
+
+impl Foo for Bar {}
+impl Foo2 for Bar {}
+
+// @!has foo/fn.foo.html '//section[@id="main"]//pre' "x: &\'x impl Foo"
+// @!has foo/fn.foo.html '//section[@id="main"]//pre' "-> &\'x impl Foo {"
+pub fn foo<'x>(x: &'x impl Foo) -> &'x impl Foo {
+    x
+}
+
+// @!has foo/fn.foo2.html '//section[@id="main"]//pre' "x: &\'x impl Foo"
+// @!has foo/fn.foo2.html '//section[@id="main"]//pre' '-> impl Foo2 {'
+pub fn foo2<'x>(_x: &'x impl Foo) -> impl Foo2 {
+    Bar
+}
+
+// @!has foo/fn.foo_foo.html '//section[@id="main"]//pre' '-> impl Foo + Foo2 {'
+pub fn foo_foo() -> impl Foo + Foo2 {
+    Bar
+}
+
+// @!has foo/fn.foo2.html '//section[@id="main"]//pre' "x: &'x (impl Foo + Foo2)"
+pub fn foo_foo_foo<'x>(_x: &'x (impl Foo + Foo2)) {
+}
index d4a9a9f379b920d4a607bb83bb4253724fc3de46..3fce62529c78f348bce7b88e62a21cfe6a032af0 100644 (file)
@@ -10,7 +10,7 @@
 
 #![crate_name = "qwop"]
 
-/// (writen on a spider's web) Some Macro
+/// (written on a spider's web) Some Macro
 #[macro_export]
 macro_rules! some_macro {
     () => {
index c822d0f8b21b8c480cc7534d98ddd99b5cec309d..81b81a9a141da48292f513365c6445cff77ce4e5 100644 (file)
@@ -75,7 +75,7 @@ pub fn this_function() {}
 
 pub trait SoAmbiguous {}
 
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 pub fn SoAmbiguous() {}
 
 
index 3f3997726c93996e6846bfa3a73c69ef36a2e9f2..082f15a39dd955254c7b94b62ef41ef0eeb9f295 100644 (file)
@@ -12,7 +12,7 @@
 
 #![feature(plugin_registrar)]
 #![feature(box_syntax, rustc_private)]
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 #![feature(macro_at_most_once_rep)]
 
 // Load rustc as a plugin to get macros
@@ -49,5 +49,5 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_late_lint_pass(box Pass);
-    reg.register_lint_group("lint_me", vec![TEST_LINT, PLEASE_LINT]);
+    reg.register_lint_group("lint_me", None, vec![TEST_LINT, PLEASE_LINT]);
 }
index ab39709c529dcd3298361937db77ad02f761c942..315dad7eea515279f0aa1d06b15ba5ea2ded568b 100644 (file)
@@ -12,7 +12,7 @@
 
 #![feature(plugin_registrar)]
 #![feature(box_syntax, rustc_private)]
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 #![feature(macro_at_most_once_rep)]
 
 extern crate syntax;
index 01fa2f3459ea71d4a6cb1c6897c1f4042c25b802..e184c0919d0ecf333fc94177986d761eeb128bb2 100644 (file)
@@ -10,7 +10,7 @@
 
 #![feature(plugin_registrar)]
 #![feature(box_syntax, rustc_private)]
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 #![feature(macro_at_most_once_rep)]
 
 extern crate syntax;
 use rustc_plugin::Registry;
 use syntax::ast;
 declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff");
+declare_tool_lint!(pub clippy::TEST_GROUP, Warn, "Warn about other stuff");
 
 struct Pass;
 
 impl LintPass for Pass {
     fn get_lints(&self) -> LintArray {
-        lint_array!(TEST_LINT)
+        lint_array!(TEST_LINT, TEST_GROUP)
     }
 }
 
@@ -39,10 +40,14 @@ fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
         if it.ident.name == "lintme" {
             cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
         }
+        if it.ident.name == "lintmetoo" {
+            cx.span_lint(TEST_GROUP, it.span, "item is named 'lintmetoo'");
+        }
     }
 }
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_early_lint_pass(box Pass);
+    reg.register_lint_group("clippy::group", Some("clippy_group"), vec![TEST_LINT, TEST_GROUP]);
 }
index ccdcd2df31b4f49afd20bd2202f1088986c2afa3..ebe10b3714f20fecf91988379b59d6d24e8f6710 100644 (file)
@@ -8,17 +8,33 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// run-pass
 // aux-build:lint_tool_test.rs
 // ignore-stage1
+// compile-flags: --cfg foo
 #![feature(plugin)]
 #![feature(tool_lints)]
 #![plugin(lint_tool_test)]
 #![allow(dead_code)]
+#![cfg_attr(foo, warn(test_lint))]
+//~^ WARNING lint name `test_lint` is deprecated and may not have an effect in the future
+//~^^ WARNING lint name `test_lint` is deprecated and may not have an effect in the future
+#![deny(clippy_group)]
+//~^ WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
 
-fn lintme() { } //~ WARNING item is named 'lintme'
+fn lintme() { } //~ ERROR item is named 'lintme'
+
+#[allow(clippy::group)]
+fn lintmetoo() {}
 
 #[allow(clippy::test_lint)]
 pub fn main() {
     fn lintme() { }
+    fn lintmetoo() { } //~ ERROR item is named 'lintmetoo'
+}
+
+#[allow(test_group)]
+//~^ WARNING lint name `test_group` is deprecated and may not have an effect in the future
+#[deny(this_lint_does_not_exist)] //~ WARNING unknown lint: `this_lint_does_not_exist`
+fn hello() {
+    fn lintmetoo() { }
 }
index 22d0f458e7d7b487690175a9f3547adc8d99bec5..ab0c317e1cd0f4ef78ab86e203c5a00bd6f3f791 100644 (file)
@@ -1,8 +1,62 @@
-warning: item is named 'lintme'
-  --> $DIR/lint_tool_test.rs:19:1
+warning: lint name `test_lint` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint_tool_test.rs:18:23
    |
-LL | fn lintme() { } //~ WARNING item is named 'lintme'
+LL | #![cfg_attr(foo, warn(test_lint))]
+   |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
+   |
+   = note: #[warn(renamed_and_removed_lints)] on by default
+
+warning: lint name `clippy_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint_tool_test.rs:21:9
+   |
+LL | #![deny(clippy_group)]
+   |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
+
+warning: lint name `test_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint_tool_test.rs:35:9
+   |
+LL | #[allow(test_group)]
+   |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
+
+warning: unknown lint: `this_lint_does_not_exist`
+  --> $DIR/lint_tool_test.rs:37:8
+   |
+LL | #[deny(this_lint_does_not_exist)] //~ WARNING unknown lint: `this_lint_does_not_exist`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: #[warn(unknown_lints)] on by default
+
+warning: lint name `test_lint` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint_tool_test.rs:18:23
+   |
+LL | #![cfg_attr(foo, warn(test_lint))]
+   |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
+
+error: item is named 'lintme'
+  --> $DIR/lint_tool_test.rs:24:1
+   |
+LL | fn lintme() { } //~ ERROR item is named 'lintme'
    | ^^^^^^^^^^^^^^^
    |
-   = note: #[warn(clippy::test_lint)] on by default
+note: lint level defined here
+  --> $DIR/lint_tool_test.rs:21:9
+   |
+LL | #![deny(clippy_group)]
+   |         ^^^^^^^^^^^^
+   = note: #[deny(clippy::test_lint)] implied by #[deny(clippy::group)]
+
+error: item is named 'lintmetoo'
+  --> $DIR/lint_tool_test.rs:32:5
+   |
+LL |     fn lintmetoo() { } //~ ERROR item is named 'lintmetoo'
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint_tool_test.rs:21:9
+   |
+LL | #![deny(clippy_group)]
+   |         ^^^^^^^^^^^^
+   = note: #[deny(clippy::test_group)] implied by #[deny(clippy::group)]
+
+error: aborting due to 2 previous errors
 
index b0cccd8728bd1f3427d3acb7105237a025ed9ac6..977faf7decdf50741f1acd147a92a546a79c32ef 100644 (file)
@@ -12,8 +12,6 @@
 
 // aux-build:generate-mod.rs
 
-#![feature(proc_macro_gen, proc_macro_path_invoc)]
-
 extern crate generate_mod;
 
 struct FromOutside;
                                      //~| WARN this was previously accepted
 struct Z;
 
+fn inner_block() {
+    #[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside` in this scope
+                                        //~| WARN cannot find type `OuterDerive` in this scope
+                                        //~| WARN this was previously accepted
+                                        //~| WARN this was previously accepted
+    struct InnerZ;
+}
+
 #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
 struct W;
 
index c024aeffbb08675a33f0c1ad24e213f2e47a285b..a981b1bc8b85a2930522ea6bc0ef59f73c533c5d 100644 (file)
@@ -1,29 +1,29 @@
 error[E0412]: cannot find type `FromOutside` in this scope
-  --> $DIR/generate-mod.rs:21:1
+  --> $DIR/generate-mod.rs:19:1
    |
 LL | generate_mod::check!(); //~ ERROR cannot find type `FromOutside` in this scope
    | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
 
 error[E0412]: cannot find type `Outer` in this scope
-  --> $DIR/generate-mod.rs:21:1
+  --> $DIR/generate-mod.rs:19:1
    |
 LL | generate_mod::check!(); //~ ERROR cannot find type `FromOutside` in this scope
    | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
 
 error[E0412]: cannot find type `FromOutside` in this scope
-  --> $DIR/generate-mod.rs:24:1
+  --> $DIR/generate-mod.rs:22:1
    |
 LL | #[generate_mod::check_attr] //~ ERROR cannot find type `FromOutside` in this scope
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
 
 error[E0412]: cannot find type `OuterAttr` in this scope
-  --> $DIR/generate-mod.rs:24:1
+  --> $DIR/generate-mod.rs:22:1
    |
 LL | #[generate_mod::check_attr] //~ ERROR cannot find type `FromOutside` in this scope
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
 
 warning: cannot find type `FromOutside` in this scope
-  --> $DIR/generate-mod.rs:28:10
+  --> $DIR/generate-mod.rs:26:10
    |
 LL | #[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside` in this scope
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
@@ -33,7 +33,7 @@ LL | #[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside
    = note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
 
 warning: cannot find type `OuterDerive` in this scope
-  --> $DIR/generate-mod.rs:28:10
+  --> $DIR/generate-mod.rs:26:10
    |
 LL | #[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside` in this scope
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
@@ -41,6 +41,24 @@ LL | #[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
 
+warning: cannot find type `FromOutside` in this scope
+  --> $DIR/generate-mod.rs:33:14
+   |
+LL |     #[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside` in this scope
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
+
+warning: cannot find type `OuterDerive` in this scope
+  --> $DIR/generate-mod.rs:33:14
+   |
+LL |     #[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside` in this scope
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
+
 error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0412`.
index 342d7ddb36cf2660866db1a9ee282b8cfc2bac18..9def03e94506a529ed964209c5a847153198444c 100644 (file)
@@ -2,37 +2,37 @@ error: can't use a procedural macro from the same crate that defines it
   --> $DIR/macro-namespace-reserved-2.rs:34:5
    |
 LL |     my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^
 
 error: can't use a procedural macro from the same crate that defines it
   --> $DIR/macro-namespace-reserved-2.rs:37:5
    |
 LL |     my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines it
-   |     ^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^
 
 error: can't use a procedural macro from the same crate that defines it
   --> $DIR/macro-namespace-reserved-2.rs:40:5
    |
 LL |     MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^
 
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:43:1
+  --> $DIR/macro-namespace-reserved-2.rs:43:3
    |
 LL | #[my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
-   | ^^^^^^^^^^^
+   |   ^^^^^^^^
 
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:45:1
+  --> $DIR/macro-namespace-reserved-2.rs:45:3
    |
 LL | #[my_macro_attr] //~ ERROR can't use a procedural macro from the same crate that defines it
-   | ^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^^^^^
 
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:47:1
+  --> $DIR/macro-namespace-reserved-2.rs:47:3
    |
 LL | #[MyTrait] //~ ERROR can't use a procedural macro from the same crate that defines it
-   | ^^^^^^^^^^
+   |   ^^^^^^^
 
 error: can't use a procedural macro from the same crate that defines it
   --> $DIR/macro-namespace-reserved-2.rs:50:10
index b5fd3cf35f28bedd306e13813b6ed3a1a1a2a261..2e3492937acb976d514f606b93518cab0487db02 100644 (file)
 
 // compile-pass
 
-#![feature(raw_identifiers)]
-//~^ WARN the feature `raw_identifiers` is included in the Rust 2018 edition
+#![feature(impl_header_lifetime_elision)]
+//~^ WARN the feature `impl_header_lifetime_elision` is included in the Rust 2018 edition
 #![feature(rust_2018_preview)]
 
-fn main() {
-    let foo = 0;
-    let bar = r#foo;
-}
+fn main() {}
index 2aa3077e48c2dad6ffa3d56be088b875f2f4492e..c40064d38d2ffda28f942c01f89e53eab11d7962 100644 (file)
@@ -1,6 +1,6 @@
-warning[E0705]: the feature `raw_identifiers` is included in the Rust 2018 edition
+warning[E0705]: the feature `impl_header_lifetime_elision` is included in the Rust 2018 edition
   --> $DIR/E0705.rs:13:12
    |
-LL | #![feature(raw_identifiers)]
-   |            ^^^^^^^^^^^^^^^
+LL | #![feature(impl_header_lifetime_elision)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
index e398f16a065bd186c4b46a2ac3c5777d14e05114..0a54ae8341bbf70440c17b90400337e91935e465 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-flags:-C panic=abort
 
-#![feature(alloc_error_handler, panic_implementation)]
+#![feature(alloc_error_handler, panic_handler)]
 #![no_std]
 #![no_main]
 
@@ -24,5 +24,5 @@ fn oom(
     loop {}
 }
 
-#[panic_implementation]
+#[panic_handler]
 fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
index 4fee9d27e51759275aea4dcbdd5cd77216413fae..b33d82cd55008ede367ce912ef4ceb7e1dc17d50 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-flags:-C panic=abort
 
-#![feature(alloc_error_handler, panic_implementation)]
+#![feature(alloc_error_handler, panic_handler)]
 #![no_std]
 #![no_main]
 
@@ -23,5 +23,5 @@ fn oom(
     loop {}
 }
 
-#[panic_implementation]
+#[panic_handler]
 fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
index 828a78055d5f2ca21edae22a5db2c7d1117d0bc0..0e102dd08ea5de6212be85f8ea879e31fcebc444 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-flags:-C panic=abort
 
-#![feature(alloc_error_handler, panic_implementation)]
+#![feature(alloc_error_handler, panic_handler)]
 #![no_std]
 #![no_main]
 
@@ -21,5 +21,5 @@ fn oom() -> ! { //~ ERROR function should have one argument
     loop {}
 }
 
-#[panic_implementation]
+#[panic_handler]
 fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
diff --git a/src/test/ui/anon-params-denied-2018.rs b/src/test/ui/anon-params-denied-2018.rs
new file mode 100644 (file)
index 0000000..5e77aa8
--- /dev/null
@@ -0,0 +1,12 @@
+// Tests that anonymous parameters are a hard error in edition 2018.
+
+// edition:2018
+
+trait T {
+    fn foo(i32); //~ expected one of `:` or `@`, found `)`
+
+    fn bar_with_default_impl(String, String) {}
+    //~^ ERROR expected one of `:` or `@`, found `,`
+}
+
+fn main() {}
diff --git a/src/test/ui/anon-params-denied-2018.stderr b/src/test/ui/anon-params-denied-2018.stderr
new file mode 100644 (file)
index 0000000..24a1e6e
--- /dev/null
@@ -0,0 +1,14 @@
+error: expected one of `:` or `@`, found `)`
+  --> $DIR/anon-params-denied-2018.rs:6:15
+   |
+LL |     fn foo(i32); //~ expected one of `:` or `@`, found `)`
+   |               ^ expected one of `:` or `@` here
+
+error: expected one of `:` or `@`, found `,`
+  --> $DIR/anon-params-denied-2018.rs:8:36
+   |
+LL |     fn bar_with_default_impl(String, String) {}
+   |                                    ^ expected one of `:` or `@` here
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/anon-params-deprecated.fixed b/src/test/ui/anon-params-deprecated.fixed
new file mode 100644 (file)
index 0000000..7eee47d
--- /dev/null
@@ -0,0 +1,19 @@
+#![warn(anonymous_parameters)]
+// Test for the anonymous_parameters deprecation lint (RFC 1685)
+
+// compile-pass
+// edition:2015
+// run-rustfix
+
+trait T {
+    fn foo(_: i32); //~ WARNING anonymous parameters are deprecated
+                 //~| WARNING hard error
+
+    fn bar_with_default_impl(_: String, _: String) {}
+    //~^ WARNING anonymous parameters are deprecated
+    //~| WARNING hard error
+    //~| WARNING anonymous parameters are deprecated
+    //~| WARNING hard error
+}
+
+fn main() {}
index 4d37ba920f3d6bfb3add472d237646ecd34e86de..74de0c0b83407492b1b2840660a1d8a23d27537a 100644 (file)
@@ -1,24 +1,18 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![forbid(anonymous_parameters)]
+#![warn(anonymous_parameters)]
 // Test for the anonymous_parameters deprecation lint (RFC 1685)
 
+// compile-pass
+// edition:2015
+// run-rustfix
+
 trait T {
-    fn foo(i32); //~ ERROR anonymous parameters are deprecated
+    fn foo(i32); //~ WARNING anonymous parameters are deprecated
                  //~| WARNING hard error
 
     fn bar_with_default_impl(String, String) {}
-    //~^ ERROR anonymous parameters are deprecated
+    //~^ WARNING anonymous parameters are deprecated
     //~| WARNING hard error
-    //~| ERROR anonymous parameters are deprecated
+    //~| WARNING anonymous parameters are deprecated
     //~| WARNING hard error
 }
 
index fa13b8d97e5d954bd7a8ab737783296a485bac93..691c3159a52616e67394496647246d2bd44199ee 100644 (file)
@@ -1,34 +1,32 @@
-error: anonymous parameters are deprecated and will be removed in the next edition.
-  --> $DIR/anon-params-deprecated.rs:15:12
+warning: anonymous parameters are deprecated and will be removed in the next edition.
+  --> $DIR/anon-params-deprecated.rs:9:12
    |
-LL |     fn foo(i32); //~ ERROR anonymous parameters are deprecated
+LL |     fn foo(i32); //~ WARNING anonymous parameters are deprecated
    |            ^^^ help: Try naming the parameter or explicitly ignoring it: `_: i32`
    |
 note: lint level defined here
-  --> $DIR/anon-params-deprecated.rs:11:11
+  --> $DIR/anon-params-deprecated.rs:1:9
    |
-LL | #![forbid(anonymous_parameters)]
-   |           ^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+LL | #![warn(anonymous_parameters)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
    = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
 
-error: anonymous parameters are deprecated and will be removed in the next edition.
-  --> $DIR/anon-params-deprecated.rs:18:30
+warning: anonymous parameters are deprecated and will be removed in the next edition.
+  --> $DIR/anon-params-deprecated.rs:12:30
    |
 LL |     fn bar_with_default_impl(String, String) {}
    |                              ^^^^^^ help: Try naming the parameter or explicitly ignoring it: `_: String`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
    = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
 
-error: anonymous parameters are deprecated and will be removed in the next edition.
-  --> $DIR/anon-params-deprecated.rs:18:38
+warning: anonymous parameters are deprecated and will be removed in the next edition.
+  --> $DIR/anon-params-deprecated.rs:12:38
    |
 LL |     fn bar_with_default_impl(String, String) {}
    |                                      ^^^^^^ help: Try naming the parameter or explicitly ignoring it: `_: String`
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
    = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
 
-error: aborting due to 3 previous errors
-
index c1feb8ac45900a052d0ae393029bd71787c9e5ac..9f1df14605b693440d1ce15179fa50f3b17e359a 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Check that the user gets an errror if they omit a binding from an
+// Check that the user gets an error if they omit a binding from an
 // object type.
 
 pub trait Foo {
index db5cd47fe0efab84bcaab41a373eafeb49516728..437907008777ad2fca85f7b5d998e2586606f320 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(attr_literals)]
 #![feature(repr_simd)]
 
 #[repr(C)] //~ ERROR: attribute should be applied to struct, enum or union
index 1f3b358545bd6f9dbb275e27407104d36e061498..8d5e49a81f01cfc463e711d357f3a88eac909ba1 100644 (file)
@@ -1,5 +1,5 @@
 error[E0517]: attribute should be applied to struct, enum or union
-  --> $DIR/attr-usage-repr.rs:14:8
+  --> $DIR/attr-usage-repr.rs:13:8
    |
 LL | #[repr(C)] //~ ERROR: attribute should be applied to struct, enum or union
    |        ^
@@ -7,7 +7,7 @@ LL | fn f() {}
    | --------- not a struct, enum or union
 
 error[E0517]: attribute should be applied to enum
-  --> $DIR/attr-usage-repr.rs:26:8
+  --> $DIR/attr-usage-repr.rs:25:8
    |
 LL | #[repr(i8)] //~ ERROR: attribute should be applied to enum
    |        ^^
@@ -15,7 +15,7 @@ LL | struct SInt(f64, f64);
    | ---------------------- not an enum
 
 error[E0517]: attribute should be applied to struct or union
-  --> $DIR/attr-usage-repr.rs:32:8
+  --> $DIR/attr-usage-repr.rs:31:8
    |
 LL | #[repr(align(8))] //~ ERROR: attribute should be applied to struct
    |        ^^^^^^^^
@@ -23,7 +23,7 @@ LL | enum EAlign { A, B }
    | -------------------- not a struct or union
 
 error[E0517]: attribute should be applied to struct or union
-  --> $DIR/attr-usage-repr.rs:35:8
+  --> $DIR/attr-usage-repr.rs:34:8
    |
 LL | #[repr(packed)] //~ ERROR: attribute should be applied to struct
    |        ^^^^^^
@@ -31,7 +31,7 @@ LL | enum EPacked { A, B }
    | --------------------- not a struct or union
 
 error[E0517]: attribute should be applied to struct
-  --> $DIR/attr-usage-repr.rs:38:8
+  --> $DIR/attr-usage-repr.rs:37:8
    |
 LL | #[repr(simd)] //~ ERROR: attribute should be applied to struct
    |        ^^^^
index 7901f1f0fba201f2f6747c4ad2acece48c215874..2f2a74e4721dc6675a2320e95aa564e69ef8e168 100644 (file)
@@ -1,4 +1,4 @@
-error[E0087]: wrong number of type arguments: expected 1, found 2
+error[E0107]: wrong number of type arguments: expected 1, found 2
   --> $DIR/bad-mid-path-type-params.rs:40:28
    |
 LL |     let _ = S::new::<isize,f64>(1, 1.0);
@@ -10,13 +10,13 @@ error[E0107]: wrong number of lifetime arguments: expected 0, found 1
 LL |     let _ = S::<'a,isize>::new::<f64>(1, 1.0);
    |                 ^^ unexpected lifetime argument
 
-error[E0087]: wrong number of type arguments: expected 1, found 2
+error[E0107]: wrong number of type arguments: expected 1, found 2
   --> $DIR/bad-mid-path-type-params.rs:46:36
    |
 LL |     let _: S2 = Trait::new::<isize,f64>(1, 1.0);
    |                                    ^^^ unexpected type argument
 
-error[E0088]: wrong number of lifetime arguments: expected 0, found 1
+error[E0107]: wrong number of lifetime arguments: expected 0, found 1
   --> $DIR/bad-mid-path-type-params.rs:49:25
    |
 LL |     let _: S2 = Trait::<'a,isize>::new::<f64>(1, 1.0);
@@ -24,5 +24,4 @@ LL |     let _: S2 = Trait::<'a,isize>::new::<f64>(1, 1.0);
 
 error: aborting due to 4 previous errors
 
-Some errors occurred: E0087, E0088, E0107.
-For more information about an error, try `rustc --explain E0087`.
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/bastion-of-the-turbofish.rs b/src/test/ui/bastion-of-the-turbofish.rs
new file mode 100644 (file)
index 0000000..eadd238
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+// Bastion of the Turbofish
+// ------------------------
+// Beware travellers, lest you venture into waters callous and unforgiving,
+// where hope must be abandoned, ere it is cruelly torn from you. For here
+// stands the bastion of the Turbofish: an impenetrable fortress holding
+// unshaking against those who would dare suggest the supererogation of the
+// Turbofish.
+//
+// Once I was young and foolish and had the impudence to imagine that I could
+// shake free from the coils by which that creature had us tightly bound. I
+// dared to suggest that there was a better way: a brighter future, in which
+// Rustaceans both new and old could be rid of that vile beast. But alas! In
+// my foolhardiness my ignorance was unveiled and my dreams were dashed
+// unforgivingly against the rock of syntactic ambiguity.
+//
+// This humble program, small and insignificant though it might seem,
+// demonstrates that to which we had previously cast a blind eye: an ambiguity
+// in permitting generic arguments to be provided without the consent of the
+// Great Turbofish. Should you be so naïve as to try to revolt against its
+// mighty clutches, here shall its wrath be indomitably displayed. This
+// program must pass for all eternity, fundamentally at odds with an impetuous
+// rebellion against the Turbofish.
+//
+// My heart aches in sorrow, for I know I am defeated. Let this be a warning
+// to all those who come after. Here stands the bastion of the Turbofish.
+
+// See https://github.com/rust-lang/rust/pull/53562
+// and https://github.com/rust-lang/rfcs/pull/2527
+// for context.
+
+fn main() {
+    let (oh, woe, is, me) = ("the", "Turbofish", "remains", "undefeated");
+    let _: (bool, bool) = (oh<woe, is>(me));
+}
index bcbe0d1ffc0008fbea2369e31ef73cd95b5f1bd5..5ed425e958a584aa720929f113881be2e91e615b 100644 (file)
@@ -19,7 +19,7 @@
 // revisions: ast migrate nll
 
 // Since we are testing nll (and migration) explicitly as a separate
-// revisions, dont worry about the --compare-mode=nll on this test.
+// revisions, don't worry about the --compare-mode=nll on this test.
 
 // ignore-compare-mode-nll
 
index 508e09318ae112a30589496fb54ef626e68afe2d..d71c8462587d06e8e1411930b0791d66255ea65d 100644 (file)
@@ -15,7 +15,7 @@
 // permitted as `Foo` is not copy (even in a static/const
 // initializer).
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 struct Foo(usize);
 
diff --git a/src/test/ui/catch/catch-bad-lifetime.nll.stderr b/src/test/ui/catch/catch-bad-lifetime.nll.stderr
deleted file mode 100644 (file)
index dd1595f..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-error[E0506]: cannot assign to `i` because it is borrowed
-  --> $DIR/catch-bad-lifetime.rs:33:13
-   |
-LL |         let k = &mut i;
-   |                 ------ borrow of `i` occurs here
-...
-LL |             i = 10; //~ ERROR cannot assign to `i` because it is borrowed
-   |             ^^^^^^ assignment to borrowed `i` occurs here
-LL |         };
-LL |         ::std::mem::drop(k); //~ ERROR use of moved value: `k`
-   |                          - borrow later used here
-
-error[E0382]: use of moved value: `k`
-  --> $DIR/catch-bad-lifetime.rs:35:26
-   |
-LL |             Err(k) ?;
-   |                 - value moved here
-...
-LL |         ::std::mem::drop(k); //~ ERROR use of moved value: `k`
-   |                          ^ value used here after move
-   |
-   = note: move occurs because `k` has type `&mut i32`, which does not implement the `Copy` trait
-
-error[E0506]: cannot assign to `i` because it is borrowed
-  --> $DIR/catch-bad-lifetime.rs:36:9
-   |
-LL |         let k = &mut i;
-   |                 ------ borrow of `i` occurs here
-...
-LL |         i = 40; //~ ERROR cannot assign to `i` because it is borrowed
-   |         ^^^^^^ assignment to borrowed `i` occurs here
-LL | 
-LL |         let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") };
-   |                                         - borrow later used here
-
-error: aborting due to 3 previous errors
-
-Some errors occurred: E0382, E0506.
-For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/catch/catch-bad-lifetime.rs b/src/test/ui/catch/catch-bad-lifetime.rs
deleted file mode 100644 (file)
index f332ffd..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(catch_expr)]
-
-// This test checks that borrows made and returned inside catch blocks are properly constrained
-pub fn main() {
-    {
-        // Test that borrows returned from a catch block must be valid for the lifetime of the
-        // result variable
-        let _result: Result<(), &str> = do catch {
-            let my_string = String::from("");
-            let my_str: & str = & my_string;
-            //~^ ERROR `my_string` does not live long enough
-            Err(my_str) ?;
-            Err("") ?;
-        };
-    }
-
-    {
-        // Test that borrows returned from catch blocks freeze their referent
-        let mut i = 5;
-        let k = &mut i;
-        let mut j: Result<(), &mut i32> = do catch {
-            Err(k) ?;
-            i = 10; //~ ERROR cannot assign to `i` because it is borrowed
-        };
-        ::std::mem::drop(k); //~ ERROR use of moved value: `k`
-        i = 40; //~ ERROR cannot assign to `i` because it is borrowed
-
-        let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") };
-        *i_ptr = 50;
-    }
-}
-
diff --git a/src/test/ui/catch/catch-bad-lifetime.stderr b/src/test/ui/catch/catch-bad-lifetime.stderr
deleted file mode 100644 (file)
index 2ea54d1..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-error[E0597]: `my_string` does not live long enough
-  --> $DIR/catch-bad-lifetime.rs:20:35
-   |
-LL |             let my_str: & str = & my_string;
-   |                                   ^^^^^^^^^ borrowed value does not live long enough
-...
-LL |         };
-   |         - `my_string` dropped here while still borrowed
-LL |     }
-   |     - borrowed value needs to live until here
-
-error[E0506]: cannot assign to `i` because it is borrowed
-  --> $DIR/catch-bad-lifetime.rs:33:13
-   |
-LL |         let k = &mut i;
-   |                      - borrow of `i` occurs here
-...
-LL |             i = 10; //~ ERROR cannot assign to `i` because it is borrowed
-   |             ^^^^^^ assignment to borrowed `i` occurs here
-
-error[E0382]: use of moved value: `k`
-  --> $DIR/catch-bad-lifetime.rs:35:26
-   |
-LL |             Err(k) ?;
-   |                 - value moved here
-...
-LL |         ::std::mem::drop(k); //~ ERROR use of moved value: `k`
-   |                          ^ value used here after move
-   |
-   = note: move occurs because `k` has type `&mut i32`, which does not implement the `Copy` trait
-
-error[E0506]: cannot assign to `i` because it is borrowed
-  --> $DIR/catch-bad-lifetime.rs:36:9
-   |
-LL |         let k = &mut i;
-   |                      - borrow of `i` occurs here
-...
-LL |         i = 40; //~ ERROR cannot assign to `i` because it is borrowed
-   |         ^^^^^^ assignment to borrowed `i` occurs here
-
-error: aborting due to 4 previous errors
-
-Some errors occurred: E0382, E0506, E0597.
-For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/catch/catch-bad-type.rs b/src/test/ui/catch/catch-bad-type.rs
deleted file mode 100644 (file)
index b369847..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(catch_expr)]
-
-pub fn main() {
-    let res: Result<u32, i32> = do catch {
-        Err("")?; //~ ERROR the trait bound `i32: std::convert::From<&str>` is not satisfied
-        5
-    };
-
-    let res: Result<i32, i32> = do catch {
-        "" //~ ERROR type mismatch
-    };
-
-    let res: Result<i32, i32> = do catch { }; //~ ERROR type mismatch
-
-    let res: () = do catch { }; //~ the trait bound `(): std::ops::Try` is not satisfied
-
-    let res: i32 = do catch { 5 }; //~ ERROR the trait bound `i32: std::ops::Try` is not satisfied
-}
diff --git a/src/test/ui/catch/catch-bad-type.stderr b/src/test/ui/catch/catch-bad-type.stderr
deleted file mode 100644 (file)
index 2ab5b3e..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-error[E0277]: the trait bound `i32: std::convert::From<&str>` is not satisfied
-  --> $DIR/catch-bad-type.rs:15:9
-   |
-LL |         Err("")?; //~ ERROR the trait bound `i32: std::convert::From<&str>` is not satisfied
-   |         ^^^^^^^^ the trait `std::convert::From<&str>` is not implemented for `i32`
-   |
-   = help: the following implementations were found:
-             <i32 as std::convert::From<bool>>
-             <i32 as std::convert::From<i16>>
-             <i32 as std::convert::From<i8>>
-             <i32 as std::convert::From<u16>>
-             <i32 as std::convert::From<u8>>
-   = note: required by `std::convert::From::from`
-
-error[E0271]: type mismatch resolving `<std::result::Result<i32, i32> as std::ops::Try>::Ok == &str`
-  --> $DIR/catch-bad-type.rs:20:9
-   |
-LL |         "" //~ ERROR type mismatch
-   |         ^^ expected i32, found &str
-   |
-   = note: expected type `i32`
-              found type `&str`
-
-error[E0271]: type mismatch resolving `<std::result::Result<i32, i32> as std::ops::Try>::Ok == ()`
-  --> $DIR/catch-bad-type.rs:23:44
-   |
-LL |     let res: Result<i32, i32> = do catch { }; //~ ERROR type mismatch
-   |                                            ^ expected i32, found ()
-   |
-   = note: expected type `i32`
-              found type `()`
-
-error[E0277]: the trait bound `(): std::ops::Try` is not satisfied
-  --> $DIR/catch-bad-type.rs:25:28
-   |
-LL |     let res: () = do catch { }; //~ the trait bound `(): std::ops::Try` is not satisfied
-   |                            ^^^ the trait `std::ops::Try` is not implemented for `()`
-   |
-   = note: required by `std::ops::Try::from_ok`
-
-error[E0277]: the trait bound `i32: std::ops::Try` is not satisfied
-  --> $DIR/catch-bad-type.rs:27:29
-   |
-LL |     let res: i32 = do catch { 5 }; //~ ERROR the trait bound `i32: std::ops::Try` is not satisfied
-   |                             ^^^^^ the trait `std::ops::Try` is not implemented for `i32`
-   |
-   = note: required by `std::ops::Try::from_ok`
-
-error: aborting due to 5 previous errors
-
-Some errors occurred: E0271, E0277.
-For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/catch/catch-block-type-error.rs b/src/test/ui/catch/catch-block-type-error.rs
deleted file mode 100644 (file)
index 10130ef..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(catch_expr)]
-
-fn foo() -> Option<()> { Some(()) }
-
-fn main() {
-    let _: Option<f32> = do catch {
-        foo()?;
-        42
-        //~^ ERROR type mismatch
-    };
-
-    let _: Option<i32> = do catch {
-        foo()?;
-    };
-    //~^ ERROR type mismatch
-}
diff --git a/src/test/ui/catch/catch-block-type-error.stderr b/src/test/ui/catch/catch-block-type-error.stderr
deleted file mode 100644 (file)
index 288168c..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-error[E0271]: type mismatch resolving `<std::option::Option<f32> as std::ops::Try>::Ok == {integer}`
-  --> $DIR/catch-block-type-error.rs:18:9
-   |
-LL |         42
-   |         ^^
-   |         |
-   |         expected f32, found integral variable
-   |         help: use a float literal: `42.0`
-   |
-   = note: expected type `f32`
-              found type `{integer}`
-
-error[E0271]: type mismatch resolving `<std::option::Option<i32> as std::ops::Try>::Ok == ()`
-  --> $DIR/catch-block-type-error.rs:24:5
-   |
-LL |     };
-   |     ^ expected i32, found ()
-   |
-   = note: expected type `i32`
-              found type `()`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/catch/catch-in-match.rs b/src/test/ui/catch/catch-in-match.rs
deleted file mode 100644 (file)
index 9f9968e..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(catch_expr)]
-
-fn main() {
-    match do catch { false } { _ => {} } //~ ERROR expected expression, found reserved keyword `do`
-}
diff --git a/src/test/ui/catch/catch-in-match.stderr b/src/test/ui/catch/catch-in-match.stderr
deleted file mode 100644 (file)
index 1542989..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected expression, found reserved keyword `do`
-  --> $DIR/catch-in-match.rs:14:11
-   |
-LL |     match do catch { false } { _ => {} } //~ ERROR expected expression, found reserved keyword `do`
-   |           ^^ expected expression
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/catch/catch-in-while.rs b/src/test/ui/catch/catch-in-while.rs
deleted file mode 100644 (file)
index cb8613e..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(catch_expr)]
-
-fn main() {
-    while do catch { false } {} //~ ERROR expected expression, found reserved keyword `do`
-}
diff --git a/src/test/ui/catch/catch-in-while.stderr b/src/test/ui/catch/catch-in-while.stderr
deleted file mode 100644 (file)
index 9316bbc..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected expression, found reserved keyword `do`
-  --> $DIR/catch-in-while.rs:14:11
-   |
-LL |     while do catch { false } {} //~ ERROR expected expression, found reserved keyword `do`
-   |           ^^ expected expression
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/catch/catch-maybe-bad-lifetime.nll.stderr b/src/test/ui/catch/catch-maybe-bad-lifetime.nll.stderr
deleted file mode 100644 (file)
index 1577931..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0382]: borrow of moved value: `x`
-  --> $DIR/catch-maybe-bad-lifetime.rs:33:24
-   |
-LL |             ::std::mem::drop(x);
-   |                              - value moved here
-LL |         };
-LL |         println!("{}", x); //~ ERROR use of moved value: `x`
-   |                        ^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/catch/catch-maybe-bad-lifetime.rs b/src/test/ui/catch/catch-maybe-bad-lifetime.rs
deleted file mode 100644 (file)
index faefb5e..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(catch_expr)]
-
-// This test checks that borrows made and returned inside catch blocks are properly constrained
-pub fn main() {
-    {
-        // Test that a borrow which *might* be returned still freezes its referent
-        let mut i = 222;
-        let x: Result<&i32, ()> = do catch {
-            Err(())?;
-            &i
-        };
-        x.ok().cloned();
-        i = 0; //~ ERROR cannot assign to `i` because it is borrowed
-        let _ = i;
-    }
-
-    {
-        let x = String::new();
-        let _y: Result<(), ()> = do catch {
-            Err(())?;
-            ::std::mem::drop(x);
-        };
-        println!("{}", x); //~ ERROR use of moved value: `x`
-    }
-
-    {
-        // Test that a borrow which *might* be assigned to an outer variable still freezes
-        // its referent
-        let mut i = 222;
-        let j;
-        let x: Result<(), ()> = do catch {
-            Err(())?;
-            j = &i;
-        };
-        i = 0; //~ ERROR cannot assign to `i` because it is borrowed
-        let _ = i;
-    }
-}
-
diff --git a/src/test/ui/catch/catch-maybe-bad-lifetime.stderr b/src/test/ui/catch/catch-maybe-bad-lifetime.stderr
deleted file mode 100644 (file)
index 21fe104..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-error[E0506]: cannot assign to `i` because it is borrowed
-  --> $DIR/catch-maybe-bad-lifetime.rs:23:9
-   |
-LL |             &i
-   |              - borrow of `i` occurs here
-...
-LL |         i = 0; //~ ERROR cannot assign to `i` because it is borrowed
-   |         ^^^^^ assignment to borrowed `i` occurs here
-
-error[E0382]: use of moved value: `x`
-  --> $DIR/catch-maybe-bad-lifetime.rs:33:24
-   |
-LL |             ::std::mem::drop(x);
-   |                              - value moved here
-LL |         };
-LL |         println!("{}", x); //~ ERROR use of moved value: `x`
-   |                        ^ value used here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
-
-error[E0506]: cannot assign to `i` because it is borrowed
-  --> $DIR/catch-maybe-bad-lifetime.rs:45:9
-   |
-LL |             j = &i;
-   |                  - borrow of `i` occurs here
-LL |         };
-LL |         i = 0; //~ ERROR cannot assign to `i` because it is borrowed
-   |         ^^^^^ assignment to borrowed `i` occurs here
-
-error: aborting due to 3 previous errors
-
-Some errors occurred: E0382, E0506.
-For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/catch/catch-opt-init.nll.stderr b/src/test/ui/catch/catch-opt-init.nll.stderr
deleted file mode 100644 (file)
index ea8c8eb..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0381]: borrow of possibly uninitialized variable: `cfg_res`
-  --> $DIR/catch-opt-init.rs:23:5
-   |
-LL |     assert_eq!(cfg_res, 5); //~ ERROR use of possibly uninitialized variable
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ use of possibly uninitialized `cfg_res`
-   |
-   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/catch/catch-opt-init.rs b/src/test/ui/catch/catch-opt-init.rs
deleted file mode 100644 (file)
index 0c41102..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(catch_expr)]
-
-fn use_val<T: Sized>(_x: T) {}
-
-pub fn main() {
-    let cfg_res;
-    let _: Result<(), ()> = do catch {
-        Err(())?;
-        cfg_res = 5;
-        Ok::<(), ()>(())?;
-        use_val(cfg_res);
-    };
-    assert_eq!(cfg_res, 5); //~ ERROR use of possibly uninitialized variable
-}
-
diff --git a/src/test/ui/catch/catch-opt-init.stderr b/src/test/ui/catch/catch-opt-init.stderr
deleted file mode 100644 (file)
index 6a14ba1..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0381]: use of possibly uninitialized variable: `cfg_res`
-  --> $DIR/catch-opt-init.rs:23:16
-   |
-LL |     assert_eq!(cfg_res, 5); //~ ERROR use of possibly uninitialized variable
-   |                ^^^^^^^ use of possibly uninitialized `cfg_res`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0381`.
index 33fe52366dbbbd5e534c98856661656a9e6e3f3a..0f51c7d68c642f2a81c8cdbf954973345906510f 100644 (file)
@@ -2,7 +2,7 @@ error[E0658]: The attribute `unknown` is currently unknown to the compiler and m
   --> $DIR/cfg-attr-unknown-attribute-macro-expansion.rs:13:27
    |
 LL |         #[cfg_attr(all(), unknown)] //~ ERROR `unknown` is currently unknown
-   |                           ^^^^^^^^
+   |                           ^^^^^^^
 ...
 LL | foo!();
    | ------- in this macro invocation
index 7c0f233a645cb00efece3fbe5a2bca54be6e0559..c5ba5beeca7a57de53875488fcec1ad0f0e9fc7d 100644 (file)
@@ -12,9 +12,9 @@
 
 #[rustc_dump_program_clauses] //~ ERROR program clause dump
 trait Foo<S, T, U> {
-    fn s(S) -> S;
-    fn t(T) -> T;
-    fn u(U) -> U;
+    fn s(_: S) -> S;
+    fn t(_: T) -> T;
+    fn u(_: U) -> U;
 }
 
 fn main() {
index 47e9398d3647eefc2646210fdd7f4f7ff8df0195..7fc48cfd56ddcc3b0ffda6253f3fd8ce9c0674ad 100644 (file)
@@ -13,7 +13,7 @@
 #[rustc_dump_program_clauses] //~ ERROR program clause dump
 trait Foo<F> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8
 {
-    fn s(F) -> F;
+    fn s(_: F) -> F;
 }
 
 fn main() {
index 67ee7c28b6a4e55941e28ccdd24eb521bd7cb986..57e95e39cd9960ee4547344836f0160b0848b706 100644 (file)
@@ -15,9 +15,9 @@
 
 #[rustc_dump_program_clauses] //~ ERROR program clause dump
 trait Foo<'a, 'b, S, T, U> where S: Debug, T: Borrow<U>, U: ?Sized, 'a: 'b, U: 'b {
-    fn s(S) -> S;
-    fn t(T) -> T;
-    fn u(U) -> U;
+    fn s(_: S) -> S;
+    fn t(_: T) -> T;
+    fn u(_: U) -> U;
 }
 
 fn main() {
diff --git a/src/test/ui/closure-expected.rs b/src/test/ui/closure-expected.rs
new file mode 100644 (file)
index 0000000..ff52948
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let x = Some(1);
+    let y = x.or_else(4);
+    //~^ ERROR expected a `std::ops::FnOnce<()>` closure, found `{integer}`
+}
diff --git a/src/test/ui/closure-expected.stderr b/src/test/ui/closure-expected.stderr
new file mode 100644 (file)
index 0000000..0da506b
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0277]: expected a `std::ops::FnOnce<()>` closure, found `{integer}`
+  --> $DIR/closure-expected.rs:13:15
+   |
+LL |     let y = x.or_else(4);
+   |               ^^^^^^^ expected an `FnOnce<()>` closure, found `{integer}`
+   |
+   = help: the trait `std::ops::FnOnce<()>` is not implemented for `{integer}`
+   = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-eval/issue-53157.rs b/src/test/ui/const-eval/issue-53157.rs
deleted file mode 100644 (file)
index 9008477..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-pass
-
-macro_rules! m {
-    () => {{
-        fn f(_: impl Sized) {}
-        f
-    }}
-}
-
-fn main() {
-    fn f() -> impl Sized {};
-    m!()(f());
-}
index cf3ad9ae8ecd7ae33bdc7bad2ba982c77c7897c7..d1d801499d37291352df9f3f353f4a24376f6a49 100644 (file)
@@ -1,22 +1,22 @@
-error[E0090]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: wrong number of lifetime arguments: expected 2, found 1
   --> $DIR/constructor-lifetime-args.rs:27:5
    |
 LL |     S::<'static>(&0, &0);
    |     ^^^^^^^^^^^^ expected 2 lifetime arguments
 
-error[E0088]: wrong number of lifetime arguments: expected 2, found 3
+error[E0107]: wrong number of lifetime arguments: expected 2, found 3
   --> $DIR/constructor-lifetime-args.rs:29:27
    |
 LL |     S::<'static, 'static, 'static>(&0, &0);
    |                           ^^^^^^^ unexpected lifetime argument
 
-error[E0090]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: wrong number of lifetime arguments: expected 2, found 1
   --> $DIR/constructor-lifetime-args.rs:32:5
    |
 LL |     E::V::<'static>(&0);
    |     ^^^^^^^^^^^^^^^ expected 2 lifetime arguments
 
-error[E0088]: wrong number of lifetime arguments: expected 2, found 3
+error[E0107]: wrong number of lifetime arguments: expected 2, found 3
   --> $DIR/constructor-lifetime-args.rs:34:30
    |
 LL |     E::V::<'static, 'static, 'static>(&0);
@@ -24,5 +24,4 @@ LL |     E::V::<'static, 'static, 'static>(&0);
 
 error: aborting due to 4 previous errors
 
-Some errors occurred: E0088, E0090.
-For more information about an error, try `rustc --explain E0088`.
+For more information about this error, try `rustc --explain E0107`.
index b0d5a6b12727b16225778adc037b0943931a7cc2..499227e71a74cc42bf5314b1de9a1ddd2a85b241 100644 (file)
@@ -11,6 +11,6 @@
 // Crate that exports a const fn. Used for testing cross-crate.
 
 #![crate_type="rlib"]
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 pub const fn foo() -> usize { 22 } //~ ERROR const fn is unstable
diff --git a/src/test/ui/consts/const-eval/auxiliary/stability.rs b/src/test/ui/consts/const-eval/auxiliary/stability.rs
new file mode 100644 (file)
index 0000000..18c6b52
--- /dev/null
@@ -0,0 +1,21 @@
+// 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.
+
+// Crate that exports a const fn. Used for testing cross-crate.
+
+#![crate_type="rlib"]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#![feature(rustc_const_unstable, const_fn)]
+#![feature(staged_api)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo")]
+pub const fn foo() -> u32 { 42 }
diff --git a/src/test/ui/consts/const-eval/const_panic.rs b/src/test/ui/consts/const-eval/const_panic.rs
new file mode 100644 (file)
index 0000000..f2170f5
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(const_panic)]
+
+fn main() {}
+
+const Z: () = panic!("cheese");
+//~^ ERROR this constant cannot be used
+
+const Y: () = unreachable!();
+//~^ ERROR this constant cannot be used
+
+const X: () = unimplemented!();
+//~^ ERROR this constant cannot be used
diff --git a/src/test/ui/consts/const-eval/const_panic.stderr b/src/test/ui/consts/const-eval/const_panic.stderr
new file mode 100644 (file)
index 0000000..c11146f
--- /dev/null
@@ -0,0 +1,33 @@
+error: this constant cannot be used
+  --> $DIR/const_panic.rs:15:1
+   |
+LL | const Z: () = panic!("cheese");
+   | ^^^^^^^^^^^^^^----------------^
+   |               |
+   |               the evaluated program panicked at 'cheese', $DIR/const_panic.rs:15:15
+   |
+   = note: #[deny(const_err)] on by default
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: this constant cannot be used
+  --> $DIR/const_panic.rs:18:1
+   |
+LL | const Y: () = unreachable!();
+   | ^^^^^^^^^^^^^^--------------^
+   |               |
+   |               the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:18:15
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: this constant cannot be used
+  --> $DIR/const_panic.rs:21:1
+   |
+LL | const X: () = unimplemented!();
+   | ^^^^^^^^^^^^^^----------------^
+   |               |
+   |               the evaluated program panicked at 'not yet implemented', $DIR/const_panic.rs:21:15
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/consts/const-eval/const_panic_libcore.rs b/src/test/ui/consts/const-eval/const_panic_libcore.rs
new file mode 100644 (file)
index 0000000..59aeca1
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![no_std]
+#![crate_type = "lib"]
+#![feature(const_panic)]
+
+const Z: () = panic!("cheese");
+//~^ ERROR this constant cannot be used
+
+const Y: () = unreachable!();
+//~^ ERROR this constant cannot be used
+
+const X: () = unimplemented!();
+//~^ ERROR this constant cannot be used
diff --git a/src/test/ui/consts/const-eval/const_panic_libcore.stderr b/src/test/ui/consts/const-eval/const_panic_libcore.stderr
new file mode 100644 (file)
index 0000000..45f2ee7
--- /dev/null
@@ -0,0 +1,33 @@
+error: this constant cannot be used
+  --> $DIR/const_panic_libcore.rs:15:1
+   |
+LL | const Z: () = panic!("cheese");
+   | ^^^^^^^^^^^^^^----------------^
+   |               |
+   |               the evaluated program panicked at 'cheese', $DIR/const_panic_libcore.rs:15:15
+   |
+   = note: #[deny(const_err)] on by default
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: this constant cannot be used
+  --> $DIR/const_panic_libcore.rs:18:1
+   |
+LL | const Y: () = unreachable!();
+   | ^^^^^^^^^^^^^^--------------^
+   |               |
+   |               the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore.rs:18:15
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: this constant cannot be used
+  --> $DIR/const_panic_libcore.rs:21:1
+   |
+LL | const X: () = unimplemented!();
+   | ^^^^^^^^^^^^^^----------------^
+   |               |
+   |               the evaluated program panicked at 'not yet implemented', $DIR/const_panic_libcore.rs:21:15
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs
new file mode 100644 (file)
index 0000000..f5e5f97
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "bin"]
+#![feature(lang_items)]
+#![feature(panic_handler)]
+#![feature(const_panic)]
+#![no_main]
+#![no_std]
+
+use core::panic::PanicInfo;
+
+const Z: () = panic!("cheese");
+//~^ ERROR this constant cannot be used
+
+const Y: () = unreachable!();
+//~^ ERROR this constant cannot be used
+
+const X: () = unimplemented!();
+//~^ ERROR this constant cannot be used
+
+#[lang = "eh_personality"]
+fn eh() {}
+#[lang = "eh_unwind_resume"]
+fn eh_unwind_resume() {}
+
+#[panic_handler]
+fn panic(_info: &PanicInfo) -> ! {
+    loop {}
+}
diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_main.stderr b/src/test/ui/consts/const-eval/const_panic_libcore_main.stderr
new file mode 100644 (file)
index 0000000..7cb9f51
--- /dev/null
@@ -0,0 +1,33 @@
+error: this constant cannot be used
+  --> $DIR/const_panic_libcore_main.rs:20:1
+   |
+LL | const Z: () = panic!("cheese");
+   | ^^^^^^^^^^^^^^----------------^
+   |               |
+   |               the evaluated program panicked at 'cheese', $DIR/const_panic_libcore_main.rs:20:15
+   |
+   = note: #[deny(const_err)] on by default
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: this constant cannot be used
+  --> $DIR/const_panic_libcore_main.rs:23:1
+   |
+LL | const Y: () = unreachable!();
+   | ^^^^^^^^^^^^^^--------------^
+   |               |
+   |               the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore_main.rs:23:15
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: this constant cannot be used
+  --> $DIR/const_panic_libcore_main.rs:26:1
+   |
+LL | const X: () = unimplemented!();
+   | ^^^^^^^^^^^^^^----------------^
+   |               |
+   |               the evaluated program panicked at 'not yet implemented', $DIR/const_panic_libcore_main.rs:26:15
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
index a9442be081d948824ee79fb1abb0619d8142e1c2..df1e6f8e4c4f0d7820dba78648a13ecefb7e1aad 100644 (file)
@@ -22,7 +22,7 @@ error: this constant cannot be used
 LL | const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR cannot be used
    | ^^^^^^^^^^^^^^^^^^^^^^^^^-------------------^^^
    |                          |
-   |                          tried to access memory with alignment 2, but alignment 4 is required
+   |                          a memory access tried to interpret some bytes as a pointer
 
 error: this constant cannot be used
   --> $DIR/const_raw_ptr_ops.rs:27:1
index 684fa1c997bf100a57c8242fba38039a06a3c531..ed3e38486baf628a045b33d3709c250044c4d5dd 100644 (file)
@@ -11,6 +11,7 @@ error[E0597]: borrowed value does not live long enough
    |
 LL |     let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     //~^ does not live long enough
 LL | }
    | - temporary value only lives until here
    |
index a590e569947f82caf0fa7c4b6599b63c4c32e996..623e99480a70a752c17d2c26eae70c861b13643c 100644 (file)
@@ -31,4 +31,5 @@ fn a() {
 fn main() {
     let _: &'static u32 = &meh(); //~ ERROR does not live long enough
     let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
+    //~^ does not live long enough
 }
index 7963cbb4e45691b56db9982621b3c33a9b3b4bf6..b9856d37b0ee1a846a47345f9bec08c6bed2dd07 100644 (file)
@@ -21,12 +21,23 @@ error[E0597]: borrowed value does not live long enough
    |
 LL |     let _: &'static u32 = &meh(); //~ ERROR does not live long enough
    |                            ^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/dont_promote_unstable_const_fn.rs:33:26
+   |
 LL |     let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     //~^ does not live long enough
 LL | }
    | - temporary value only lives until here
    |
    = note: borrowed value must be valid for the static lifetime...
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.nll.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.nll.stderr
new file mode 100644 (file)
index 0000000..4c8f2f4
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:19:29
+   |
+LL |     let _x: &'static u32 = &foo(); //~ ERROR does not live long enough
+   |                             ^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.rs b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.rs
new file mode 100644 (file)
index 0000000..81be5d4
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:stability.rs
+
+extern crate stability;
+
+use stability::foo;
+
+fn main() {
+    let _: &'static u32 = &foo(); //~ ERROR does not live long enough
+    let _x: &'static u32 = &foo(); //~ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr
new file mode 100644 (file)
index 0000000..cea36a0
--- /dev/null
@@ -0,0 +1,24 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:18:28
+   |
+LL |     let _: &'static u32 = &foo(); //~ ERROR does not live long enough
+   |                            ^^^^^ temporary value does not live long enough
+LL |     let _x: &'static u32 = &foo(); //~ ERROR does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:19:29
+   |
+LL |     let _x: &'static u32 = &foo(); //~ ERROR does not live long enough
+   |                             ^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
index 2a0a674e237feafee0d0b595f3534ba12258af21..21025877340eabd482f19268d2a2535b003577bf 100644 (file)
@@ -5,7 +5,7 @@ LL | / static FOO: (&Foo, &Bar) = unsafe {( //~ undefined behavior
 LL | |     Union { usize: &BAR }.foo,
 LL | |     Union { usize: &BAR }.bar,
 LL | | )};
-   | |___^ type validation failed: encountered 5 at (*.1).TAG, but expected something in the range 42..=99
+   | |___^ type validation failed: encountered invalid enum discriminant 5 at .1.<deref>
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
diff --git a/src/test/ui/consts/const-eval/feature-gate-const_panic.rs b/src/test/ui/consts/const-eval/feature-gate-const_panic.rs
new file mode 100644 (file)
index 0000000..26eb95d
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {}
+
+const Z: () = panic!("cheese");
+//~^ ERROR panicking in constants is unstable
+
+const Y: () = unreachable!();
+//~^ ERROR panicking in constants is unstable
+
+const X: () = unimplemented!();
+//~^ ERROR panicking in constants is unstable
diff --git a/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr b/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr
new file mode 100644 (file)
index 0000000..f4d05ed
--- /dev/null
@@ -0,0 +1,30 @@
+error[E0658]: panicking in constants is unstable (see issue #51999)
+  --> $DIR/feature-gate-const_panic.rs:13:15
+   |
+LL | const Z: () = panic!("cheese");
+   |               ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_panic)] to the crate attributes to enable
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0658]: panicking in constants is unstable (see issue #51999)
+  --> $DIR/feature-gate-const_panic.rs:19:15
+   |
+LL | const X: () = unimplemented!();
+   |               ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_panic)] to the crate attributes to enable
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0658]: panicking in constants is unstable (see issue #51999)
+  --> $DIR/feature-gate-const_panic.rs:16:15
+   |
+LL | const Y: () = unreachable!();
+   |               ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_panic)] to the crate attributes to enable
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
index c0b45f0ba3041a9df2dec53de039f03eea1e3838..200f423f6e39b5de9d5718650fcd299fc3577cbd 100644 (file)
@@ -10,7 +10,7 @@
 
 #![warn(const_err)]
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const fn foo(x: u32) -> u32 {
     x
index f6a2db31d371ad6c86c54296fc12104eb4c6cc38..2bc860e3ef94fb2890dc870a709674a050893032 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-pass
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 struct S(pub &'static u32, pub u32);
 
diff --git a/src/test/ui/consts/const-eval/issue-53157.rs b/src/test/ui/consts/const-eval/issue-53157.rs
new file mode 100644 (file)
index 0000000..9008477
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+macro_rules! m {
+    () => {{
+        fn f(_: impl Sized) {}
+        f
+    }}
+}
+
+fn main() {
+    fn f() -> impl Sized {};
+    m!()(f());
+}
diff --git a/src/test/ui/consts/const-eval/issue-53401.rs b/src/test/ui/consts/const-eval/issue-53401.rs
new file mode 100644 (file)
index 0000000..cb74f4f
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+pub const STATIC_TRAIT: &Test = &();
+
+fn main() {}
+
+pub trait Test {
+    fn test() where Self: Sized {}
+}
+
+impl Test for () {}
diff --git a/src/test/ui/consts/const-eval/transmute-const-promotion.rs b/src/test/ui/consts/const-eval/transmute-const-promotion.rs
new file mode 100644 (file)
index 0000000..ea55584
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(const_transmute)]
+
+use std::mem;
+
+fn main() {
+    let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
+    //~^ ERROR value does not live long enough
+}
diff --git a/src/test/ui/consts/const-eval/transmute-const-promotion.stderr b/src/test/ui/consts/const-eval/transmute-const-promotion.stderr
new file mode 100644 (file)
index 0000000..2f46684
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/transmute-const-promotion.rs:16:37
+   |
+LL |     let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     //~^ ERROR value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-eval/transmute-const.rs b/src/test/ui/consts/const-eval/transmute-const.rs
new file mode 100644 (file)
index 0000000..a585a44
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(const_transmute)]
+
+use std::mem;
+
+static FOO: bool = unsafe { mem::transmute(3u8) };
+//~^ ERROR this static likely exhibits undefined behavior
+//~^^ type validation failed: encountered 3, but expected something in the range 0..=1
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/transmute-const.stderr b/src/test/ui/consts/const-eval/transmute-const.stderr
new file mode 100644 (file)
index 0000000..c9beca7
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0080]: this static likely exhibits undefined behavior
+  --> $DIR/transmute-const.rs:15:1
+   |
+LL | static FOO: bool = unsafe { mem::transmute(3u8) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3, but expected something in the range 0..=1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-enum-ptr.rs b/src/test/ui/consts/const-eval/ub-enum-ptr.rs
deleted file mode 100644 (file)
index 8538dd1..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[repr(usize)]
-#[derive(Copy, Clone)]
-enum Enum {
-    A = 0,
-}
-
-union Foo {
-    a: &'static u8,
-    b: Enum,
-}
-
-// A pointer is guaranteed non-null
-const BAD_ENUM: Enum = unsafe { Foo { a: &1 }.b};
-//~^ ERROR this constant likely exhibits undefined behavior
-
-fn main() {
-}
diff --git a/src/test/ui/consts/const-eval/ub-enum-ptr.stderr b/src/test/ui/consts/const-eval/ub-enum-ptr.stderr
deleted file mode 100644 (file)
index 4b7ccc2..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/ub-enum-ptr.rs:23:1
-   |
-LL | const BAD_ENUM: Enum = unsafe { Foo { a: &1 }.b};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer at .TAG, but expected something in the range 0..=0
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs
new file mode 100644 (file)
index 0000000..bcb71af
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[repr(usize)]
+#[derive(Copy, Clone)]
+enum Enum {
+    A = 0,
+}
+union TransmuteEnum {
+    a: &'static u8,
+    b: Enum,
+}
+
+// A pointer is guaranteed non-null
+const BAD_ENUM: Enum = unsafe { TransmuteEnum { a: &1 }.b };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+// Invalid enum discriminant
+#[repr(usize)]
+#[derive(Copy, Clone)]
+enum Enum2 {
+    A = 2,
+}
+union TransmuteEnum2 {
+    a: usize,
+    b: Enum2,
+}
+const BAD_ENUM2 : Enum2 = unsafe { TransmuteEnum2 { a: 0 }.b };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+// Invalid enum field content (mostly to test printing of apths for enum tuple
+// variants and tuples).
+union TransmuteChar {
+    a: u32,
+    b: char,
+}
+// Need to create something which does not clash with enum layout optimizations.
+const BAD_ENUM_CHAR : Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
+//~^ ERROR this constant likely exhibits undefined behavior
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr
new file mode 100644 (file)
index 0000000..572d08d
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-enum.rs:22:1
+   |
+LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { a: &1 }.b };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer enum discriminant
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-enum.rs:35:1
+   |
+LL | const BAD_ENUM2 : Enum2 = unsafe { TransmuteEnum2 { a: 0 }.b };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid enum discriminant 0
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-enum.rs:45:1
+   |
+LL | const BAD_ENUM_CHAR : Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered character at .Some.0.1, but expected a valid unicode codepoint
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
index 341cc7bb49116d8bfb3ef1f28968f8cd44616ce1..30a738a83a3b67d2b769f8be34840c1c3cb02464 100644 (file)
 
 // Test that we can't call random fns in a const fn or do other bad things.
 
-#![feature(const_fn)]
+#![feature(const_fn, const_transmute)]
 
 use std::mem::transmute;
 
 fn random() -> u32 { 0 }
 
 const fn sub(x: &u32) -> usize {
-    unsafe { transmute(x) } //~ ERROR E0015
+    unsafe { transmute(x) }
 }
 
 const fn sub1() -> u32 {
index 1e99a4378faf366480298cc4e844a022360da143..613670acc93264ede0300a5364baacd94f7fe917 100644 (file)
@@ -1,9 +1,3 @@
-error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/const-fn-not-safe-for-const.rs:20:14
-   |
-LL |     unsafe { transmute(x) } //~ ERROR E0015
-   |              ^^^^^^^^^^^^
-
 error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
   --> $DIR/const-fn-not-safe-for-const.rs:24:5
    |
@@ -70,7 +64,7 @@ LL |     x + y
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
 
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
 
 Some errors occurred: E0013, E0015, E0658.
 For more information about an error, try `rustc --explain E0013`.
index 87d5e13df6eb30475e10794ebec02436c2d992c7..4f02b1eef3a0fef1a81922bc43a6c3aca273615c 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-pass
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 #[derive(PartialEq, Eq)]
 enum Cake {
index fed8e1885de8a996296b37ce83cb1affc554262f..04c054f8b6db25dfa5ade5642953eb02ed8f73e2 100644 (file)
@@ -10,8 +10,6 @@
 
 // error-pattern: cycle detected
 
-#![feature(const_fn)]
-
 struct Foo {
     bytes: [u8; std::mem::size_of::<Foo>()]
 }
index b10dd509e0b13b7956fbd5a5d2c6466ea7a42024..ab8b5792e681d58bb7e6c9af3193f77664c00252 100644 (file)
@@ -2,16 +2,16 @@ error[E0391]: cycle detected when computing layout of `Foo`
    |
 note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All }, value: [u8; _] }`...
 note: ...which requires const-evaluating `Foo::bytes::{{constant}}`...
-  --> $SRC_DIR/libcore/mem.rs:323:14
+  --> $SRC_DIR/libcore/mem.rs:LL:COL
    |
-LL |     unsafe { intrinsics::size_of::<T>() }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::size_of::<T>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires computing layout of `Foo`, completing the cycle
 note: cycle used when const-evaluating `Foo::bytes::{{constant}}`
-  --> $SRC_DIR/libcore/mem.rs:323:14
+  --> $SRC_DIR/libcore/mem.rs:LL:COL
    |
-LL |     unsafe { intrinsics::size_of::<T>() }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::size_of::<T>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
new file mode 100644 (file)
index 0000000..b156e5a
--- /dev/null
@@ -0,0 +1,224 @@
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:49:25
+   |
+LL |     const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated
+   |                         ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:51:5
+   |
+LL |     const fn get_mut(&mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:56:28
+   |
+LL |     const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated
+   |                            ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:58:5
+   |
+LL |     const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:63:27
+   |
+LL |     const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors
+   |                           ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:65:5
+   |
+LL |     const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:70:5
+   |
+LL |     const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:88:16
+   |
+LL | const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
+   |                ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:90:18
+   |
+LL | const fn foo11_2<T: Send>(t: T) -> T { t }
+   |                  ^
+
+error: only int, `bool` and `char` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:92:33
+   |
+LL | const fn foo19(f: f32) -> f32 { f * 2.0 }
+   |                                 ^^^^^^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:94:35
+   |
+LL | const fn foo19_2(f: f32) -> f32 { 2.0 - f }
+   |                                   ^^^^^^^
+
+error: only int and `bool` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:96:35
+   |
+LL | const fn foo19_3(f: f32) -> f32 { -f }
+   |                                   ^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:98:43
+   |
+LL | const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
+   |                                           ^^^^^
+
+error: cannot access `static` items in const fn
+  --> $DIR/min_const_fn.rs:102:27
+   |
+LL | const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn
+   |                           ^^^
+
+error: cannot access `static` items in const fn
+  --> $DIR/min_const_fn.rs:103:36
+   |
+LL | const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items
+   |                                    ^^^^
+
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:104:42
+   |
+LL | const fn foo30(x: *const u32) -> usize { x as usize }
+   |                                          ^^^^^^^^^^
+
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:106:42
+   |
+LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
+   |                                          ^^^^^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:108:38
+   |
+LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:110:29
+   |
+LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
+   |                             ^^^^^^^^^^^
+
+error: local variables in const fn are unstable
+  --> $DIR/min_const_fn.rs:111:34
+   |
+LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+   |                                  ^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:112:44
+   |
+LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
+   |                                            ^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:114:44
+   |
+LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
+   |                                            ^^^^^^
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:116:14
+   |
+LL | const fn inc(x: &mut i32) { *x += 1 }
+   |              ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:121:6
+   |
+LL | impl<T: std::fmt::Debug> Foo<T> {
+   |      ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:126:6
+   |
+LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
+   |      ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:131:6
+   |
+LL | impl<T: Sync + Sized> Foo<T> {
+   |      ^
+
+error: `impl Trait` in const fn is unstable
+  --> $DIR/min_const_fn.rs:137:1
+   |
+LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:139:34
+   |
+LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
+   |                                  ^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:141:22
+   |
+LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+   |                      ^^^^^^^^^^^^^^^^^^^^
+
+error: `impl Trait` in const fn is unstable
+  --> $DIR/min_const_fn.rs:142:1
+   |
+LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:143:23
+   |
+LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+   |                       ^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:144:1
+   |
+LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/min_const_fn.rs:144:64
+   |
+LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+   |                                                                ^^ - temporary value only lives until here
+   |                                                                |
+   |                                                                temporary value does not live long enough
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:149:41
+   |
+LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/min_const_fn.rs:152:21
+   |
+LL | const fn no_fn_ptrs(_x: fn()) {}
+   |                     ^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/min_const_fn.rs:154:1
+   |
+LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 36 previous errors
+
+Some errors occurred: E0493, E0597.
+For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs
new file mode 100644 (file)
index 0000000..b861e31
--- /dev/null
@@ -0,0 +1,156 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(min_const_fn)]
+
+// ok
+const fn foo1() {}
+const fn foo2(x: i32) -> i32 { x }
+const fn foo3<T>(x: T) -> T { x }
+const fn foo7() {
+    (
+        foo1(),
+        foo2(420),
+        foo3(69),
+    ).0
+}
+const fn foo12<T: Sized>(t: T) -> T { t }
+const fn foo13<T: ?Sized>(t: &T) -> &T { t }
+const fn foo14<'a, T: 'a>(t: &'a T) -> &'a T { t }
+const fn foo15<T>(t: T) -> T where T: Sized { t }
+const fn foo15_2<T>(t: &T) -> &T where T: ?Sized { t }
+const fn foo16(f: f32) -> f32 { f }
+const fn foo17(f: f32) -> u32 { f as u32 }
+const fn foo18(i: i32) -> i32 { i * 3 }
+const fn foo20(b: bool) -> bool { !b }
+const fn foo21<T, U>(t: T, u: U) -> (T, U) { (t, u) }
+const fn foo22(s: &[u8], i: usize) -> u8 { s[i] }
+const FOO: u32 = 42;
+const fn foo23() -> u32 { FOO }
+const fn foo24() -> &'static u32 { &FOO }
+const fn foo27(x: &u32) -> u32 { *x }
+const fn foo28(x: u32) -> u32 { *&x }
+const fn foo29(x: u32) -> i32 { x as i32 }
+const fn foo31(a: bool, b: bool) -> bool { a & b }
+const fn foo32(a: bool, b: bool) -> bool { a | b }
+const fn foo33(a: bool, b: bool) -> bool { a & b }
+const fn foo34(a: bool, b: bool) -> bool { a | b }
+const fn foo35(a: bool, b: bool) -> bool { a ^ b }
+struct Foo<T: ?Sized>(T);
+impl<T> Foo<T> {
+    const fn new(t: T) -> Self { Foo(t) }
+    const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated
+    const fn get(&self) -> &T { &self.0 }
+    const fn get_mut(&mut self) -> &mut T { &mut self.0 }
+    //~^ mutable references in const fn are unstable
+}
+impl<'a, T> Foo<T> {
+    const fn new_lt(t: T) -> Self { Foo(t) }
+    const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated
+    const fn get_lt(&'a self) -> &T { &self.0 }
+    const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
+    //~^ mutable references in const fn are unstable
+}
+impl<T: Sized> Foo<T> {
+    const fn new_s(t: T) -> Self { Foo(t) }
+    const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors
+    const fn get_s(&self) -> &T { &self.0 }
+    const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
+    //~^ mutable references in const fn are unstable
+}
+impl<T: ?Sized> Foo<T> {
+    const fn get_sq(&self) -> &T { &self.0 }
+    const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
+    //~^ mutable references in const fn are unstable
+}
+
+
+const fn char_ops(c: char, d: char) -> bool { c == d }
+const fn char_ops2(c: char, d: char) -> bool { c < d }
+const fn char_ops3(c: char, d: char) -> bool { c != d }
+const fn i32_ops(c: i32, d: i32) -> bool { c == d }
+const fn i32_ops2(c: i32, d: i32) -> bool { c < d }
+const fn i32_ops3(c: i32, d: i32) -> bool { c != d }
+const fn i32_ops4(c: i32, d: i32) -> i32 { c + d }
+const fn char_cast(u: u8) -> char { u as char }
+const unsafe fn foo4() -> i32 { 42 }
+const unsafe fn foo5<T>() -> *const T { 0 as *const T }
+const unsafe fn foo6<T>() -> *mut T { 0 as *mut T }
+
+// not ok
+const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+const fn foo11_2<T: Send>(t: T) -> T { t }
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+const fn foo19(f: f32) -> f32 { f * 2.0 }
+//~^ ERROR only int, `bool` and `char` operations are stable in const fn
+const fn foo19_2(f: f32) -> f32 { 2.0 - f }
+//~^ ERROR only int, `bool` and `char` operations are stable in const fn
+const fn foo19_3(f: f32) -> f32 { -f }
+//~^ ERROR only int and `bool` operations are stable in const fn
+const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
+//~^ ERROR only int, `bool` and `char` operations are stable in const fn
+
+static BAR: u32 = 42;
+const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn
+const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items
+const fn foo30(x: *const u32) -> usize { x as usize }
+//~^ ERROR casting pointers to int
+const fn foo30_2(x: *mut u32) -> usize { x as usize }
+//~^ ERROR casting pointers to int
+const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
+//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
+const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
+const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+const fn foo36(a: bool, b: bool) -> bool { a && b }
+//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
+const fn foo37(a: bool, b: bool) -> bool { a || b }
+//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
+const fn inc(x: &mut i32) { *x += 1 }
+//~^ ERROR mutable references in const fn are unstable
+
+fn main() {}
+
+impl<T: std::fmt::Debug> Foo<T> {
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+    const fn foo(&self) {}
+}
+
+impl<T: std::fmt::Debug + Sized> Foo<T> {
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+    const fn foo2(&self) {}
+}
+
+impl<T: Sync + Sized> Foo<T> {
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+    const fn foo3(&self) {}
+}
+
+struct AlanTuring<T>(T);
+const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
+//~^ ERROR `impl Trait` in const fn is unstable
+const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
+//~^ ERROR trait bounds other than `Sized`
+const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
+const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+//~^ ERROR trait bounds other than `Sized`
+
+const fn no_unsafe() { unsafe {} }
+
+const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
+//~^ ERROR trait bounds other than `Sized`
+
+const fn no_fn_ptrs(_x: fn()) {}
+//~^ ERROR function pointers in const fn are unstable
+const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
+//~^ ERROR function pointers in const fn are unstable
+
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
new file mode 100644 (file)
index 0000000..019948c
--- /dev/null
@@ -0,0 +1,213 @@
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:49:25
+   |
+LL |     const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated
+   |                         ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:51:5
+   |
+LL |     const fn get_mut(&mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:56:28
+   |
+LL |     const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated
+   |                            ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:58:5
+   |
+LL |     const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:63:27
+   |
+LL |     const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors
+   |                           ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:65:5
+   |
+LL |     const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:70:5
+   |
+LL |     const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:88:16
+   |
+LL | const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
+   |                ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:90:18
+   |
+LL | const fn foo11_2<T: Send>(t: T) -> T { t }
+   |                  ^
+
+error: only int, `bool` and `char` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:92:33
+   |
+LL | const fn foo19(f: f32) -> f32 { f * 2.0 }
+   |                                 ^^^^^^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:94:35
+   |
+LL | const fn foo19_2(f: f32) -> f32 { 2.0 - f }
+   |                                   ^^^^^^^
+
+error: only int and `bool` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:96:35
+   |
+LL | const fn foo19_3(f: f32) -> f32 { -f }
+   |                                   ^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:98:43
+   |
+LL | const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
+   |                                           ^^^^^
+
+error: cannot access `static` items in const fn
+  --> $DIR/min_const_fn.rs:102:27
+   |
+LL | const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn
+   |                           ^^^
+
+error: cannot access `static` items in const fn
+  --> $DIR/min_const_fn.rs:103:36
+   |
+LL | const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items
+   |                                    ^^^^
+
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:104:42
+   |
+LL | const fn foo30(x: *const u32) -> usize { x as usize }
+   |                                          ^^^^^^^^^^
+
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:106:42
+   |
+LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
+   |                                          ^^^^^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:108:38
+   |
+LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:110:29
+   |
+LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
+   |                             ^^^^^^^^^^^
+
+error: local variables in const fn are unstable
+  --> $DIR/min_const_fn.rs:111:34
+   |
+LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+   |                                  ^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:112:44
+   |
+LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
+   |                                            ^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:114:44
+   |
+LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
+   |                                            ^^^^^^
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:116:14
+   |
+LL | const fn inc(x: &mut i32) { *x += 1 }
+   |              ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:121:6
+   |
+LL | impl<T: std::fmt::Debug> Foo<T> {
+   |      ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:126:6
+   |
+LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
+   |      ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:131:6
+   |
+LL | impl<T: Sync + Sized> Foo<T> {
+   |      ^
+
+error: `impl Trait` in const fn is unstable
+  --> $DIR/min_const_fn.rs:137:1
+   |
+LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:139:34
+   |
+LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
+   |                                  ^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:141:22
+   |
+LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+   |                      ^^^^^^^^^^^^^^^^^^^^
+
+error: `impl Trait` in const fn is unstable
+  --> $DIR/min_const_fn.rs:142:1
+   |
+LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:143:23
+   |
+LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+   |                       ^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:144:1
+   |
+LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:149:41
+   |
+LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/min_const_fn.rs:152:21
+   |
+LL | const fn no_fn_ptrs(_x: fn()) {}
+   |                     ^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/min_const_fn.rs:154:1
+   |
+LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 35 previous errors
+
+For more information about this error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr
new file mode 100644 (file)
index 0000000..cfcc799
--- /dev/null
@@ -0,0 +1,25 @@
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn_dyn.rs:21:5
+   |
+LL |     x.0.field;
+   |     ^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn_dyn.rs:24:66
+   |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+   |                                                                  ^^
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/min_const_fn_dyn.rs:24:67
+   |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+   |                                                                   ^    - temporary value only lives until here
+   |                                                                   |
+   |                                                                   temporary value does not live long enough
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs
new file mode 100644 (file)
index 0000000..38e2825
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(min_const_fn)]
+
+struct HasDyn {
+    field: &'static dyn std::fmt::Debug,
+}
+
+struct Hide(HasDyn);
+
+const fn no_inner_dyn_trait(_x: Hide) {}
+const fn no_inner_dyn_trait2(x: Hide) {
+    x.0.field;
+//~^ ERROR trait bounds other than `Sized`
+}
+const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+//~^ ERROR trait bounds other than `Sized`
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
new file mode 100644 (file)
index 0000000..3a1055f
--- /dev/null
@@ -0,0 +1,14 @@
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn_dyn.rs:21:5
+   |
+LL |     x.0.field;
+   |     ^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn_dyn.rs:24:66
+   |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+   |                                                                  ^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs
new file mode 100644 (file)
index 0000000..100d275
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(min_const_fn)]
+
+struct HasPtr {
+    field: fn(),
+}
+
+struct Hide(HasPtr);
+
+fn field() {}
+
+const fn no_inner_dyn_trait(_x: Hide) {}
+const fn no_inner_dyn_trait2(x: Hide) {
+    x.0.field;
+//~^ ERROR function pointers in const fn
+}
+const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) }
+//~^ ERROR function pointers in const fn
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr
new file mode 100644 (file)
index 0000000..c10af3d
--- /dev/null
@@ -0,0 +1,14 @@
+error: function pointers in const fn are unstable
+  --> $DIR/min_const_fn_fn_ptr.rs:23:5
+   |
+LL |     x.0.field;
+   |     ^^^^^^^^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/min_const_fn_fn_ptr.rs:26:59
+   |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) }
+   |                                                           ^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs b/src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs
new file mode 100644 (file)
index 0000000..fcc9545
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(integer_atomics, min_const_fn)]
+
+// compile-pass
+
+use std::cell::UnsafeCell;
+use std::sync::atomic::AtomicU32;
+pub struct Condvar {
+    condvar: UnsafeCell<AtomicU32>,
+}
+
+unsafe impl Send for Condvar {}
+unsafe impl Sync for Condvar {}
+
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+struct NoWait(u32);
+
+const CONDVAR_HAS_NO_WAITERS: NoWait = NoWait(42);
+
+impl Condvar {
+    pub const fn new() -> Condvar {
+        Condvar {
+            condvar: UnsafeCell::new(AtomicU32::new(CONDVAR_HAS_NO_WAITERS.0)),
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs
new file mode 100644 (file)
index 0000000..9f5d0ad
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![unstable(feature = "humans",
+            reason = "who ever let humans program computers,
+            we're apparently really bad at it",
+            issue = "0")]
+
+#![feature(rustc_const_unstable, const_fn, foo, foo2)]
+#![feature(staged_api)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo")]
+const fn foo() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn`
+
+#[unstable(feature = "rust1", issue="0")]
+const fn foo2() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn`
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// conformity is required, even with `const_fn` feature gate
+const fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` operations
+
+// check whether this function cannot be called even with the feature gate active
+#[unstable(feature = "foo2", issue="0")]
+const fn foo2_gated() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn`
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr
new file mode 100644 (file)
index 0000000..1ef7ffd
--- /dev/null
@@ -0,0 +1,26 @@
+error: can only call other `min_const_fn` within a `min_const_fn`
+  --> $DIR/min_const_fn_libstd_stability.rs:25:25
+   |
+LL | const fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn`
+   |                         ^^^^^
+
+error: can only call other `min_const_fn` within a `min_const_fn`
+  --> $DIR/min_const_fn_libstd_stability.rs:32:26
+   |
+LL | const fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn`
+   |                          ^^^^^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+  --> $DIR/min_const_fn_libstd_stability.rs:36:26
+   |
+LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` operations
+   |                          ^^^^^^^^^^^^^
+
+error: can only call other `min_const_fn` within a `min_const_fn`
+  --> $DIR/min_const_fn_libstd_stability.rs:44:32
+   |
+LL | const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn`
+   |                                ^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
new file mode 100644 (file)
index 0000000..e7caa4c
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(min_const_fn)]
+
+// ok
+const unsafe fn foo4() -> i32 { 42 }
+const unsafe fn foo5<T>() -> *const T { 0 as *const T }
+const unsafe fn foo6<T>() -> *mut T { 0 as *mut T }
+const fn no_unsafe() { unsafe {} }
+
+// not ok
+const fn foo8() -> i32 {
+    unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const fn
+}
+const fn foo9() -> *const String {
+    unsafe { foo5::<String>() } //~ ERROR unsafe operations are not allowed in const fn
+}
+const fn foo10() -> *const Vec<std::cell::Cell<u32>> {
+    unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR not allowed in const fn
+}
+const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+//~^ dereferencing raw pointers in constant functions
+
+fn main() {}
+
+const unsafe fn no_union() {
+    union Foo { x: (), y: () }
+    Foo { x: () }.y //~ ERROR not allowed in const fn
+    //~^ unions in const fn
+}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
new file mode 100644 (file)
index 0000000..17cba85
--- /dev/null
@@ -0,0 +1,59 @@
+error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
+  --> $DIR/min_const_fn_unsafe.rs:29:51
+   |
+LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+   |                                                   ^^
+   |
+   = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
+
+error[E0658]: unions in const fn are unstable (see issue #51909)
+  --> $DIR/min_const_fn_unsafe.rs:36:5
+   |
+LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn_union)] to the crate attributes to enable
+
+error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
+  --> $DIR/min_const_fn_unsafe.rs:21:14
+   |
+LL |     unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const fn
+   |              ^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
+  --> $DIR/min_const_fn_unsafe.rs:24:14
+   |
+LL |     unsafe { foo5::<String>() } //~ ERROR unsafe operations are not allowed in const fn
+   |              ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
+  --> $DIR/min_const_fn_unsafe.rs:27:14
+   |
+LL |     unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR not allowed in const fn
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
+  --> $DIR/min_const_fn_unsafe.rs:29:51
+   |
+LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+   |                                                   ^^ dereference of raw pointer
+   |
+   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: access to union field is unsafe and unsafe operations are not allowed in const fn
+  --> $DIR/min_const_fn_unsafe.rs:36:5
+   |
+LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
+   |     ^^^^^^^^^^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/crate-in-paths.rs b/src/test/ui/crate-in-paths.rs
new file mode 100644 (file)
index 0000000..ef01294
--- /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.
+
+// edition:2018
+
+#![feature(edition_2018_preview)]
+
+mod bar {
+    crate struct Foo;
+}
+
+fn main() {
+    Foo;
+    //~^ ERROR cannot find value `Foo` in this scope [E0425]
+}
diff --git a/src/test/ui/crate-in-paths.stderr b/src/test/ui/crate-in-paths.stderr
new file mode 100644 (file)
index 0000000..5bb1a28
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0425]: cannot find value `Foo` in this scope
+  --> $DIR/crate-in-paths.rs:20:5
+   |
+LL |     Foo;
+   |     ^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use crate::bar::Foo;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
index ad8e0e76e14137511b0b0599eb31eb1add49bbcd..a8d82a35946498814ed182b94f7b36baf1fd718a 100644 (file)
@@ -10,7 +10,7 @@
 
 // Unresolved multi-segment attributes are not treated as custom.
 
-#![feature(custom_attribute, proc_macro_path_invoc)]
+#![feature(custom_attribute)]
 
 mod existent {}
 
index 4adfe1e450ee5c76d89e5541360b2e07f5bde354..6ecad7d79b86772d649cdf8dbf37aecf4ba390b7 100644 (file)
@@ -1,24 +1,24 @@
 error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/custom_attribute.rs:13:1
+  --> $DIR/custom_attribute.rs:13:3
    |
 LL | #[foo] //~ ERROR The attribute `foo`
-   | ^^^^^^
+   |   ^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/custom_attribute.rs:15:5
+  --> $DIR/custom_attribute.rs:15:7
    |
 LL |     #[foo] //~ ERROR The attribute `foo`
-   |     ^^^^^^
+   |       ^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/custom_attribute.rs:17:5
+  --> $DIR/custom_attribute.rs:17:7
    |
 LL |     #[foo] //~ ERROR The attribute `foo`
-   |     ^^^^^^
+   |       ^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
index ac8ac85824edcc34783e3d161d76cdc9280f30f2..b53ef0f5ba823986f5ec9f80a7f04eae2a137a92 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// We need to opt inot the `!` feature in order to trigger the
+// We need to opt into the `!` feature in order to trigger the
 // requirement that this is testing.
 #![feature(never_type)]
 
index 04ba4ab905eb1fb8980f046cbae83a7d9ce26c05..1776a71a6bb472b24e529409141a81f10c529a70 100644 (file)
@@ -15,20 +15,26 @@ macro_rules! borrow {
 fn foo(_: String) {}
 
 fn foo2(s: &String) {
-    foo(s); //~ ERROR mismatched types
+    foo(s);
+    //~^ ERROR mismatched types
 }
 
 fn foo3(_: u32) {}
 fn foo4(u: &u32) {
-    foo3(u); //~ ERROR mismatched types
+    foo3(u);
+    //~^ ERROR mismatched types
 }
 
 fn main() {
     let s = String::new();
     let r_s = &s;
     foo2(r_s);
-    foo(&"aaa".to_owned()); //~ ERROR mismatched types
-    foo(&mut "aaa".to_owned()); //~ ERROR mismatched types
+    foo(&"aaa".to_owned());
+    //~^ ERROR mismatched types
+    foo(&mut "aaa".to_owned());
+    //~^ ERROR mismatched types
     foo3(borrow!(0));
     foo4(&0);
+    assert_eq!(3i32, &3i32);
+    //~^ ERROR mismatched types
 }
index a5f87928924cacf5d464b2463edbc9f08723c050..9811c5969dad69ebc7d00ab10c10603cf02f2249 100644 (file)
@@ -1,7 +1,7 @@
 error[E0308]: mismatched types
   --> $DIR/deref-suggestion.rs:18:9
    |
-LL |     foo(s); //~ ERROR mismatched types
+LL |     foo(s);
    |         ^
    |         |
    |         expected struct `std::string::String`, found reference
@@ -11,9 +11,9 @@ LL |     foo(s); //~ ERROR mismatched types
               found type `&std::string::String`
 
 error[E0308]: mismatched types
-  --> $DIR/deref-suggestion.rs:23:10
+  --> $DIR/deref-suggestion.rs:24:10
    |
-LL |     foo3(u); //~ ERROR mismatched types
+LL |     foo3(u);
    |          ^
    |          |
    |          expected u32, found &u32
@@ -23,9 +23,9 @@ LL |     foo3(u); //~ ERROR mismatched types
               found type `&u32`
 
 error[E0308]: mismatched types
-  --> $DIR/deref-suggestion.rs:30:9
+  --> $DIR/deref-suggestion.rs:32:9
    |
-LL |     foo(&"aaa".to_owned()); //~ ERROR mismatched types
+LL |     foo(&"aaa".to_owned());
    |         ^^^^^^^^^^^^^^^^^
    |         |
    |         expected struct `std::string::String`, found reference
@@ -35,9 +35,9 @@ LL |     foo(&"aaa".to_owned()); //~ ERROR mismatched types
               found type `&std::string::String`
 
 error[E0308]: mismatched types
-  --> $DIR/deref-suggestion.rs:31:9
+  --> $DIR/deref-suggestion.rs:34:9
    |
-LL |     foo(&mut "aaa".to_owned()); //~ ERROR mismatched types
+LL |     foo(&mut "aaa".to_owned());
    |         ^^^^^^^^^^^^^^^^^^^^^
    |         |
    |         expected struct `std::string::String`, found mutable reference
@@ -58,6 +58,16 @@ LL |     foo3(borrow!(0));
    = note: expected type `u32`
               found type `&{integer}`
 
-error: aborting due to 5 previous errors
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:38:5
+   |
+LL |     assert_eq!(3i32, &3i32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found &i32
+   |
+   = note: expected type `i32`
+              found type `&i32`
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
index 8f80e000e3caf2485cb385794e2522d7f427994c..9343312fdd84f91953475818cb627f318d1b79ab 100644 (file)
@@ -10,8 +10,7 @@
 
 // edition:2015
 
-#![feature(raw_identifiers)]
-#![allow(async_idents)]
+#![allow(keyword_idents)]
 
 #[macro_export]
 macro_rules! produces_async {
index 85ef15858fe912a02e3ae906f6a9ea4c6708d482..19a7b91624fe339b6b8791060ea21fd06fa8bb2d 100644 (file)
@@ -10,7 +10,7 @@
 
 // edition:2018
 
-#![allow(async_idents)]
+#![allow(keyword_idents)]
 
 #[macro_export]
 macro_rules! produces_async {
index 3b78ce80be20820e180f74c02912f9d9e76af733..382c7c1f325a3bf5b8acbbd5bf3d698096bda345 100644 (file)
@@ -12,8 +12,7 @@
 // aux-build:edition-kw-macro-2015.rs
 // compile-pass
 
-#![feature(raw_identifiers)]
-#![allow(async_idents)]
+#![allow(keyword_idents)]
 
 #[macro_use]
 extern crate edition_kw_macro_2015;
index 08cba2d2908a65c36cd3ce8f2d44a7baf03a464b..bdb190c748acea248d0bbfd7e1880cd420e34ab9 100644 (file)
@@ -11,8 +11,6 @@
 // edition:2015
 // aux-build:edition-kw-macro-2015.rs
 
-#![feature(raw_identifiers)]
-
 #[macro_use]
 extern crate edition_kw_macro_2015;
 
index 5b6fd3e1c9c434c8fa24c4a60348fc482fb991ab..a629d13e6c31bd72526a5e4c64b4c62868344f70 100644 (file)
@@ -1,11 +1,11 @@
 error: no rules expected the token `r#async`
-  --> $DIR/edition-keywords-2015-2015-parsing.rs:24:31
+  --> $DIR/edition-keywords-2015-2015-parsing.rs:22:31
    |
 LL |     r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
    |                               ^^^^^^^
 
 error: no rules expected the token `async`
-  --> $DIR/edition-keywords-2015-2015-parsing.rs:25:35
+  --> $DIR/edition-keywords-2015-2015-parsing.rs:23:35
    |
 LL |     r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
    |                                   ^^^^^
index 41d5ebd3e7db12fa5acdd8f5646891c10b85a859..291fd0285e57c922efb4bc8a862caa24196bdf1d 100644 (file)
@@ -11,8 +11,6 @@
 // edition:2015
 // aux-build:edition-kw-macro-2018.rs
 
-#![feature(raw_identifiers)]
-
 #[macro_use]
 extern crate edition_kw_macro_2018;
 
index 5852d56e6d37438c1437bfded9ecba6be2a9510c..d087146d7a14a592c198c9d7a1a269bb055c318b 100644 (file)
@@ -1,5 +1,5 @@
 error: expected identifier, found reserved keyword `async`
-  --> $DIR/edition-keywords-2015-2018-expansion.rs:20:5
+  --> $DIR/edition-keywords-2015-2018-expansion.rs:18:5
    |
 LL |     produces_async! {} //~ ERROR expected identifier, found reserved keyword
    |     ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword
index 337d6be6bbcd88d0ba3101b85a7865a6b650501b..1b7bfb530596a0b782cef4cbfb790ac705bbfbec 100644 (file)
@@ -11,8 +11,6 @@
 // edition:2015
 // aux-build:edition-kw-macro-2018.rs
 
-#![feature(raw_identifiers)]
-
 #[macro_use]
 extern crate edition_kw_macro_2018;
 
index 60cfbce3ff0e49bdd4e85a3143499e44f77edc06..ab8a34a4a9e3dabee4decdcbcfe8fe50a533d8fe 100644 (file)
@@ -1,11 +1,11 @@
 error: no rules expected the token `r#async`
-  --> $DIR/edition-keywords-2015-2018-parsing.rs:24:31
+  --> $DIR/edition-keywords-2015-2018-parsing.rs:22:31
    |
 LL |     r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
    |                               ^^^^^^^
 
 error: no rules expected the token `async`
-  --> $DIR/edition-keywords-2015-2018-parsing.rs:25:35
+  --> $DIR/edition-keywords-2015-2018-parsing.rs:23:35
    |
 LL |     r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
    |                                   ^^^^^
index 911dcd855aad6c2fb21e68161e24fc2368558f55..46434daaab9244c12cce7dad984684c326cd8f8f 100644 (file)
@@ -12,7 +12,7 @@
 // aux-build:edition-kw-macro-2015.rs
 // compile-pass
 
-#![allow(async_idents)]
+#![allow(keyword_idents)]
 
 #[macro_use]
 extern crate edition_kw_macro_2015;
index 3a243330ad9b06f4b70cb9cc9361b490ca37e3cb..dab22de1b6e58101ae13cfa0a110baa78f739bc1 100644 (file)
@@ -18,3 +18,4 @@ enum Eu64 {
     Bu64 = 0x8000_0000_0000_0000 //~ERROR already exists
 }
 
+fn main() {}
index 3b4ac436898e6e5d48a112ff9ccdc7384750876b..e4419d6285127a5312a94f04b1f3f331ee8547c9 100644 (file)
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `enum_discrim_autosizing`
-   |
-   = note: consider adding a `main` function to `$DIR/enum-discrim-autosizing.rs`
-
 error[E0081]: discriminant value `0` already exists
   --> $DIR/enum-discrim-autosizing.rs:18:12
    |
@@ -10,7 +6,6 @@ LL |     Au64 = 0,
 LL |     Bu64 = 0x8000_0000_0000_0000 //~ERROR already exists
    |            ^^^^^^^^^^^^^^^^^^^^^ enum already has `0`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0081, E0601.
-For more information about an error, try `rustc --explain E0081`.
+For more information about this error, try `rustc --explain E0081`.
diff --git a/src/test/ui/error-codes/E0087.rs b/src/test/ui/error-codes/E0087.rs
deleted file mode 100644 (file)
index bea76f3..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.
-
-fn foo() {}
-fn bar<T>() {}
-
-fn main() {
-    foo::<f64>(); //~ ERROR wrong number of type arguments: expected 0, found 1 [E0087]
-
-    bar::<f64, u64>(); //~ ERROR wrong number of type arguments: expected 1, found 2 [E0087]
-}
diff --git a/src/test/ui/error-codes/E0087.stderr b/src/test/ui/error-codes/E0087.stderr
deleted file mode 100644 (file)
index a07f1bb..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0087]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/E0087.rs:15:11
-   |
-LL |     foo::<f64>(); //~ ERROR wrong number of type arguments: expected 0, found 1 [E0087]
-   |           ^^^ unexpected type argument
-
-error[E0087]: wrong number of type arguments: expected 1, found 2
-  --> $DIR/E0087.rs:17:16
-   |
-LL |     bar::<f64, u64>(); //~ ERROR wrong number of type arguments: expected 1, found 2 [E0087]
-   |                ^^^ unexpected type argument
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0087`.
diff --git a/src/test/ui/error-codes/E0088.rs b/src/test/ui/error-codes/E0088.rs
deleted file mode 100644 (file)
index db84a4e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn f() {}
-fn g<'a>() -> &'a u8 { loop {} }
-
-fn main() {
-    f::<'static>(); //~ ERROR E0088
-    g::<'static, 'static>(); //~ ERROR E0088
-}
diff --git a/src/test/ui/error-codes/E0088.stderr b/src/test/ui/error-codes/E0088.stderr
deleted file mode 100644 (file)
index 6b95602..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0088]: wrong number of lifetime arguments: expected 0, found 1
-  --> $DIR/E0088.rs:15:9
-   |
-LL |     f::<'static>(); //~ ERROR E0088
-   |         ^^^^^^^ unexpected lifetime argument
-
-error[E0088]: wrong number of lifetime arguments: expected 1, found 2
-  --> $DIR/E0088.rs:16:18
-   |
-LL |     g::<'static, 'static>(); //~ ERROR E0088
-   |                  ^^^^^^^ unexpected lifetime argument
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0088`.
diff --git a/src/test/ui/error-codes/E0089.rs b/src/test/ui/error-codes/E0089.rs
deleted file mode 100644 (file)
index 4e6196a..0000000
+++ /dev/null
@@ -1,15 +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 foo<T, U>() {}
-
-fn main() {
-    foo::<f64>(); //~ ERROR wrong number of type arguments: expected 2, found 1 [E0089]
-}
diff --git a/src/test/ui/error-codes/E0089.stderr b/src/test/ui/error-codes/E0089.stderr
deleted file mode 100644 (file)
index f79c478..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0089]: wrong number of type arguments: expected 2, found 1
-  --> $DIR/E0089.rs:14:5
-   |
-LL |     foo::<f64>(); //~ ERROR wrong number of type arguments: expected 2, found 1 [E0089]
-   |     ^^^^^^^^^^ expected 2 type arguments
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0089`.
diff --git a/src/test/ui/error-codes/E0090.rs b/src/test/ui/error-codes/E0090.rs
deleted file mode 100644 (file)
index 26be4c1..0000000
+++ /dev/null
@@ -1,15 +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 foo<'a: 'b, 'b: 'a>() {}
-
-fn main() {
-    foo::<'static>(); //~ ERROR wrong number of lifetime arguments: expected 2, found 1 [E0090]
-}
diff --git a/src/test/ui/error-codes/E0090.stderr b/src/test/ui/error-codes/E0090.stderr
deleted file mode 100644 (file)
index 9029b6c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0090]: wrong number of lifetime arguments: expected 2, found 1
-  --> $DIR/E0090.rs:14:5
-   |
-LL |     foo::<'static>(); //~ ERROR wrong number of lifetime arguments: expected 2, found 1 [E0090]
-   |     ^^^^^^^^^^^^^^ expected 2 lifetime arguments
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0090`.
diff --git a/src/test/ui/error-codes/E0243.rs b/src/test/ui/error-codes/E0243.rs
deleted file mode 100644 (file)
index 615ce0b..0000000
+++ /dev/null
@@ -1,16 +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.
-
-struct Foo<T> { x: T }
-struct Bar { x: Foo }
-                //~^ ERROR wrong number of type arguments: expected 1, found 0 [E0243]
-
-fn main() {
-}
diff --git a/src/test/ui/error-codes/E0243.stderr b/src/test/ui/error-codes/E0243.stderr
deleted file mode 100644 (file)
index 0477d1b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0243]: wrong number of type arguments: expected 1, found 0
-  --> $DIR/E0243.rs:12:17
-   |
-LL | struct Bar { x: Foo }
-   |                 ^^^ expected 1 type argument
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0243`.
diff --git a/src/test/ui/error-codes/E0244.rs b/src/test/ui/error-codes/E0244.rs
deleted file mode 100644 (file)
index 9a78b31..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Foo { x: bool }
-struct Bar<S, T> { x: Foo<S, T> }
-                      //~^ ERROR wrong number of type arguments: expected 0, found 2 [E0244]
-
-
-fn main() {
-}
diff --git a/src/test/ui/error-codes/E0244.stderr b/src/test/ui/error-codes/E0244.stderr
deleted file mode 100644 (file)
index 87f063c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0244]: wrong number of type arguments: expected 0, found 2
-  --> $DIR/E0244.rs:12:23
-   |
-LL | struct Bar<S, T> { x: Foo<S, T> }
-   |                       ^^^^^^^^^ 2 unexpected type arguments
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0244`.
index 490a8e0ff0f1d1cfb0217d59aa67c741df9b0c14..438dd50f2bfa80aaca4ed97b47cf152bed233132 100644 (file)
@@ -4,8 +4,8 @@ error[E0308]: intrinsic has wrong type
 LL |     fn size_of<T>(); //~ ERROR E0308
    |     ^^^^^^^^^^^^^^^^ expected (), found usize
    |
-   = note: expected type `unsafe extern "rust-intrinsic" fn()`
-              found type `unsafe extern "rust-intrinsic" fn() -> usize`
+   = note: expected type `extern "rust-intrinsic" fn()`
+              found type `extern "rust-intrinsic" fn() -> usize`
 
 error: aborting due to previous error
 
index 5b66d1093408e5b01f02a4cc1379cb06454499c9..b088e8330e998dfeed32b00701f141e85cc40255 100644 (file)
@@ -24,7 +24,7 @@ error[E0401]: can't use type parameters from outer function
   --> $DIR/E0401.rs:32:25
    |
 LL | impl<T> Iterator for A<T> {
-   | ---- `Self` type implicitely declared here, on the `impl`
+   | ---- `Self` type implicitly declared here, on the `impl`
 ...
 LL |         fn helper(sel: &Self) -> u8 { //~ ERROR E0401
    |            ------       ^^^^ use of type variable from outer function
index d3e68c7c0daf8613f3c8cd95f184106d4f743654..d7cbb823013244696520876a6ed56379e354066a 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(attr_literals)]
-
 // deprecated doesn't currently support literals
 #[deprecated("since")] //~ ERROR E0565
 fn f() {  }
index 745e79ba2ec04200f74c7165dd4e5b3184e7127c..2a9bf92e9dd48fd7fec8beaaca4e5f7d7539a61a 100644 (file)
@@ -1,5 +1,5 @@
 error[E0565]: unsupported literal
-  --> $DIR/E0565-1.rs:14:14
+  --> $DIR/E0565-1.rs:12:14
    |
 LL | #[deprecated("since")] //~ ERROR E0565
    |              ^^^^^^^
index b2d369223e7dac02cc76e6871dc5a9d2a999f2a7..af8b10edab8a58fb84abfa3faba8cdb28697e2dc 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(attr_literals)]
-
 // repr currently doesn't support literals
 #[repr("C")] //~ ERROR E0565
 struct A {  }
index 1d0f34be39bebb88af0f91f5ccbe8013eca41998..abea4290f0a6861999ce0b3b231ff18c68b283d4 100644 (file)
@@ -1,5 +1,5 @@
 error[E0565]: unsupported literal
-  --> $DIR/E0565.rs:14:8
+  --> $DIR/E0565.rs:12:8
    |
 LL | #[repr("C")] //~ ERROR E0565
    |        ^^^
diff --git a/src/test/ui/exhaustive_integer_patterns.rs b/src/test/ui/exhaustive_integer_patterns.rs
new file mode 100644 (file)
index 0000000..7825aaa
--- /dev/null
@@ -0,0 +1,173 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(exhaustive_integer_patterns)]
+#![feature(exclusive_range_pattern)]
+#![deny(unreachable_patterns)]
+
+use std::{char, usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128};
+
+fn main() {
+    let x: u8 = 0;
+
+    // A single range covering the entire domain.
+    match x {
+        0 ..= 255 => {} // ok
+    }
+
+    // A combination of ranges and values.
+    // These are currently allowed to be overlapping.
+    match x {
+        0 ..= 32 => {}
+        33 => {}
+        34 .. 128 => {}
+        100 ..= 200 => {}
+        200 => {} //~ ERROR unreachable pattern
+        201 ..= 255 => {}
+    }
+
+    // An incomplete set of values.
+    match x { //~ ERROR non-exhaustive patterns
+        0 .. 128 => {}
+    }
+
+    // A more incomplete set of values.
+    match x { //~ ERROR non-exhaustive patterns
+        0 ..= 10 => {}
+        20 ..= 30 => {}
+        35 => {}
+        70 .. 255 => {}
+    }
+
+    let x: i8 = 0;
+    match x { //~ ERROR non-exhaustive patterns
+        -7 => {}
+        -5..=120 => {}
+        -2..=20 => {} //~ ERROR unreachable pattern
+        125 => {}
+    }
+
+    // Let's test other types too!
+    let c: char = '\u{0}';
+    match c {
+        '\u{0}' ..= char::MAX => {} // ok
+    }
+
+    // We can actually get away with just covering the
+    // following two ranges, which correspond to all
+    // valid Unicode Scalar Values.
+    match c {
+        '\u{0000}' ..= '\u{D7FF}' => {}
+        '\u{E000}' ..= '\u{10_FFFF}' => {}
+    }
+
+    match 0usize {
+        0 ..= usize::MAX => {} // ok
+    }
+
+    match 0u16 {
+        0 ..= u16::MAX => {} // ok
+    }
+
+    match 0u32 {
+        0 ..= u32::MAX => {} // ok
+    }
+
+    match 0u64 {
+        0 ..= u64::MAX => {} // ok
+    }
+
+    match 0u128 {
+        0 ..= u128::MAX => {} // ok
+    }
+
+    match 0isize {
+        isize::MIN ..= isize::MAX => {} // ok
+    }
+
+    match 0i8 {
+        -128 ..= 127 => {} // ok
+    }
+
+    match 0i8 { //~ ERROR non-exhaustive patterns
+        -127 ..= 127 => {}
+    }
+
+    match 0i16 {
+        i16::MIN ..= i16::MAX => {} // ok
+    }
+
+    match 0i16 { //~ ERROR non-exhaustive patterns
+        i16::MIN ..= -1 => {}
+        1 ..= i16::MAX => {}
+    }
+
+    match 0i32 {
+        i32::MIN ..= i32::MAX => {} // ok
+    }
+
+    match 0i64 {
+        i64::MIN ..= i64::MAX => {} // ok
+    }
+
+    match 0i128 {
+        i128::MIN ..= i128::MAX => {} // ok
+    }
+
+    // Make sure that guards don't factor into the exhaustiveness checks.
+    match 0u8 { //~ ERROR non-exhaustive patterns
+        0 .. 128 => {}
+        128 ..= 255 if true => {}
+    }
+
+    match 0u8 {
+        0 .. 128 => {}
+        128 ..= 255 if false => {}
+        128 ..= 255 => {} // ok, because previous arm was guarded
+    }
+
+    // Now things start getting a bit more interesting. Testing products!
+    match (0u8, Some(())) { //~ ERROR non-exhaustive patterns
+        (1, _) => {}
+        (_, None) => {}
+    }
+
+    match (0u8, true) { //~ ERROR non-exhaustive patterns
+        (0 ..= 125, false) => {}
+        (128 ..= 255, false) => {}
+        (0 ..= 255, true) => {}
+    }
+
+    match (0u8, true) { // ok
+        (0 ..= 125, false) => {}
+        (128 ..= 255, false) => {}
+        (0 ..= 255, true) => {}
+        (125 .. 128, false) => {}
+    }
+
+    match 0u8 { // ok
+        0 .. 2 => {}
+        1 ..= 2 => {}
+        _ => {}
+    }
+
+    const LIM: u128 = u128::MAX - 1;
+    match 0u128 { //~ ERROR non-exhaustive patterns
+        0 ..= LIM => {}
+    }
+
+    match 0u128 { //~ ERROR non-exhaustive patterns
+        0 ..= 4 => {}
+    }
+
+    match 0u128 { //~ ERROR non-exhaustive patterns
+        4 ..= u128::MAX => {}
+    }
+}
diff --git a/src/test/ui/exhaustive_integer_patterns.stderr b/src/test/ui/exhaustive_integer_patterns.stderr
new file mode 100644 (file)
index 0000000..44b05a1
--- /dev/null
@@ -0,0 +1,87 @@
+error: unreachable pattern
+  --> $DIR/exhaustive_integer_patterns.rs:32:9
+   |
+LL |         200 => {} //~ ERROR unreachable pattern
+   |         ^^^
+   |
+note: lint level defined here
+  --> $DIR/exhaustive_integer_patterns.rs:13:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error[E0004]: non-exhaustive patterns: `128u8..=255u8` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:37:11
+   |
+LL |     match x { //~ ERROR non-exhaustive patterns
+   |           ^ pattern `128u8..=255u8` not covered
+
+error[E0004]: non-exhaustive patterns: `11u8..=19u8`, `31u8..=34u8`, `36u8..=69u8` and 1 more not covered
+  --> $DIR/exhaustive_integer_patterns.rs:42:11
+   |
+LL |     match x { //~ ERROR non-exhaustive patterns
+   |           ^ patterns `11u8..=19u8`, `31u8..=34u8`, `36u8..=69u8` and 1 more not covered
+
+error: unreachable pattern
+  --> $DIR/exhaustive_integer_patterns.rs:53:9
+   |
+LL |         -2..=20 => {} //~ ERROR unreachable pattern
+   |         ^^^^^^^
+
+error[E0004]: non-exhaustive patterns: `-128i8..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered
+  --> $DIR/exhaustive_integer_patterns.rs:50:11
+   |
+LL |     match x { //~ ERROR non-exhaustive patterns
+   |           ^ patterns `-128i8..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered
+
+error[E0004]: non-exhaustive patterns: `-128i8` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:99:11
+   |
+LL |     match 0i8 { //~ ERROR non-exhaustive patterns
+   |           ^^^ pattern `-128i8` not covered
+
+error[E0004]: non-exhaustive patterns: `0i16` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:107:11
+   |
+LL |     match 0i16 { //~ ERROR non-exhaustive patterns
+   |           ^^^^ pattern `0i16` not covered
+
+error[E0004]: non-exhaustive patterns: `128u8..=255u8` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:125:11
+   |
+LL |     match 0u8 { //~ ERROR non-exhaustive patterns
+   |           ^^^ pattern `128u8..=255u8` not covered
+
+error[E0004]: non-exhaustive patterns: `(0u8, Some(_))` and `(2u8..=255u8, Some(_))` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:137:11
+   |
+LL |     match (0u8, Some(())) { //~ ERROR non-exhaustive patterns
+   |           ^^^^^^^^^^^^^^^ patterns `(0u8, Some(_))` and `(2u8..=255u8, Some(_))` not covered
+
+error[E0004]: non-exhaustive patterns: `(126u8..=127u8, false)` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:142:11
+   |
+LL |     match (0u8, true) { //~ ERROR non-exhaustive patterns
+   |           ^^^^^^^^^^^ pattern `(126u8..=127u8, false)` not covered
+
+error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211455u128` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:162:11
+   |
+LL |     match 0u128 { //~ ERROR non-exhaustive patterns
+   |           ^^^^^ pattern `340282366920938463463374607431768211455u128` not covered
+
+error[E0004]: non-exhaustive patterns: `5u128..=340282366920938463463374607431768211455u128` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:166:11
+   |
+LL |     match 0u128 { //~ ERROR non-exhaustive patterns
+   |           ^^^^^ pattern `5u128..=340282366920938463463374607431768211455u128` not covered
+
+error[E0004]: non-exhaustive patterns: `0u128..=3u128` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:170:11
+   |
+LL |     match 0u128 { //~ ERROR non-exhaustive patterns
+   |           ^^^^^ pattern `0u128..=3u128` not covered
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/existential_types/nested_existential_types.rs b/src/test/ui/existential_types/nested_existential_types.rs
new file mode 100644 (file)
index 0000000..aac72c7
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(existential_type)]
+// compile-pass
+mod my_mod {
+  use std::fmt::Debug;
+
+  pub existential type Foo: Debug;
+  pub existential type Foot: Debug;
+
+  pub fn get_foo() -> Foo {
+      5i32
+  }
+
+  pub fn get_foot() -> Foot {
+      get_foo()
+  }
+}
+
+fn main() {
+    let _: my_mod::Foot = my_mod::get_foot();
+}
+
index ffb4f4cc1440070449b8a48929f498451e3a5d10..06e40fd6ab554ff8aec2d8a5aa52e4138514fe2b 100644 (file)
@@ -1,10 +1,15 @@
-error[E0391]: cycle detected when normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All }, value: Foo }`
+error[E0391]: cycle detected when processing `Foo`
   --> $DIR/no_inferrable_concrete_type.rs:16:1
    |
 LL | existential type Foo: Copy; //~ cycle detected
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: ...which again requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All }, value: Foo }`, completing the cycle
+note: ...which requires processing `bar`...
+  --> $DIR/no_inferrable_concrete_type.rs:19:23
+   |
+LL | fn bar(x: Foo) -> Foo { x }
+   |                       ^^^^^
+   = note: ...which again requires processing `Foo`, completing the cycle
 
 error: aborting due to previous error
 
index 66b06c505e476768cd64fd62b8685fd154e7d629..ea313385c10185caf87aecdc37ee3de8b93c8559 100644 (file)
@@ -17,5 +17,5 @@ fn main() {
     // extern functions are extern "C" fn
     let _x: extern "C" fn() = f; // OK
     is_fn(f);
-    //~^ ERROR `extern "C" fn() {f}: std::ops::Fn<()>` is not satisfied
+    //~^ ERROR expected a `std::ops::Fn<()>` closure, found `extern "C" fn() {f}`
 }
index 35e0d68e46aa897305ebb03e14a32645ef9a5486..0d8185839ccb47b380e556df6fa3d5b84d307907 100644 (file)
@@ -1,9 +1,11 @@
-error[E0277]: the trait bound `extern "C" fn() {f}: std::ops::Fn<()>` is not satisfied
+error[E0277]: expected a `std::ops::Fn<()>` closure, found `extern "C" fn() {f}`
   --> $DIR/extern-wrong-value-type.rs:19:5
    |
 LL |     is_fn(f);
-   |     ^^^^^ the trait `std::ops::Fn<()>` is not implemented for `extern "C" fn() {f}`
+   |     ^^^^^ expected an `Fn<()>` closure, found `extern "C" fn() {f}`
    |
+   = help: the trait `std::ops::Fn<()>` is not implemented for `extern "C" fn() {f}`
+   = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }
 note: required by `is_fn`
   --> $DIR/extern-wrong-value-type.rs:14:1
    |
diff --git a/src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.rs b/src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.rs
new file mode 100644 (file)
index 0000000..6207d99
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[cfg(rustdoc)] //~ ERROR: `cfg(rustdoc)` is experimental and subject to change
+pub struct SomeStruct;
+
+fn main() {}
diff --git a/src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.stderr b/src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.stderr
new file mode 100644 (file)
index 0000000..be2c263
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: `cfg(rustdoc)` is experimental and subject to change (see issue #43781)
+  --> $DIR/feature-gate-doc_cfg-cfg-rustdoc.rs:11:7
+   |
+LL | #[cfg(rustdoc)] //~ ERROR: `cfg(rustdoc)` is experimental and subject to change
+   |       ^^^^^^^
+   |
+   = help: add #![feature(doc_cfg)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate-exhaustive_integer_patterns.rs b/src/test/ui/feature-gate-exhaustive_integer_patterns.rs
new file mode 100644 (file)
index 0000000..3aa1522
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let x: u8 = 0;
+    match x { //~ ERROR non-exhaustive patterns: `_` not covered
+        0 ..= 255 => {}
+    }
+}
diff --git a/src/test/ui/feature-gate-exhaustive_integer_patterns.stderr b/src/test/ui/feature-gate-exhaustive_integer_patterns.stderr
new file mode 100644 (file)
index 0000000..63d98f6
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/feature-gate-exhaustive_integer_patterns.rs:13:11
+   |
+LL |     match x { //~ ERROR non-exhaustive patterns: `_` not covered
+   |           ^ pattern `_` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/feature-gate-rustc-attrs-1.rs b/src/test/ui/feature-gate-rustc-attrs-1.rs
deleted file mode 100644 (file)
index 7295de8..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.
-
-// ignore-tidy-linelength
-
-// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
-
-#[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
-#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
-
-fn main() {}
diff --git a/src/test/ui/feature-gate-rustc-attrs-1.stderr b/src/test/ui/feature-gate-rustc-attrs-1.stderr
deleted file mode 100644 (file)
index 54a580c..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
-  --> $DIR/feature-gate-rustc-attrs-1.rs:15:1
-   |
-LL | #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
-   | ^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
-
-error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
-  --> $DIR/feature-gate-rustc-attrs-1.rs:16:1
-   |
-LL | #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
-   | ^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate-uniform-paths.rs b/src/test/ui/feature-gate-uniform-paths.rs
deleted file mode 100644 (file)
index 140655d..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub mod foo {
-    pub use bar::Bar;
-    //~^ ERROR unresolved import `bar`
-
-    pub mod bar {
-        pub struct Bar;
-    }
-}
-
-fn main() {
-    let _ = foo::Bar;
-}
diff --git a/src/test/ui/feature-gate-uniform-paths.stderr b/src/test/ui/feature-gate-uniform-paths.stderr
deleted file mode 100644 (file)
index 68faacf..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0432]: unresolved import `bar`
-  --> $DIR/feature-gate-uniform-paths.rs:12:13
-   |
-LL |     pub use bar::Bar;
-   |             ^^^ Did you mean `self::bar`?
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/feature-gate-unrestricted-attribute-tokens.rs b/src/test/ui/feature-gate-unrestricted-attribute-tokens.rs
deleted file mode 100644 (file)
index daebbe6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(custom_attribute)]
-
-#[my_attr(a b c d)]
-//~^ ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `b`
-//~| ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `c`
-//~| ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `d`
-fn main() {}
diff --git a/src/test/ui/feature-gate-unrestricted-attribute-tokens.stderr b/src/test/ui/feature-gate-unrestricted-attribute-tokens.stderr
deleted file mode 100644 (file)
index cc5694b..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: expected one of `(`, `)`, `,`, `::`, or `=`, found `b`
-  --> $DIR/feature-gate-unrestricted-attribute-tokens.rs:13:13
-   |
-LL | #[my_attr(a b c d)]
-   |             ^ expected one of `(`, `)`, `,`, `::`, or `=` here
-
-error: expected one of `(`, `)`, `,`, `::`, or `=`, found `c`
-  --> $DIR/feature-gate-unrestricted-attribute-tokens.rs:13:15
-   |
-LL | #[my_attr(a b c d)]
-   |               ^ expected one of `(`, `)`, `,`, `::`, or `=` here
-
-error: expected one of `(`, `)`, `,`, `::`, or `=`, found `d`
-  --> $DIR/feature-gate-unrestricted-attribute-tokens.rs:13:17
-   |
-LL | #[my_attr(a b c d)]
-   |                 ^ expected one of `(`, `)`, `,`, `::`, or `=` here
-
-error: aborting due to 3 previous errors
-
diff --git a/src/test/ui/feature-gates/feature-gate-catch_expr.rs b/src/test/ui/feature-gates/feature-gate-catch_expr.rs
deleted file mode 100644 (file)
index 5568a5c..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub fn main() {
-    let catch_result = do catch { //~ ERROR `catch` expression is experimental
-        let x = 5;
-        x
-    };
-    assert_eq!(catch_result, 5);
-}
diff --git a/src/test/ui/feature-gates/feature-gate-catch_expr.stderr b/src/test/ui/feature-gates/feature-gate-catch_expr.stderr
deleted file mode 100644 (file)
index 4ab7146..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0658]: `catch` expression is experimental (see issue #31436)
-  --> $DIR/feature-gate-catch_expr.rs:12:24
-   |
-LL |       let catch_result = do catch { //~ ERROR `catch` expression is experimental
-   |  ________________________^
-LL | |         let x = 5;
-LL | |         x
-LL | |     };
-   | |_____^
-   |
-   = help: add #![feature(catch_expr)] to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
index 1d1dedddaaa3e72099f70dab571a40f976d0359e..f774658975b79d983021d8ee80f4c430704a83a2 100644 (file)
@@ -8,9 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test use of const fn without feature gate.
+// Test use of const fn without the `const_fn` feature gate.
+// `min_const_fn` is checked in its own file
+#![feature(min_const_fn)]
 
-const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
+const fn foo() -> usize { 0 } // ok
 
 trait Foo {
     const fn foo() -> u32; //~ ERROR const fn is unstable
@@ -20,12 +22,11 @@ const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
 }
 
 impl Foo {
-    const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
+    const fn baz() -> u32 { 0 } // ok
 }
 
 impl Foo for u32 {
-    const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
-                                //~| ERROR trait fns cannot be declared const
+    const fn foo() -> u32 { 0 } //~ ERROR trait fns cannot be declared const
 }
 
 static FOO: usize = foo();
index d7c00a3e0cb40e7f6ca568ac48921d33b4a8dcdd..26c0c7877b4ecc6f51b03b1531e65a720dced564 100644 (file)
@@ -1,31 +1,23 @@
 error[E0379]: trait fns cannot be declared const
-  --> $DIR/feature-gate-const_fn.rs:16:5
+  --> $DIR/feature-gate-const_fn.rs:18:5
    |
 LL |     const fn foo() -> u32; //~ ERROR const fn is unstable
    |     ^^^^^ trait fns cannot be const
 
 error[E0379]: trait fns cannot be declared const
-  --> $DIR/feature-gate-const_fn.rs:18:5
+  --> $DIR/feature-gate-const_fn.rs:20:5
    |
 LL |     const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
    |     ^^^^^ trait fns cannot be const
 
 error[E0379]: trait fns cannot be declared const
-  --> $DIR/feature-gate-const_fn.rs:27:5
+  --> $DIR/feature-gate-const_fn.rs:29:5
    |
-LL |     const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
+LL |     const fn foo() -> u32 { 0 } //~ ERROR trait fns cannot be declared const
    |     ^^^^^ trait fns cannot be const
 
 error[E0658]: const fn is unstable (see issue #24111)
-  --> $DIR/feature-gate-const_fn.rs:13:1
-   |
-LL | const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(const_fn)] to the crate attributes to enable
-
-error[E0658]: const fn is unstable (see issue #24111)
-  --> $DIR/feature-gate-const_fn.rs:16:5
+  --> $DIR/feature-gate-const_fn.rs:18:5
    |
 LL |     const fn foo() -> u32; //~ ERROR const fn is unstable
    |     ^^^^^^^^^^^^^^^^^^^^^^
@@ -33,30 +25,14 @@ LL |     const fn foo() -> u32; //~ ERROR const fn is unstable
    = help: add #![feature(const_fn)] to the crate attributes to enable
 
 error[E0658]: const fn is unstable (see issue #24111)
-  --> $DIR/feature-gate-const_fn.rs:18:5
+  --> $DIR/feature-gate-const_fn.rs:20:5
    |
 LL |     const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_fn)] to the crate attributes to enable
 
-error[E0658]: const fn is unstable (see issue #24111)
-  --> $DIR/feature-gate-const_fn.rs:23:5
-   |
-LL |     const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(const_fn)] to the crate attributes to enable
-
-error[E0658]: const fn is unstable (see issue #24111)
-  --> $DIR/feature-gate-const_fn.rs:27:5
-   |
-LL |     const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(const_fn)] to the crate attributes to enable
-
-error: aborting due to 8 previous errors
+error: aborting due to 5 previous errors
 
 Some errors occurred: E0379, E0658.
 For more information about an error, try `rustc --explain E0379`.
diff --git a/src/test/ui/feature-gates/feature-gate-const_transmute.rs b/src/test/ui/feature-gates/feature-gate-const_transmute.rs
new file mode 100644 (file)
index 0000000..c879ab5
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::mem;
+
+#[repr(transparent)]
+struct Foo(u32);
+
+const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
+//~^ ERROR The use of std::mem::transmute() is gated in constants (see issue #53605)
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-const_transmute.stderr b/src/test/ui/feature-gates/feature-gate-const_transmute.stderr
new file mode 100644 (file)
index 0000000..bb09b93
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: The use of std::mem::transmute() is gated in constants (see issue #53605)
+  --> $DIR/feature-gate-const_transmute.rs:16:38
+   |
+LL | const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_transmute)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
index b54288035175d33c9a477d8279841fe374ad1c62..ed8392ad7a3d1841a632fcfb1e8881d6db113807 100644 (file)
@@ -10,7 +10,7 @@
 
 // Check that literals in attributes parse just fine.
 
-#![feature(rustc_attrs, attr_literals)]
+#![feature(rustc_attrs)]
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
index 36f5898f1c70e1f1c2844bad442a19eacc5ced73..e60e9a342a99c39bf88f225d53eb70678f3f19d9 100644 (file)
 error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute.rs:17:1
+  --> $DIR/feature-gate-custom_attribute.rs:17:3
    |
 LL | #[fake_attr] //~ ERROR attribute `fake_attr` is currently unknown
-   | ^^^^^^^^^^^^
+   |   ^^^^^^^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute.rs:18:1
+  --> $DIR/feature-gate-custom_attribute.rs:18:3
    |
 LL | #[fake_attr(100)] //~ ERROR attribute `fake_attr` is currently unknown
-   | ^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute.rs:19:1
+  --> $DIR/feature-gate-custom_attribute.rs:19:3
    |
 LL | #[fake_attr(1, 2, 3)] //~ ERROR attribute `fake_attr` is currently unknown
-   | ^^^^^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute.rs:20:1
+  --> $DIR/feature-gate-custom_attribute.rs:20:3
    |
 LL | #[fake_attr("hello")] //~ ERROR attribute `fake_attr` is currently unknown
-   | ^^^^^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute.rs:21:1
+  --> $DIR/feature-gate-custom_attribute.rs:21:3
    |
 LL | #[fake_attr(name = "hello")] //~ ERROR attribute `fake_attr` is currently unknown
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute.rs:22:1
+  --> $DIR/feature-gate-custom_attribute.rs:22:3
    |
 LL | #[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR attribute `fake_attr` is currently unknown
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute.rs:23:1
+  --> $DIR/feature-gate-custom_attribute.rs:23:3
    |
 LL | #[fake_attr(key = "hello", val = 10)] //~ ERROR attribute `fake_attr` is currently unknown
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute.rs:24:1
+  --> $DIR/feature-gate-custom_attribute.rs:24:3
    |
 LL | #[fake_attr(key("hello"), val(10))] //~ ERROR attribute `fake_attr` is currently unknown
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute.rs:25:1
+  --> $DIR/feature-gate-custom_attribute.rs:25:3
    |
 LL | #[fake_attr(enabled = true, disabled = false)] //~ ERROR attribute `fake_attr` is currently unknown
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute.rs:26:1
+  --> $DIR/feature-gate-custom_attribute.rs:26:3
    |
 LL | #[fake_attr(true)] //~ ERROR attribute `fake_attr` is currently unknown
-   | ^^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute.rs:27:1
+  --> $DIR/feature-gate-custom_attribute.rs:27:3
    |
 LL | #[fake_attr(pi = 3.14159)] //~ ERROR attribute `fake_attr` is currently unknown
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute.rs:28:1
+  --> $DIR/feature-gate-custom_attribute.rs:28:3
    |
 LL | #[fake_attr(b"hi")] //~ ERROR attribute `fake_attr` is currently unknown
-   | ^^^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `fake_doc` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute.rs:29:1
+  --> $DIR/feature-gate-custom_attribute.rs:29:3
    |
 LL | #[fake_doc(r"doc")] //~ ERROR attribute `fake_doc` is currently unknown
-   | ^^^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
index e633a5a9c993048d99ab7e157f3721fc1071a380..0979372daea3066d56029ca486e5b861a4b58ede 100644 (file)
@@ -1,8 +1,8 @@
 error[E0658]: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644)
-  --> $DIR/feature-gate-custom_derive.rs:11:1
+  --> $DIR/feature-gate-custom_derive.rs:11:3
    |
 LL | #[derive_Clone]
-   | ^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^^^^
    |
    = help: add #![feature(custom_derive)] to the crate attributes to enable
 
index 347066268664324aebffcbf3f6c254a96fa60e15..bbaae1ef449fc7df57870ebb45ef801780d7d0cc 100644 (file)
@@ -19,6 +19,7 @@ trait PointerFamily<U> {
 }
 
 struct Foo;
+
 impl PointerFamily<u32> for Foo {
     type Pointer<usize> = Box<usize>;
     //~^ ERROR generic associated types are unstable
@@ -31,5 +32,9 @@ trait Bar {
     //~^ ERROR where clauses on associated types are unstable
 }
 
+impl Bar for Foo {
+    type Assoc where Self: Sized = Foo;
+    //~^ ERROR where clauses on associated types are unstable
+}
 
 fn main() {}
index d7891f13c6b4d9f6f283ecdb16ea2cc69e725502..f12cbe727fbed994229df4a1e8d82cc86d15d64f 100644 (file)
@@ -23,7 +23,7 @@ LL |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
 error[E0658]: generic associated types are unstable (see issue #44265)
-  --> $DIR/feature-gate-generic_associated_types.rs:23:5
+  --> $DIR/feature-gate-generic_associated_types.rs:24:5
    |
 LL |     type Pointer<usize> = Box<usize>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -31,7 +31,7 @@ LL |     type Pointer<usize> = Box<usize>;
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
 error[E0658]: generic associated types are unstable (see issue #44265)
-  --> $DIR/feature-gate-generic_associated_types.rs:25:5
+  --> $DIR/feature-gate-generic_associated_types.rs:26:5
    |
 LL |     type Pointer2<u32> = Box<u32>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -39,13 +39,21 @@ LL |     type Pointer2<u32> = Box<u32>;
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
 error[E0658]: where clauses on associated types are unstable (see issue #44265)
-  --> $DIR/feature-gate-generic_associated_types.rs:30:5
+  --> $DIR/feature-gate-generic_associated_types.rs:31:5
    |
 LL |     type Assoc where Self: Sized;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
-error: aborting due to 6 previous errors
+error[E0658]: where clauses on associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:36:5
+   |
+LL |     type Assoc where Self: Sized = Foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-macro-vis-matcher.rs b/src/test/ui/feature-gates/feature-gate-macro-vis-matcher.rs
deleted file mode 100644 (file)
index 5d6f2ac..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that the MSP430 interrupt ABI cannot be used when msp430_interrupt
-// feature gate is not used.
-
-macro_rules! m { ($v:vis) => {} }
-//~^ ERROR :vis fragment specifier is experimental and subject to change
-
-fn main() {
-    m!(pub);
-}
diff --git a/src/test/ui/feature-gates/feature-gate-macro-vis-matcher.stderr b/src/test/ui/feature-gates/feature-gate-macro-vis-matcher.stderr
deleted file mode 100644 (file)
index 9d98091..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: :vis fragment specifier is experimental and subject to change (see issue #41022)
-  --> $DIR/feature-gate-macro-vis-matcher.rs:14:19
-   |
-LL | macro_rules! m { ($v:vis) => {} }
-   |                   ^^^^^^
-   |
-   = help: add #![feature(macro_vis_matcher)] to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-min_const_fn.rs b/src/test/ui/feature-gates/feature-gate-min_const_fn.rs
new file mode 100644 (file)
index 0000000..e052ba9
--- /dev/null
@@ -0,0 +1,46 @@
+// 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.
+
+// Test use of min_const_fn without feature gate.
+
+const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
+
+trait Foo {
+    const fn foo() -> u32; //~ ERROR const fn is unstable
+                           //~| ERROR trait fns cannot be declared const
+    const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
+                                //~| ERROR trait fns cannot be declared const
+}
+
+impl Foo {
+    const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
+}
+
+impl Foo for u32 {
+    const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
+                                //~| ERROR trait fns cannot be declared const
+}
+
+static FOO: usize = foo();
+const BAR: usize = foo();
+
+macro_rules! constant {
+    ($n:ident: $t:ty = $v:expr) => {
+        const $n: $t = $v;
+    }
+}
+
+constant! {
+    BAZ: usize = foo()
+}
+
+fn main() {
+    let x: [usize; foo()] = [];
+}
diff --git a/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr b/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr
new file mode 100644 (file)
index 0000000..aa77503
--- /dev/null
@@ -0,0 +1,62 @@
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/feature-gate-min_const_fn.rs:16:5
+   |
+LL |     const fn foo() -> u32; //~ ERROR const fn is unstable
+   |     ^^^^^ trait fns cannot be const
+
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/feature-gate-min_const_fn.rs:18:5
+   |
+LL |     const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
+   |     ^^^^^ trait fns cannot be const
+
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/feature-gate-min_const_fn.rs:27:5
+   |
+LL |     const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
+   |     ^^^^^ trait fns cannot be const
+
+error[E0658]: const fn is unstable (see issue #53555)
+  --> $DIR/feature-gate-min_const_fn.rs:13:1
+   |
+LL | const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(min_const_fn)] to the crate attributes to enable
+
+error[E0658]: const fn is unstable (see issue #24111)
+  --> $DIR/feature-gate-min_const_fn.rs:16:5
+   |
+LL |     const fn foo() -> u32; //~ ERROR const fn is unstable
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0658]: const fn is unstable (see issue #24111)
+  --> $DIR/feature-gate-min_const_fn.rs:18:5
+   |
+LL |     const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0658]: const fn is unstable (see issue #53555)
+  --> $DIR/feature-gate-min_const_fn.rs:23:5
+   |
+LL |     const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(min_const_fn)] to the crate attributes to enable
+
+error[E0658]: const fn is unstable (see issue #53555)
+  --> $DIR/feature-gate-min_const_fn.rs:27:5
+   |
+LL |     const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(min_const_fn)] to the crate attributes to enable
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0379, E0658.
+For more information about an error, try `rustc --explain E0379`.
diff --git a/src/test/ui/feature-gates/feature-gate-panic-handler.rs b/src/test/ui/feature-gates/feature-gate-panic-handler.rs
new file mode 100644 (file)
index 0000000..fd16268
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-C panic=abort
+
+#![no_std]
+#![no_main]
+
+use core::panic::PanicInfo;
+
+#[panic_handler] //~ ERROR #[panic_handler] is an unstable feature (see issue #44489)
+fn panic(info: &PanicInfo) -> ! {
+    loop {}
+}
diff --git a/src/test/ui/feature-gates/feature-gate-panic-handler.stderr b/src/test/ui/feature-gates/feature-gate-panic-handler.stderr
new file mode 100644 (file)
index 0000000..9680a24
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: #[panic_handler] is an unstable feature (see issue #44489)
+  --> $DIR/feature-gate-panic-handler.rs:18:1
+   |
+LL | #[panic_handler] //~ ERROR #[panic_handler] is an unstable feature (see issue #44489)
+   | ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(panic_handler)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
index ae9fbc7b13bd53db338dfc94f6e316e40194f767..84e5f302c1676e027c04c17a6e9862642daa8d76 100644 (file)
@@ -15,7 +15,7 @@
 
 use core::panic::PanicInfo;
 
-#[panic_implementation] //~ ERROR #[panic_implementation] is an unstable feature (see issue #44489)
+#[panic_implementation] //~ ERROR This attribute was renamed to `panic_handler` (see issue #44489)
 fn panic(info: &PanicInfo) -> ! {
     loop {}
 }
index f99228bef1d623b4d4993f2af8308a448f413a0f..926a49ae83199b4c6e07c386d6f5a3719ecfb685 100644 (file)
@@ -1,7 +1,7 @@
-error[E0658]: #[panic_implementation] is an unstable feature (see issue #44489)
+error[E0658]: This attribute was renamed to `panic_handler` (see issue #44489)
   --> $DIR/feature-gate-panic-implementation.rs:18:1
    |
-LL | #[panic_implementation] //~ ERROR #[panic_implementation] is an unstable feature (see issue #44489)
+LL | #[panic_implementation] //~ ERROR This attribute was renamed to `panic_handler` (see issue #44489)
    | ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(panic_implementation)] to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-raw-identifiers.rs b/src/test/ui/feature-gates/feature-gate-raw-identifiers.rs
deleted file mode 100644 (file)
index 38024fe..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
-    let r#foo = 3; //~ ERROR raw identifiers are experimental and subject to change
-    println!("{}", foo);
-}
diff --git a/src/test/ui/feature-gates/feature-gate-raw-identifiers.stderr b/src/test/ui/feature-gates/feature-gate-raw-identifiers.stderr
deleted file mode 100644 (file)
index 02eff72..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: raw identifiers are experimental and subject to change (see issue #48589)
-  --> $DIR/feature-gate-raw-identifiers.rs:12:9
-   |
-LL |     let r#foo = 3; //~ ERROR raw identifiers are experimental and subject to change
-   |         ^^^^^
-   |
-   = help: add #![feature(raw_identifiers)] to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs
new file mode 100644 (file)
index 0000000..7295de8
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-tidy-linelength
+
+// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
+
+#[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
+#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
new file mode 100644 (file)
index 0000000..54a580c
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
+  --> $DIR/feature-gate-rustc-attrs-1.rs:15:1
+   |
+LL | #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
+  --> $DIR/feature-gate-rustc-attrs-1.rs:16:1
+   |
+LL | #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
+   | ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
index 52a4d3664ce23388b658411fef00c7e4be3460d9..882549c1eafbadbab9c00b059756ed0f1b43ec02 100644 (file)
@@ -1,8 +1,8 @@
 error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
-  --> $DIR/feature-gate-rustc-attrs.rs:15:1
+  --> $DIR/feature-gate-rustc-attrs.rs:15:3
    |
 LL | #[rustc_foo]
-   | ^^^^^^^^^^^^
+   |   ^^^^^^^^^
    |
    = help: add #![feature(rustc_attrs)] to the crate attributes to enable
 
diff --git a/src/test/ui/feature-gates/feature-gate-tool_attributes.rs b/src/test/ui/feature-gates/feature-gate-tool_attributes.rs
deleted file mode 100644 (file)
index 5aa1670..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
-    #[rustfmt::skip] //~ ERROR tool attributes are unstable
-    let x = 3
-        ;
-}
diff --git a/src/test/ui/feature-gates/feature-gate-tool_attributes.stderr b/src/test/ui/feature-gates/feature-gate-tool_attributes.stderr
deleted file mode 100644 (file)
index ca9542d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: tool attributes are unstable (see issue #44690)
-  --> $DIR/feature-gate-tool_attributes.rs:12:5
-   |
-LL |     #[rustfmt::skip] //~ ERROR tool attributes are unstable
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(tool_attributes)] to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-try_blocks.rs b/src/test/ui/feature-gates/feature-gate-try_blocks.rs
new file mode 100644 (file)
index 0000000..6536280
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition 2018
+
+pub fn main() {
+    let try_result: Option<_> = try { //~ ERROR `try` expression is experimental
+        let x = 5;
+        x
+    };
+    assert_eq!(try_result, Some(5));
+}
diff --git a/src/test/ui/feature-gates/feature-gate-try_blocks.stderr b/src/test/ui/feature-gates/feature-gate-try_blocks.stderr
new file mode 100644 (file)
index 0000000..29ef2f8
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0658]: `try` expression is experimental (see issue #31436)
+  --> $DIR/feature-gate-try_blocks.rs:14:33
+   |
+LL |       let try_result: Option<_> = try { //~ ERROR `try` expression is experimental
+   |  _________________________________^
+LL | |         let x = 5;
+LL | |         x
+LL | |     };
+   | |_____^
+   |
+   = help: add #![feature(try_blocks)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-uniform-paths.rs b/src/test/ui/feature-gates/feature-gate-uniform-paths.rs
new file mode 100644 (file)
index 0000000..140655d
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub mod foo {
+    pub use bar::Bar;
+    //~^ ERROR unresolved import `bar`
+
+    pub mod bar {
+        pub struct Bar;
+    }
+}
+
+fn main() {
+    let _ = foo::Bar;
+}
diff --git a/src/test/ui/feature-gates/feature-gate-uniform-paths.stderr b/src/test/ui/feature-gates/feature-gate-uniform-paths.stderr
new file mode 100644 (file)
index 0000000..68faacf
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `bar`
+  --> $DIR/feature-gate-uniform-paths.rs:12:13
+   |
+LL |     pub use bar::Bar;
+   |             ^^^ Did you mean `self::bar`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/feature-gates/feature-gate-unrestricted-attribute-tokens.rs b/src/test/ui/feature-gates/feature-gate-unrestricted-attribute-tokens.rs
new file mode 100644 (file)
index 0000000..daebbe6
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(custom_attribute)]
+
+#[my_attr(a b c d)]
+//~^ ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `b`
+//~| ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `c`
+//~| ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `d`
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-unrestricted-attribute-tokens.stderr b/src/test/ui/feature-gates/feature-gate-unrestricted-attribute-tokens.stderr
new file mode 100644 (file)
index 0000000..cc5694b
--- /dev/null
@@ -0,0 +1,20 @@
+error: expected one of `(`, `)`, `,`, `::`, or `=`, found `b`
+  --> $DIR/feature-gate-unrestricted-attribute-tokens.rs:13:13
+   |
+LL | #[my_attr(a b c d)]
+   |             ^ expected one of `(`, `)`, `,`, `::`, or `=` here
+
+error: expected one of `(`, `)`, `,`, `::`, or `=`, found `c`
+  --> $DIR/feature-gate-unrestricted-attribute-tokens.rs:13:15
+   |
+LL | #[my_attr(a b c d)]
+   |               ^ expected one of `(`, `)`, `,`, `::`, or `=` here
+
+error: expected one of `(`, `)`, `,`, `::`, or `=`, found `d`
+  --> $DIR/feature-gate-unrestricted-attribute-tokens.rs:13:17
+   |
+LL | #[my_attr(a b c d)]
+   |                 ^ expected one of `(`, `)`, `,`, `::`, or `=` here
+
+error: aborting due to 3 previous errors
+
index 56d64d77ee2581bccf1b10b293e23d3218defdd4..ac7b0a609846281197761aacb176cf6efff8529a 100644 (file)
@@ -27,5 +27,5 @@ fn main() {
     //~| found type `std::boxed::Box<dyn std::ops::FnMut() -> isize>`
 
     needs_fn(1);
-    //~^ ERROR : std::ops::Fn<(isize,)>`
+    //~^ ERROR expected a `std::ops::Fn<(isize,)>` closure, found `{integer}`
 }
index 5bf1ed76d5f465a9a212a4901c7be8d5b4e38b1f..198b343cdd3e76481ef3db3bed0a98de1059825f 100644 (file)
@@ -25,15 +25,13 @@ LL |     let _: () = (box || -> isize { unimplemented!() }) as Box<FnMut() -> is
    = note: expected type `()`
               found type `std::boxed::Box<dyn std::ops::FnMut() -> isize>`
 
-error[E0277]: the trait bound `{integer}: std::ops::Fn<(isize,)>` is not satisfied
+error[E0277]: expected a `std::ops::Fn<(isize,)>` closure, found `{integer}`
   --> $DIR/fn-trait-formatting.rs:29:5
    |
 LL |     needs_fn(1);
-   |     ^^^^^^^^ the trait `std::ops::Fn<(isize,)>` is not implemented for `{integer}`
+   |     ^^^^^^^^ expected an `Fn<(isize,)>` closure, found `{integer}`
    |
-   = help: the following implementations were found:
-             <&'a F as std::ops::Fn<A>>
-             <core::str::LinesAnyMap as std::ops::Fn<(&'a str,)>>
+   = help: the trait `std::ops::Fn<(isize,)>` is not implemented for `{integer}`
 note: required by `needs_fn`
   --> $DIR/fn-trait-formatting.rs:13:1
    |
index 56f4ff33eb2d8b2e133a8af6a3fafc30cacfdbf8..c239131ee1685af1139868f186f5cdee44f69e3b 100644 (file)
@@ -10,7 +10,7 @@ note: lint level defined here
 LL | #![deny(future_incompatible)]
    |         ^^^^^^^^^^^^^^^^^^^
    = note: #[deny(anonymous_parameters)] implied by #[deny(future_incompatible)]
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
    = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
 
 error: aborting due to previous error
diff --git a/src/test/ui/gated-attr-literals.rs b/src/test/ui/gated-attr-literals.rs
deleted file mode 100644 (file)
index 8d36745..0000000
+++ /dev/null
@@ -1,43 +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.
-
-// Check that literals in attributes don't parse without the feature gate.
-
-// gate-test-attr_literals
-
-#![feature(custom_attribute)]
-
-#[fake_attr] // OK
-#[fake_attr(100)]
-    //~^ ERROR non-string literals in attributes
-#[fake_attr(1, 2, 3)]
-    //~^ ERROR non-string literals in attributes
-#[fake_attr("hello")]
-    //~^ ERROR string literals in top-level positions, are experimental
-#[fake_attr(name = "hello")] // OK
-#[fake_attr(1, "hi", key = 12, true, false)]
-    //~^ ERROR non-string literals in attributes, or string literals in top-level positions
-#[fake_attr(key = "hello", val = 10)]
-    //~^ ERROR non-string literals in attributes
-#[fake_attr(key("hello"), val(10))]
-    //~^ ERROR non-string literals in attributes, or string literals in top-level positions
-#[fake_attr(enabled = true, disabled = false)]
-    //~^ ERROR non-string literals in attributes
-#[fake_attr(true)]
-    //~^ ERROR non-string literals in attributes
-#[fake_attr(pi = 3.14159)]
-    //~^ ERROR non-string literals in attributes
-#[fake_attr(b"hi")]
-    //~^ ERROR string literals in top-level positions, are experimental
-#[fake_doc(r"doc")]
-    //~^ ERROR string literals in top-level positions, are experimental
-struct Q {  }
-
-fn main() { }
diff --git a/src/test/ui/gated-attr-literals.stderr b/src/test/ui/gated-attr-literals.stderr
deleted file mode 100644 (file)
index e69b648..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-error[E0658]: non-string literals in attributes, or string literals in top-level positions, are experimental (see issue #34981)
-  --> $DIR/gated-attr-literals.rs:18:1
-   |
-LL | #[fake_attr(100)]
-   | ^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(attr_literals)] to the crate attributes to enable
-
-error[E0658]: non-string literals in attributes, or string literals in top-level positions, are experimental (see issue #34981)
-  --> $DIR/gated-attr-literals.rs:20:1
-   |
-LL | #[fake_attr(1, 2, 3)]
-   | ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(attr_literals)] to the crate attributes to enable
-
-error[E0658]: non-string literals in attributes, or string literals in top-level positions, are experimental (see issue #34981)
-  --> $DIR/gated-attr-literals.rs:22:1
-   |
-LL | #[fake_attr("hello")]
-   | ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(attr_literals)] to the crate attributes to enable
-
-error[E0658]: non-string literals in attributes, or string literals in top-level positions, are experimental (see issue #34981)
-  --> $DIR/gated-attr-literals.rs:25:1
-   |
-LL | #[fake_attr(1, "hi", key = 12, true, false)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(attr_literals)] to the crate attributes to enable
-
-error[E0658]: non-string literals in attributes, or string literals in top-level positions, are experimental (see issue #34981)
-  --> $DIR/gated-attr-literals.rs:27:1
-   |
-LL | #[fake_attr(key = "hello", val = 10)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(attr_literals)] to the crate attributes to enable
-
-error[E0658]: non-string literals in attributes, or string literals in top-level positions, are experimental (see issue #34981)
-  --> $DIR/gated-attr-literals.rs:29:1
-   |
-LL | #[fake_attr(key("hello"), val(10))]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(attr_literals)] to the crate attributes to enable
-
-error[E0658]: non-string literals in attributes, or string literals in top-level positions, are experimental (see issue #34981)
-  --> $DIR/gated-attr-literals.rs:31:1
-   |
-LL | #[fake_attr(enabled = true, disabled = false)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(attr_literals)] to the crate attributes to enable
-
-error[E0658]: non-string literals in attributes, or string literals in top-level positions, are experimental (see issue #34981)
-  --> $DIR/gated-attr-literals.rs:33:1
-   |
-LL | #[fake_attr(true)]
-   | ^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(attr_literals)] to the crate attributes to enable
-
-error[E0658]: non-string literals in attributes, or string literals in top-level positions, are experimental (see issue #34981)
-  --> $DIR/gated-attr-literals.rs:35:1
-   |
-LL | #[fake_attr(pi = 3.14159)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(attr_literals)] to the crate attributes to enable
-
-error[E0658]: non-string literals in attributes, or string literals in top-level positions, are experimental (see issue #34981)
-  --> $DIR/gated-attr-literals.rs:37:1
-   |
-LL | #[fake_attr(b"hi")]
-   | ^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(attr_literals)] to the crate attributes to enable
-
-error[E0658]: non-string literals in attributes, or string literals in top-level positions, are experimental (see issue #34981)
-  --> $DIR/gated-attr-literals.rs:39:1
-   |
-LL | #[fake_doc(r"doc")]
-   | ^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(attr_literals)] to the crate attributes to enable
-
-error: aborting due to 11 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
index 5baafd4153159f3f6b27b31c5b0042720c51484e..0d74f9011c3ecdbac0c029c9ad94dd5b667b22cc 100644 (file)
@@ -20,3 +20,5 @@
 #![feature = "foo"] //~ ERROR: malformed feature
 
 #![feature(test_removed_feature)] //~ ERROR: feature has been removed
+
+fn main() {}
index 2bed241d68cabb0d52649105e42d3409ab0d672e..68be49a7277d26bb0b71a78fd4a4b89ed7c4d5a1 100644 (file)
@@ -28,11 +28,7 @@ error[E0557]: feature has been removed
 LL | #![feature(test_removed_feature)] //~ ERROR: feature has been removed
    |            ^^^^^^^^^^^^^^^^^^^^
 
-error[E0601]: `main` function not found in crate `gated_bad_feature`
-   |
-   = note: consider adding a `main` function to `$DIR/gated-bad-feature.rs`
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
-Some errors occurred: E0555, E0556, E0557, E0601.
+Some errors occurred: E0555, E0556, E0557.
 For more information about an error, try `rustc --explain E0555`.
index 81869ad0d08a53f93bf9930a4cd56dd0b6bfca1f..5cbaa29794fad0cfe44256972d3a0dc363574d9d 100644 (file)
@@ -1,4 +1,4 @@
-error[E0088]: wrong number of lifetime arguments: expected 1, found 2
+error[E0107]: wrong number of lifetime arguments: expected 1, found 2
   --> $DIR/generic-arg-mismatch-recover.rs:16:20
    |
 LL |     Foo::<'static, 'static, ()>(&0); //~ ERROR wrong number of lifetime arguments
@@ -13,13 +13,13 @@ LL |     Foo::<'static, 'static, ()>(&0); //~ ERROR wrong number of lifetime arg
    = note: expected type `&'static ()`
               found type `&{integer}`
 
-error[E0088]: wrong number of lifetime arguments: expected 1, found 2
+error[E0107]: wrong number of lifetime arguments: expected 1, found 2
   --> $DIR/generic-arg-mismatch-recover.rs:19:20
    |
 LL |     Bar::<'static, 'static, ()>(&()); //~ ERROR wrong number of lifetime arguments
    |                    ^^^^^^^ unexpected lifetime argument
 
-error[E0087]: wrong number of type arguments: expected 0, found 1
+error[E0107]: wrong number of type arguments: expected 0, found 1
   --> $DIR/generic-arg-mismatch-recover.rs:19:29
    |
 LL |     Bar::<'static, 'static, ()>(&()); //~ ERROR wrong number of lifetime arguments
@@ -27,5 +27,5 @@ LL |     Bar::<'static, 'static, ()>(&()); //~ ERROR wrong number of lifetime ar
 
 error: aborting due to 4 previous errors
 
-Some errors occurred: E0087, E0088, E0308.
-For more information about an error, try `rustc --explain E0087`.
+Some errors occurred: E0107, E0308.
+For more information about an error, try `rustc --explain E0107`.
index a10b500f9f8b8d760a1a5dc59e8881bfb7535fb9..94ae02a7b4b080f76f6e2d8706825c00060d2a8f 100644 (file)
@@ -1,4 +1,4 @@
-error[E0243]: wrong number of type arguments: expected at least 2, found 1
+error[E0107]: wrong number of type arguments: expected at least 2, found 1
   --> $DIR/generic-impl-less-params-with-defaults.rs:21:5
    |
 LL |     Foo::<isize>::new();
@@ -6,4 +6,4 @@ LL |     Foo::<isize>::new();
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0243`.
+For more information about this error, try `rustc --explain E0107`.
index b614da88ba164953eda612e7cba816500ccf8763..43a7413856b3fc7b43b745aef927af0b1c03cab6 100644 (file)
@@ -1,9 +1,9 @@
-error[E0244]: wrong number of type arguments: expected at most 2, found 3
+error[E0107]: wrong number of type arguments: expected at most 2, found 3
   --> $DIR/generic-impl-more-params-with-defaults.rs:23:5
    |
 LL |     Vec::<isize, Heap, bool>::new();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected at most 2 type argument
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected at most 2 type arguments
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0244`.
+For more information about this error, try `rustc --explain E0107`.
index c873fa676008d9905e8fc496b717302760961502..295f0fbc77ed08eb54967f152b8cda40d4229703 100644 (file)
@@ -17,5 +17,5 @@ struct Vec<T, A = Heap>(
 
 fn main() {
     let _: Vec;
-    //~^ ERROR wrong number of type arguments: expected at least 1, found 0 [E0243]
+    //~^ ERROR wrong number of type arguments: expected at least 1, found 0 [E0107]
 }
index 28867eb2254ea4c410d16c3168e7d13e3c050bfb..b024be55c8db928a6ee817b53d8ac9820c96ac8d 100644 (file)
@@ -1,4 +1,4 @@
-error[E0243]: wrong number of type arguments: expected at least 1, found 0
+error[E0107]: wrong number of type arguments: expected at least 1, found 0
   --> $DIR/generic-type-less-params-with-defaults.rs:19:12
    |
 LL |     let _: Vec;
@@ -6,4 +6,4 @@ LL |     let _: Vec;
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0243`.
+For more information about this error, try `rustc --explain E0107`.
index 0d1b1943ca2203df062fd91a7b7cecb61acf2d36..84c3a2f2230242022c41f01127989deaf158f3f0 100644 (file)
@@ -17,5 +17,5 @@ struct Vec<T, A = Heap>(
 
 fn main() {
     let _: Vec<isize, Heap, bool>;
-    //~^ ERROR wrong number of type arguments: expected at most 2, found 3 [E0244]
+    //~^ ERROR wrong number of type arguments: expected at most 2, found 3 [E0107]
 }
index f226921816d09f72ef1d263a5780feaae7a507f0..2d3e1c5970cd3bf318d9d3bfaee6bb948a56291b 100644 (file)
@@ -1,9 +1,9 @@
-error[E0244]: wrong number of type arguments: expected at most 2, found 3
+error[E0107]: wrong number of type arguments: expected at most 2, found 3
   --> $DIR/generic-type-more-params-with-defaults.rs:19:12
    |
 LL |     let _: Vec<isize, Heap, bool>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^ expected at most 2 type argument
+   |            ^^^^^^^^^^^^^^^^^^^^^^ expected at most 2 type arguments
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0244`.
+For more information about this error, try `rustc --explain E0107`.
index 1999df909ed2b8f7f7a82ab4dd3b82c69443eca7..bb4e922fdc0d23cebb585281ecbebdd1583d839e 100644 (file)
@@ -18,17 +18,33 @@ LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
 LL | |                                     fn(Inv<'y>)) }
    | |__________________________________________________- in this macro invocation
 
-error: compilation successful
-  --> $DIR/hr-subtype.rs:110:1
+error: unsatisfied lifetime constraints
+  --> $DIR/hr-subtype.rs:43:13
    |
-LL | / fn main() {
-LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful
-LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful
-LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful
-LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful
-LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful
-LL | | }
-   | |_^
+LL |           fn subtype<'x,'y:'x,'z:'y>() {
+   |                      -- -- lifetime `'y` defined here
+   |                      |
+   |                      lifetime `'x` defined here
+LL |               gimme::<$t2>(None::<$t1>);
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y`
+...
+LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
+LL | |                                     fn(Inv<'y>)) }
+   | |__________________________________________________- in this macro invocation
+
+error: unsatisfied lifetime constraints
+  --> $DIR/hr-subtype.rs:49:13
+   |
+LL |           fn supertype<'x,'y:'x,'z:'y>() {
+   |                        -- -- lifetime `'y` defined here
+   |                        |
+   |                        lifetime `'x` defined here
+LL |               gimme::<$t1>(None::<$t2>);
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y`
+...
+LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
+LL | |                                     fn(Inv<'y>)) }
+   | |__________________________________________________- in this macro invocation
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
index f76b26b5191d3d411e22fca14fe4329f975443d8..c33e6fbfde72ca9bd87f752b655f7f284ba3b333 100644 (file)
@@ -8,17 +8,19 @@ LL | / check! { free_x_vs_free_y: (fn(&'x u32),
 LL | |                             fn(&'y u32)) }
    | |__________________________________________- in this macro invocation
 
-error: compilation successful
-  --> $DIR/hr-subtype.rs:110:1
+error: unsatisfied lifetime constraints
+  --> $DIR/hr-subtype.rs:49:13
    |
-LL | / fn main() {
-LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful
-LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful
-LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful
-LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful
-LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful
-LL | | }
-   | |_^
+LL |           fn supertype<'x,'y:'x,'z:'y>() {
+   |                        -- -- lifetime `'y` defined here
+   |                        |
+   |                        lifetime `'x` defined here
+LL |               gimme::<$t1>(None::<$t2>);
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y`
+...
+LL | / check! { free_x_vs_free_y: (fn(&'x u32),
+LL | |                             fn(&'y u32)) }
+   | |__________________________________________- in this macro invocation
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hygiene/expansion-info-reset.rs b/src/test/ui/hygiene/expansion-info-reset.rs
new file mode 100644 (file)
index 0000000..d80c112
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// FIXME: Investigate why expansion info for a single expansion id is reset from
+// `MacroBang(format_args)` to `MacroAttribute(derive(Clone))` (issue #52363).
+
+fn main() {
+    format_args!({ #[derive(Clone)] struct S; });
+    //~^ ERROR format argument must be a string literal
+}
diff --git a/src/test/ui/hygiene/expansion-info-reset.stderr b/src/test/ui/hygiene/expansion-info-reset.stderr
new file mode 100644 (file)
index 0000000..02a7b0d
--- /dev/null
@@ -0,0 +1,12 @@
+error: format argument must be a string literal
+  --> $DIR/expansion-info-reset.rs:15:18
+   |
+LL |     format_args!({ #[derive(Clone)] struct S; });
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: you might be missing a string literal to format with
+   |
+LL |     format_args!("{}", { #[derive(Clone)] struct S; });
+   |                  ^^^^^
+
+error: aborting due to previous error
+
index 56b77714991ca61e7d5d5ca72684aad75686a1cb..9b25a865f921e1ff806c5efb99a478ece047f0c4 100644 (file)
@@ -1,9 +1,6 @@
 error[E0382]: use of moved value: `foo.x`
   --> $DIR/fields-move.rs:28:9
    |
-LL |    $foo.x
-   |    ------ value moved here
-...
 LL |         $foo.x //~ ERROR use of moved value: `foo.x`
    |         ^^^^^^ value used here after move
 ...
@@ -28,14 +25,9 @@ LL |     assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved val
 error[E0382]: use of moved value: `foo.x`
   --> $DIR/fields-move.rs:39:42
    |
-LL |    $foo.x
-   |    ------ value moved here
-...
 LL |         $foo.x //~ ERROR use of moved value: `foo.x`
    |         ------ value moved here
 ...
-LL |     assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
-   |                                          ----- value moved here
 LL |     assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
    |                                          ^^^^^ value used here after move
    |
index 2b2108558a0f385908c02d0b9b75a3f1afd8badd..efb3696cf851376557fb1f39a118a54422bda97e 100644 (file)
@@ -55,3 +55,5 @@ fn check_legacy() {
     struct FromOutside;
     genmod_legacy!();
 }
+
+fn main() {}
index 0c5905c5acb4fdc9ba2f93595feabfc269f30b66..f86444bae77e817d3a884ae0fb80cb4b416f786e 100644 (file)
@@ -46,11 +46,6 @@ LL |         type Inner = Outer; //~ ERROR cannot find type `Outer` in this scop
 LL |     genmod_legacy!();
    |     ----------------- in this macro invocation
 
-error[E0601]: `main` function not found in crate `generate_mod`
-   |
-   = note: consider adding a `main` function to `$DIR/generate-mod.rs`
-
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
-Some errors occurred: E0412, E0601.
-For more information about an error, try `rustc --explain E0412`.
+For more information about this error, try `rustc --explain E0412`.
index c90c7b3093c9f0e5d04a15371b082d4cf05dbf38..bf07bc05491cc3752afd543338b08af9a5ff4c09 100644 (file)
@@ -23,3 +23,5 @@ mod bar {
     }
     fn f() { ::foo::m!(); }
 }
+
+fn main() {}
index b3d82e9094ba732ebc6001ee6a355914943984bf..463fdbf00ce54bbc3783b5042395a90c36c82456 100644 (file)
@@ -7,10 +7,6 @@ LL |     fn f() { ::bar::m!(); }
 LL |         Vec::new(); //~ ERROR failed to resolve
    |         ^^^ Use of undeclared type or module `Vec`
 
-error[E0601]: `main` function not found in crate `no_implicit_prelude`
-   |
-   = note: consider adding a `main` function to `$DIR/no_implicit_prelude.rs`
-
 error[E0599]: no method named `clone` found for type `()` in the current scope
   --> $DIR/no_implicit_prelude.rs:22:12
    |
@@ -24,7 +20,7 @@ LL |         ().clone() //~ ERROR no method named `clone` found
    = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
            `use std::clone::Clone;`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors occurred: E0433, E0599, E0601.
+Some errors occurred: E0433, E0599.
 For more information about an error, try `rustc --explain E0433`.
index a5f1580b60d2f6ee0290a1a3e3780f9c0ebe868e..7ad16b1f8f237c0eeb2510d8e59f754b5e274b70 100644 (file)
@@ -30,7 +30,7 @@ error[E0643]: method `hash` has incompatible signature for trait
 LL |     fn hash(&self, hasher: &mut impl Hasher) {}
    |                                 ^^^^^^^^^^^ expected generic parameter, found `impl Trait`
    | 
-  ::: $SRC_DIR/libcore/hash/mod.rs:185:13
+  ::: $SRC_DIR/libcore/hash/mod.rs:LL:COL
    |
 LL |     fn hash<H: Hasher>(&self, state: &mut H);
    |             - declaration in trait here
index 2891cd59e3e1f1f82f5e3d5102f48ea618248dba..69f6d202f14ade457d4ac0cde23a72cc8ad61815 100644 (file)
@@ -125,7 +125,7 @@ trait InTraitDefnReturn {
 // Allowed and disallowed in trait impls
 trait DummyTrait {
     type Out;
-    fn in_trait_impl_parameter(impl Debug);
+    fn in_trait_impl_parameter(_: impl Debug);
     fn in_trait_impl_return() -> Self::Out;
 }
 impl DummyTrait for () {
index d9cc17791ed563bd7ce65ab7d3435a2eb3fe4e47..b2e92fe0e1bf9212c78ce8dc0f4a29dddc5f4af5 100644 (file)
@@ -25,3 +25,5 @@ mod test {
 
     fn test() { f1066(); } //~ ERROR cannot find function `f1066` in this scope
 }
+
+fn main() {}
index 078a6a3937a47282a727988d7afdf753df2dc460..fdff04cc2414892bb320ab77f6e3336b4e75557d 100644 (file)
@@ -4,11 +4,6 @@ error[E0425]: cannot find function `f1066` in this scope
 LL |     fn test() { f1066(); } //~ ERROR cannot find function `f1066` in this scope
    |                 ^^^^^ not found in this scope
 
-error[E0601]: `main` function not found in crate `import_glob_circular`
-   |
-   = note: consider adding a `main` function to `$DIR/import-glob-circular.rs`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0425, E0601.
-For more information about an error, try `rustc --explain E0425`.
+For more information about this error, try `rustc --explain E0425`.
index b7bbe11a4dc96b01e5b274d64ef036aa0c75f781..0bc968872db5bcc2a10b249ebaf378957e8f3614 100644 (file)
@@ -19,3 +19,5 @@ mod b {
 
     fn main() { let y = x; }
 }
+
+fn main() {}
index 717f74643ebb40b286194309fd916fdf5bd001a4..09c2e7918f37627fe213297e2b0eef074e1cec34 100644 (file)
@@ -4,16 +4,6 @@ error[E0432]: unresolved import `a::x`
 LL |     pub use a::x;
    |             ^^^^ no `x` in `a`
 
-error[E0601]: `main` function not found in crate `import_loop_2`
-   |
-   = note: the main function must be defined at the crate level but you have one or more functions named 'main' that are not defined at the crate level. Either move the definition or attach the `#[main]` attribute to override this behavior.
-note: here is a function named 'main'
-  --> $DIR/import-loop-2.rs:20:5
-   |
-LL |     fn main() { let y = x; }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0432, E0601.
-For more information about an error, try `rustc --explain E0432`.
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-53140.rs b/src/test/ui/imports/issue-53140.rs
new file mode 100644 (file)
index 0000000..dcfa054
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+mod m {
+    pub struct S(u8);
+
+    use S as Z;
+}
+
+use m::*;
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-53269.rs b/src/test/ui/imports/issue-53269.rs
new file mode 100644 (file)
index 0000000..1b21e3b
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Ambiguity between a `macro_rules` macro and a non-existent import recovered as `Def::Err`
+
+macro_rules! mac { () => () }
+
+mod m {
+    use nonexistent_module::mac; //~ ERROR unresolved import `nonexistent_module`
+
+    mac!(); //~ ERROR `mac` is ambiguous
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-53269.stderr b/src/test/ui/imports/issue-53269.stderr
new file mode 100644 (file)
index 0000000..0036d71
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0432]: unresolved import `nonexistent_module`
+  --> $DIR/issue-53269.rs:16:9
+   |
+LL |     use nonexistent_module::mac; //~ ERROR unresolved import `nonexistent_module`
+   |         ^^^^^^^^^^^^^^^^^^ Maybe a missing `extern crate nonexistent_module;`?
+
+error[E0659]: `mac` is ambiguous
+  --> $DIR/issue-53269.rs:18:5
+   |
+LL |     mac!(); //~ ERROR `mac` is ambiguous
+   |     ^^^
+   |
+note: `mac` could refer to the name defined here
+  --> $DIR/issue-53269.rs:13:1
+   |
+LL | macro_rules! mac { () => () }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: `mac` could also refer to the name imported here
+  --> $DIR/issue-53269.rs:16:9
+   |
+LL |     use nonexistent_module::mac; //~ ERROR unresolved import `nonexistent_module`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0432, E0659.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-53512.rs b/src/test/ui/imports/issue-53512.rs
new file mode 100644 (file)
index 0000000..82ae75e
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Macro from prelude is shadowed by non-existent import recovered as `Def::Err`.
+
+use std::assert; //~ ERROR unresolved import `std::assert`
+
+fn main() {
+    assert!(true);
+}
diff --git a/src/test/ui/imports/issue-53512.stderr b/src/test/ui/imports/issue-53512.stderr
new file mode 100644 (file)
index 0000000..e79e759
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `std::assert`
+  --> $DIR/issue-53512.rs:13:5
+   |
+LL | use std::assert; //~ ERROR unresolved import `std::assert`
+   |     ^^^^^^^^^^^ no `assert` in the root
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
index afdebc4533ff6370dff3ef88ead1b366633b2ddb..1ae7ed268ebf8567745f4806e8ec4407e61c9e0b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// `#[macro_export] macro_rules` that doen't originate from macro expansions can be placed
+// `#[macro_export] macro_rules` that doesn't originate from macro expansions can be placed
 // into the root module soon enough to act as usual items and shadow globs and preludes.
 
 #![feature(decl_macro)]
index 6691d98c2b7f43332fdfdc050d02a62436d7b08e..1cd7cc56a400d062b8c4340c04fad22ae4e4ae34 100644 (file)
@@ -22,9 +22,11 @@ macro_rules! exported {
 mod m {
     use exported;
     //~^ ERROR macro-expanded `macro_export` macros from the current crate cannot
+    //~| WARN this was previously accepted
 }
 
 fn main() {
     ::exported!();
     //~^ ERROR macro-expanded `macro_export` macros from the current crate cannot
+    //~| WARN this was previously accepted
 }
index 34c50e04288e50d8df200f2a54ed85de66830466..6c5c789e5ee8008ef37aa5c4671f13832027af75 100644 (file)
@@ -4,6 +4,9 @@ error: macro-expanded `macro_export` macros from the current crate cannot be ref
 LL |     use exported;
    |         ^^^^^^^^
    |
+   = note: #[deny(macro_expanded_macro_exports_accessed_by_absolute_paths)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #52234 <https://github.com/rust-lang/rust/issues/52234>
 note: the macro is defined here
   --> $DIR/local-modularized-tricky-fail-3.rs:15:5
    |
@@ -16,11 +19,13 @@ LL |   define_exported!();
    |   ------------------- in this macro invocation
 
 error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
-  --> $DIR/local-modularized-tricky-fail-3.rs:28:5
+  --> $DIR/local-modularized-tricky-fail-3.rs:29:5
    |
 LL |     ::exported!();
    |     ^^^^^^^^^^
    |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #52234 <https://github.com/rust-lang/rust/issues/52234>
 note: the macro is defined here
   --> $DIR/local-modularized-tricky-fail-3.rs:15:5
    |
index 01d1f4fdfad03df261080be2fa31a4b06a28b30c..2c0c4642067ac5f3dc4bb77815d130f1cd91736c 100644 (file)
@@ -1,15 +1,15 @@
-error: `m` is ambiguous
+error[E0659]: `m` is ambiguous
   --> $DIR/macros.rs:48:5
    |
 LL |     m!(); //~ ERROR ambiguous
    |     ^
    |
-note: `m` could refer to the macro defined here
+note: `m` could refer to the name defined here
   --> $DIR/macros.rs:46:5
    |
 LL |     macro_rules! m { () => {} }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: `m` could also refer to the macro imported here
+note: `m` could also refer to the name imported here
   --> $DIR/macros.rs:47:9
    |
 LL |     use two_macros::m;
index 90718abc37b3101ef9aaca11992e63354254cfbf..ec3f4107e38fcd7dd0c8afe3d1079fbaf79080aa 100644 (file)
@@ -37,10 +37,10 @@ macro_rules! panic { () => {} } // ok
 
 mod m5 {
     macro_rules! m { () => {
-        macro_rules! panic { () => {} } //~ ERROR `panic` is already in scope
+        macro_rules! panic { () => {} }
     } }
     m!();
-    panic!();
+    panic!(); //~ ERROR `panic` is ambiguous
 }
 
 #[macro_use(n)]
index 693b7aadeca4e334d8767f269317eb38fcde4d0e..5c7f15b6fe26f898e4b65f66a4884970e9a54abe 100644 (file)
@@ -1,13 +1,19 @@
-error: `panic` is already in scope
+error[E0659]: `panic` is ambiguous
+  --> $DIR/shadow_builtin_macros.rs:43:5
+   |
+LL |     panic!(); //~ ERROR `panic` is ambiguous
+   |     ^^^^^
+   |
+note: `panic` could refer to the name defined here
   --> $DIR/shadow_builtin_macros.rs:40:9
    |
-LL |         macro_rules! panic { () => {} } //~ ERROR `panic` is already in scope
+LL |         macro_rules! panic { () => {} }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |     } }
 LL |     m!();
    |     ----- in this macro invocation
-   |
-   = note: macro-expanded `macro_rules!`s may not shadow existing macros (see RFC 1560)
+   = note: `panic` is also a builtin macro
+   = note: macro-expanded macros do not shadow
 
 error[E0659]: `panic` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:25:14
index 4f1f67214509e5bb1c8c48f6915a9088ffc1b7b6..63ae18cf9c2fa1d3c0cf735e778afb8aae26c965 100644 (file)
@@ -10,7 +10,7 @@
 
 //https://github.com/rust-lang/rust/issues/31364
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 const fn a() -> usize { b() }
 const fn b() -> usize { a() }
 const ARR: [i32; a()] = [5; 6]; //~ ERROR could not evaluate constant expression
index 6d42515704ea117a95e42655de397df4602bcf7c..904a9acf9e53097f41f00996de95307aa4f85f16 100644 (file)
@@ -12,3 +12,5 @@
 #![crate_type(lib)]  //~ ERROR `crate_type` requires a value
 
 fn my_lib_fn() {}
+
+fn main() {}
index b609695b86ee5b92b61f5f5871bdc82e0beb7194..6f02f96faca93e91c7a753c734d42cf037f75669 100644 (file)
@@ -6,10 +6,5 @@ LL | #![crate_type(lib)]  //~ ERROR `crate_type` requires a value
    |
    = note: for example: `#![crate_type="lib"]`
 
-error[E0601]: `main` function not found in crate `invalid_crate_type_syntax`
-   |
-   = note: consider adding a `main` function to `$DIR/invalid_crate_type_syntax.rs`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/issue-52992.rs b/src/test/ui/issue-52992.rs
new file mode 100644 (file)
index 0000000..2ece0ee
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for an NLL-related ICE (#52992) -- computing
+// implied bounds was causing outlives relations that were not
+// properly handled.
+//
+// compile-pass
+
+#![feature(nll)]
+
+fn main() {}
+
+fn fail<'a>() -> Struct<'a, Generic<()>> {
+    Struct(&Generic(()))
+}
+
+struct Struct<'a, T>(&'a T) where
+    T: Trait + 'a,
+    T::AT: 'a; // only fails with this bound
+
+struct Generic<T>(T);
+
+trait Trait {
+    type AT;
+}
+
+impl<T> Trait for Generic<T> {
+    type AT = T; // only fails with a generic AT
+}
index f12afa4a79208a077b041f0a5b8a39091da0040e..51ea745bedb57c1e6f7c7bcfd36dca1078f30a95 100644 (file)
@@ -1,4 +1,4 @@
-error[E0087]: wrong number of type arguments: expected 0, found 1
+error[E0107]: wrong number of type arguments: expected 0, found 1
   --> $DIR/issue-53251.rs:21:24
    |
 LL |                 S::f::<i64>();
@@ -9,4 +9,4 @@ LL | impl_add!(a b);
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0087`.
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/issue-53300.rs b/src/test/ui/issue-53300.rs
new file mode 100644 (file)
index 0000000..d055a6f
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+// issue 53300
+
+pub trait A {
+    fn add(&self, b: i32) -> i32;
+}
+
+fn addition() -> Wrapper<impl A> {}
+//~^ ERROR cannot find type `Wrapper` in this scope [E0412]
+
+fn main() {
+    let res = addition();
+}
diff --git a/src/test/ui/issue-53300.stderr b/src/test/ui/issue-53300.stderr
new file mode 100644 (file)
index 0000000..920287a
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `Wrapper` in this scope
+  --> $DIR/issue-53300.rs:17:18
+   |
+LL | fn addition() -> Wrapper<impl A> {}
+   |                  ^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/issue-53419.rs b/src/test/ui/issue-53419.rs
new file mode 100644 (file)
index 0000000..e4ade1b
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//compile-pass
+
+#![feature(infer_outlives_requirements)]
+
+struct Foo {
+    bar: for<'r> Fn(usize, &'r FnMut())
+}
+
+fn main() {
+}
+
diff --git a/src/test/ui/issue-53568.rs b/src/test/ui/issue-53568.rs
new file mode 100644 (file)
index 0000000..6b479f7
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for an NLL-related ICE (#53568) -- we failed to
+// resolve inference variables in "custom type-ops".
+//
+// compile-pass
+
+#![feature(nll)]
+#![allow(dead_code)]
+
+trait Future {
+    type Item;
+}
+
+impl<F, T> Future for F
+where F: Fn() -> T
+{
+    type Item = T;
+}
+
+trait Connect {}
+
+struct Connector<H> {
+    handler: H,
+}
+
+impl<H, T> Connect for Connector<H>
+where
+    T: 'static,
+    H: Future<Item = T>
+{
+}
+
+struct Client<C> {
+    connector: C,
+}
+
+fn build<C>(_connector: C) -> Client<C> {
+    unimplemented!()
+}
+
+fn client<H>(handler: H) -> Client<impl Connect>
+where H: Fn() + Copy
+{
+    let connector = Connector {
+        handler,
+    };
+    let client = build(connector);
+    client
+}
+
+fn main() { }
+
index 449de26769ff318f7522bc6f996db2432bcca05a..fdce4b7a31dfb1afe708f84df02bd971ec421216 100644 (file)
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 fn fn1(0: Box) {}
-        //~^ ERROR wrong number of type arguments: expected 1, found 0 [E0243]
+        //~^ ERROR wrong number of type arguments: expected 1, found 0 [E0107]
 
 fn main() {}
index f90ea4776ab7c47e9a8d97b6e31ebff9c2de706c..98f18d7544881c5ebf858a5684e230eafabf2283 100644 (file)
@@ -1,4 +1,4 @@
-error[E0243]: wrong number of type arguments: expected 1, found 0
+error[E0107]: wrong number of type arguments: expected 1, found 0
   --> $DIR/issue-14092.rs:11:11
    |
 LL | fn fn1(0: Box) {}
@@ -6,4 +6,4 @@ LL | fn fn1(0: Box) {}
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0243`.
+For more information about this error, try `rustc --explain E0107`.
index 17ec77d77eea2c1f0b0a04f6ee7334418201580d..16cf4fd1b32e4edae0cbb86b6ee2e03a768a6257 100644 (file)
@@ -15,6 +15,5 @@
 const C2: &'static mut usize = unsafe { &mut S };
 //~^ ERROR: constants cannot refer to statics
 //~| ERROR: references in constants may only refer to immutable values
-//~| ERROR: references in constants may only refer to immutable values
 
 fn main() {}
index 0ab7f965b63ebd6346ff67a0580bc9baad8c240c..85424e5b73e545e8cb6748a40852d4d965e3592a 100644 (file)
@@ -16,13 +16,7 @@ error[E0017]: references in constants may only refer to immutable values
 LL | const C2: &'static mut usize = unsafe { &mut S };
    |                                         ^^^^^^ constants require immutable values
 
-error[E0017]: references in constants may only refer to immutable values
-  --> $DIR/issue-17718-const-bad-values.rs:15:32
-   |
-LL | const C2: &'static mut usize = unsafe { &mut S };
-   |                                ^^^^^^^^^^^^^^^^^ constants require immutable values
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors occurred: E0013, E0017.
 For more information about an error, try `rustc --explain E0013`.
index 5271ea79917841658ac2b6ca58e60b9d3f49b602..2708de2c13a8fc185408a838cdad805c590489b6 100644 (file)
@@ -16,6 +16,6 @@ fn main() {
     let ptr: *mut () = 0 as *mut _;
     let _: &mut Fn() = unsafe {
         &mut *(ptr as *mut Fn())
-        //~^ ERROR `(): std::ops::Fn<()>` is not satisfied
+        //~^ ERROR expected a `std::ops::Fn<()>` closure, found `()`
     };
 }
index bac62a1301aadd48183cd2a47b5f03c6fff75dd6..da376fedbb98af5313eadeac191d0794e19e2100 100644 (file)
@@ -1,9 +1,11 @@
-error[E0277]: the trait bound `(): std::ops::Fn<()>` is not satisfied
+error[E0277]: expected a `std::ops::Fn<()>` closure, found `()`
   --> $DIR/issue-22034.rs:18:16
    |
 LL |         &mut *(ptr as *mut Fn())
-   |                ^^^ the trait `std::ops::Fn<()>` is not implemented for `()`
+   |                ^^^ expected an `Fn<()>` closure, found `()`
    |
+   = help: the trait `std::ops::Fn<()>` is not implemented for `()`
+   = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }
    = note: required for the cast to the object type `dyn std::ops::Fn()`
 
 error: aborting due to previous error
index 5d9b49f486c69d20e733649522c48693cdc56be3..1c2c815ea9c326a013548e6c95a703819db0c68f 100644 (file)
@@ -18,6 +18,6 @@ fn h(x:i32) -> i32 {3*x}
     vfnfer.push(box h);
     println!("{:?}",(vfnfer[0] as Fn)(3));
     //~^ ERROR the precise format of `Fn`-family traits'
-    //~| ERROR wrong number of type arguments: expected 1, found 0 [E0243]
+    //~| ERROR wrong number of type arguments: expected 1, found 0 [E0107]
     //~| ERROR the value of the associated type `Output` (from the trait `std::ops::FnOnce`)
 }
index 39c79d8f14e8a13ba2082e53fa1ec4c646d6c938..129d094530361386d87553468c839a22e79e1f97 100644 (file)
@@ -6,7 +6,7 @@ LL |     println!("{:?}",(vfnfer[0] as Fn)(3));
    |
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error[E0243]: wrong number of type arguments: expected 1, found 0
+error[E0107]: wrong number of type arguments: expected 1, found 0
   --> $DIR/issue-23024.rs:19:35
    |
 LL |     println!("{:?}",(vfnfer[0] as Fn)(3));
@@ -20,5 +20,5 @@ LL |     println!("{:?}",(vfnfer[0] as Fn)(3));
 
 error: aborting due to 3 previous errors
 
-Some errors occurred: E0191, E0243, E0658.
-For more information about an error, try `rustc --explain E0191`.
+Some errors occurred: E0107, E0191, E0658.
+For more information about an error, try `rustc --explain E0107`.
index 07d2cfbf55f10fd6b93d9c4d9a06aaaff6c9db48..0418933180c00b97dbd96bafb89cf62f1d711370 100644 (file)
@@ -1,8 +1,10 @@
-error[E0277]: the trait bound `(): std::ops::FnMut<(_, char)>` is not satisfied
+error[E0277]: expected a `std::ops::FnMut<(_, char)>` closure, found `()`
   --> $DIR/issue-23966.rs:12:16
    |
 LL |     "".chars().fold(|_, _| (), ());
-   |                ^^^^ the trait `std::ops::FnMut<(_, char)>` is not implemented for `()`
+   |                ^^^^ expected an `FnMut<(_, char)>` closure, found `()`
+   |
+   = help: the trait `std::ops::FnMut<(_, char)>` is not implemented for `()`
 
 error: aborting due to previous error
 
index 514255e46769e8b6c34f373cf67ae859b7b7dec3..418754b9a244676ad096606bcb66babe270fb019 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Checks lexical scopes cannot see through normal module boundries
+// Checks lexical scopes cannot see through normal module boundaries
 
 fn f() {
     fn g() {}
index 2c4b9f84105eac84b240879f1ac9bc97b74540bc..d831be9ad3e9f3ae5f4339bbed97bfe1e9dc6bd8 100644 (file)
@@ -9,7 +9,7 @@ LL |     struct foo {
 LL |         x: T, //~ ERROR can't use type parameters from outer function
    |            ^ use of type variable from outer function
 
-error[E0244]: wrong number of type arguments: expected 0, found 1
+error[E0107]: wrong number of type arguments: expected 0, found 1
   --> $DIR/issue-3214.rs:16:26
    |
 LL |     impl<T> Drop for foo<T> {
@@ -17,5 +17,5 @@ LL |     impl<T> Drop for foo<T> {
 
 error: aborting due to 2 previous errors
 
-Some errors occurred: E0244, E0401.
-For more information about an error, try `rustc --explain E0244`.
+Some errors occurred: E0107, E0401.
+For more information about an error, try `rustc --explain E0107`.
index a1323808a91ea7a3ca412d7aa649b0bc71e681c6..f930217fe9ef5e0d311c84a9524cb8a194e81e9c 100644 (file)
@@ -1,8 +1,8 @@
 error[E0658]: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644)
-  --> $DIR/issue-32655.rs:16:9
+  --> $DIR/issue-32655.rs:16:11
    |
 LL |         #[derive_Clone] //~ ERROR attributes of the form
-   |         ^^^^^^^^^^^^^^^
+   |           ^^^^^^^^^^^^
 ...
 LL | foo!();
    | ------- in this macro invocation
@@ -10,10 +10,10 @@ LL | foo!();
    = help: add #![feature(custom_derive)] to the crate attributes to enable
 
 error[E0658]: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644)
-  --> $DIR/issue-32655.rs:28:5
+  --> $DIR/issue-32655.rs:28:7
    |
 LL |     #[derive_Clone] //~ ERROR attributes of the form
-   |     ^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^
    |
    = help: add #![feature(custom_derive)] to the crate attributes to enable
 
index 60e83138c76e9351efee926d9c8d057f6de2bbe2..2d333f324c4d36a8533bf8cbd6adaf8dfdf07eb3 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 static S : u64 = { { panic!("foo"); 0 } };
-//~^ ERROR calls in statics are limited
+//~^ ERROR panicking in statics is unstable
 
 fn main() {
     println!("{:?}", S);
index 30b6a6429046c0877f4d9a4a498ac9a9a4bcb2b1..55ee6d80d1f89fb8fcaa818d243155a066e53f5e 100644 (file)
@@ -1,11 +1,12 @@
-error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
+error[E0658]: panicking in statics is unstable (see issue #51999)
   --> $DIR/issue-32829.rs:11:22
    |
 LL | static S : u64 = { { panic!("foo"); 0 } };
    |                      ^^^^^^^^^^^^^^
    |
+   = help: add #![feature(const_panic)] to the crate attributes to enable
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0658`.
index 552653c21bad61724113cd2e3d6d38cee8653183..5c745d1fab3b5374a367f8cf2f0af04d9abd753c 100644 (file)
@@ -14,3 +14,5 @@ macro_rules! foo { ($i:ident) => {} }
 #[macro_export]
 macro_rules! foo { () => {} } //~ ERROR a macro named `foo` has already been exported
                               //~| WARN this was previously accepted
+
+fn main() {}
index a0dbcbd18c67336ab4e81fea35f0f3709554d6a7..67b27cc83cc897e74ea42ea3b41039dd525c8b88 100644 (file)
@@ -13,10 +13,5 @@ note: previous macro export is now shadowed
 LL | macro_rules! foo { ($i:ident) => {} }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0601]: `main` function not found in crate `issue_38715`
-   |
-   = note: consider adding a `main` function to `$DIR/issue-38715.rs`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0601`.
index 7547c4a17beba30e3edb1b8c6df585b7726d073c..46c8cb740ded7cfc3b101d87a2039115490963b2 100644 (file)
@@ -8,10 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 
 macro_rules! foo {
     ($($p:vis)*) => {} //~ ERROR repetition matches empty token tree
 }
 
 foo!(a);
+
+fn main() {}
index 91439061996162b5f26737e9b8612a30e81906a6..fa736edc47f5bf8207b045f332a00575764ab0d4 100644 (file)
@@ -4,10 +4,5 @@ error: repetition matches empty token tree
 LL |     ($($p:vis)*) => {} //~ ERROR repetition matches empty token tree
    |       ^^^^^^^^
 
-error[E0601]: `main` function not found in crate `issue_42755`
-   |
-   = note: consider adding a `main` function to `$DIR/issue-42755.rs`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0601`.
index 94b5c0034a76deca5addf72a4af88fe64b2a54aa..1ff1238ec54b83724b806bca0bd5875ed8aeee6f 100644 (file)
@@ -23,3 +23,5 @@ impl<T> Partial<T> for T::Assoc where
 impl<T> Complete for T { //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied
     type Assoc = T;
 }
+
+fn main() {}
index 798d8c660166847d613c291f1ae0d840e91deb9b..18e97e24b733a334315853005787a5d2fdbfa769 100644 (file)
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `issue_43784_associated_type`
-   |
-   = note: consider adding a `main` function to `$DIR/issue-43784-associated-type.rs`
-
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
   --> $DIR/issue-43784-associated-type.rs:23:9
    |
@@ -10,7 +6,6 @@ LL | impl<T> Complete for T { //~ ERROR the trait bound `T: std::marker::Copy` i
    |
    = help: consider adding a `where T: std::marker::Copy` bound
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0277, E0601.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.
index e70df113da33cfcb7e3b2e212e222789052f3602..30132c3be88a7a4f9bc700db7bb1c6c5ecef5b0f 100644 (file)
@@ -16,3 +16,5 @@ pub trait Complete: Partial {
 
 impl<T> Partial for T where T: Complete {}
 impl<T> Complete for T {} //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied
+
+fn main() {}
index 8646b315abdab59160810251d498ee3d59162564..422075f62aa0d086771646a276a8b9e3ae13645a 100644 (file)
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `issue_43784_supertrait`
-   |
-   = note: consider adding a `main` function to `$DIR/issue-43784-supertrait.rs`
-
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
   --> $DIR/issue-43784-supertrait.rs:18:9
    |
@@ -10,7 +6,6 @@ LL | impl<T> Complete for T {} //~ ERROR the trait bound `T: std::marker::Copy`
    |
    = help: consider adding a `where T: std::marker::Copy` bound
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0277, E0601.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.
index 8ad576472903b0354614f4b4576c9c2fbd04e5e2..7875c16c0e496a3c03856fd8eb113959e48c603a 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(attr_literals)]
-
 #[link(name="foo", cfg("rlib"))] //~ ERROR invalid argument for `cfg(..)`
 extern {}
 
index 995289aec01734fb7ce535e638d094cd8e804ed3..e93ea9c7bc7a52f2f0969db2ae0bcb7d21fc148a 100644 (file)
@@ -1,5 +1,5 @@
 error: invalid argument for `cfg(..)`
-  --> $DIR/issue-43925.rs:13:24
+  --> $DIR/issue-43925.rs:11:24
    |
 LL | #[link(name="foo", cfg("rlib"))] //~ ERROR invalid argument for `cfg(..)`
    |                        ^^^^^^
index 5d295510844ab277d3ae529d495d9e733f80fb92..bd50f93945c51f00b0dfb18b93c75851bab993c2 100644 (file)
@@ -10,7 +10,7 @@
 
 //~^^^^^^^^^^ ERROR cycle detected when computing layout of
 
-#![feature(const_fn)]
+
 #![feature(core_intrinsics)]
 
 use std::intrinsics;
index da42e171fcc5089fdfa8b78d605336e6b88048f8..8624dbd28dceb4b4764bbbe55ef50daf7ec61b4c 100644 (file)
@@ -24,7 +24,7 @@
 
 // run-pass
 
-// This test has structs and functions that are by definiton unusable
+// This test has structs and functions that are by definition unusable
 // all over the place, so just go ahead and allow dead_code
 #![allow(dead_code)]
 
index 7d12827dda5d2e958d9a4d2339749af16d4a21df..3f098fa37ce5c9b48b48730a75772ae35e05bd23 100644 (file)
@@ -12,16 +12,13 @@ LL | }
 error[E0597]: `z` does not live long enough (Mir)
   --> $DIR/issue-46471-1.rs:16:9
    |
-LL |       let y = {
-   |  _____________-
-LL | |         let mut z = 0;
-LL | |         &mut z
-   | |         ^^^^^^ borrowed value does not live long enough
-LL | |     };
-   | |     -
-   | |     |
-   | |_____`z` dropped here while still borrowed
-   |       borrow later used here
+LL |         &mut z
+   |         ^^^^^^
+   |         |
+   |         borrowed value does not live long enough
+   |         borrow later used here
+LL |     };
+   |     - `z` dropped here while still borrowed
 
 error: aborting due to 2 previous errors
 
index 888222b69cc4e6dc63a9ca2988fd526d2d3072a2..6c9d1eac3568436aa9788aa2dc7e1bf31db2324a 100644 (file)
@@ -1,8 +1,8 @@
 error[E0658]: The attribute `marco_use` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/issue-49074.rs:13:1
+  --> $DIR/issue-49074.rs:13:3
    |
 LL | #[marco_use] // typo
-   | ^^^^^^^^^^^^
+   |   ^^^^^^^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
index b8a7a089c2313f536ded33d6adb96d4e829a8be1..6c87d520934735432822a867f2d60369ae69062e 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Confirm that we don't accidently divide or mod by zero in llvm_type
+// Confirm that we don't accidentally divide or mod by zero in llvm_type
 
 // compile-pass
 
diff --git a/src/test/ui/issues/issue-52060.rs b/src/test/ui/issues/issue-52060.rs
new file mode 100644 (file)
index 0000000..54eff22
--- /dev/null
@@ -0,0 +1,8 @@
+// Regression test for https://github.com/rust-lang/rust/issues/52060
+// The compiler shouldn't ICE in this case
+static A: &'static [u32] = &[1];
+static B: [u32; 1] = [0; A.len()];
+//~^ ERROR [E0013]
+//~| ERROR `core::slice::<impl [T]>::len` is not yet stable as a const fn
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr
new file mode 100644 (file)
index 0000000..988bfd4
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0013]: constants cannot refer to statics, use a constant instead
+  --> $DIR/issue-52060.rs:4:26
+   |
+LL | static B: [u32; 1] = [0; A.len()];
+   |                          ^
+
+error: `core::slice::<impl [T]>::len` is not yet stable as a const fn
+  --> $DIR/issue-52060.rs:4:26
+   |
+LL | static B: [u32; 1] = [0; A.len()];
+   |                          ^^^^^^^
+   |
+   = help: in Nightly builds, add `#![feature(const_slice_len)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0013`.
index 18644033e4ff885b26d04ad9bfa3c70477696114..8315104d37ff41d41f55409a7b35f145b3a18bba 100644 (file)
@@ -10,7 +10,7 @@
 
 #![feature(label_break_value)]
 
-// These are forbidden occurences of label-break-value
+// These are forbidden occurrences of label-break-value
 
 fn labeled_unsafe() {
     unsafe 'b: {} //~ ERROR expected one of `extern`, `fn`, or `{`
index c5f3510fa0ed26d3b22ed886e7180f1f26d355d8..b4cbed03153a74193e06d112e7885805426f4f1c 100644 (file)
@@ -4,14 +4,15 @@ warning: not reporting region error due to nll
 LL |     x.push(y); //~ ERROR explicit lifetime required
    |            ^
 
-error[E0282]: type annotations needed
-  --> $DIR/ex2a-push-one-existing-name-early-bound.rs:20:9
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/ex2a-push-one-existing-name-early-bound.rs:17:5
    |
-LL | let x = baz;
-   |     -   ^^^ cannot infer type for `T`
-   |     |
-   |     consider giving `x` a type
+LL | fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T)
+   |                                          -- help: add explicit lifetime `'a` to the type of `y`: `&'a T`
+...
+LL |     x.push(y); //~ ERROR explicit lifetime required
+   |     ^^^^^^^^^ lifetime `'a` required
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0621`.
index 18a720f345d7f39511e8020129141efa9fb31358..cad0a3c6ac13df67d8a44c7fc8f8f876f7769ad4 100644 (file)
@@ -17,5 +17,4 @@ fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T)
     x.push(y); //~ ERROR explicit lifetime required
 }
 fn main() {
-let x = baz;
 }
index 20a2cbfd3aa784b41d1dc9a569d85c5dd5d17d83..6b0ca2ce9e00402842501ff435f817e481e5b1ab 100644 (file)
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 // FIXME: Change to UI Test
-// Check notes are placed on an assignment that can actually precede the current assigmnent
-// Don't emmit a first assignment for assignment in a loop.
+// Check notes are placed on an assignment that can actually precede the current assignment
+// Don't emit a first assignment for assignment in a loop.
 
 // compile-flags: -Zborrowck=compare
 
diff --git a/src/test/ui/lint/lint-anon-param-edition.fixed b/src/test/ui/lint/lint-anon-param-edition.fixed
deleted file mode 100644 (file)
index c4379b4..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.
-
-// tests that the anonymous_parameters lint is warn-by-default on the 2018 edition
-
-// compile-pass
-// edition:2018
-// run-rustfix
-
-trait Foo {
-    fn foo(_: u8);
-    //^ WARN anonymous parameters are deprecated
-    //| WARN this was previously accepted
-}
-
-fn main() {}
diff --git a/src/test/ui/lint/lint-anon-param-edition.rs b/src/test/ui/lint/lint-anon-param-edition.rs
deleted file mode 100644 (file)
index 13eb5df..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.
-
-// tests that the anonymous_parameters lint is warn-by-default on the 2018 edition
-
-// compile-pass
-// edition:2018
-// run-rustfix
-
-trait Foo {
-    fn foo(u8);
-    //^ WARN anonymous parameters are deprecated
-    //| WARN this was previously accepted
-}
-
-fn main() {}
diff --git a/src/test/ui/lint/lint-anon-param-edition.stderr b/src/test/ui/lint/lint-anon-param-edition.stderr
deleted file mode 100644 (file)
index de34777..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-warning: anonymous parameters are deprecated and will be removed in the next edition.
-  --> $DIR/lint-anon-param-edition.rs:18:12
-   |
-LL |     fn foo(u8);
-   |            ^^ help: Try naming the parameter or explicitly ignoring it: `_: u8`
-   |
-   = note: #[warn(anonymous_parameters)] on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
-
index 9f33f57f48a281aad0297646f125f26480aa68ae..55d6168e6e0085205d0044dca7e8f4ab517d8c7a 100644 (file)
@@ -8,16 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(bad_style)]
+#![deny(nonstandard_style)]
 #![allow(dead_code)]
 
 fn CamelCase() {} //~ ERROR should have a snake
 
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 mod test {
     fn CamelCase() {}
 
-    #[forbid(bad_style)]
+    #[forbid(nonstandard_style)]
     mod bad {
         fn CamelCase() {} //~ ERROR should have a snake
 
@@ -25,7 +25,7 @@ fn CamelCase() {} //~ ERROR should have a snake
     }
 
     mod warn {
-        #![warn(bad_style)]
+        #![warn(nonstandard_style)]
 
         fn CamelCase() {} //~ WARN should have a snake
 
index c1b15160bc501c345a9cb032b042363e9bb8c585..6b91ce5b93ca604ab9d28b5b7a816028ea96fe30 100644 (file)
@@ -7,9 +7,9 @@ LL | fn CamelCase() {} //~ ERROR should have a snake
 note: lint level defined here
   --> $DIR/lint-group-style.rs:11:9
    |
-LL | #![deny(bad_style)]
-   |         ^^^^^^^^^
-   = note: #[deny(non_snake_case)] implied by #[deny(bad_style)]
+LL | #![deny(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^
+   = note: #[deny(non_snake_case)] implied by #[deny(nonstandard_style)]
 
 error: function `CamelCase` should have a snake case name such as `camel_case`
   --> $DIR/lint-group-style.rs:22:9
@@ -20,9 +20,9 @@ LL |         fn CamelCase() {} //~ ERROR should have a snake
 note: lint level defined here
   --> $DIR/lint-group-style.rs:20:14
    |
-LL |     #[forbid(bad_style)]
-   |              ^^^^^^^^^
-   = note: #[forbid(non_snake_case)] implied by #[forbid(bad_style)]
+LL |     #[forbid(nonstandard_style)]
+   |              ^^^^^^^^^^^^^^^^^
+   = note: #[forbid(non_snake_case)] implied by #[forbid(nonstandard_style)]
 
 error: static variable `bad` should have an upper case name such as `BAD`
   --> $DIR/lint-group-style.rs:24:9
@@ -33,9 +33,9 @@ LL |         static bad: isize = 1; //~ ERROR should have an upper
 note: lint level defined here
   --> $DIR/lint-group-style.rs:20:14
    |
-LL |     #[forbid(bad_style)]
-   |              ^^^^^^^^^
-   = note: #[forbid(non_upper_case_globals)] implied by #[forbid(bad_style)]
+LL |     #[forbid(nonstandard_style)]
+   |              ^^^^^^^^^^^^^^^^^
+   = note: #[forbid(non_upper_case_globals)] implied by #[forbid(nonstandard_style)]
 
 warning: function `CamelCase` should have a snake case name such as `camel_case`
   --> $DIR/lint-group-style.rs:30:9
@@ -46,9 +46,9 @@ LL |         fn CamelCase() {} //~ WARN should have a snake
 note: lint level defined here
   --> $DIR/lint-group-style.rs:28:17
    |
-LL |         #![warn(bad_style)]
-   |                 ^^^^^^^^^
-   = note: #[warn(non_snake_case)] implied by #[warn(bad_style)]
+LL |         #![warn(nonstandard_style)]
+   |                 ^^^^^^^^^^^^^^^^^
+   = note: #[warn(non_snake_case)] implied by #[warn(nonstandard_style)]
 
 warning: type `snake_case` should have a camel case name such as `SnakeCase`
   --> $DIR/lint-group-style.rs:32:9
@@ -59,9 +59,9 @@ LL |         struct snake_case; //~ WARN should have a camel
 note: lint level defined here
   --> $DIR/lint-group-style.rs:28:17
    |
-LL |         #![warn(bad_style)]
-   |                 ^^^^^^^^^
-   = note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)]
+LL |         #![warn(nonstandard_style)]
+   |                 ^^^^^^^^^^^^^^^^^
+   = note: #[warn(non_camel_case_types)] implied by #[warn(nonstandard_style)]
 
 error: aborting due to 3 previous errors
 
index 97a976a493f80c90372d1a4e5602ee77c8812112..1e37ac0dc586c9b00ccbf25bc1463a15d7ba5487 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(bad_style, unused_variables)]
+#![allow(nonstandard_style, unused_variables)]
 #![deny(non_shorthand_field_patterns)]
 
 struct Foo {
index 8f0b53fd599713c3519654d6ef236a7f27a7aa1d..4ef185ee71c5ae2be5076b094f1489ac13f9562e 100644 (file)
@@ -35,7 +35,7 @@
 use other::*;
 
 mod foo {
-    // Test that this is unused even though an earler `extern crate` is used.
+    // Test that this is unused even though an earlier `extern crate` is used.
     extern crate lint_unused_extern_crate2; //~ ERROR unused extern crate
 }
 
index 0f9003877cc0621ac554154a989d7ae9e1fd7eb7..3785968df871ad292aa32947948b39832622da1f 100644 (file)
@@ -11,7 +11,8 @@
 // aux-build:lints-in-foreign-macros.rs
 // compile-pass
 
-#![warn(unused_imports)]
+#![warn(unused_imports)] //~ missing documentation for crate [missing_docs]
+#![warn(missing_docs)]
 
 #[macro_use]
 extern crate lints_in_foreign_macros;
@@ -24,5 +25,7 @@ macro_rules! foo {
 mod b { bar!(); }
 mod c { baz!(use std::string::ToString;); } //~ WARN: unused import
 mod d { baz2!(use std::string::ToString;); } //~ WARN: unused import
+baz!(pub fn undocumented() {}); //~ WARN: missing documentation for a function
+baz2!(pub fn undocumented2() {}); //~ WARN: missing documentation for a function
 
 fn main() {}
index e9f6d3d3815414299b233479f58a1041e01fbec3..2ddca7781231fb00e5e64ed10f119a3e1a1fd8e3 100644 (file)
@@ -1,5 +1,5 @@
 warning: unused import: `std::string::ToString`
-  --> $DIR/lints-in-foreign-macros.rs:20:16
+  --> $DIR/lints-in-foreign-macros.rs:21:16
    |
 LL |     () => {use std::string::ToString;} //~ WARN: unused import
    |                ^^^^^^^^^^^^^^^^^^^^^
@@ -10,18 +10,48 @@ LL | mod a { foo!(); }
 note: lint level defined here
   --> $DIR/lints-in-foreign-macros.rs:14:9
    |
-LL | #![warn(unused_imports)]
+LL | #![warn(unused_imports)] //~ missing documentation for crate [missing_docs]
    |         ^^^^^^^^^^^^^^
 
 warning: unused import: `std::string::ToString`
-  --> $DIR/lints-in-foreign-macros.rs:25:18
+  --> $DIR/lints-in-foreign-macros.rs:26:18
    |
 LL | mod c { baz!(use std::string::ToString;); } //~ WARN: unused import
    |                  ^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused import: `std::string::ToString`
-  --> $DIR/lints-in-foreign-macros.rs:26:19
+  --> $DIR/lints-in-foreign-macros.rs:27:19
    |
 LL | mod d { baz2!(use std::string::ToString;); } //~ WARN: unused import
    |                   ^^^^^^^^^^^^^^^^^^^^^
 
+warning: missing documentation for crate
+  --> $DIR/lints-in-foreign-macros.rs:14:1
+   |
+LL | / #![warn(unused_imports)] //~ missing documentation for crate [missing_docs]
+LL | | #![warn(missing_docs)]
+LL | |
+LL | | #[macro_use]
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+   |
+note: lint level defined here
+  --> $DIR/lints-in-foreign-macros.rs:15:9
+   |
+LL | #![warn(missing_docs)]
+   |         ^^^^^^^^^^^^
+
+warning: missing documentation for a function
+  --> $DIR/lints-in-foreign-macros.rs:28:6
+   |
+LL | baz!(pub fn undocumented() {}); //~ WARN: missing documentation for a function
+   |      ^^^^^^^^^^^^^^^^^^^^^
+
+warning: missing documentation for a function
+  --> $DIR/lints-in-foreign-macros.rs:29:7
+   |
+LL | baz2!(pub fn undocumented2() {}); //~ WARN: missing documentation for a function
+   |       ^^^^^^^^^^^^^^^^^^^^^^
+
index d72f307b46124f00bbebc1e0644e0b30155cbc81..23e98cc22fc3ae725b1ce257a6056edc61895f1f 100644 (file)
@@ -11,7 +11,7 @@
 // Forbidding a group (here, `unused`) overrules subsequent allowance of both
 // the group, and an individual lint in the group (here, `unused_variables`);
 // and, forbidding an individual lint (here, `non_snake_case`) overrules
-// subsequent allowance of a lint group containing it (here, `bad_style`). See
+// subsequent allowance of a lint group containing it (here, `nonstandard_style`). See
 // Issue #42873.
 
 #![forbid(unused, non_snake_case)]
@@ -22,7 +22,7 @@ fn foo() {}
 #[allow(unused)] //~ ERROR overruled
 fn bar() {}
 
-#[allow(bad_style)] //~ ERROR overruled
+#[allow(nonstandard_style)] //~ ERROR overruled
 fn main() {
     println!("hello forbidden world")
 }
index e49dcd4a2d19d0a39f5a795b14f965c063bf3946..c011b49eaee7ded8c8863ca47fdd384f83edba1d 100644 (file)
@@ -16,14 +16,14 @@ LL | #![forbid(unused, non_snake_case)]
 LL | #[allow(unused)] //~ ERROR overruled
    |         ^^^^^^ overruled by previous forbid
 
-error[E0453]: allow(bad_style) overruled by outer forbid(non_snake_case)
+error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case)
   --> $DIR/outer-forbid.rs:25:9
    |
 LL | #![forbid(unused, non_snake_case)]
    |                   -------------- `forbid` level set here
 ...
-LL | #[allow(bad_style)] //~ ERROR overruled
-   |         ^^^^^^^^^ overruled by previous forbid
+LL | #[allow(nonstandard_style)] //~ ERROR overruled
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
 
 error: aborting due to 3 previous errors
 
index 0a1926f8ae56a11dd9ad7f91881d37c3827cbbde..0089617b11c0b9a84e1c3f5db6b8731694185a69 100644 (file)
@@ -16,7 +16,7 @@
 
 // compile-pass
 
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 
 #![allow(unused)]
 #![warn(unreachable_pub)]
index 5bb67670d85c2ae6f9bcfa708e28c944ed82f2c4..7fd4a901090711bcfaf666bf456533ca5d9128a3 100644 (file)
@@ -11,7 +11,7 @@
 // compile-pass
 
 #![feature(crate_visibility_modifier)]
-#![feature(macro_vis_matcher)]
+#![cfg_attr(stage0, feature(macro_vis_matcher))]
 
 #![allow(unused)]
 #![warn(unreachable_pub)]
index c93c7144f9ebe08bc8165f2ad7f648aaf226cb5f..8f954158a6315cad8a815ffd46e8bc849fe59f26 100644 (file)
@@ -11,10 +11,10 @@ LL | #![feature(macro_reexport)] //~ ERROR feature has been removed
    |            ^^^^^^^^^^^^^^
 
 error[E0658]: The attribute `macro_reexport` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/macro-reexport-removed.rs:15:1
+  --> $DIR/macro-reexport-removed.rs:15:3
    |
 LL | #[macro_reexport(macro_one)] //~ ERROR attribute `macro_reexport` is currently unknown
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^^^^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
index a07cc834411732da96fd7dc9e87df1bc72ce64e2..fefc6ff6ca615559862dfa7f8188f7d30bd499df 100644 (file)
@@ -13,3 +13,5 @@
 #[allow(unused_extern_crates)]
 #[macro_use(foo(bar))]  //~ ERROR bad macro import
 extern crate std;
+
+fn main() {}
index 19a8c7c0382d13357ccae6e2d294369b06b92faa..308fb6c76e1b9444d9bc862235281e6f7c4bed16 100644 (file)
@@ -4,11 +4,6 @@ error[E0466]: bad macro import
 LL | #[macro_use(foo(bar))]  //~ ERROR bad macro import
    |             ^^^^^^^^
 
-error[E0601]: `main` function not found in crate `macro_use_bad_args_1`
-   |
-   = note: consider adding a `main` function to `$DIR/macro-use-bad-args-1.rs`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0466, E0601.
-For more information about an error, try `rustc --explain E0466`.
+For more information about this error, try `rustc --explain E0466`.
index 89004f16897742944693a75edb034c449fab82bb..81352cf2e427de855c7972fb4cd9adcedf1e08de 100644 (file)
@@ -13,3 +13,5 @@
 #[allow(unused_extern_crates)]
 #[macro_use(foo="bar")]  //~ ERROR bad macro import
 extern crate std;
+
+fn main() {}
index 0ac18201d791e0a49eb02ded907db51071b2339a..62e3c22fab3ec5b2e256dc49a280d233b60fc9c3 100644 (file)
@@ -4,11 +4,6 @@ error[E0466]: bad macro import
 LL | #[macro_use(foo="bar")]  //~ ERROR bad macro import
    |             ^^^^^^^^^
 
-error[E0601]: `main` function not found in crate `macro_use_bad_args_2`
-   |
-   = note: consider adding a `main` function to `$DIR/macro-use-bad-args-2.rs`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0466, E0601.
-For more information about an error, try `rustc --explain E0466`.
+For more information about this error, try `rustc --explain E0466`.
index 26fcaa65d77f9d37df687db9cc267d5ce3c1f99b..40dd9e25a17392c4b19d000c39c656a1ee5c526d 100644 (file)
@@ -5,17 +5,14 @@ LL |         match self.0 { ref mut x => x } //~ ERROR mismatched types
    |                                     ^
 
 error: unsatisfied lifetime constraints
-  --> $DIR/match-ref-mut-invariance.rs:19:49
+  --> $DIR/match-ref-mut-invariance.rs:20:9
    |
-LL |   impl<'b> S<'b> {
-   |        -- lifetime `'b` defined here
-LL |       fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
-   |  ____________--___________________________________^
-   | |            |
-   | |            lifetime `'a` defined here
-LL | |         match self.0 { ref mut x => x } //~ ERROR mismatched types
-LL | |     }
-   | |_____^ returning this value requires that `'a` must outlive `'b`
+LL | impl<'b> S<'b> {
+   |      -- lifetime `'b` defined here
+LL |     fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
+   |            -- lifetime `'a` defined here
+LL |         match self.0 { ref mut x => x } //~ ERROR mismatched types
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b`
 
 error: aborting due to previous error
 
index b1ec6adee9ea0a6bccff129062f1b020acf71b64..5314f37a3f88cad4fb428597b9ebe3986b626411 100644 (file)
@@ -5,18 +5,15 @@ LL |         x //~ ERROR mismatched types
    |         ^
 
 error: unsatisfied lifetime constraints
-  --> $DIR/match-ref-mut-let-invariance.rs:19:49
+  --> $DIR/match-ref-mut-let-invariance.rs:21:9
    |
-LL |   impl<'b> S<'b> {
-   |        -- lifetime `'b` defined here
-LL |       fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
-   |  ____________--___________________________________^
-   | |            |
-   | |            lifetime `'a` defined here
-LL | |         let ref mut x = self.0;
-LL | |         x //~ ERROR mismatched types
-LL | |     }
-   | |_____^ returning this value requires that `'a` must outlive `'b`
+LL | impl<'b> S<'b> {
+   |      -- lifetime `'b` defined here
+LL |     fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
+   |            -- lifetime `'a` defined here
+LL |         let ref mut x = self.0;
+LL |         x //~ ERROR mismatched types
+   |         ^ returning this value requires that `'a` must outlive `'b`
 
 error: aborting due to previous error
 
index d86a9f48e003e347bc1102ab98347e4e5ae9d9c3..ce283ec964ef432b0e05f3e9ba14c39c2fba568c 100644 (file)
@@ -1,10 +1,10 @@
-error[E0090]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: wrong number of lifetime arguments: expected 2, found 1
   --> $DIR/method-call-lifetime-args-fail.rs:26:7
    |
 LL |     S.early::<'static>();
    |       ^^^^^ expected 2 lifetime arguments
 
-error[E0088]: wrong number of lifetime arguments: expected 2, found 3
+error[E0107]: wrong number of lifetime arguments: expected 2, found 3
   --> $DIR/method-call-lifetime-args-fail.rs:28:33
    |
 LL |     S.early::<'static, 'static, 'static>();
@@ -178,13 +178,13 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
    |                          ^^
 
-error[E0090]: wrong number of lifetime arguments: expected 2, found 1
+error[E0107]: wrong number of lifetime arguments: expected 2, found 1
   --> $DIR/method-call-lifetime-args-fail.rs:73:5
    |
 LL |     S::early::<'static>(S);
    |     ^^^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
 
-error[E0088]: wrong number of lifetime arguments: expected 2, found 3
+error[E0107]: wrong number of lifetime arguments: expected 2, found 3
   --> $DIR/method-call-lifetime-args-fail.rs:75:34
    |
 LL |     S::early::<'static, 'static, 'static>(S);
@@ -192,5 +192,4 @@ LL |     S::early::<'static, 'static, 'static>(S);
 
 error: aborting due to 18 previous errors
 
-Some errors occurred: E0088, E0090.
-For more information about an error, try `rustc --explain E0088`.
+For more information about this error, try `rustc --explain E0107`.
index 3842d48f8fab110a759979429c8963adbf8e3435..1096027c8dc0becb64d663398e9773072a9edfa6 100644 (file)
@@ -13,9 +13,9 @@
 
 #![no_std]
 #![crate_type = "staticlib"]
-#![feature(panic_implementation, alloc_error_handler, alloc)]
+#![feature(panic_handler, alloc_error_handler, alloc)]
 
-#[panic_implementation]
+#[panic_handler]
 fn panic(_: &core::panic::PanicInfo) -> ! {
     loop {}
 }
index c949dcb635aad5ccbc0bf998cb06531515e109b1..f4331c4b99480cc2f2dd5b38afe0106c1e83513e 100644 (file)
@@ -13,9 +13,9 @@
 
 #![no_std]
 #![crate_type = "staticlib"]
-#![feature(panic_implementation, alloc_error_handler, alloc)]
+#![feature(panic_handler, alloc_error_handler, alloc)]
 
-#[panic_implementation]
+#[panic_handler]
 fn panic(_: &core::panic::PanicInfo) -> ! {
     loop {}
 }
index aac37289bb74952ddce176abc833629fdab68a0b..2378cccf56f76c34e8590116e9755cde779f3adf 100644 (file)
@@ -14,3 +14,5 @@ fn hd<U>(v: Vec<U> ) -> U {
 
     return hd1(v);
 }
+
+fn main() {}
index 93b934f610f8ca65c6ff711e552f1d12a9b60708..58b6cd18989f2171db70f3c272bfac407acdf64b 100644 (file)
@@ -18,11 +18,6 @@ LL |     fn hd1(w: [U]) -> U { return w[0]; }
    |        |
    |        help: try using a local type parameter instead: `hd1<U>`
 
-error[E0601]: `main` function not found in crate `nested_ty_params`
-   |
-   = note: consider adding a `main` function to `$DIR/nested-ty-params.rs`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors occurred: E0401, E0601.
-For more information about an error, try `rustc --explain E0401`.
+For more information about this error, try `rustc --explain E0401`.
index 5538eca362974acc261c0e35fee9d53e8a0297ce..808114f3fa9b4f64e900a615a7a27d118107fe17 100644 (file)
@@ -8,10 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//compile-flags: -Z emit-end-regions -Zborrowck=mir
-
-
 #![allow(warnings)]
+#![feature(nll)]
 
 struct Wrap<'p> { p: &'p mut i32 }
 
index 327454ee60e53085bf1fc6e788cd7ca5bf4deb79..6fc26d502d30de8b7edea00c4c60ab90c8c2c4ea 100644 (file)
@@ -1,5 +1,5 @@
 error[E0506]: cannot assign to `x` because it is borrowed
-  --> $DIR/maybe-initialized-drop-implicit-fragment-drop.rs:32:5
+  --> $DIR/maybe-initialized-drop-implicit-fragment-drop.rs:30:5
    |
 LL |     let wrap = Wrap { p: &mut x };
    |                          ------ borrow of `x` occurs here
index 695dddbf7e9d553585baa1a208f5a4ffc40726c3..7ef6572a5d79973316e20a878a5e3389995e23e2 100644 (file)
@@ -15,9 +15,9 @@
 use std::fmt::Debug;
 
 fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
-    //~^ ERROR unsatisfied lifetime constraints
     x
-    //~^ WARNING not reporting region error due to nll
+    //~^ ERROR unsatisfied lifetime constraints
+    //~| WARNING not reporting region error due to nll
 }
 
 fn main() {}
index 4219c07673a45879330567bd163ea786f22732e8..a965e611f992a42d5bf00e48b9fe1978dd98a8ac 100644 (file)
@@ -1,21 +1,16 @@
 warning: not reporting region error due to nll
-  --> $DIR/mir_check_cast_unsize.rs:19:5
+  --> $DIR/mir_check_cast_unsize.rs:18:5
    |
 LL |     x
    |     ^
 
 error: unsatisfied lifetime constraints
-  --> $DIR/mir_check_cast_unsize.rs:17:46
+  --> $DIR/mir_check_cast_unsize.rs:18:5
    |
-LL |   fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
-   |  ________--____________________________________^
-   | |        |
-   | |        lifetime `'a` defined here
-LL | |     //~^ ERROR unsatisfied lifetime constraints
-LL | |     x
-LL | |     //~^ WARNING not reporting region error due to nll
-LL | | }
-   | |_^ returning this value requires that `'a` must outlive `'static`
+LL | fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
+   |        -- lifetime `'a` defined here
+LL |     x
+   |     ^ returning this value requires that `'a` must outlive `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/user-annotations/adt-brace-enums.rs b/src/test/ui/nll/user-annotations/adt-brace-enums.rs
new file mode 100644 (file)
index 0000000..4465be4
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+enum SomeEnum<T> {
+    SomeVariant { t: T }
+}
+
+fn no_annot() {
+    let c = 66;
+    SomeEnum::SomeVariant { t: &c };
+}
+
+fn annot_underscore() {
+    let c = 66;
+    SomeEnum::SomeVariant::<_> { t: &c };
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    SomeEnum::SomeVariant::<&u32> { t: &c };
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    SomeEnum::SomeVariant::<&'static u32> { t: &c }; //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    SomeEnum::SomeVariant::<&'a u32> { t: &c }; //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    SomeEnum::SomeVariant::<&'a u32> { t: c };
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        SomeEnum::SomeVariant::<&'a u32> { t: &c }; //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        SomeEnum::SomeVariant::<&'a u32> { t: c };
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/adt-brace-enums.stderr b/src/test/ui/nll/user-annotations/adt-brace-enums.stderr
new file mode 100644 (file)
index 0000000..842bb62
--- /dev/null
@@ -0,0 +1,41 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-enums.rs:37:48
+   |
+LL |     SomeEnum::SomeVariant::<&'static u32> { t: &c }; //~ ERROR
+   |                                                ^^ borrowed value does not live long enough
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-enums.rs:42:43
+   |
+LL |     SomeEnum::SomeVariant::<&'a u32> { t: &c }; //~ ERROR
+   |                                           ^^ borrowed value does not live long enough
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 40:35...
+  --> $DIR/adt-brace-enums.rs:40:35
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   ^^
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-enums.rs:52:47
+   |
+LL |         SomeEnum::SomeVariant::<&'a u32> { t: &c }; //~ ERROR
+   |                                               ^^ borrowed value does not live long enough
+LL |     };
+   |     - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 49:46...
+  --> $DIR/adt-brace-enums.rs:49:46
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/adt-brace-structs.rs b/src/test/ui/nll/user-annotations/adt-brace-structs.rs
new file mode 100644 (file)
index 0000000..c479e05
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+struct SomeStruct<T> { t: T }
+
+fn no_annot() {
+    let c = 66;
+    SomeStruct { t: &c };
+}
+
+fn annot_underscore() {
+    let c = 66;
+    SomeStruct::<_> { t: &c };
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    SomeStruct::<&u32> { t: &c };
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    SomeStruct::<&'static u32> { t: &c }; //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    SomeStruct::<&'a u32> { t: &c }; //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    SomeStruct::<&'a u32> { t: c };
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        SomeStruct::<&'a u32> { t: &c }; //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        SomeStruct::<&'a u32> { t: c };
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/adt-brace-structs.stderr b/src/test/ui/nll/user-annotations/adt-brace-structs.stderr
new file mode 100644 (file)
index 0000000..7ba7621
--- /dev/null
@@ -0,0 +1,41 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-structs.rs:35:37
+   |
+LL |     SomeStruct::<&'static u32> { t: &c }; //~ ERROR
+   |                                     ^^ borrowed value does not live long enough
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-structs.rs:40:32
+   |
+LL |     SomeStruct::<&'a u32> { t: &c }; //~ ERROR
+   |                                ^^ borrowed value does not live long enough
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 38:35...
+  --> $DIR/adt-brace-structs.rs:38:35
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   ^^
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-structs.rs:50:36
+   |
+LL |         SomeStruct::<&'a u32> { t: &c }; //~ ERROR
+   |                                    ^^ borrowed value does not live long enough
+LL |     };
+   |     - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 47:46...
+  --> $DIR/adt-brace-structs.rs:47:46
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/adt-nullary-enums.rs b/src/test/ui/nll/user-annotations/adt-nullary-enums.rs
new file mode 100644 (file)
index 0000000..df62b67
--- /dev/null
@@ -0,0 +1,80 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+#![allow(warnings)]
+
+use std::cell::Cell;
+
+enum SomeEnum<T> {
+    SomeVariant(T),
+    SomeOtherVariant,
+}
+
+fn combine<T>(_: T, _: T) { }
+
+fn no_annot() {
+    let c = 66;
+    combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant);
+}
+
+fn annot_underscore() {
+    let c = 66;
+    combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::<Cell<_>>);
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::<Cell<&u32>>);
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    combine(
+        SomeEnum::SomeVariant(Cell::new(&c)), //~ ERROR
+        SomeEnum::SomeOtherVariant::<Cell<&'static u32>>,
+    );
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    combine(
+        SomeEnum::SomeVariant(Cell::new(&c)), //~ ERROR
+        SomeEnum::SomeOtherVariant::<Cell<&'a u32>>,
+    );
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    combine(SomeEnum::SomeVariant(Cell::new(c)), SomeEnum::SomeOtherVariant::<Cell<&'a u32>>);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        combine(
+            SomeEnum::SomeVariant(Cell::new(&c)), //~ ERROR
+            SomeEnum::SomeOtherVariant::<Cell<&'a u32>>,
+        );
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        combine(
+            SomeEnum::SomeVariant(Cell::new(c)),
+            SomeEnum::SomeOtherVariant::<Cell<&'a u32>>,
+        );
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr b/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr
new file mode 100644 (file)
index 0000000..fa251f3
--- /dev/null
@@ -0,0 +1,44 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-nullary-enums.rs:44:41
+   |
+LL |         SomeEnum::SomeVariant(Cell::new(&c)), //~ ERROR
+   |                                         ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-nullary-enums.rs:52:41
+   |
+LL |         SomeEnum::SomeVariant(Cell::new(&c)), //~ ERROR
+   |                                         ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 49:35...
+  --> $DIR/adt-nullary-enums.rs:49:35
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   ^^
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-nullary-enums.rs:65:45
+   |
+LL |             SomeEnum::SomeVariant(Cell::new(&c)), //~ ERROR
+   |                                             ^^ borrowed value does not live long enough
+...
+LL |     };
+   |     - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 61:46...
+  --> $DIR/adt-nullary-enums.rs:61:46
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/adt-tuple-enums.rs b/src/test/ui/nll/user-annotations/adt-tuple-enums.rs
new file mode 100644 (file)
index 0000000..ae75a54
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+#![allow(warnings)]
+
+enum SomeEnum<T> {
+    SomeVariant(T),
+    SomeOtherVariant,
+}
+
+fn no_annot() {
+    let c = 66;
+    SomeEnum::SomeVariant(&c);
+}
+
+fn annot_underscore() {
+    let c = 66;
+    SomeEnum::SomeVariant::<_>(&c);
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    SomeEnum::SomeVariant::<&u32>(&c);
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    SomeEnum::SomeVariant::<&'static u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    SomeEnum::SomeVariant::<&'a u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    SomeEnum::SomeVariant::<&'a u32>(c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        SomeEnum::SomeVariant::<&'a u32>(&c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        SomeEnum::SomeVariant::<&'a u32>(c);
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr b/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr
new file mode 100644 (file)
index 0000000..18d1cc7
--- /dev/null
@@ -0,0 +1,41 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-enums.rs:39:43
+   |
+LL |     SomeEnum::SomeVariant::<&'static u32>(&c); //~ ERROR
+   |                                           ^^ borrowed value does not live long enough
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-enums.rs:44:38
+   |
+LL |     SomeEnum::SomeVariant::<&'a u32>(&c); //~ ERROR
+   |                                      ^^ borrowed value does not live long enough
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 42:35...
+  --> $DIR/adt-tuple-enums.rs:42:35
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   ^^
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-enums.rs:54:42
+   |
+LL |         SomeEnum::SomeVariant::<&'a u32>(&c); //~ ERROR
+   |                                          ^^ borrowed value does not live long enough
+LL |     };
+   |     - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 51:46...
+  --> $DIR/adt-tuple-enums.rs:51:46
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/adt-tuple-struct.rs b/src/test/ui/nll/user-annotations/adt-tuple-struct.rs
new file mode 100644 (file)
index 0000000..401a71c
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+struct SomeStruct<T>(T);
+
+fn no_annot() {
+    let c = 66;
+    SomeStruct(&c);
+}
+
+fn annot_underscore() {
+    let c = 66;
+    SomeStruct::<_>(&c);
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    SomeStruct::<&u32>(&c);
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    SomeStruct::<&'static u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    SomeStruct::<&'a u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    SomeStruct::<&'a u32>(c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        SomeStruct::<&'a u32>(&c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        SomeStruct::<&'a u32>(c);
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr b/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr
new file mode 100644 (file)
index 0000000..397016e
--- /dev/null
@@ -0,0 +1,41 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-struct.rs:35:32
+   |
+LL |     SomeStruct::<&'static u32>(&c); //~ ERROR
+   |                                ^^ borrowed value does not live long enough
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-struct.rs:40:27
+   |
+LL |     SomeStruct::<&'a u32>(&c); //~ ERROR
+   |                           ^^ borrowed value does not live long enough
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 38:35...
+  --> $DIR/adt-tuple-struct.rs:38:35
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   ^^
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-struct.rs:50:31
+   |
+LL |         SomeStruct::<&'a u32>(&c); //~ ERROR
+   |                               ^^ borrowed value does not live long enough
+LL |     };
+   |     - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 47:46...
+  --> $DIR/adt-tuple-struct.rs:47:46
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs
new file mode 100644 (file)
index 0000000..970fbf9
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+// compile-flags:-Zverbose
+
+#![allow(warnings)]
+#![feature(nll)]
+#![feature(rustc_attrs)]
+
+struct SomeStruct<T> { t: T }
+
+#[rustc_dump_user_substs]
+fn main() {
+    SomeStruct { t: 22 }; // Nothing given, no annotation.
+
+    SomeStruct::<_> { t: 22 }; // Nothing interesting given, no annotation.
+
+    SomeStruct::<u32> { t: 22 }; //~ ERROR [u32]
+}
diff --git a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr
new file mode 100644 (file)
index 0000000..2b0e503
--- /dev/null
@@ -0,0 +1,8 @@
+error: user substs: Canonical { variables: [], value: [u32] }
+  --> $DIR/dump-adt-brace-struct.rs:28:5
+   |
+LL |     SomeStruct::<u32> { t: 22 }; //~ ERROR [u32]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/user-annotations/dump-fn-method.rs b/src/test/ui/nll/user-annotations/dump-fn-method.rs
new file mode 100644 (file)
index 0000000..7f726d1
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+// compile-flags:-Zverbose
+
+#![feature(nll)]
+#![feature(rustc_attrs)]
+
+// Note: we reference the names T and U in the comments below.
+trait Bazoom<T> {
+    fn method<U>(&self, arg: T, arg2: U) { }
+}
+
+impl<T, U> Bazoom<U> for T {
+}
+
+fn foo<'a, T>(_: T) { }
+
+#[rustc_dump_user_substs]
+fn main() {
+    // Here: nothing is given, so we don't have any annotation.
+    let x = foo;
+    x(22);
+
+    // Here: `u32` is given.
+    let x = foo::<u32>; //~ ERROR [u32]
+    x(22);
+
+    // Here: we only want the `T` to be given, the rest should be variables.
+    //
+    // (`T` refers to the declaration of `Bazoom`)
+    let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [?0, u32, ?1]
+    x(&22, 44, 66);
+
+    // Here: all are given
+    let x = <u8 as Bazoom<u16>>::method::<u32>; //~ ERROR [u8, u16, u32]
+    x(&22, 44, 66);
+
+    // Here: we want in particular that *only* the method `U`
+    // annotation is given, the rest are variables.
+    //
+    // (`U` refers to the declaration of `Bazoom`)
+    let y = 22_u32;
+    y.method::<u32>(44, 66); //~ ERROR [?0, ?1, u32]
+
+    // Here: nothing is given, so we don't have any annotation.
+    let y = 22_u32;
+    y.method(44, 66);
+}
diff --git a/src/test/ui/nll/user-annotations/dump-fn-method.stderr b/src/test/ui/nll/user-annotations/dump-fn-method.stderr
new file mode 100644 (file)
index 0000000..6531f87
--- /dev/null
@@ -0,0 +1,26 @@
+error: user substs: Canonical { variables: [], value: [u32] }
+  --> $DIR/dump-fn-method.rs:36:13
+   |
+LL |     let x = foo::<u32>; //~ ERROR [u32]
+   |             ^^^^^^^^^^
+
+error: user substs: Canonical { variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: [?0, u32, ?1] }
+  --> $DIR/dump-fn-method.rs:42:13
+   |
+LL |     let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [?0, u32, ?1]
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: user substs: Canonical { variables: [], value: [u8, u16, u32] }
+  --> $DIR/dump-fn-method.rs:46:13
+   |
+LL |     let x = <u8 as Bazoom<u16>>::method::<u32>; //~ ERROR [u8, u16, u32]
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: user substs: Canonical { variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: [?0, ?1, u32] }
+  --> $DIR/dump-fn-method.rs:54:5
+   |
+LL |     y.method::<u32>(44, 66); //~ ERROR [?0, ?1, u32]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/nll/user-annotations/fns.rs b/src/test/ui/nll/user-annotations/fns.rs
new file mode 100644 (file)
index 0000000..4f26d54
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+fn some_fn<T>(arg: T) { }
+
+fn no_annot() {
+    let c = 66;
+    some_fn(&c); // OK
+}
+
+fn annot_underscore() {
+    let c = 66;
+    some_fn::<_>(&c); // OK
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    some_fn::<&u32>(&c); // OK
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    some_fn::<&'static u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    some_fn::<&'a u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    some_fn::<&'a u32>(c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        some_fn::<&'a u32>(&c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        some_fn::<&'a u32>(c);
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/fns.stderr b/src/test/ui/nll/user-annotations/fns.stderr
new file mode 100644 (file)
index 0000000..b6ef336
--- /dev/null
@@ -0,0 +1,41 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/fns.rs:35:29
+   |
+LL |     some_fn::<&'static u32>(&c); //~ ERROR
+   |                             ^^ borrowed value does not live long enough
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/fns.rs:40:24
+   |
+LL |     some_fn::<&'a u32>(&c); //~ ERROR
+   |                        ^^ borrowed value does not live long enough
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 38:35...
+  --> $DIR/fns.rs:38:35
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   ^^
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/fns.rs:50:28
+   |
+LL |         some_fn::<&'a u32>(&c); //~ ERROR
+   |                            ^^ borrowed value does not live long enough
+LL |     };
+   |     - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 47:46...
+  --> $DIR/fns.rs:47:46
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/method-call.rs b/src/test/ui/nll/user-annotations/method-call.rs
new file mode 100644 (file)
index 0000000..9a03679
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+trait Bazoom<T> {
+    fn method<U>(&self, arg: T, arg2: U) { }
+}
+
+impl<T, U> Bazoom<U> for T {
+}
+
+fn no_annot() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    a.method(b,  &c); // OK
+}
+
+fn annot_underscore() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    a.method::<_>(b,  &c); // OK
+}
+
+fn annot_reference_any_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    a.method::<&u32>(b,  &c); // OK
+}
+
+fn annot_reference_static_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    a.method::<&'static u32>(b,  &c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    a.method::<&'a u32>(b,  &c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    let a = 22;
+    let b = 44;
+    a.method::<&'a u32>(b,  c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        let c = 66;
+        a.method::<&'a u32>(b,  &c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        a.method::<&'a u32>(b,  c);
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/method-call.stderr b/src/test/ui/nll/user-annotations/method-call.stderr
new file mode 100644 (file)
index 0000000..f1c7ff1
--- /dev/null
@@ -0,0 +1,41 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-call.rs:48:34
+   |
+LL |     a.method::<&'static u32>(b,  &c); //~ ERROR
+   |                                  ^^ borrowed value does not live long enough
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-call.rs:55:29
+   |
+LL |     a.method::<&'a u32>(b,  &c); //~ ERROR
+   |                             ^^ borrowed value does not live long enough
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 51:35...
+  --> $DIR/method-call.rs:51:35
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   ^^
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-call.rs:69:33
+   |
+LL |         a.method::<&'a u32>(b,  &c); //~ ERROR
+   |                                 ^^ borrowed value does not live long enough
+LL |     };
+   |     - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 64:46...
+  --> $DIR/method-call.rs:64:46
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-1.rs b/src/test/ui/nll/user-annotations/method-ufcs-1.rs
new file mode 100644 (file)
index 0000000..5ac2ba5
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+trait Bazoom<T>: Sized {
+    fn method<U>(self, arg: T, arg2: U) { }
+}
+
+impl<T, U> Bazoom<U> for T {
+}
+
+fn annot_underscore() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method::<_>(&a, b, c); // OK
+}
+
+fn annot_reference_any_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <&u32 as Bazoom<_>>::method(&a, b, c); // OK
+}
+
+fn annot_reference_static_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    let x = <&'static u32 as Bazoom<_>>::method;
+    x(&a, b, c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <&'a u32 as Bazoom<_>>::method(&a, b, c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(a: &'a u32) {
+    let b = 44;
+    let c = 66;
+    <&'a u32 as Bazoom<_>>::method(&a, b, c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        let c = 66;
+        <&'a u32 as Bazoom<_>>::method(&a, b, c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(a: &'a u32) {
+    let b = 44;
+    let c = 66;
+    let _closure = || {
+        <&'a u32 as Bazoom<_>>::method(&a, b, c);
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-1.stderr b/src/test/ui/nll/user-annotations/method-ufcs-1.stderr
new file mode 100644 (file)
index 0000000..f439748
--- /dev/null
@@ -0,0 +1,45 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/method-ufcs-1.rs:42:7
+   |
+LL |     x(&a, b, c); //~ ERROR
+   |       ^^ borrowed value does not live long enough
+LL | }
+   | - `a` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `a` does not live long enough
+  --> $DIR/method-ufcs-1.rs:49:36
+   |
+LL |     <&'a u32 as Bazoom<_>>::method(&a, b, c); //~ ERROR
+   |                                    ^^ borrowed value does not live long enough
+LL | }
+   | - `a` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 45:35...
+  --> $DIR/method-ufcs-1.rs:45:35
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   ^^
+
+error[E0597]: `a` does not live long enough
+  --> $DIR/method-ufcs-1.rs:63:41
+   |
+LL |     let _closure = || {
+   |                    -- value captured here
+LL |         let c = 66;
+LL |         <&'a u32 as Bazoom<_>>::method(&a, b, c); //~ ERROR
+   |                                         ^ borrowed value does not live long enough
+LL |     };
+LL | }
+   | - `a` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 58:46...
+  --> $DIR/method-ufcs-1.rs:58:46
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-2.rs b/src/test/ui/nll/user-annotations/method-ufcs-2.rs
new file mode 100644 (file)
index 0000000..082cc56
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+trait Bazoom<T>: Sized {
+    fn method<U>(self, arg: T, arg2: U) { }
+}
+
+impl<T, U> Bazoom<U> for T {
+}
+
+fn annot_underscore() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method(a, &b, c); // OK
+}
+
+fn annot_reference_any_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<&u32>>::method(a, &b, c); // OK
+}
+
+fn annot_reference_static_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    let x = <&'static u32 as Bazoom<_>>::method;
+    x(&a, b, c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<&'a u32>>::method(a, &b, c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(b: &'a u32) {
+    let a = 44;
+    let c = 66;
+    <_ as Bazoom<&'a u32>>::method(a, &b, c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        let c = 66;
+        <_ as Bazoom<&'a u32>>::method(a, &b, c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(b: &'a u32) {
+    let a = 44;
+    let c = 66;
+    let _closure = || {
+        <_ as Bazoom<&'a u32>>::method(a, &b, c);
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-2.stderr b/src/test/ui/nll/user-annotations/method-ufcs-2.stderr
new file mode 100644 (file)
index 0000000..dc0f559
--- /dev/null
@@ -0,0 +1,45 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/method-ufcs-2.rs:42:7
+   |
+LL |     x(&a, b, c); //~ ERROR
+   |       ^^ borrowed value does not live long enough
+LL | }
+   | - `a` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `b` does not live long enough
+  --> $DIR/method-ufcs-2.rs:49:39
+   |
+LL |     <_ as Bazoom<&'a u32>>::method(a, &b, c); //~ ERROR
+   |                                       ^^ borrowed value does not live long enough
+LL | }
+   | - `b` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 45:35...
+  --> $DIR/method-ufcs-2.rs:45:35
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   ^^
+
+error[E0597]: `b` does not live long enough
+  --> $DIR/method-ufcs-2.rs:63:44
+   |
+LL |     let _closure = || {
+   |                    -- value captured here
+LL |         let c = 66;
+LL |         <_ as Bazoom<&'a u32>>::method(a, &b, c); //~ ERROR
+   |                                            ^ borrowed value does not live long enough
+LL |     };
+LL | }
+   | - `b` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 58:46...
+  --> $DIR/method-ufcs-2.rs:58:46
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-3.rs b/src/test/ui/nll/user-annotations/method-ufcs-3.rs
new file mode 100644 (file)
index 0000000..f4fdb3e
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+trait Bazoom<T> {
+    fn method<U>(&self, arg: T, arg2: U) { }
+}
+
+impl<T, U> Bazoom<U> for T {
+}
+
+fn no_annot() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method(&a, b, &c); // OK
+}
+
+fn annot_underscore() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method::<_>(&a, b, &c); // OK
+}
+
+fn annot_reference_any_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method::<&u32>(&a, b, &c); // OK
+}
+
+fn annot_reference_static_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method::<&'static u32>(&a, b, &c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    let a = 22;
+    let b = 44;
+    <_ as Bazoom<_>>::method::<&'a u32>(&a, b, c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        let c = 66;
+        <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        <_ as Bazoom<_>>::method::<&'a u32>(&a, b, c);
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-3.stderr b/src/test/ui/nll/user-annotations/method-ufcs-3.stderr
new file mode 100644 (file)
index 0000000..7ddea3e
--- /dev/null
@@ -0,0 +1,41 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-ufcs-3.rs:48:53
+   |
+LL |     <_ as Bazoom<_>>::method::<&'static u32>(&a, b, &c); //~ ERROR
+   |                                                     ^^ borrowed value does not live long enough
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-ufcs-3.rs:55:48
+   |
+LL |     <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c); //~ ERROR
+   |                                                ^^ borrowed value does not live long enough
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 51:35...
+  --> $DIR/method-ufcs-3.rs:51:35
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   ^^
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-ufcs-3.rs:69:52
+   |
+LL |         <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c); //~ ERROR
+   |                                                    ^^ borrowed value does not live long enough
+LL |     };
+   |     - `c` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 64:46...
+  --> $DIR/method-ufcs-3.rs:64:46
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
index 0d21dddc7c9bcb26d43f996c9bb911e1b14165db..2dc0a10f425ae0c370ed18c8436c140cec60a544 100644 (file)
@@ -5,20 +5,15 @@ LL |     ss
    |     ^^
 
 error: unsatisfied lifetime constraints
-  --> $DIR/object-lifetime-default-elision.rs:64:53
+  --> $DIR/object-lifetime-default-elision.rs:81:5
    |
-LL |   fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
-   |  __________--_--______________________________________^
-   | |          |  |
-   | |          |  lifetime `'b` defined here
-   | |          lifetime `'a` defined here
-LL | |     // Under old rules, the fully elaborated types of input/output were:
-LL | |     //
-LL | |     // for<'a,'b,'c>fn(&'a (SomeTrait+'c)) -> &'b (SomeTrait+'a)
-...  |
-LL | |         //~| ERROR cannot infer
-LL | | }
-   | |_^ returning this value requires that `'a` must outlive `'b`
+LL | fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
+   |          -- -- lifetime `'b` defined here
+   |          |
+   |          lifetime `'a` defined here
+...
+LL |     ss
+   |     ^^ returning this value requires that `'a` must outlive `'b`
 
 error: aborting due to previous error
 
index 5cfced1a72fbebe4fcdff2278b781eb0fbd3ddb9..19279b53c1c8b5650f18b19dd0dda3dc38c5498e 100644 (file)
@@ -11,18 +11,13 @@ LL |     ss.r = b; //~ ERROR 41:12: 41:13: explicit lifetime required in the typ
    |            ^
 
 error[E0621]: explicit lifetime required in the type of `ss`
-  --> $DIR/object-lifetime-default-from-box-error.rs:24:48
+  --> $DIR/object-lifetime-default-from-box-error.rs:28:5
    |
-LL |   fn load(ss: &mut SomeStruct) -> Box<SomeTrait> {
-   |  _____________---------------____________________^
-   | |             |
-   | |             help: add explicit lifetime `'static` to the type of `ss`: `&mut SomeStruct<'static>`
-LL | |     // `Box<SomeTrait>` defaults to a `'static` bound, so this return
-LL | |     // is illegal.
-LL | |
-LL | |     ss.r //~ ERROR explicit lifetime required in the type of `ss` [E0621]
-LL | | }
-   | |_^ lifetime `'static` required
+LL | fn load(ss: &mut SomeStruct) -> Box<SomeTrait> {
+   |             --------------- help: add explicit lifetime `'static` to the type of `ss`: `&mut SomeStruct<'static>`
+...
+LL |     ss.r //~ ERROR explicit lifetime required in the type of `ss` [E0621]
+   |     ^^^^ lifetime `'static` required
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/object-lifetime-default-from-box-error.rs:28:5
diff --git a/src/test/ui/panic-handler/auxiliary/some-panic-impl.rs b/src/test/ui/panic-handler/auxiliary/some-panic-impl.rs
new file mode 100644 (file)
index 0000000..e3b4fba
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+#![feature(panic_handler)]
+#![no_std]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+    loop {}
+}
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs
new file mode 100644 (file)
index 0000000..cc7e337
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-C panic=abort
+
+#![feature(panic_handler)]
+#![no_std]
+#![no_main]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic(
+    info: PanicInfo, //~ ERROR argument should be `&PanicInfo`
+) -> () //~ ERROR return type should be `!`
+{
+}
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-1.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-1.stderr
new file mode 100644 (file)
index 0000000..5771f42
--- /dev/null
@@ -0,0 +1,14 @@
+error: return type should be `!`
+  --> $DIR/panic-handler-bad-signature-1.rs:22:6
+   |
+LL | ) -> () //~ ERROR return type should be `!`
+   |      ^^
+
+error: argument should be `&PanicInfo`
+  --> $DIR/panic-handler-bad-signature-1.rs:21:11
+   |
+LL |     info: PanicInfo, //~ ERROR argument should be `&PanicInfo`
+   |           ^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs
new file mode 100644 (file)
index 0000000..ec69890
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-C panic=abort
+
+#![feature(panic_handler)]
+#![no_std]
+#![no_main]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic(
+    info: &'static PanicInfo, //~ ERROR argument should be `&PanicInfo`
+) -> !
+{
+    loop {}
+}
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-2.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-2.stderr
new file mode 100644 (file)
index 0000000..4823f8a
--- /dev/null
@@ -0,0 +1,8 @@
+error: argument should be `&PanicInfo`
+  --> $DIR/panic-handler-bad-signature-2.rs:21:11
+   |
+LL |     info: &'static PanicInfo, //~ ERROR argument should be `&PanicInfo`
+   |           ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs
new file mode 100644 (file)
index 0000000..585716c
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-C panic=abort
+
+#![feature(panic_handler)]
+#![no_std]
+#![no_main]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic() -> ! { //~ ERROR function should have one argument
+    loop {}
+}
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr
new file mode 100644 (file)
index 0000000..0eb0d4e
--- /dev/null
@@ -0,0 +1,10 @@
+error: function should have one argument
+  --> $DIR/panic-handler-bad-signature-3.rs:20:1
+   |
+LL | / fn panic() -> ! { //~ ERROR function should have one argument
+LL | |     loop {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs
new file mode 100644 (file)
index 0000000..9cda37f
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-C panic=abort
+
+#![feature(panic_handler)]
+#![no_std]
+#![no_main]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic<T>(pi: &PanicInfo) -> ! {
+    //~^ ERROR should have no type parameters
+    loop {}
+}
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr
new file mode 100644 (file)
index 0000000..a61b9b3
--- /dev/null
@@ -0,0 +1,11 @@
+error: should have no type parameters
+  --> $DIR/panic-handler-bad-signature-4.rs:20:1
+   |
+LL | / fn panic<T>(pi: &PanicInfo) -> ! {
+LL | |     //~^ ERROR should have no type parameters
+LL | |     loop {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/panic-handler/panic-handler-duplicate.rs b/src/test/ui/panic-handler/panic-handler-duplicate.rs
new file mode 100644 (file)
index 0000000..7d7fe25
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-C panic=abort
+
+#![feature(lang_items)]
+#![feature(panic_handler)]
+#![no_std]
+#![no_main]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+    loop {}
+}
+
+#[lang = "panic_impl"]
+fn panic2(info: &PanicInfo) -> ! { //~ ERROR duplicate lang item found: `panic_impl`.
+    loop {}
+}
diff --git a/src/test/ui/panic-handler/panic-handler-duplicate.stderr b/src/test/ui/panic-handler/panic-handler-duplicate.stderr
new file mode 100644 (file)
index 0000000..d8afaa2
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0152]: duplicate lang item found: `panic_impl`.
+  --> $DIR/panic-handler-duplicate.rs:26:1
+   |
+LL | / fn panic2(info: &PanicInfo) -> ! { //~ ERROR duplicate lang item found: `panic_impl`.
+LL | |     loop {}
+LL | | }
+   | |_^
+   |
+note: first defined here.
+  --> $DIR/panic-handler-duplicate.rs:21:1
+   |
+LL | / fn panic(info: &PanicInfo) -> ! {
+LL | |     loop {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0152`.
diff --git a/src/test/ui/panic-handler/panic-handler-requires-panic-info.rs b/src/test/ui/panic-handler/panic-handler-requires-panic-info.rs
new file mode 100644 (file)
index 0000000..ec68a41
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-C panic=abort
+// error-pattern: language item required, but not found: `panic_info`
+
+#![feature(lang_items)]
+#![feature(no_core)]
+#![feature(panic_handler)]
+#![no_core]
+#![no_main]
+
+#[panic_handler]
+fn panic() -> ! {
+    loop {}
+}
+
+#[lang = "sized"]
+trait Sized {}
diff --git a/src/test/ui/panic-handler/panic-handler-requires-panic-info.stderr b/src/test/ui/panic-handler/panic-handler-requires-panic-info.stderr
new file mode 100644 (file)
index 0000000..2bae12e
--- /dev/null
@@ -0,0 +1,4 @@
+error: language item required, but not found: `panic_info`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/panic-handler/panic-handler-std.rs b/src/test/ui/panic-handler/panic-handler-std.rs
new file mode 100644 (file)
index 0000000..7cbe0a3
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern: duplicate lang item found: `panic_impl`.
+
+#![feature(panic_handler)]
+
+use std::panic::PanicInfo;
+
+#[panic_handler]
+fn panic(info: PanicInfo) -> ! {
+    loop {}
+}
+
+fn main() {}
diff --git a/src/test/ui/panic-handler/panic-handler-std.stderr b/src/test/ui/panic-handler/panic-handler-std.stderr
new file mode 100644 (file)
index 0000000..b141a21
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0152]: duplicate lang item found: `panic_impl`.
+  --> $DIR/panic-handler-std.rs:18:1
+   |
+LL | / fn panic(info: PanicInfo) -> ! {
+LL | |     loop {}
+LL | | }
+   | |_^
+   |
+   = note: first defined in crate `std`.
+
+error: argument should be `&PanicInfo`
+  --> $DIR/panic-handler-std.rs:18:16
+   |
+LL | fn panic(info: PanicInfo) -> ! {
+   |                ^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0152`.
diff --git a/src/test/ui/panic-implementation/auxiliary/some-panic-impl.rs b/src/test/ui/panic-implementation/auxiliary/some-panic-impl.rs
deleted file mode 100644 (file)
index db16ac3..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-#![feature(panic_implementation)]
-#![no_std]
-
-use core::panic::PanicInfo;
-
-#[panic_implementation]
-fn panic(info: &PanicInfo) -> ! {
-    loop {}
-}
diff --git a/src/test/ui/panic-implementation/panic-implementation-bad-signature-1.rs b/src/test/ui/panic-implementation/panic-implementation-bad-signature-1.rs
deleted file mode 100644 (file)
index fec11fd..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags:-C panic=abort
-
-#![feature(panic_implementation)]
-#![no_std]
-#![no_main]
-
-use core::panic::PanicInfo;
-
-#[panic_implementation]
-fn panic(
-    info: PanicInfo, //~ ERROR argument should be `&PanicInfo`
-) -> () //~ ERROR return type should be `!`
-{
-}
diff --git a/src/test/ui/panic-implementation/panic-implementation-bad-signature-1.stderr b/src/test/ui/panic-implementation/panic-implementation-bad-signature-1.stderr
deleted file mode 100644 (file)
index 0e020fb..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: return type should be `!`
-  --> $DIR/panic-implementation-bad-signature-1.rs:22:6
-   |
-LL | ) -> () //~ ERROR return type should be `!`
-   |      ^^
-
-error: argument should be `&PanicInfo`
-  --> $DIR/panic-implementation-bad-signature-1.rs:21:11
-   |
-LL |     info: PanicInfo, //~ ERROR argument should be `&PanicInfo`
-   |           ^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/panic-implementation/panic-implementation-bad-signature-2.rs b/src/test/ui/panic-implementation/panic-implementation-bad-signature-2.rs
deleted file mode 100644 (file)
index 2a628c0..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags:-C panic=abort
-
-#![feature(panic_implementation)]
-#![no_std]
-#![no_main]
-
-use core::panic::PanicInfo;
-
-#[panic_implementation]
-fn panic(
-    info: &'static PanicInfo, //~ ERROR argument should be `&PanicInfo`
-) -> !
-{
-    loop {}
-}
diff --git a/src/test/ui/panic-implementation/panic-implementation-bad-signature-2.stderr b/src/test/ui/panic-implementation/panic-implementation-bad-signature-2.stderr
deleted file mode 100644 (file)
index 71ed1ef..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: argument should be `&PanicInfo`
-  --> $DIR/panic-implementation-bad-signature-2.rs:21:11
-   |
-LL |     info: &'static PanicInfo, //~ ERROR argument should be `&PanicInfo`
-   |           ^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/panic-implementation/panic-implementation-bad-signature-3.rs b/src/test/ui/panic-implementation/panic-implementation-bad-signature-3.rs
deleted file mode 100644 (file)
index 2933702..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags:-C panic=abort
-
-#![feature(panic_implementation)]
-#![no_std]
-#![no_main]
-
-use core::panic::PanicInfo;
-
-#[panic_implementation]
-fn panic() -> ! { //~ ERROR function should have one argument
-    loop {}
-}
diff --git a/src/test/ui/panic-implementation/panic-implementation-bad-signature-3.stderr b/src/test/ui/panic-implementation/panic-implementation-bad-signature-3.stderr
deleted file mode 100644 (file)
index 3fd29bc..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: function should have one argument
-  --> $DIR/panic-implementation-bad-signature-3.rs:20:1
-   |
-LL | / fn panic() -> ! { //~ ERROR function should have one argument
-LL | |     loop {}
-LL | | }
-   | |_^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/panic-implementation/panic-implementation-bad-signature-4.rs b/src/test/ui/panic-implementation/panic-implementation-bad-signature-4.rs
deleted file mode 100644 (file)
index d5f942b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags:-C panic=abort
-
-#![feature(panic_implementation)]
-#![no_std]
-#![no_main]
-
-use core::panic::PanicInfo;
-
-#[panic_implementation]
-fn panic<T>(pi: &PanicInfo) -> ! {
-    //~^ ERROR `#[panic_implementation]` function should have no type parameters
-    loop {}
-}
diff --git a/src/test/ui/panic-implementation/panic-implementation-bad-signature-4.stderr b/src/test/ui/panic-implementation/panic-implementation-bad-signature-4.stderr
deleted file mode 100644 (file)
index 362be2f..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: `#[panic_implementation]` function should have no type parameters
-  --> $DIR/panic-implementation-bad-signature-4.rs:20:1
-   |
-LL | / fn panic<T>(pi: &PanicInfo) -> ! {
-LL | |     //~^ ERROR `#[panic_implementation]` function should have no type parameters
-LL | |     loop {}
-LL | | }
-   | |_^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/panic-implementation/panic-implementation-deprecated.rs b/src/test/ui/panic-implementation/panic-implementation-deprecated.rs
new file mode 100644 (file)
index 0000000..c4bec01
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-C panic=abort
+
+#![deny(deprecated)]
+#![feature(panic_implementation)]
+#![no_std]
+
+use core::panic::PanicInfo;
+
+#[panic_implementation]
+fn panic(info: &PanicInfo) -> ! {
+    loop {}
+}
+
+fn main() {}
diff --git a/src/test/ui/panic-implementation/panic-implementation-deprecated.stderr b/src/test/ui/panic-implementation/panic-implementation-deprecated.stderr
new file mode 100644 (file)
index 0000000..43f5144
--- /dev/null
@@ -0,0 +1,14 @@
+error: use of deprecated attribute `panic_implementation`: This attribute was renamed to `panic_handler`. See https://github.com/rust-lang/rust/issues/44489#issuecomment-415140224
+  --> $DIR/panic-implementation-deprecated.rs:19:1
+   |
+LL | #[panic_implementation]
+   | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: lint level defined here
+  --> $DIR/panic-implementation-deprecated.rs:13:9
+   |
+LL | #![deny(deprecated)]
+   |         ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/panic-implementation/panic-implementation-duplicate.rs b/src/test/ui/panic-implementation/panic-implementation-duplicate.rs
deleted file mode 100644 (file)
index 017113a..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags:-C panic=abort
-
-#![feature(lang_items)]
-#![feature(panic_implementation)]
-#![no_std]
-#![no_main]
-
-use core::panic::PanicInfo;
-
-#[panic_implementation]
-fn panic(info: &PanicInfo) -> ! {
-    loop {}
-}
-
-#[lang = "panic_impl"]
-fn panic2(info: &PanicInfo) -> ! { //~ ERROR duplicate lang item found: `panic_impl`.
-    loop {}
-}
diff --git a/src/test/ui/panic-implementation/panic-implementation-duplicate.stderr b/src/test/ui/panic-implementation/panic-implementation-duplicate.stderr
deleted file mode 100644 (file)
index d553c02..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0152]: duplicate lang item found: `panic_impl`.
-  --> $DIR/panic-implementation-duplicate.rs:26:1
-   |
-LL | / fn panic2(info: &PanicInfo) -> ! { //~ ERROR duplicate lang item found: `panic_impl`.
-LL | |     loop {}
-LL | | }
-   | |_^
-   |
-note: first defined here.
-  --> $DIR/panic-implementation-duplicate.rs:21:1
-   |
-LL | / fn panic(info: &PanicInfo) -> ! {
-LL | |     loop {}
-LL | | }
-   | |_^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0152`.
diff --git a/src/test/ui/panic-implementation/panic-implementation-requires-panic-info.rs b/src/test/ui/panic-implementation/panic-implementation-requires-panic-info.rs
deleted file mode 100644 (file)
index 597f44d..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags:-C panic=abort
-// error-pattern: language item required, but not found: `panic_info`
-
-#![feature(lang_items)]
-#![feature(no_core)]
-#![feature(panic_implementation)]
-#![no_core]
-#![no_main]
-
-#[panic_implementation]
-fn panic() -> ! {
-    loop {}
-}
-
-#[lang = "sized"]
-trait Sized {}
diff --git a/src/test/ui/panic-implementation/panic-implementation-requires-panic-info.stderr b/src/test/ui/panic-implementation/panic-implementation-requires-panic-info.stderr
deleted file mode 100644 (file)
index 2bae12e..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-error: language item required, but not found: `panic_info`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/panic-implementation/panic-implementation-std.rs b/src/test/ui/panic-implementation/panic-implementation-std.rs
deleted file mode 100644 (file)
index f25cd36..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern: duplicate lang item found: `panic_impl`.
-
-#![feature(panic_implementation)]
-
-use std::panic::PanicInfo;
-
-#[panic_implementation]
-fn panic(info: PanicInfo) -> ! {
-    loop {}
-}
-
-fn main() {}
diff --git a/src/test/ui/panic-implementation/panic-implementation-std.stderr b/src/test/ui/panic-implementation/panic-implementation-std.stderr
deleted file mode 100644 (file)
index 5016d50..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0152]: duplicate lang item found: `panic_impl`.
-  --> $DIR/panic-implementation-std.rs:18:1
-   |
-LL | / fn panic(info: PanicInfo) -> ! {
-LL | |     loop {}
-LL | | }
-   | |_^
-   |
-   = note: first defined in crate `std`.
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0152`.
index 4fa9a639928f98f41ca54f3d9ddfe19f694819fa..6642db6ee76bf25a73a8258866428d2a55735e99 100644 (file)
@@ -12,9 +12,9 @@
 
 #![crate_type = "rlib"]
 #![no_std]
-#![feature(panic_implementation)]
+#![feature(panic_handler)]
 
-#[panic_implementation]
+#[panic_handler]
 pub fn panic_fmt(_: &::core::panic::PanicInfo) -> ! {
     |x: u8| x;
     loop {}
index 3c53c3acf55c14fea8ed8356cfbaf26fcfb7e43b..f7a632dfaa1a012f744c9b2b3224a2571ded2c4d 100644 (file)
@@ -20,3 +20,5 @@
 )]
 trait T {}
 //~^^^ ERROR expected one of `)` or `,`, found `label`
+
+fn main() {  }
index 9bb6653d770803e7065064a2696ab99ee3e5bbe1..f1bfbc95eb39564b80948b42910e7d0a7414fbe5 100644 (file)
@@ -10,8 +10,6 @@
 
 // compile-flags: -Z parse-only
 
-#![feature(raw_identifiers)]
-
 fn test_if() {
     r#if true { } //~ ERROR found `true`
 }
index 022f80ae8a4ecb31ba854774a2e9a7b961dd8b8d..8a6b91b4b4b6f2f1230618db0821c92a71f9904b 100644 (file)
@@ -1,17 +1,17 @@
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `true`
-  --> $DIR/raw-literal-keywords.rs:16:10
+  --> $DIR/raw-literal-keywords.rs:14:10
    |
 LL |     r#if true { } //~ ERROR found `true`
    |          ^^^^ expected one of 8 possible tokens here
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test`
-  --> $DIR/raw-literal-keywords.rs:20:14
+  --> $DIR/raw-literal-keywords.rs:18:14
    |
 LL |     r#struct Test; //~ ERROR found `Test`
    |              ^^^^ expected one of 8 possible tokens here
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test`
-  --> $DIR/raw-literal-keywords.rs:24:13
+  --> $DIR/raw-literal-keywords.rs:22:13
    |
 LL |     r#union Test; //~ ERROR found `Test`
    |             ^^^^ expected one of 8 possible tokens here
index f88d6cf9a67bd635df468f0697e9f965dba7cce5..17496d767b6226b95b56c0590d0f7f2e8bc82cf7 100644 (file)
@@ -10,8 +10,6 @@
 
 // compile-flags: -Z parse-only
 
-#![feature(raw_identifiers)]
-
 fn self_test(r#self: u32) {
     //~^ ERROR `r#self` is not currently supported.
 }
index e3345847aa895367624496deb0981c21de063e1f..f4b759372471cdb79dfd34fe990d3e4f3bc22298 100644 (file)
@@ -1,5 +1,5 @@
 error: `r#self` is not currently supported.
-  --> $DIR/raw-literal-self.rs:15:14
+  --> $DIR/raw-literal-self.rs:13:14
    |
 LL | fn self_test(r#self: u32) {
    |              ^^^^^^
index 8338cf6a6069c5e79dc49298735e0600a68b236b..f0def1888b9cdcfc8bcf870966d530aa44bfd382 100644 (file)
@@ -31,43 +31,31 @@ LL |     let x: Box<Foo + 'static> = Box::new(v);
    |                                 ^^^^^^^^^^^ lifetime `'static` required
 
 error[E0621]: explicit lifetime required in the type of `v`
-  --> $DIR/region-object-lifetime-in-coercion.rs:23:38
+  --> $DIR/region-object-lifetime-in-coercion.rs:24:5
    |
-LL |   fn b(v: &[u8]) -> Box<Foo + 'static> {
-   |  _________-----________________________^
-   | |         |
-   | |         help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
-LL | |     Box::new(v)
-LL | |         //~^ ERROR explicit lifetime required in the type of `v` [E0621]
-LL | | }
-   | |_^ lifetime `'static` required
+LL | fn b(v: &[u8]) -> Box<Foo + 'static> {
+   |         ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+LL |     Box::new(v)
+   |     ^^^^^^^^^^^ lifetime `'static` required
 
 error[E0621]: explicit lifetime required in the type of `v`
-  --> $DIR/region-object-lifetime-in-coercion.rs:28:28
+  --> $DIR/region-object-lifetime-in-coercion.rs:31:5
    |
-LL |   fn c(v: &[u8]) -> Box<Foo> {
-   |  _________-----______________^
-   | |         |
-   | |         help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
-LL | |     // same as previous case due to RFC 599
-LL | |
-LL | |     Box::new(v)
-LL | |         //~^ ERROR explicit lifetime required in the type of `v` [E0621]
-LL | | }
-   | |_^ lifetime `'static` required
+LL | fn c(v: &[u8]) -> Box<Foo> {
+   |         ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+...
+LL |     Box::new(v)
+   |     ^^^^^^^^^^^ lifetime `'static` required
 
 error: unsatisfied lifetime constraints
-  --> $DIR/region-object-lifetime-in-coercion.rs:35:41
+  --> $DIR/region-object-lifetime-in-coercion.rs:36:5
    |
-LL |   fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
-   |  ______--_--______________________________^
-   | |      |  |
-   | |      |  lifetime `'b` defined here
-   | |      lifetime `'a` defined here
-LL | |     Box::new(v)
-LL | |         //~^ ERROR cannot infer an appropriate lifetime due to conflicting
-LL | | }
-   | |_^ returning this value requires that `'a` must outlive `'b`
+LL | fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
+   |      -- -- lifetime `'b` defined here
+   |      |
+   |      lifetime `'a` defined here
+LL |     Box::new(v)
+   |     ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b`
 
 error: aborting due to 4 previous errors
 
index 701becc24d7184ebb9bb67d4725fcc9199807687..85724cfabd814f8ddf0afcb5764b65c0b9118825 100644 (file)
@@ -5,15 +5,12 @@ LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
    |           ^^^
 
 error: unsatisfied lifetime constraints
-  --> $DIR/regions-close-object-into-object-2.rs:19:57
+  --> $DIR/regions-close-object-into-object-2.rs:20:5
    |
-LL |   fn g<'a, T: 'static>(v: Box<A<T>+'a>) -> Box<X+'static> {
-   |  ______--_________________________________________________^
-   | |      |
-   | |      lifetime `'a` defined here
-LL | |     box B(&*v) as Box<X> //~ ERROR cannot infer
-LL | | }
-   | |_^ returning this value requires that `'a` must outlive `'static`
+LL | fn g<'a, T: 'static>(v: Box<A<T>+'a>) -> Box<X+'static> {
+   |      -- lifetime `'a` defined here
+LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
+   |     ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
 
 error[E0597]: `*v` does not live long enough
   --> $DIR/regions-close-object-into-object-2.rs:20:11
index e01ae145e90d92977fffd26c1f754f7c6132db51..3dc8df3608f06a108d163e056aea13c026cc3862 100644 (file)
@@ -28,17 +28,6 @@ warning: not reporting region error due to nll
 LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
    |     ^^^^^^^^^^
 
-error: unsatisfied lifetime constraints
-  --> $DIR/regions-close-object-into-object-4.rs:19:51
-   |
-LL |   fn i<'a, T, U>(v: Box<A<U>+'a>) -> Box<X+'static> {
-   |  ______--___________________________________________^
-   | |      |
-   | |      lifetime `'a` defined here
-LL | |     box B(&*v) as Box<X> //~ ERROR cannot infer
-LL | | }
-   | |_^ returning this value requires that `'a` must outlive `'static`
-
 error[E0310]: the parameter type `U` may not live long enough
   --> $DIR/regions-close-object-into-object-4.rs:20:5
    |
@@ -47,6 +36,14 @@ LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
    |
    = help: consider adding an explicit lifetime bound `U: 'static`...
 
+error: unsatisfied lifetime constraints
+  --> $DIR/regions-close-object-into-object-4.rs:20:5
+   |
+LL | fn i<'a, T, U>(v: Box<A<U>+'a>) -> Box<X+'static> {
+   |      -- lifetime `'a` defined here
+LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
+   |     ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
 error[E0310]: the parameter type `U` may not live long enough
   --> $DIR/regions-close-object-into-object-4.rs:20:9
    |
index 00728aa4783d4f4a25aaaa907d13825faac8ed23..f19feed175272661108e4a5a0b7bb1a2a2967062 100644 (file)
@@ -5,16 +5,13 @@ LL |     Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the typ
    |              ^^^^^^^^^^^^^
 
 error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/regions-proc-bound-capture.rs:17:62
+  --> $DIR/regions-proc-bound-capture.rs:19:5
    |
-LL |   fn static_proc(x: &isize) -> Box<FnMut()->(isize) + 'static> {
-   |  ___________________------_____________________________________^
-   | |                   |
-   | |                   help: add explicit lifetime `'static` to the type of `x`: `&'static isize`
-LL | |     // This is illegal, because the region bound on `proc` is 'static.
-LL | |     Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the type of `x` [E0621]
-LL | | }
-   | |_^ lifetime `'static` required
+LL | fn static_proc(x: &isize) -> Box<FnMut()->(isize) + 'static> {
+   |                   ------ help: add explicit lifetime `'static` to the type of `x`: `&'static isize`
+LL |     // This is illegal, because the region bound on `proc` is 'static.
+LL |     Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the type of `x` [E0621]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
 
 error: aborting due to previous error
 
index 37454ff78a126d10c071024ef175d2c64178fcd6..89575ca9bc809097171f44e5f56fb55826b0497b 100644 (file)
@@ -5,16 +5,14 @@ LL |     &mut ***p //~ ERROR 14:5: 14:14: lifetime mismatch [E0623]
    |     ^^^^^^^^^
 
 error: unsatisfied lifetime constraints
-  --> $DIR/regions-reborrow-from-shorter-mut-ref-mut-ref.rs:13:85
+  --> $DIR/regions-reborrow-from-shorter-mut-ref-mut-ref.rs:14:5
    |
-LL |   fn copy_borrowed_ptr<'a, 'b, 'c>(p: &'a mut &'b mut &'c mut isize) -> &'b mut isize {
-   |  ______________________--__--_________________________________________________________^
-   | |                      |   |
-   | |                      |   lifetime `'b` defined here
-   | |                      lifetime `'a` defined here
-LL | |     &mut ***p //~ ERROR 14:5: 14:14: lifetime mismatch [E0623]
-LL | | }
-   | |_^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+LL | fn copy_borrowed_ptr<'a, 'b, 'c>(p: &'a mut &'b mut &'c mut isize) -> &'b mut isize {
+   |                      --  -- lifetime `'b` defined here
+   |                      |
+   |                      lifetime `'a` defined here
+LL |     &mut ***p //~ ERROR 14:5: 14:14: lifetime mismatch [E0623]
+   |     ^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
 
 error: aborting due to previous error
 
index 455ee6f794936ffda9e812e35ae6d1ab1ace2966..9c57813f26be6a67069a93c669bb70bada1c8283 100644 (file)
@@ -5,16 +5,14 @@ LL |     &mut **p //~ ERROR 16:5: 16:13: lifetime mismatch [E0623]
    |     ^^^^^^^^
 
 error: unsatisfied lifetime constraints
-  --> $DIR/regions-reborrow-from-shorter-mut-ref.rs:15:73
+  --> $DIR/regions-reborrow-from-shorter-mut-ref.rs:16:5
    |
-LL |   fn copy_borrowed_ptr<'a, 'b>(p: &'a mut &'b mut isize) -> &'b mut isize {
-   |  ______________________--__--_____________________________________________^
-   | |                      |   |
-   | |                      |   lifetime `'b` defined here
-   | |                      lifetime `'a` defined here
-LL | |     &mut **p //~ ERROR 16:5: 16:13: lifetime mismatch [E0623]
-LL | | }
-   | |_^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+LL | fn copy_borrowed_ptr<'a, 'b>(p: &'a mut &'b mut isize) -> &'b mut isize {
+   |                      --  -- lifetime `'b` defined here
+   |                      |
+   |                      lifetime `'a` defined here
+LL |     &mut **p //~ ERROR 16:5: 16:13: lifetime mismatch [E0623]
+   |     ^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
 
 error: aborting due to previous error
 
index 99bee4a36c1d1c5dfcd13137dd0fb4935d8d8a3f..01db25a07f76e6bf7634411ef83ac37490005f27 100644 (file)
@@ -11,18 +11,15 @@ LL |     x //~ ERROR mismatched types
    |     ^
 
 error: unsatisfied lifetime constraints
-  --> $DIR/regions-trait-object-subtyping.rs:23:51
+  --> $DIR/regions-trait-object-subtyping.rs:25:5
    |
-LL |   fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
-   |  _________--_--_____________________________________^
-   | |         |  |
-   | |         |  lifetime `'b` defined here
-   | |         lifetime `'a` defined here
-LL | |     // Without knowing 'a:'b, we can't coerce
-LL | |     x //~ ERROR lifetime bound not satisfied
-LL | |      //~^ ERROR cannot infer an appropriate lifetime
-LL | | }
-   | |_^ returning this value requires that `'a` must outlive `'b`
+LL | fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
+   |         -- -- lifetime `'b` defined here
+   |         |
+   |         lifetime `'a` defined here
+LL |     // Without knowing 'a:'b, we can't coerce
+LL |     x //~ ERROR lifetime bound not satisfied
+   |     ^ returning this value requires that `'a` must outlive `'b`
 
 error: unsatisfied lifetime constraints
   --> $DIR/regions-trait-object-subtyping.rs:32:5
index 685d62dc3a9c836ca9ff97b3d997def2715dc910..be6f3cf9eb205e96af215e105084299595dc8019 100644 (file)
@@ -36,3 +36,5 @@ fn cant_repr_this() {}
 
 #[repr(transparent)] //~ ERROR should be applied to struct
 static CANT_REPR_THIS: u32 = 0;
+
+fn main() {}
index e5889cf53e58ab2a638bc91ec9ac2856d02705ad..5a1978991480e62041e155fc916f556063301710 100644 (file)
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `repr_transparent_other_items`
-   |
-   = note: consider adding a `main` function to `$DIR/repr-transparent-other-items.rs`
-
 error[E0517]: attribute should be applied to struct
   --> $DIR/repr-transparent-other-items.rs:13:8
    |
@@ -67,7 +63,7 @@ LL | #[repr(transparent)] //~ ERROR unsupported representation for zero-variant
 LL | enum Void {}         //~| ERROR should be applied to struct
    | ------------ zero-variant enum
 
-error: aborting due to 8 previous errors
+error: aborting due to 7 previous errors
 
-Some errors occurred: E0084, E0517, E0601.
+Some errors occurred: E0084, E0517.
 For more information about an error, try `rustc --explain E0084`.
index a391c0ae1f82ef5c29deaf083ca82c0a00a517a1..aed8a69f66ef81e6518799a3fa58b31fdcfd1a12 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(repr_align, attr_literals)]
+#![feature(repr_align)]
 
 // See also repr-transparent.rs
 
@@ -26,3 +26,5 @@ struct TransparentPlusC {
 #[repr(transparent)] //~ ERROR cannot have other repr
 #[repr(C)]
 struct SeparateAttributes(*mut u8);
+
+fn main() {}
index 40f41c474dbdaa328656c2a138c87e74bc120ba4..c8f5dea3c1242e60b1d5cd4193ea089d8d954239 100644 (file)
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `repr_transparent_other_reprs`
-   |
-   = note: consider adding a `main` function to `$DIR/repr-transparent-other-reprs.rs`
-
 error[E0692]: transparent struct cannot have other repr hints
   --> $DIR/repr-transparent-other-reprs.rs:15:8
    |
@@ -28,7 +24,6 @@ LL | #[repr(transparent)] //~ ERROR cannot have other repr
 LL | #[repr(C)]
    |        ^
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors occurred: E0601, E0692.
-For more information about an error, try `rustc --explain E0601`.
+For more information about this error, try `rustc --explain E0692`.
index 4d8ec4cdb407c6ff1b17ce82901f47624563b2f1..f5b99af156ee0567d3c7547aba9a143f21ba0f00 100644 (file)
@@ -13,7 +13,7 @@
 // - repr-transparent-other-reprs.rs
 // - repr-transparent-other-items.rs
 
-#![feature(repr_align, attr_literals)]
+#![feature(repr_align)]
 
 use std::marker::PhantomData;
 
@@ -48,3 +48,5 @@
 
 #[repr(transparent)]
 struct GenericAlign<T>(ZstAlign32<T>, u32); //~ ERROR alignment larger than 1
+
+fn main() {}
index 0f620880fa9d32a18f6ef90d1d0bfcb75c1c6216..f7bfdbdc625bbd70e4db39276416365adec948a8 100644 (file)
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `repr_transparent`
-   |
-   = note: consider adding a `main` function to `$DIR/repr-transparent.rs`
-
 error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
   --> $DIR/repr-transparent.rs:21:1
    |
@@ -70,7 +66,7 @@ error[E0691]: zero-sized field in transparent struct has alignment larger than 1
 LL | struct GenericAlign<T>(ZstAlign32<T>, u32); //~ ERROR alignment larger than 1
    |                        ^^^^^^^^^^^^^
 
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
-Some errors occurred: E0601, E0690, E0691.
-For more information about an error, try `rustc --explain E0601`.
+Some errors occurred: E0690, E0691.
+For more information about an error, try `rustc --explain E0690`.
index e8bfcc04f48b912c3c184326173b58b899706e62..efcd1ec67d7e9491a5d88a53edee7a984bfd8bab 100644 (file)
@@ -1,8 +1,8 @@
 error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
-  --> $DIR/reserved-attr-on-macro.rs:11:1
+  --> $DIR/reserved-attr-on-macro.rs:11:3
    |
 LL | #[rustc_attribute_should_be_reserved] //~ ERROR attributes with the prefix `rustc_` are reserved
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(rustc_attrs)] to the crate attributes to enable
 
index 9432e727fa5b7f1d1bade9a267babdd4a47b6b59..05bf4b928b7251abc421ec09afb31e8bc3a0c8a0 100644 (file)
@@ -17,3 +17,5 @@ impl SomeNonExistentTrait for isize {}
 
 fn f<T:SomeNonExistentTrait>() {}
 //~^ ERROR cannot find trait `SomeNonExistentTrait` in this scope
+
+fn main() {}
index 8a2d791654d2f58c5d1be6be5f28d6aa1ff3f342..74b190f86845fcd23369cd7c83a970efc03b4d7a 100644 (file)
@@ -16,11 +16,6 @@ error[E0405]: cannot find trait `SomeNonExistentTrait` in this scope
 LL | fn f<T:SomeNonExistentTrait>() {}
    |        ^^^^^^^^^^^^^^^^^^^^ not found in this scope
 
-error[E0601]: `main` function not found in crate `resolve_unknown_trait`
-   |
-   = note: consider adding a `main` function to `$DIR/resolve-unknown-trait.rs`
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors occurred: E0405, E0601.
-For more information about an error, try `rustc --explain E0405`.
+For more information about this error, try `rustc --explain E0405`.
index a89fd802baf0c11f936c9672da05c4be557ad6b3..c5dd367c0ab88e21fd4f25e87b51e9869d207a93 100644 (file)
@@ -32,3 +32,5 @@ mod d {
         }
     }
 }
+
+fn main() {}
index 8538da06baf64aac433b9114edd67de346d49682..40b2a4bf9684254a705c763c258e139b15200124 100644 (file)
@@ -22,11 +22,6 @@ error[E0432]: unresolved import `alloc`
 LL |                 use alloc::HashMap;
    |                     ^^^^^ Did you mean `a::alloc`?
 
-error[E0601]: `main` function not found in crate `resolve_self_super_hint`
-   |
-   = note: consider adding a `main` function to `$DIR/resolve_self_super_hint.rs`
-
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors occurred: E0432, E0601.
-For more information about an error, try `rustc --explain E0432`.
+For more information about this error, try `rustc --explain E0432`.
index 89771be7bc84f12a2277aad3660ea30a13fdf2fd..104bd9e166c791318a07ac847a553c6ce975b12f 100644 (file)
@@ -30,7 +30,7 @@ impl Tr2 for ::S {}
 mod unused {
     use m::Tr1 as _; //~ WARN unused import
     use S as _; //~ WARN unused import
-    extern crate core as _; //~ WARN unused extern crate
+    extern crate core as _; // OK
 }
 
 mod outer {
index c12c74b50e26402bbb54b2e5042dd19337073160..2be0317019d3c0c558d90b96322fcec02df15487 100644 (file)
@@ -16,15 +16,3 @@ warning: unused import: `S as _`
 LL |     use S as _; //~ WARN unused import
    |         ^^^^^^
 
-warning: unused extern crate
-  --> $DIR/basic.rs:33:5
-   |
-LL |     extern crate core as _; //~ WARN unused extern crate
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
-   |
-note: lint level defined here
-  --> $DIR/basic.rs:14:25
-   |
-LL | #![warn(unused_imports, unused_extern_crates)]
-   |                         ^^^^^^^^^^^^^^^^^^^^
-
index 6cdcaf256839431ea1f8e27e9319b996748fb845..ddc6a29a8f0bdd33bc08a9b2ed75fa539c04b3ce 100644 (file)
@@ -11,7 +11,7 @@
 #![feature(generic_associated_types)]
 
 //FIXME(#44265): The lifetime shadowing and type parameter shadowing
-// should cause an error. Now it compiles (errorneously) and this will be addressed
+// should cause an error. Now it compiles (erroneously) and this will be addressed
 // by a future PR. Then remove the following:
 // compile-pass
 
index 3bc468483bda2a1487ceeff1cd3119864fb4f761..9a046bc6952b39157b306e08ea70fdf884e2e427 100644 (file)
@@ -12,7 +12,7 @@
 
 #![deny(rust_2018_compatibility)]
 
-// Don't make a suggestion for a raw identifer replacement unless raw
+// Don't make a suggestion for a raw identifier replacement unless raw
 // identifiers are enabled.
 
 fn main() {
index 1644102cdca1acb815834a7304fe513a37194577..68d7930e0434af4eb2cfbcabd0f1ff39cae27469 100644 (file)
@@ -2,14 +2,14 @@ error: `async` is a keyword in the 2018 edition
   --> $DIR/async-ident-allowed.rs:19:9
    |
 LL |     let async = 3; //~ ERROR: is a keyword
-   |         ^^^^^
+   |         ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
 note: lint level defined here
   --> $DIR/async-ident-allowed.rs:13:9
    |
 LL | #![deny(rust_2018_compatibility)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^
-   = note: #[deny(async_idents)] implied by #[deny(rust_2018_compatibility)]
+   = note: #[deny(keyword_idents)] implied by #[deny(rust_2018_compatibility)]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
index 228bf911253373276201bb1ea56240ef44b90135..ef88f835fc83d1fc454d2903c81fc39b1fde44ab 100644 (file)
@@ -8,9 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(raw_identifiers)]
 #![allow(dead_code, unused_variables, non_camel_case_types, non_upper_case_globals)]
-#![deny(async_idents)]
+#![deny(keyword_idents)]
 
 // edition:2015
 // run-rustfix
index cc400c2a92e0e44d8925e5f3e6ca3cd5683299cf..069da7ffcdd4dd4ecd8f594d0994d7dcf7182ff6 100644 (file)
@@ -8,9 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(raw_identifiers)]
 #![allow(dead_code, unused_variables, non_camel_case_types, non_upper_case_globals)]
-#![deny(async_idents)]
+#![deny(keyword_idents)]
 
 // edition:2015
 // run-rustfix
index 94fd3e70434cbbd47225b813f31f3e9a6ee98a17..b9bb2e254b44e0fa008efd0e3325382156aa91bf 100644 (file)
@@ -1,19 +1,19 @@
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:18:4
+  --> $DIR/async-ident.rs:17:4
    |
 LL | fn async() {} //~ ERROR async
    |    ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
    |
 note: lint level defined here
-  --> $DIR/async-ident.rs:13:9
+  --> $DIR/async-ident.rs:12:9
    |
-LL | #![deny(async_idents)]
-   |         ^^^^^^^^^^^^
+LL | #![deny(keyword_idents)]
+   |         ^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:23:7
+  --> $DIR/async-ident.rs:22:7
    |
 LL |     ($async:expr, async) => {};
    |       ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -22,7 +22,7 @@ LL |     ($async:expr, async) => {};
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:23:19
+  --> $DIR/async-ident.rs:22:19
    |
 LL |     ($async:expr, async) => {};
    |                   ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -31,7 +31,7 @@ LL |     ($async:expr, async) => {};
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:37:11
+  --> $DIR/async-ident.rs:36:11
    |
 LL |     trait async {}
    |           ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -40,7 +40,7 @@ LL |     trait async {}
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:41:10
+  --> $DIR/async-ident.rs:40:10
    |
 LL |     impl async for MyStruct {}
    |          ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -49,7 +49,7 @@ LL |     impl async for MyStruct {}
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:47:12
+  --> $DIR/async-ident.rs:46:12
    |
 LL |     static async: u32 = 0;
    |            ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -58,7 +58,7 @@ LL |     static async: u32 = 0;
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:53:11
+  --> $DIR/async-ident.rs:52:11
    |
 LL |     const async: u32 = 0;
    |           ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -67,7 +67,7 @@ LL |     const async: u32 = 0;
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:59:15
+  --> $DIR/async-ident.rs:58:15
    |
 LL | impl Foo { fn async() {} }
    |               ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -76,7 +76,7 @@ LL | impl Foo { fn async() {} }
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:64:12
+  --> $DIR/async-ident.rs:63:12
    |
 LL |     struct async {}
    |            ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -85,7 +85,7 @@ LL |     struct async {}
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:67:9
+  --> $DIR/async-ident.rs:66:9
    |
 LL |     let async: async = async {};
    |         ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -94,7 +94,7 @@ LL |     let async: async = async {};
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:67:16
+  --> $DIR/async-ident.rs:66:16
    |
 LL |     let async: async = async {};
    |                ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -103,7 +103,7 @@ LL |     let async: async = async {};
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:67:24
+  --> $DIR/async-ident.rs:66:24
    |
 LL |     let async: async = async {};
    |                        ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -112,7 +112,7 @@ LL |     let async: async = async {};
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:78:19
+  --> $DIR/async-ident.rs:77:19
    |
 LL |     () => (pub fn async() {})
    |                   ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -121,7 +121,7 @@ LL |     () => (pub fn async() {})
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:85:6
+  --> $DIR/async-ident.rs:84:6
    |
 LL |     (async) => (1)
    |      ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
diff --git a/src/test/ui/rust-2018/auxiliary/remove-extern-crate.rs b/src/test/ui/rust-2018/auxiliary/remove-extern-crate.rs
new file mode 100644 (file)
index 0000000..9daaca1
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_export]
+macro_rules! foo {
+    () => ()
+}
+
+#[macro_export]
+macro_rules! bar {
+    () => ()
+}
diff --git a/src/test/ui/rust-2018/remove-extern-crate.fixed b/src/test/ui/rust-2018/remove-extern-crate.fixed
new file mode 100644 (file)
index 0000000..995be42
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-rustfix
+// edition:2018
+// compile-pass
+// aux-build:remove-extern-crate.rs
+
+#![warn(rust_2018_idioms)]
+
+
+use core as another_name;
+use remove_extern_crate;
+#[macro_use]
+extern crate remove_extern_crate as something_else;
+
+fn main() {
+    another_name::mem::drop(3);
+    another::foo();
+    remove_extern_crate::foo!();
+    bar!();
+}
+
+mod another {
+    use core;
+    use remove_extern_crate;
+
+    pub fn foo() {
+        core::mem::drop(4);
+        remove_extern_crate::foo!();
+    }
+}
diff --git a/src/test/ui/rust-2018/remove-extern-crate.rs b/src/test/ui/rust-2018/remove-extern-crate.rs
new file mode 100644 (file)
index 0000000..3ab97a7
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-rustfix
+// edition:2018
+// compile-pass
+// aux-build:remove-extern-crate.rs
+
+#![warn(rust_2018_idioms)]
+
+extern crate core;
+extern crate core as another_name;
+use remove_extern_crate;
+#[macro_use]
+extern crate remove_extern_crate as something_else;
+
+fn main() {
+    another_name::mem::drop(3);
+    another::foo();
+    remove_extern_crate::foo!();
+    bar!();
+}
+
+mod another {
+    extern crate core;
+    use remove_extern_crate;
+
+    pub fn foo() {
+        core::mem::drop(4);
+        remove_extern_crate::foo!();
+    }
+}
diff --git a/src/test/ui/rust-2018/remove-extern-crate.stderr b/src/test/ui/rust-2018/remove-extern-crate.stderr
new file mode 100644 (file)
index 0000000..752a7b1
--- /dev/null
@@ -0,0 +1,25 @@
+warning: unused extern crate
+  --> $DIR/remove-extern-crate.rs:18:1
+   |
+LL | extern crate core;
+   | ^^^^^^^^^^^^^^^^^^ help: remove it
+   |
+note: lint level defined here
+  --> $DIR/remove-extern-crate.rs:16:9
+   |
+LL | #![warn(rust_2018_idioms)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: #[warn(unused_extern_crates)] implied by #[warn(rust_2018_idioms)]
+
+warning: `extern crate` is not idiomatic in the new edition
+  --> $DIR/remove-extern-crate.rs:19:1
+   |
+LL | extern crate core as another_name;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+
+warning: `extern crate` is not idiomatic in the new edition
+  --> $DIR/remove-extern-crate.rs:32:5
+   |
+LL |     extern crate core;
+   |     ^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+
diff --git a/src/test/ui/rust-2018/try-ident.fixed b/src/test/ui/rust-2018/try-ident.fixed
new file mode 100644 (file)
index 0000000..96a0cd0
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-rustfix
+// compile-pass
+
+#![warn(rust_2018_compatibility)]
+
+fn main() {
+    r#try();
+}
+
+fn r#try() {
+}
diff --git a/src/test/ui/rust-2018/try-ident.rs b/src/test/ui/rust-2018/try-ident.rs
new file mode 100644 (file)
index 0000000..ade2e03
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-rustfix
+// compile-pass
+
+#![warn(rust_2018_compatibility)]
+
+fn main() {
+    try();
+}
+
+fn try() {
+}
diff --git a/src/test/ui/rust-2018/try-ident.stderr b/src/test/ui/rust-2018/try-ident.stderr
new file mode 100644 (file)
index 0000000..72bd815
--- /dev/null
@@ -0,0 +1,24 @@
+warning: `try` is a keyword in the 2018 edition
+  --> $DIR/try-ident.rs:17:5
+   |
+LL |     try();
+   |     ^^^ help: you can use a raw identifier to stay compatible: `r#try`
+   |
+note: lint level defined here
+  --> $DIR/try-ident.rs:14:9
+   |
+LL | #![warn(rust_2018_compatibility)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: #[warn(keyword_idents)] implied by #[warn(rust_2018_compatibility)]
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+warning: `try` is a keyword in the 2018 edition
+  --> $DIR/try-ident.rs:20:4
+   |
+LL | fn try() {
+   |    ^^^ help: you can use a raw identifier to stay compatible: `r#try`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
index aac9299eaafb9d91b256f4cd33363daf8173510d..35b43b4c460a428165b4613d94001a227185eb8f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(attr_literals, rustc_attrs, const_fn)]
+#![feature(rustc_attrs, const_fn)]
 
 #[rustc_args_required_const(0)]
 fn foo(_a: i32) {
index aa63019307b5b0ff920d1e22bd53cd6eeb57106b..c4ca5a0ca5c5d68afecb3f66c2f75cedcfb7c915 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(attr_literals, rustc_attrs, const_fn)]
+#![feature(rustc_attrs, const_fn)]
 
 #[rustc_args_required_const(0)]
 fn foo(_a: i32) {
index 068f08eebe76cc8a1dc116135e7b9350886b1651..6ef9f5de4ebcdcc569811fa598c811abeef05e50 100644 (file)
@@ -1,10 +1,10 @@
-error[E0244]: wrong number of type arguments: expected 0, found 1
+error[E0107]: wrong number of type arguments: expected 0, found 1
   --> $DIR/seq-args.rs:14:13
    |
 LL | impl<T> seq<T> for Vec<T> { //~ ERROR wrong number of type arguments
    |             ^ unexpected type argument
 
-error[E0244]: wrong number of type arguments: expected 0, found 1
+error[E0107]: wrong number of type arguments: expected 0, found 1
   --> $DIR/seq-args.rs:17:10
    |
 LL | impl seq<bool> for u32 { //~ ERROR wrong number of type arguments
@@ -12,4 +12,4 @@ LL | impl seq<bool> for u32 { //~ ERROR wrong number of type arguments
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0244`.
+For more information about this error, try `rustc --explain E0107`.
index 4706b9cbb092c21fa3323368b22a429484316cb6..81adf89fd4330a46df5eba03d52fcc0edcc6e4e1 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // Test that we DO NOT warn when lifetime name is used multiple
-// argments, or more than once in a single argument.
+// arguments, or more than once in a single argument.
 //
 // compile-pass
 
index cbec4f6b0a63bd6ee3c32a2ceea8e87a85f34aab..e7dd8e7aa8fa073c1510131cb506e1b48a54624d 100644 (file)
@@ -1,16 +1,16 @@
 error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/issue-36530.rs:11:1
+  --> $DIR/issue-36530.rs:11:3
    |
 LL | #[foo] //~ ERROR is currently unknown to the compiler
-   | ^^^^^^
+   |   ^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/issue-36530.rs:13:5
+  --> $DIR/issue-36530.rs:13:8
    |
 LL |     #![foo] //~ ERROR is currently unknown to the compiler
-   |     ^^^^^^^
+   |        ^^^
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
index f522521b400e405faec70ce4842488266a36b494..f8e5e3914eb3cc2fcb64216e89a2be526ce97eae 100644 (file)
@@ -1,17 +1,12 @@
 error[E0597]: `tmp0` does not live long enough
   --> $DIR/regions-close-over-type-parameter-2.rs:33:20
    |
-LL |       let _ = {
-   |  _____________-
-LL | |         let tmp0 = 3;
-LL | |         let tmp1 = &tmp0;
-   | |                    ^^^^^ borrowed value does not live long enough
-LL | |         repeater3(tmp1)
-LL | |     };
-   | |     -
-   | |     |
-   | |_____`tmp0` dropped here while still borrowed
-   |       borrow later used here
+LL |         let tmp1 = &tmp0;
+   |                    ^^^^^ borrowed value does not live long enough
+LL |         repeater3(tmp1)
+   |         --------------- borrow later used here
+LL |     };
+   |     - `tmp0` dropped here while still borrowed
 
 error: aborting due to previous error
 
index 26b8b737f340d7a7e418adef7853977a0e8cf442..068eb7a448556cc02d3e639cb14dbcb3b1993c36 100644 (file)
@@ -21,3 +21,5 @@
 
 trait Tr {}
 default impl !Tr for S {} //~ ERROR negative impls are only allowed for auto traits
+
+fn main() {}
index 54b92da7b2192c53f6732e6db320f6d608e35233..c25c428eb4e9403d9a3138cdbd1b86577150cdc7 100644 (file)
@@ -6,10 +6,6 @@ LL | default impl S {} //~ ERROR inherent impls cannot be default
    |
    = note: only trait implementations may be annotated with default
 
-error[E0601]: `main` function not found in crate `validation`
-   |
-   = note: consider adding a `main` function to `$DIR/validation.rs`
-
 error: impls of auto traits cannot be default
   --> $DIR/validation.rs:19:1
    |
@@ -28,7 +24,6 @@ error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and
 LL | default impl !Tr for S {} //~ ERROR negative impls are only allowed for auto traits
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors occurred: E0192, E0601.
-For more information about an error, try `rustc --explain E0192`.
+For more information about this error, try `rustc --explain E0192`.
index dfa219e0872ce89fbfe4181ea76b7e726547b629..97a64bf3b55d4ddd45aa2d84795b0209a54f06ed 100644 (file)
@@ -70,7 +70,7 @@ LL |         x: 7,
    = note: expected type `f32`
               found type `{integer}`
 
-error[E0244]: wrong number of type arguments: expected 0, found 1
+error[E0107]: wrong number of type arguments: expected 0, found 1
   --> $DIR/structure-constructor-type-mismatch.rs:58:24
    |
 LL |     let pt3 = PointF::<i32> { //~ ERROR wrong number of type arguments
@@ -100,7 +100,7 @@ LL |         y: 10, //~ ERROR mismatched types
    = note: expected type `f32`
               found type `{integer}`
 
-error[E0244]: wrong number of type arguments: expected 0, found 1
+error[E0107]: wrong number of type arguments: expected 0, found 1
   --> $DIR/structure-constructor-type-mismatch.rs:64:18
    |
 LL |         PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments
@@ -135,5 +135,5 @@ LL |         PairF::<u32> { .. } => {} //~ ERROR mismatched types
 
 error: aborting due to 13 previous errors
 
-Some errors occurred: E0244, E0308.
-For more information about an error, try `rustc --explain E0244`.
+Some errors occurred: E0107, E0308.
+For more information about an error, try `rustc --explain E0107`.
index bf55b7bdcb1def55da516ae84240abe19d0b3876..2e6c3994159cf82864ccd95925d35ecdf13777f4 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(attr_literals)]
-
 #[path = 1usize] //~ ERROR: suffixed literals are not allowed in attributes
 #[path = 1u8] //~ ERROR: suffixed literals are not allowed in attributes
 #[path = 1u16] //~ ERROR: suffixed literals are not allowed in attributes
index 6d88ab1df16b47de6c0d8825ae46a57550eb3430..53ff60b0705e16ccefff7dd2d3f6809cb9f3722a 100644 (file)
@@ -1,5 +1,5 @@
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:13:10
+  --> $DIR/suffixed-literal-meta.rs:11:10
    |
 LL | #[path = 1usize] //~ ERROR: suffixed literals are not allowed in attributes
    |          ^^^^^^
@@ -7,7 +7,7 @@ LL | #[path = 1usize] //~ ERROR: suffixed literals are not allowed in attributes
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:14:10
+  --> $DIR/suffixed-literal-meta.rs:12:10
    |
 LL | #[path = 1u8] //~ ERROR: suffixed literals are not allowed in attributes
    |          ^^^
@@ -15,7 +15,7 @@ LL | #[path = 1u8] //~ ERROR: suffixed literals are not allowed in attributes
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:15:10
+  --> $DIR/suffixed-literal-meta.rs:13:10
    |
 LL | #[path = 1u16] //~ ERROR: suffixed literals are not allowed in attributes
    |          ^^^^
@@ -23,7 +23,7 @@ LL | #[path = 1u16] //~ ERROR: suffixed literals are not allowed in attributes
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:16:10
+  --> $DIR/suffixed-literal-meta.rs:14:10
    |
 LL | #[path = 1u32] //~ ERROR: suffixed literals are not allowed in attributes
    |          ^^^^
@@ -31,7 +31,7 @@ LL | #[path = 1u32] //~ ERROR: suffixed literals are not allowed in attributes
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:17:10
+  --> $DIR/suffixed-literal-meta.rs:15:10
    |
 LL | #[path = 1u64] //~ ERROR: suffixed literals are not allowed in attributes
    |          ^^^^
@@ -39,7 +39,7 @@ LL | #[path = 1u64] //~ ERROR: suffixed literals are not allowed in attributes
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:18:10
+  --> $DIR/suffixed-literal-meta.rs:16:10
    |
 LL | #[path = 1isize] //~ ERROR: suffixed literals are not allowed in attributes
    |          ^^^^^^
@@ -47,7 +47,7 @@ LL | #[path = 1isize] //~ ERROR: suffixed literals are not allowed in attributes
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:19:10
+  --> $DIR/suffixed-literal-meta.rs:17:10
    |
 LL | #[path = 1i8] //~ ERROR: suffixed literals are not allowed in attributes
    |          ^^^
@@ -55,7 +55,7 @@ LL | #[path = 1i8] //~ ERROR: suffixed literals are not allowed in attributes
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:20:10
+  --> $DIR/suffixed-literal-meta.rs:18:10
    |
 LL | #[path = 1i16] //~ ERROR: suffixed literals are not allowed in attributes
    |          ^^^^
@@ -63,7 +63,7 @@ LL | #[path = 1i16] //~ ERROR: suffixed literals are not allowed in attributes
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:21:10
+  --> $DIR/suffixed-literal-meta.rs:19:10
    |
 LL | #[path = 1i32] //~ ERROR: suffixed literals are not allowed in attributes
    |          ^^^^
@@ -71,7 +71,7 @@ LL | #[path = 1i32] //~ ERROR: suffixed literals are not allowed in attributes
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:22:10
+  --> $DIR/suffixed-literal-meta.rs:20:10
    |
 LL | #[path = 1i64] //~ ERROR: suffixed literals are not allowed in attributes
    |          ^^^^
@@ -79,7 +79,7 @@ LL | #[path = 1i64] //~ ERROR: suffixed literals are not allowed in attributes
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:23:10
+  --> $DIR/suffixed-literal-meta.rs:21:10
    |
 LL | #[path = 1.0f32] //~ ERROR: suffixed literals are not allowed in attributes
    |          ^^^^^^
@@ -87,7 +87,7 @@ LL | #[path = 1.0f32] //~ ERROR: suffixed literals are not allowed in attributes
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:24:10
+  --> $DIR/suffixed-literal-meta.rs:22:10
    |
 LL | #[path = 1.0f64] //~ ERROR: suffixed literals are not allowed in attributes
    |          ^^^^^^
index 1431ee9cc86479ff3d9f2f77b1a5054c449ecd14..dffdcb20ad250538555570e64acce3e0351448da 100644 (file)
@@ -1,4 +1,4 @@
-error[E0243]: wrong number of type arguments: expected 1, found 0
+error[E0107]: wrong number of type arguments: expected 1, found 0
   --> $DIR/tag-type-args.rs:15:11
    |
 LL | fn foo(c: quux) { assert!((false)); }
@@ -6,4 +6,4 @@ LL | fn foo(c: quux) { assert!((false)); }
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0243`.
+For more information about this error, try `rustc --explain E0107`.
index 7a6b9ae9943bc99c818d3d8cdf095c939e3e5981..8d3cfb5a16706346e7fcd1900cb792f51a35e219 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(tool_attributes, custom_attribute)]
+#![feature(custom_attribute)]
 
 type A = rustfmt; //~ ERROR expected type, found tool module `rustfmt`
 type B = rustfmt::skip; //~ ERROR expected type, found tool attribute `rustfmt::skip`
index 102edf2813b213eaac89ebb7648eb95ab1849830..e61ea9d5b443f74fe90725795cf181819e07d5b6 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(tool_attributes)]
-
 #[derive(rustfmt::skip)] //~ ERROR expected a macro, found tool attribute
 struct S;
 
index 5b968cd6b8ecdd31268d54377f12001160a9a8c2..ae47203a975802c050de96e3699e2733627c4443 100644 (file)
@@ -1,11 +1,11 @@
 error: expected a macro, found tool attribute
-  --> $DIR/tool-attributes-misplaced-2.rs:13:10
+  --> $DIR/tool-attributes-misplaced-2.rs:11:10
    |
 LL | #[derive(rustfmt::skip)] //~ ERROR expected a macro, found tool attribute
    |          ^^^^^^^^^^^^^
 
 error: expected a macro, found tool attribute
-  --> $DIR/tool-attributes-misplaced-2.rs:17:5
+  --> $DIR/tool-attributes-misplaced-2.rs:15:5
    |
 LL |     rustfmt::skip!(); //~ ERROR expected a macro, found tool attribute
    |     ^^^^^^^^^^^^^
index 7913c9f40b5538b32f2ff99079ea45be82db4528..b6a24ccf748e1c3ba51254cfcd67cb884bb1d6c9 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(tool_attributes, proc_macro_path_invoc)]
-
 mod rustfmt {}
 
 #[rustfmt::skip] //~ ERROR failed to resolve. Could not find `skip` in `rustfmt`
index f668d677f7a20deec27f9b8c525294eaa15d5cfa..d593350f123c629351136bae9a2a06015f3abaa8 100644 (file)
@@ -1,5 +1,5 @@
 error[E0433]: failed to resolve. Could not find `skip` in `rustfmt`
-  --> $DIR/tool-attributes-shadowing.rs:15:12
+  --> $DIR/tool-attributes-shadowing.rs:13:12
    |
 LL | #[rustfmt::skip] //~ ERROR failed to resolve. Could not find `skip` in `rustfmt`
    |            ^^^^ Could not find `skip` in `rustfmt`
index c0b65a7aa5c380207dc2f50cb868023343c16ff2..33ddb4c0ec3ed95bce32685da6f15cbbfb78e9ec 100644 (file)
@@ -16,7 +16,7 @@ error[E0107]: wrong number of lifetime arguments: expected 1, found 2
 LL |     let _: S<'static, 'static>;
    |                       ^^^^^^^ unexpected lifetime argument
 
-error[E0243]: wrong number of type arguments: expected 1, found 0
+error[E0107]: wrong number of type arguments: expected 1, found 0
   --> $DIR/trait-object-vs-lifetime.rs:23:12
    |
 LL |     let _: S<'static, 'static>;
@@ -30,5 +30,5 @@ LL |     let _: S<'static +, 'static>;
 
 error: aborting due to 5 previous errors
 
-Some errors occurred: E0107, E0224, E0243.
+Some errors occurred: E0107, E0224.
 For more information about an error, try `rustc --explain E0107`.
index fb9cd7019224d9be6a3997beaf1c155d28562125..1e1fcbe340e58259430f1901be149585f8f2a507 100644 (file)
@@ -1,10 +1,10 @@
-error[E0087]: wrong number of type arguments: expected 0, found 1
+error[E0107]: wrong number of type arguments: expected 0, found 1
   --> $DIR/trait-test-2.rs:18:14
    |
 LL |     10.dup::<i32>(); //~ ERROR wrong number of type arguments: expected 0, found 1
    |              ^^^ unexpected type argument
 
-error[E0087]: wrong number of type arguments: expected 1, found 2
+error[E0107]: wrong number of type arguments: expected 1, found 2
   --> $DIR/trait-test-2.rs:19:20
    |
 LL |     10.blah::<i32, i32>(); //~ ERROR wrong number of type arguments: expected 1, found 2
@@ -37,5 +37,5 @@ LL |     (box 10 as Box<bar>).dup();
 
 error: aborting due to 5 previous errors
 
-Some errors occurred: E0038, E0087, E0277.
+Some errors occurred: E0038, E0107, E0277.
 For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/try-block/try-block-bad-lifetime.rs b/src/test/ui/try-block/try-block-bad-lifetime.rs
new file mode 100644 (file)
index 0000000..576a020
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+#![inline(never)]
+fn do_something_with<T>(_x: T) {}
+
+// This test checks that borrows made and returned inside try blocks are properly constrained
+pub fn main() {
+    {
+        // Test that borrows returned from a try block must be valid for the lifetime of the
+        // result variable
+        let result: Result<(), &str> = try {
+            let my_string = String::from("");
+            let my_str: & str = & my_string;
+            //~^ ERROR `my_string` does not live long enough
+            Err(my_str) ?;
+            Err("") ?;
+        };
+        do_something_with(result);
+    }
+
+    {
+        // Test that borrows returned from try blocks freeze their referent
+        let mut i = 5;
+        let k = &mut i;
+        let mut j: Result<(), &mut i32> = try {
+            Err(k) ?;
+            i = 10; //~ ERROR cannot assign to `i` because it is borrowed
+        };
+        ::std::mem::drop(k); //~ ERROR use of moved value: `k`
+        i = 40; //~ ERROR cannot assign to `i` because it is borrowed
+
+        let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") };
+        *i_ptr = 50;
+    }
+}
+
diff --git a/src/test/ui/try-block/try-block-bad-lifetime.stderr b/src/test/ui/try-block/try-block-bad-lifetime.stderr
new file mode 100644 (file)
index 0000000..36c89fa
--- /dev/null
@@ -0,0 +1,50 @@
+error[E0597]: `my_string` does not live long enough
+  --> $DIR/try-block-bad-lifetime.rs:25:33
+   |
+LL |             let my_str: & str = & my_string;
+   |                                 ^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |         };
+   |         - `my_string` dropped here while still borrowed
+LL |         do_something_with(result);
+   |                           ------ borrow later used here
+
+error[E0506]: cannot assign to `i` because it is borrowed
+  --> $DIR/try-block-bad-lifetime.rs:39:13
+   |
+LL |         let k = &mut i;
+   |                 ------ borrow of `i` occurs here
+...
+LL |             i = 10; //~ ERROR cannot assign to `i` because it is borrowed
+   |             ^^^^^^ assignment to borrowed `i` occurs here
+LL |         };
+LL |         ::std::mem::drop(k); //~ ERROR use of moved value: `k`
+   |                          - borrow later used here
+
+error[E0382]: use of moved value: `k`
+  --> $DIR/try-block-bad-lifetime.rs:41:26
+   |
+LL |             Err(k) ?;
+   |                 - value moved here
+...
+LL |         ::std::mem::drop(k); //~ ERROR use of moved value: `k`
+   |                          ^ value used here after move
+   |
+   = note: move occurs because `k` has type `&mut i32`, which does not implement the `Copy` trait
+
+error[E0506]: cannot assign to `i` because it is borrowed
+  --> $DIR/try-block-bad-lifetime.rs:42:9
+   |
+LL |         let k = &mut i;
+   |                 ------ borrow of `i` occurs here
+...
+LL |         i = 40; //~ ERROR cannot assign to `i` because it is borrowed
+   |         ^^^^^^ assignment to borrowed `i` occurs here
+LL | 
+LL |         let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") };
+   |                                         - borrow later used here
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0382, E0506, E0597.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/try-block/try-block-bad-type.rs b/src/test/ui/try-block/try-block-bad-type.rs
new file mode 100644 (file)
index 0000000..a984b63
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+pub fn main() {
+    let res: Result<u32, i32> = try {
+        Err("")?; //~ ERROR the trait bound `i32: std::convert::From<&str>` is not satisfied
+        5
+    };
+
+    let res: Result<i32, i32> = try {
+        "" //~ ERROR type mismatch
+    };
+
+    let res: Result<i32, i32> = try { }; //~ ERROR type mismatch
+
+    let res: () = try { }; //~ the trait bound `(): std::ops::Try` is not satisfied
+
+    let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: std::ops::Try` is not satisfied
+}
diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr
new file mode 100644 (file)
index 0000000..159e43e
--- /dev/null
@@ -0,0 +1,52 @@
+error[E0277]: the trait bound `i32: std::convert::From<&str>` is not satisfied
+  --> $DIR/try-block-bad-type.rs:17:9
+   |
+LL |         Err("")?; //~ ERROR the trait bound `i32: std::convert::From<&str>` is not satisfied
+   |         ^^^^^^^^ the trait `std::convert::From<&str>` is not implemented for `i32`
+   |
+   = help: the following implementations were found:
+             <i32 as std::convert::From<bool>>
+             <i32 as std::convert::From<i16>>
+             <i32 as std::convert::From<i8>>
+             <i32 as std::convert::From<u16>>
+             <i32 as std::convert::From<u8>>
+   = note: required by `std::convert::From::from`
+
+error[E0271]: type mismatch resolving `<std::result::Result<i32, i32> as std::ops::Try>::Ok == &str`
+  --> $DIR/try-block-bad-type.rs:22:9
+   |
+LL |         "" //~ ERROR type mismatch
+   |         ^^ expected i32, found &str
+   |
+   = note: expected type `i32`
+              found type `&str`
+
+error[E0271]: type mismatch resolving `<std::result::Result<i32, i32> as std::ops::Try>::Ok == ()`
+  --> $DIR/try-block-bad-type.rs:25:39
+   |
+LL |     let res: Result<i32, i32> = try { }; //~ ERROR type mismatch
+   |                                       ^ expected i32, found ()
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error[E0277]: the trait bound `(): std::ops::Try` is not satisfied
+  --> $DIR/try-block-bad-type.rs:27:23
+   |
+LL |     let res: () = try { }; //~ the trait bound `(): std::ops::Try` is not satisfied
+   |                       ^^^ the trait `std::ops::Try` is not implemented for `()`
+   |
+   = note: required by `std::ops::Try::from_ok`
+
+error[E0277]: the trait bound `i32: std::ops::Try` is not satisfied
+  --> $DIR/try-block-bad-type.rs:29:24
+   |
+LL |     let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: std::ops::Try` is not satisfied
+   |                        ^^^^^ the trait `std::ops::Try` is not implemented for `i32`
+   |
+   = note: required by `std::ops::Try::from_ok`
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0271, E0277.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/try-block/try-block-in-edition2015.rs b/src/test/ui/try-block/try-block-in-edition2015.rs
new file mode 100644 (file)
index 0000000..64485bb
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition 2015
+
+pub fn main() {
+    let try_result: Option<_> = try {
+    //~^ ERROR expected struct, variant or union type, found macro `try`
+        let x = 5; //~ ERROR expected identifier, found keyword
+        x
+    };
+    assert_eq!(try_result, Some(5));
+}
diff --git a/src/test/ui/try-block/try-block-in-edition2015.stderr b/src/test/ui/try-block/try-block-in-edition2015.stderr
new file mode 100644 (file)
index 0000000..7e6d515
--- /dev/null
@@ -0,0 +1,18 @@
+error: expected identifier, found keyword `let`
+  --> $DIR/try-block-in-edition2015.rs:16:9
+   |
+LL |     let try_result: Option<_> = try {
+   |                                 --- while parsing this struct
+LL |     //~^ ERROR expected struct, variant or union type, found macro `try`
+LL |         let x = 5; //~ ERROR expected identifier, found keyword
+   |         ^^^ expected identifier, found keyword
+
+error[E0574]: expected struct, variant or union type, found macro `try`
+  --> $DIR/try-block-in-edition2015.rs:14:33
+   |
+LL |     let try_result: Option<_> = try {
+   |                                 ^^^ did you mean `try!(...)`?
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/try-block/try-block-in-match.rs b/src/test/ui/try-block/try-block-in-match.rs
new file mode 100644 (file)
index 0000000..d101491
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+fn main() {
+    match try { false } { _ => {} } //~ ERROR expected expression, found reserved keyword `try`
+}
diff --git a/src/test/ui/try-block/try-block-in-match.stderr b/src/test/ui/try-block/try-block-in-match.stderr
new file mode 100644 (file)
index 0000000..f07d238
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected expression, found reserved keyword `try`
+  --> $DIR/try-block-in-match.rs:16:11
+   |
+LL |     match try { false } { _ => {} } //~ ERROR expected expression, found reserved keyword `try`
+   |           ^^^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/try-block/try-block-in-while.rs b/src/test/ui/try-block/try-block-in-while.rs
new file mode 100644 (file)
index 0000000..b531267
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+fn main() {
+    while try { false } {} //~ ERROR expected expression, found reserved keyword `try`
+}
diff --git a/src/test/ui/try-block/try-block-in-while.stderr b/src/test/ui/try-block/try-block-in-while.stderr
new file mode 100644 (file)
index 0000000..36577d7
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected expression, found reserved keyword `try`
+  --> $DIR/try-block-in-while.rs:16:11
+   |
+LL |     while try { false } {} //~ ERROR expected expression, found reserved keyword `try`
+   |           ^^^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/try-block/try-block-maybe-bad-lifetime.rs b/src/test/ui/try-block/try-block-maybe-bad-lifetime.rs
new file mode 100644 (file)
index 0000000..b5e0ebd
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+#![inline(never)]
+fn do_something_with<T>(_x: T) {}
+
+// This test checks that borrows made and returned inside try blocks are properly constrained
+pub fn main() {
+    {
+        // Test that a borrow which *might* be returned still freezes its referent
+        let mut i = 222;
+        let x: Result<&i32, ()> = try {
+            Err(())?;
+            &i
+        };
+        i = 0; //~ ERROR cannot assign to `i` because it is borrowed
+        let _ = i;
+        do_something_with(x);
+    }
+
+    {
+        let x = String::new();
+        let _y: Result<(), ()> = try {
+            Err(())?;
+            ::std::mem::drop(x);
+        };
+        println!("{}", x); //~ ERROR borrow of moved value: `x`
+    }
+
+    {
+        // Test that a borrow which *might* be assigned to an outer variable still freezes
+        // its referent
+        let mut i = 222;
+        let mut j = &-1;
+        let _x: Result<(), ()> = try {
+            Err(())?;
+            j = &i;
+        };
+        i = 0; //~ ERROR cannot assign to `i` because it is borrowed
+        let _ = i;
+        do_something_with(j);
+    }
+}
+
diff --git a/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr b/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr
new file mode 100644 (file)
index 0000000..366a8da
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0506]: cannot assign to `i` because it is borrowed
+  --> $DIR/try-block-maybe-bad-lifetime.rs:27:9
+   |
+LL |             &i
+   |             -- borrow of `i` occurs here
+LL |         };
+LL |         i = 0; //~ ERROR cannot assign to `i` because it is borrowed
+   |         ^^^^^ assignment to borrowed `i` occurs here
+LL |         let _ = i;
+LL |         do_something_with(x);
+   |                           - borrow later used here
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/try-block-maybe-bad-lifetime.rs:38:24
+   |
+LL |             ::std::mem::drop(x);
+   |                              - value moved here
+LL |         };
+LL |         println!("{}", x); //~ ERROR borrow of moved value: `x`
+   |                        ^ value borrowed here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0506]: cannot assign to `i` because it is borrowed
+  --> $DIR/try-block-maybe-bad-lifetime.rs:50:9
+   |
+LL |             j = &i;
+   |                 -- borrow of `i` occurs here
+LL |         };
+LL |         i = 0; //~ ERROR cannot assign to `i` because it is borrowed
+   |         ^^^^^ assignment to borrowed `i` occurs here
+LL |         let _ = i;
+LL |         do_something_with(j);
+   |                           - borrow later used here
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0382, E0506.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/try-block/try-block-opt-init.rs b/src/test/ui/try-block/try-block-opt-init.rs
new file mode 100644 (file)
index 0000000..ca81a9c
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+fn use_val<T: Sized>(_x: T) {}
+
+pub fn main() {
+    let cfg_res;
+    let _: Result<(), ()> = try {
+        Err(())?;
+        cfg_res = 5;
+        Ok::<(), ()>(())?;
+        use_val(cfg_res);
+    };
+    assert_eq!(cfg_res, 5); //~ ERROR borrow of possibly uninitialized variable: `cfg_res`
+}
+
diff --git a/src/test/ui/try-block/try-block-opt-init.stderr b/src/test/ui/try-block/try-block-opt-init.stderr
new file mode 100644 (file)
index 0000000..3ebcb7d
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0381]: borrow of possibly uninitialized variable: `cfg_res`
+  --> $DIR/try-block-opt-init.rs:25:5
+   |
+LL |     assert_eq!(cfg_res, 5); //~ ERROR borrow of possibly uninitialized variable: `cfg_res`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ use of possibly uninitialized `cfg_res`
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/try-block/try-block-type-error.rs b/src/test/ui/try-block/try-block-type-error.rs
new file mode 100644 (file)
index 0000000..6a69cff
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+fn foo() -> Option<()> { Some(()) }
+
+fn main() {
+    let _: Option<f32> = try {
+        foo()?;
+        42
+        //~^ ERROR type mismatch
+    };
+
+    let _: Option<i32> = try {
+        foo()?;
+    };
+    //~^ ERROR type mismatch
+}
diff --git a/src/test/ui/try-block/try-block-type-error.stderr b/src/test/ui/try-block/try-block-type-error.stderr
new file mode 100644 (file)
index 0000000..3b67e92
--- /dev/null
@@ -0,0 +1,24 @@
+error[E0271]: type mismatch resolving `<std::option::Option<f32> as std::ops::Try>::Ok == {integer}`
+  --> $DIR/try-block-type-error.rs:20:9
+   |
+LL |         42
+   |         ^^
+   |         |
+   |         expected f32, found integral variable
+   |         help: use a float literal: `42.0`
+   |
+   = note: expected type `f32`
+              found type `{integer}`
+
+error[E0271]: type mismatch resolving `<std::option::Option<i32> as std::ops::Try>::Ok == ()`
+  --> $DIR/try-block-type-error.rs:26:5
+   |
+LL |     };
+   |     ^ expected i32, found ()
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
index 22d54a3834073d4f205701f49847732f13183c45..c8b77bfabdb9568733a0c085818b7fd3e2ea38d7 100644 (file)
@@ -15,3 +15,5 @@ mod foo {
     //~^ ERROR expected one of `)` or `,`, found `(`
     //~| ERROR cannot find type `foo` in this scope
 }
+
+fn main() {}
index 59228ea8c14d2ca41e9bb8d5f5474d90b33ff92b..f83e9dd5458fbad6d370fa68d4f36ea0684dfe80 100644 (file)
@@ -10,11 +10,6 @@ error[E0412]: cannot find type `foo` in this scope
 LL |     struct S2(pub((foo)) ());
    |                    ^^^ not found in this scope
 
-error[E0601]: `main` function not found in crate `test`
-   |
-   = note: consider adding a `main` function to `$DIR/test.rs`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors occurred: E0412, E0601.
-For more information about an error, try `rustc --explain E0412`.
+For more information about this error, try `rustc --explain E0412`.
index 9285b8ca6bcf04fb1eb25cb218127fa66ff5354d..715ffe92299305369796f5d7acae688093b54317 100644 (file)
@@ -9,20 +9,20 @@
 // except according to those terms.
 
 fn foo1<T:Copy<U>, U>(x: T) {}
-//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0244]
+//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
 
 trait Trait: Copy<Send> {}
-//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0244]
+//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
 
 struct MyStruct1<T: Copy<T>>;
-//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0244]
+//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
 
 struct MyStruct2<'a, T: Copy<'a>>;
-//~^ ERROR: wrong number of lifetime arguments: expected 0, found 1
+//~^ ERROR: wrong number of lifetime arguments: expected 0, found 1 [E0107]
 
 
 fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
-//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0244]
+//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
 //~| ERROR: wrong number of lifetime arguments: expected 0, found 1
 
 fn main() {
index b6444181dd8bd80755fd9004327d9ec1c87073d3..6fc32a4fccd7821b32d5af479f249dd340174dc7 100644 (file)
@@ -1,16 +1,16 @@
-error[E0244]: wrong number of type arguments: expected 0, found 1
+error[E0107]: wrong number of type arguments: expected 0, found 1
   --> $DIR/typeck-builtin-bound-type-parameters.rs:11:16
    |
 LL | fn foo1<T:Copy<U>, U>(x: T) {}
    |                ^ unexpected type argument
 
-error[E0244]: wrong number of type arguments: expected 0, found 1
+error[E0107]: wrong number of type arguments: expected 0, found 1
   --> $DIR/typeck-builtin-bound-type-parameters.rs:14:19
    |
 LL | trait Trait: Copy<Send> {}
    |                   ^^^^ unexpected type argument
 
-error[E0244]: wrong number of type arguments: expected 0, found 1
+error[E0107]: wrong number of type arguments: expected 0, found 1
   --> $DIR/typeck-builtin-bound-type-parameters.rs:17:26
    |
 LL | struct MyStruct1<T: Copy<T>>;
@@ -28,7 +28,7 @@ error[E0107]: wrong number of lifetime arguments: expected 0, found 1
 LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
    |                    ^^ unexpected lifetime argument
 
-error[E0244]: wrong number of type arguments: expected 0, found 1
+error[E0107]: wrong number of type arguments: expected 0, found 1
   --> $DIR/typeck-builtin-bound-type-parameters.rs:24:24
    |
 LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
@@ -36,5 +36,4 @@ LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
 
 error: aborting due to 6 previous errors
 
-Some errors occurred: E0107, E0244.
-For more information about an error, try `rustc --explain E0107`.
+For more information about this error, try `rustc --explain E0107`.
index 49774ab173a8acf694482705bc4b6031fc5dc29e..cef7b6eebc94501fc6b87e649da0ddcc3f6b33bc 100644 (file)
@@ -17,5 +17,5 @@ struct Foo<'a, T:'a> {
 
 pub fn main() {
     let c: Foo<_, _> = Foo { r: &5 };
-    //~^ ERROR wrong number of type arguments: expected 1, found 2 [E0244]
+    //~^ ERROR wrong number of type arguments: expected 1, found 2 [E0107]
 }
index a49839b731070174d96e386d3887df99bb6a94fb..8da357452a708e3a3d9134a44b972c50a1353a3b 100644 (file)
@@ -1,4 +1,4 @@
-error[E0244]: wrong number of type arguments: expected 1, found 2
+error[E0107]: wrong number of type arguments: expected 1, found 2
   --> $DIR/typeck_type_placeholder_lifetime_1.rs:19:19
    |
 LL |     let c: Foo<_, _> = Foo { r: &5 };
@@ -6,4 +6,4 @@ LL |     let c: Foo<_, _> = Foo { r: &5 };
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0244`.
+For more information about this error, try `rustc --explain E0107`.
index 40617613ed7c67449fa7ea37f9dd223353599e6a..4c25a2528f07ef5fd7b076ce6b15e6497cc1ece0 100644 (file)
@@ -17,5 +17,5 @@ struct Foo<'a, T:'a> {
 
 pub fn main() {
     let c: Foo<_, usize> = Foo { r: &5 };
-    //~^ ERROR wrong number of type arguments: expected 1, found 2 [E0244]
+    //~^ ERROR wrong number of type arguments: expected 1, found 2 [E0107]
 }
index cafb6f507a0e9052d7e2b00bb773b931dd6223d6..c43f73a5f1a02b660fd650fff1f3f29e621d35f3 100644 (file)
@@ -1,4 +1,4 @@
-error[E0244]: wrong number of type arguments: expected 1, found 2
+error[E0107]: wrong number of type arguments: expected 1, found 2
   --> $DIR/typeck_type_placeholder_lifetime_2.rs:19:19
    |
 LL |     let c: Foo<_, usize> = Foo { r: &5 };
@@ -6,4 +6,4 @@ LL |     let c: Foo<_, usize> = Foo { r: &5 };
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0244`.
+For more information about this error, try `rustc --explain E0107`.
index 2653b7bf4ac7b839fda5c5dacdbd51874c3a8a90..7536205dc0f07a1a0f8eb4c7e1279e3065aa414f 100644 (file)
@@ -1,4 +1,4 @@
-error[E0089]: wrong number of type arguments: expected 1, found 0
+error[E0107]: wrong number of type arguments: expected 1, found 0
   --> $DIR/ufcs-qpath-missing-params.rs:24:5
    |
 LL |     <String as IntoCow>::into_cow("foo".to_string());
@@ -6,4 +6,4 @@ LL |     <String as IntoCow>::into_cow("foo".to_string());
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0089`.
+For more information about this error, try `rustc --explain E0107`.
index feac4274357b5d5b1033035bb10e4abe74304295..f15868af7c0aad2ac00252d619d6938551d9a42f 100644 (file)
@@ -1,4 +1,4 @@
-error[E0243]: wrong number of type arguments: expected 3, found 1
+error[E0107]: wrong number of type arguments: expected 3, found 1
   --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:15:12
    |
 LL | fn foo(_: &Three())
@@ -12,5 +12,5 @@ LL | fn foo(_: &Three())
 
 error: aborting due to 2 previous errors
 
-Some errors occurred: E0220, E0243.
-For more information about an error, try `rustc --explain E0220`.
+Some errors occurred: E0107, E0220.
+For more information about an error, try `rustc --explain E0107`.
index 89587c47cf67d1a1c71bd53dc2f2ac22d451f153..d54f7741944fc854b35e83a659a5e3f1868832af 100644 (file)
@@ -1,4 +1,4 @@
-error[E0244]: wrong number of type arguments: expected 0, found 1
+error[E0107]: wrong number of type arguments: expected 0, found 1
   --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:15:15
    |
 LL | fn foo(_: Zero())
@@ -12,5 +12,5 @@ LL | fn foo(_: Zero())
 
 error: aborting due to 2 previous errors
 
-Some errors occurred: E0220, E0244.
-For more information about an error, try `rustc --explain E0220`.
+Some errors occurred: E0107, E0220.
+For more information about an error, try `rustc --explain E0107`.
index 1519ceb8988518983f670cf027bd55234a35ece8..5e4e180201d6f59fbfcf93a124cdfc56e902bec5 100644 (file)
@@ -13,7 +13,7 @@
 trait Trait {}
 
 fn f<F:Trait(isize) -> isize>(x: F) {}
-//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0244]
+//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
 //~| ERROR E0220
 
 fn main() {}
index 5d8c86f5a580974241d8ece24fa5960e861d97f8..a4784ee0ae88004311a41313258ca6b185196449 100644 (file)
@@ -1,8 +1,8 @@
-error[E0244]: wrong number of type arguments: expected 0, found 1
+error[E0107]: wrong number of type arguments: expected 0, found 1
   --> $DIR/unboxed-closure-sugar-wrong-trait.rs:15:13
    |
 LL | fn f<F:Trait(isize) -> isize>(x: F) {}
-   |             ^^^^^^^^^^^^^^^^ unexpected type argument
+   |             ^^^^^^^ unexpected type argument
 
 error[E0220]: associated type `Output` not found for `Trait`
   --> $DIR/unboxed-closure-sugar-wrong-trait.rs:15:24
@@ -12,5 +12,5 @@ LL | fn f<F:Trait(isize) -> isize>(x: F) {}
 
 error: aborting due to 2 previous errors
 
-Some errors occurred: E0220, E0244.
-For more information about an error, try `rustc --explain E0220`.
+Some errors occurred: E0107, E0220.
+For more information about an error, try `rustc --explain E0107`.
index 95aa3f15b7648f0022724ea1816239f2681e66dd..e5e66efcaa2ced9cd2b62c7010e0ad72c03c48ab 100644 (file)
@@ -1,9 +1,10 @@
-error[E0277]: the trait bound `S: std::ops::Fn<(isize,)>` is not satisfied
+error[E0277]: expected a `std::ops::Fn<(isize,)>` closure, found `S`
   --> $DIR/unboxed-closures-fnmut-as-fn.rs:38:13
    |
 LL |     let x = call_it(&S, 22);
-   |             ^^^^^^^ the trait `std::ops::Fn<(isize,)>` is not implemented for `S`
+   |             ^^^^^^^ expected an `Fn<(isize,)>` closure, found `S`
    |
+   = help: the trait `std::ops::Fn<(isize,)>` is not implemented for `S`
 note: required by `call_it`
   --> $DIR/unboxed-closures-fnmut-as-fn.rs:33:1
    |
index 16b2b11ad7b42b3463909494b06cef2fe0844aa0..7c76c10443af91763ee0c6e454b9f7236cd3e7f6 100644 (file)
@@ -1,33 +1,36 @@
-error[E0277]: the trait bound `for<'r> for<'s> unsafe fn(&'s isize) -> isize {square}: std::ops::Fn<(&'r isize,)>` is not satisfied
+error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:22:13
    |
 LL |     let x = call_it(&square, 22);
-   |             ^^^^^^^ the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |             ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
    |
+   = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
 note: required by `call_it`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:17:1
    |
 LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `for<'r> for<'s> unsafe fn(&'s isize) -> isize {square}: std::ops::FnMut<(&'r isize,)>` is not satisfied
+error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:27:13
    |
 LL |     let y = call_it_mut(&mut square, 22);
-   |             ^^^^^^^^^^^ the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |             ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
    |
+   = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
 note: required by `call_it_mut`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:1
    |
 LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `for<'r> for<'s> unsafe fn(&'s isize) -> isize {square}: std::ops::FnOnce<(&'r isize,)>` is not satisfied
+error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:32:13
    |
 LL |     let z = call_it_once(square, 22);
-   |             ^^^^^^^^^^^^ the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |             ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
    |
+   = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
 note: required by `call_it_once`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:19:1
    |
index 6e5e1b928a2c0bae31efd2e83f6f77d91679b4a5..18ade48de664080d54ff9db4b563650de44316fa 100644 (file)
@@ -1,33 +1,36 @@
-error[E0277]: the trait bound `for<'r> for<'s> extern "C" fn(&'s isize) -> isize {square}: std::ops::Fn<(&'r isize,)>` is not satisfied
+error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-abi.rs:22:13
    |
 LL |     let x = call_it(&square, 22);
-   |             ^^^^^^^ the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |             ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
    |
+   = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
 note: required by `call_it`
   --> $DIR/unboxed-closures-wrong-abi.rs:17:1
    |
 LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `for<'r> for<'s> extern "C" fn(&'s isize) -> isize {square}: std::ops::FnMut<(&'r isize,)>` is not satisfied
+error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-abi.rs:27:13
    |
 LL |     let y = call_it_mut(&mut square, 22);
-   |             ^^^^^^^^^^^ the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |             ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
    |
+   = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
 note: required by `call_it_mut`
   --> $DIR/unboxed-closures-wrong-abi.rs:18:1
    |
 LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `for<'r> for<'s> extern "C" fn(&'s isize) -> isize {square}: std::ops::FnOnce<(&'r isize,)>` is not satisfied
+error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-abi.rs:32:13
    |
 LL |     let z = call_it_once(square, 22);
-   |             ^^^^^^^^^^^^ the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |             ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
    |
+   = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
 note: required by `call_it_once`
   --> $DIR/unboxed-closures-wrong-abi.rs:19:1
    |
index 5c2e73f57160dfe5152f6787acaa4dcf67db0383..f27b73017a28fed53e9f7745f9fda65843b61585 100644 (file)
@@ -1,33 +1,36 @@
-error[E0277]: the trait bound `for<'r> unsafe fn(isize) -> isize {square}: std::ops::Fn<(&'r isize,)>` is not satisfied
+error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:23:13
    |
 LL |     let x = call_it(&square, 22);
-   |             ^^^^^^^ the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+   |             ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
    |
+   = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
 note: required by `call_it`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:18:1
    |
 LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `for<'r> unsafe fn(isize) -> isize {square}: std::ops::FnMut<(&'r isize,)>` is not satisfied
+error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:28:13
    |
 LL |     let y = call_it_mut(&mut square, 22);
-   |             ^^^^^^^^^^^ the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+   |             ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
    |
+   = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
 note: required by `call_it_mut`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:1
    |
 LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `for<'r> unsafe fn(isize) -> isize {square}: std::ops::FnOnce<(&'r isize,)>` is not satisfied
+error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:33:13
    |
 LL |     let z = call_it_once(square, 22);
-   |             ^^^^^^^^^^^^ the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+   |             ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
    |
+   = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
 note: required by `call_it_once`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:20:1
    |
index 799b0982b940f68747934c249a55bf27161b5d1d..58939b0f64f5a99603fabb5d02f1c1dd1544eb6e 100644 (file)
@@ -23,16 +23,13 @@ LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: unsatisfied lifetime constraints
-  --> $DIR/dyn-trait-underscore.rs:16:52
+  --> $DIR/dyn-trait-underscore.rs:18:5
    |
-LL |   fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
-   |  ________________-___________________________________^
-   | |                |
-   | |                let's call the lifetime of this reference `'1`
-LL | |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
-LL | |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
-LL | | }
-   | |_^ returning this value requires that `'1` must outlive `'static`
+LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
+   |                - let's call the lifetime of this reference `'1`
+LL |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
+LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+   |     ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
 
 error: aborting due to previous error
 
index cfce92ece7a921da496263721a927bd80a472f79..0c42d28eb00f49d148cd8fcb5929a932b2e06539 100644 (file)
@@ -8,11 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused)]
+
 // normalize-stderr-test "alignment \d+" -> "alignment N"
 // normalize-stderr-test "offset \d+" -> "offset N"
 // normalize-stderr-test "allocation \d+" -> "allocation N"
 // normalize-stderr-test "size \d+" -> "size N"
 
+union BoolTransmute {
+  val: u8,
+  bl: bool,
+}
+
 #[repr(C)]
 #[derive(Copy, Clone)]
 struct SliceRepr {
@@ -32,6 +39,8 @@ union SliceTransmute {
     bad: BadSliceRepr,
     slice: &'static [u8],
     str: &'static str,
+    my_str: &'static MyStr,
+    my_slice: &'static MySliceBool,
 }
 
 #[repr(C)]
@@ -63,32 +72,68 @@ union DynTransmute {
 }
 
 trait Trait {}
+impl Trait for bool {}
+
+// custom unsized type
+struct MyStr(str);
+
+// custom unsized type with sized fields
+struct MySlice<T: ?Sized>(bool, T);
+type MySliceBool = MySlice<[bool]>;
 
 // OK
 const A: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str};
-// should lint
+// bad str
 const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
-// bad
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad str
 const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
 //~^ ERROR this constant likely exhibits undefined behavior
+// bad str in user-defined unsized type
+const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
+//~^ ERROR this constant likely exhibits undefined behavior
 
 // OK
 const A2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice};
-// should lint
+// bad slice
 const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
-// bad
-const C2: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad slice
+const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
 //~^ ERROR this constant likely exhibits undefined behavior
 
-// bad
+// bad trait object
 const D: &Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
 //~^ ERROR this constant likely exhibits undefined behavior
-// bad
+// bad trait object
 const E: &Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
 //~^ ERROR this constant likely exhibits undefined behavior
-// bad
+// bad trait object
 const F: &Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
 //~^ ERROR this constant likely exhibits undefined behavior
 
+// bad data *inside* the trait object
+const G: &Trait = &unsafe { BoolTransmute { val: 3 }.bl };
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad data *inside* the slice
+const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
+//~^ ERROR this constant likely exhibits undefined behavior
+
+// good MySliceBool
+const I1: &MySliceBool = &MySlice(true, [false]);
+// bad: sized field is not okay
+const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad: unsized part is not okay
+const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
+//~^ ERROR this constant likely exhibits undefined behavior
+
+// invalid UTF-8
+const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
+//~^ ERROR this constant likely exhibits undefined behavior
+// invalid UTF-8 in user-defined str-like
+const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
+//~^ ERROR this constant likely exhibits undefined behavior
+
 fn main() {
 }
index f0298d9013c933b6ff03de3318a9c553dbc60810..5d817dce205b15091e6829790629ec3ab9cd1c0c 100644 (file)
 error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:72:1
+  --> $DIR/union-ub-fat-ptr.rs:87:1
+   |
+LL | const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or out-of-bounds memory at .<deref>
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:90:1
    |
 LL | const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered length is not a valid integer
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
 error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:80:1
+  --> $DIR/union-ub-fat-ptr.rs:93:1
    |
-LL | const C2: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered length is not a valid integer
+LL | const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
 error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:84:1
+  --> $DIR/union-ub-fat-ptr.rs:99:1
+   |
+LL | const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or out-of-bounds memory at .<deref>[1]
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:102:1
+   |
+LL | const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:106:1
    |
 LL | const D: &Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tried to access memory with alignment N, but alignment N is required
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid vtable in fat pointer at .<deref>
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
 error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:87:1
+  --> $DIR/union-ub-fat-ptr.rs:109:1
    |
 LL | const E: &Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access at offset N, outside bounds of allocation N which has size N
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid vtable in fat pointer at .<deref>
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
 error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:90:1
+  --> $DIR/union-ub-fat-ptr.rs:112:1
    |
 LL | const F: &Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered vtable address is not a pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-pointer vtable in fat pointer
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:116:1
+   |
+LL | const G: &Trait = &unsafe { BoolTransmute { val: 3 }.bl };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>, but expected something in the range 0..=1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:119:1
+   |
+LL | const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>[0], but expected something in the range 0..=1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:125:1
+   |
+LL | const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.0, but expected something in the range 0..=1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:128:1
+   |
+LL | const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.1[0], but expected something in the range 0..=1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:132:1
+   |
+LL | const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-UTF-8 data in str at .<deref>
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:135:1
+   |
+LL | const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-UTF-8 data in str at .<deref>.0
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
-error: aborting due to 5 previous errors
+error: aborting due to 14 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index 99c336c28cd29c6db14a37e3c37594cf9ad39635..cd2aeb7494a5a3202ea55c6e1001972cfe02877e 100644 (file)
@@ -8,7 +8,5 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(proc_macro_path_invoc)]
-
 #[foo::bar] //~ ERROR failed to resolve. Use of undeclared type or module `foo`
 fn main() {}
index 151f957ac568a641f3a5da21accdf60203b19921..8381c6de83a6744a91e73809dac52955d24e5998 100644 (file)
@@ -1,5 +1,5 @@
 error[E0433]: failed to resolve. Use of undeclared type or module `foo`
-  --> $DIR/unknown-tool-name.rs:13:3
+  --> $DIR/unknown-tool-name.rs:11:3
    |
 LL | #[foo::bar] //~ ERROR failed to resolve. Use of undeclared type or module `foo`
    |   ^^^ Use of undeclared type or module `foo`
index a3eeb6de96bda1f9867a1d6d9c13510571f76bdb..efa7494647691a28ed57e277e0cdfce0e398bbac 100644 (file)
@@ -55,3 +55,5 @@ enum Enum {
 
     fn item() {}
 }
+
+fn main() {}
index 1e663cde48a65d94bf24e3b11b66da4ff439c7ec..9bcebb0011a75d9336ae2c4a362bb99b395597ca 100644 (file)
@@ -34,11 +34,6 @@ error[E0432]: unresolved import `Enum`
 LL |     use Enum::*; //~ ERROR unresolved import `Enum` [E0432]
    |         ^^^^ Did you mean `self::Enum`?
 
-error[E0601]: `main` function not found in crate `unresolved_import`
-   |
-   = note: consider adding a `main` function to `$DIR/unresolved-import.rs`
-
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
-Some errors occurred: E0432, E0601.
-For more information about an error, try `rustc --explain E0432`.
+For more information about this error, try `rustc --explain E0432`.
index 765e2059a4b5efbc629b0197091b9718ac16decc..fe0bb7533a86f316f53ed19a548d763ea4a136bc 100644 (file)
@@ -10,7 +10,7 @@
 
 // A quick test of 'unsafe const fn' functionality
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const unsafe fn dummy(v: u32) -> u32 {
     !v
index 02e1a585fa89d054d267c206ca636f4ff4f5c093..fe76d58f1ef76d26444eaf809ba38e4df62d77a7 100644 (file)
@@ -11,3 +11,5 @@
 #![allow(unused_macros)]
 
 macro_rules! macro_rules { () => {} } //~ ERROR user-defined macros may not be named `macro_rules`
+
+fn main() {}
index 3359aa4bcd720ed249e1a9add4d46cbcbf606fb9..1f8b18166c9c96124461bc2fc5eb14522e2f5113 100644 (file)
@@ -4,10 +4,5 @@ error: user-defined macros may not be named `macro_rules`
 LL | macro_rules! macro_rules { () => {} } //~ ERROR user-defined macros may not be named `macro_rules`
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0601]: `main` function not found in crate `user_defined_macro_rules`
-   |
-   = note: consider adding a `main` function to `$DIR/user-defined-macro-rules.rs`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0601`.
index ec5669f639277f6db2623791bf8b4ac7c47df91b..a5011c3abe7a7a72f6e7daecb9816b4365366803 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-arm stdcall isn't suppported
+// ignore-arm stdcall isn't supported
 
 fn baz(f: extern "stdcall" fn(usize, ...)) {
     //~^ ERROR: variadic function must have C or cdecl calling convention
index f245306f4d8f6e08545cf0e492a09cc3d1e3c07d..d81e61cac566d6c9e114b439979396f5a630ac77 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-arm stdcall isn't suppported
-// ignore-aarch64 stdcall isn't suppported
+// ignore-arm stdcall isn't supported
+// ignore-aarch64 stdcall isn't supported
 
 extern "stdcall" {
     fn printf(_: *const u8, ...); //~ ERROR: variadic function must have C or cdecl calling
index 5631a70192afd0962bbb6548a0d79278d1bca52a..9f431e78061391e98e473977a799faea28ab4c4a 100644 (file)
@@ -21,3 +21,5 @@
 
 #[link_section = "test"]
 pub static D: &usize = &C; //~ ERROR: no extra levels of indirection
+
+fn main() {}
index 9b96b99e02ae4ebb78c8de511c2dffbbfb8c6b16..cea6e5c41923a1013a1d5e754d7c5ee29829172c 100644 (file)
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `wasm_custom_section_relocations`
-   |
-   = note: consider adding a `main` function to `$DIR/wasm-custom-section-relocations.rs`
-
 error: statics with a custom `#[link_section]` must be a simple list of bytes on the wasm target with no extra levels of indirection such as references
   --> $DIR/wasm-custom-section-relocations.rs:14:1
    |
@@ -14,6 +10,5 @@ error: statics with a custom `#[link_section]` must be a simple list of bytes on
 LL | pub static D: &usize = &C; //~ ERROR: no extra levels of indirection
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0601`.
index bf8fc29217338bf2e6e953ccac2ec4eb608ea196..6179bdb34a38134902b868da68214f39bcbbb734 100644 (file)
@@ -10,7 +10,7 @@
 
 // Test that we can quantify lifetimes outside a constraint (i.e., including
 // the self type) in a where clause. Specifically, test that implementing for a
-// specific lifetime is not enough to satisify the `for<'a> ...` constraint, which
+// specific lifetime is not enough to satisfy the `for<'a> ...` constraint, which
 // should require *all* lifetimes.
 
 static X: &'static u32 = &42;
diff --git a/src/tools/build-manifest/README.md b/src/tools/build-manifest/README.md
new file mode 100644 (file)
index 0000000..6834f56
--- /dev/null
@@ -0,0 +1,30 @@
+# build-manifest
+
+This tool generates the manifests uploaded to static.rust-lang.org and used by
+rustup. The tool is invoked by the bootstrap tool.
+
+## Testing changes locally
+
+In order to test the changes locally you need to have a valid dist directory
+available locally. If you don't want to build all the compiler, you can easily
+create one from the nightly artifacts with:
+
+```
+#!/bin/bash
+for cmpn in rust rustc rust-std rust-docs cargo; do
+    wget https://static.rust-lang.org/dist/${cmpn}-nightly-x86_64-unknown-linux-gnu.tar.gz
+done
+```
+
+Then, you can generate the manifest and all the packages from `path/to/dist` to
+`path/to/output` with:
+
+```
+$ BUILD_MANIFEST_DISABLE_SIGNING=1 cargo +nightly run \
+    path/to/dist path/to/output 1970-01-01 \
+    nightly nightly nightly nightly nightly nightly nightly \
+    http://example.com
+```
+
+In the future, if the tool complains about missing arguments just add more
+`nightly`s in the middle.
index ee1345c7f9411caf31d14c0cd2577d721a2c75a5..f81964ccbc23c6405d4533fe5bd06865004bcd34 100644 (file)
     "armv7-unknown-cloudabi-eabihf",
     "armv7-unknown-linux-gnueabihf",
     "armv7-unknown-linux-musleabihf",
+    "armebv7r-none-eabi",
     "armebv7r-none-eabihf",
+    "armv7r-none-eabi",
+    "armv7r-none-eabihf",
     "armv7s-apple-ios",
     "asmjs-unknown-emscripten",
     "i386-apple-ios",
@@ -89,6 +92,7 @@
     "powerpc64-unknown-linux-gnu",
     "powerpc64le-unknown-linux-gnu",
     "powerpc64le-unknown-linux-musl",
+    "riscv32imc-unknown-none-elf",
     "riscv32imac-unknown-none-elf",
     "s390x-unknown-linux-gnu",
     "sparc-unknown-linux-gnu",
     "x86_64-unknown-redox",
 ];
 
+static DOCS_TARGETS: &'static [&'static str] = &[
+    "i686-apple-darwin",
+    "i686-pc-windows-gnu",
+    "i686-pc-windows-msvc",
+    "i686-unknown-linux-gnu",
+    "x86_64-apple-darwin",
+    "x86_64-pc-windows-gnu",
+    "x86_64-pc-windows-msvc",
+    "x86_64-unknown-linux-gnu",
+];
+
 static MINGW: &'static [&'static str] = &[
     "i686-pc-windows-gnu",
     "x86_64-pc-windows-gnu",
@@ -213,9 +228,23 @@ struct Builder {
     rustfmt_git_commit_hash: Option<String>,
     llvm_tools_git_commit_hash: Option<String>,
     lldb_git_commit_hash: Option<String>,
+
+    should_sign: bool,
 }
 
 fn main() {
+    // Avoid signing packages while manually testing
+    // Do NOT set this envvar in CI
+    let should_sign = env::var("BUILD_MANIFEST_DISABLE_SIGNING").is_err();
+
+    // Safety check to ensure signing is always enabled on CI
+    // The CI environment variable is set by both Travis and AppVeyor
+    if !should_sign && env::var("CI").is_ok() {
+        println!("The 'BUILD_MANIFEST_DISABLE_SIGNING' env var can't be enabled on CI.");
+        println!("If you're not running this on CI, unset the 'CI' env var.");
+        panic!();
+    }
+
     let mut args = env::args().skip(1);
     let input = PathBuf::from(args.next().unwrap());
     let output = PathBuf::from(args.next().unwrap());
@@ -228,8 +257,12 @@ fn main() {
     let llvm_tools_release = args.next().unwrap();
     let lldb_release = args.next().unwrap();
     let s3_address = args.next().unwrap();
+
+    // Do not ask for a passphrase while manually testing
     let mut passphrase = String::new();
-    t!(io::stdin().read_to_string(&mut passphrase));
+    if should_sign {
+        t!(io::stdin().read_to_string(&mut passphrase));
+    }
 
     Builder {
         rust_release,
@@ -262,6 +295,8 @@ fn main() {
         rustfmt_git_commit_hash: None,
         llvm_tools_git_commit_hash: None,
         lldb_git_commit_hash: None,
+
+        should_sign,
     }.build();
 }
 
@@ -273,7 +308,8 @@ fn build(&mut self) {
         self.clippy_version = self.version("clippy", "x86_64-unknown-linux-gnu");
         self.rustfmt_version = self.version("rustfmt", "x86_64-unknown-linux-gnu");
         self.llvm_tools_version = self.version("llvm-tools", "x86_64-unknown-linux-gnu");
-        self.lldb_version = self.version("lldb", "x86_64-unknown-linux-gnu");
+        // lldb is only built for macOS.
+        self.lldb_version = self.version("lldb", "x86_64-apple-darwin");
 
         self.rust_git_commit_hash = self.git_commit_hash("rust", "x86_64-unknown-linux-gnu");
         self.cargo_git_commit_hash = self.git_commit_hash("cargo", "x86_64-unknown-linux-gnu");
@@ -314,7 +350,7 @@ fn build_manifest(&mut self) -> Manifest {
         self.package("cargo", &mut manifest.pkg, HOSTS);
         self.package("rust-mingw", &mut manifest.pkg, MINGW);
         self.package("rust-std", &mut manifest.pkg, TARGETS);
-        self.package("rust-docs", &mut manifest.pkg, TARGETS);
+        self.package("rust-docs", &mut manifest.pkg, DOCS_TARGETS);
         self.package("rust-src", &mut manifest.pkg, &["*"]);
         self.package("rls-preview", &mut manifest.pkg, HOSTS);
         self.package("clippy-preview", &mut manifest.pkg, HOSTS);
@@ -323,15 +359,7 @@ fn build_manifest(&mut self) -> Manifest {
         self.package("llvm-tools-preview", &mut manifest.pkg, TARGETS);
         self.package("lldb-preview", &mut manifest.pkg, TARGETS);
 
-        let clippy_present = manifest.pkg.contains_key("clippy-preview");
-        let rls_present = manifest.pkg.contains_key("rls-preview");
-        let rustfmt_present = manifest.pkg.contains_key("rustfmt-preview");
-        let llvm_tools_present = manifest.pkg.contains_key("llvm-tools-preview");
-        let lldb_present = manifest.pkg.contains_key("lldb-preview");
-
-        if rls_present {
-            manifest.renames.insert("rls".to_owned(), Rename { to: "rls-preview".to_owned() });
-        }
+        manifest.renames.insert("rls".to_owned(), Rename { to: "rls-preview".to_owned() });
 
         let mut pkg = Package {
             version: self.cached_version("rust")
@@ -370,40 +398,17 @@ fn build_manifest(&mut self) -> Manifest {
                 });
             }
 
-            if clippy_present {
-                extensions.push(Component {
-                    pkg: "clippy-preview".to_string(),
-                    target: host.to_string(),
-                });
-            }
-            if rls_present {
-                extensions.push(Component {
-                    pkg: "rls-preview".to_string(),
-                    target: host.to_string(),
-                });
-            }
-            if rustfmt_present {
-                extensions.push(Component {
-                    pkg: "rustfmt-preview".to_string(),
-                    target: host.to_string(),
-                });
-            }
-            if llvm_tools_present {
-                extensions.push(Component {
-                    pkg: "llvm-tools-preview".to_string(),
-                    target: host.to_string(),
-                });
-            }
-            if lldb_present {
-                extensions.push(Component {
-                    pkg: "lldb-preview".to_string(),
-                    target: host.to_string(),
-                });
-            }
-            extensions.push(Component {
-                pkg: "rust-analysis".to_string(),
-                target: host.to_string(),
-            });
+            // Tools are always present in the manifest, but might be marked as unavailable if they
+            // weren't built
+            extensions.extend(vec![
+                Component { pkg: "clippy-preview".to_string(), target: host.to_string() },
+                Component { pkg: "rls-preview".to_string(), target: host.to_string() },
+                Component { pkg: "rustfmt-preview".to_string(), target: host.to_string() },
+                Component { pkg: "llvm-tools-preview".to_string(), target: host.to_string() },
+                Component { pkg: "lldb-preview".to_string(), target: host.to_string() },
+                Component { pkg: "rust-analysis".to_string(), target: host.to_string() },
+            ]);
+
             for target in TARGETS {
                 if target != host {
                     extensions.push(Component {
@@ -429,11 +434,7 @@ fn build_manifest(&mut self) -> Manifest {
                         Some(p) => p,
                         None => return false,
                     };
-                    let target = match pkg.target.get(&c.target) {
-                        Some(t) => t,
-                        None => return false,
-                    };
-                    target.available
+                    pkg.target.get(&c.target).is_some()
                 };
                 extensions.retain(&has_component);
                 components.retain(&has_component);
@@ -458,32 +459,43 @@ fn package(&mut self,
                pkgname: &str,
                dst: &mut BTreeMap<String, Package>,
                targets: &[&str]) {
-        let version = match *self.cached_version(pkgname) {
-            Some(ref version) => version.clone(),
-            None => {
-                println!("Skipping package {}", pkgname);
-                return;
-            }
+        let (version, is_present) = match *self.cached_version(pkgname) {
+            Some(ref version) => (version.clone(), true),
+            None => (String::new(), false),
         };
 
         let targets = targets.iter().map(|name| {
-            let filename = self.filename(pkgname, name);
-            let digest = match self.digests.remove(&filename) {
-                Some(digest) => digest,
-                None => return (name.to_string(), Target::unavailable()),
-            };
-            let xz_filename = filename.replace(".tar.gz", ".tar.xz");
-            let xz_digest = self.digests.remove(&xz_filename);
-
-            (name.to_string(), Target {
-                available: true,
-                url: Some(self.url(&filename)),
-                hash: Some(digest),
-                xz_url: xz_digest.as_ref().map(|_| self.url(&xz_filename)),
-                xz_hash: xz_digest,
-                components: None,
-                extensions: None,
-            })
+            if is_present {
+                let filename = self.filename(pkgname, name);
+                let digest = match self.digests.remove(&filename) {
+                    Some(digest) => digest,
+                    None => return (name.to_string(), Target::unavailable()),
+                };
+                let xz_filename = filename.replace(".tar.gz", ".tar.xz");
+                let xz_digest = self.digests.remove(&xz_filename);
+
+                (name.to_string(), Target {
+                    available: true,
+                    url: Some(self.url(&filename)),
+                    hash: Some(digest),
+                    xz_url: xz_digest.as_ref().map(|_| self.url(&xz_filename)),
+                    xz_hash: xz_digest,
+                    components: None,
+                    extensions: None,
+                })
+            } else {
+                // If the component is not present for this build add it anyway but mark it as
+                // unavailable -- this way rustup won't allow upgrades without --force
+                (name.to_string(), Target {
+                    available: false,
+                    url: None,
+                    hash: None,
+                    xz_url: None,
+                    xz_hash: None,
+                    components: None,
+                    extensions: None,
+                })
+            }
         }).collect();
 
         dst.insert(pkgname.to_string(), Package {
@@ -604,6 +616,10 @@ fn hash(&self, path: &Path) -> String {
     }
 
     fn sign(&self, path: &Path) {
+        if !self.should_sign {
+            return;
+        }
+
         let filename = path.file_name().unwrap().to_str().unwrap();
         let asc = self.output.join(format!("{}.asc", filename));
         println!("signing: {:?}", path);
index 6a7672ef5344c1bb570610f2574250fbee932355..0ec7281b9c36ca7f724bfac8b029633910270a48 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 6a7672ef5344c1bb570610f2574250fbee932355
+Subproject commit 0ec7281b9c36ca7f724bfac8b029633910270a48
index f05a1038b59cd4217e58b3aef7a0751a0efd01e4..9abf6fca9c7288cb3bb99c0f7627f94b7930ee98 160000 (submodule)
@@ -1 +1 @@
-Subproject commit f05a1038b59cd4217e58b3aef7a0751a0efd01e4
+Subproject commit 9abf6fca9c7288cb3bb99c0f7627f94b7930ee98
index 3fd67366a8ca4aaac7c0cc18e64ce7612c5e0a87..db856a1dcf94fe4fc2defe721673bd1c76c5fd2e 100644 (file)
@@ -559,7 +559,7 @@ fn parse_env(&self, line: &str, name: &str) -> Option<(String, String)> {
             let mut strs: Vec<String> = nv.splitn(2, '=').map(str::to_owned).collect();
 
             match strs.len() {
-                1 => (strs.pop().unwrap(), "".to_owned()),
+                1 => (strs.pop().unwrap(), String::new()),
                 2 => {
                     let end = strs.pop().unwrap();
                     (strs.pop().unwrap(), end)
index b136173082600f58eff31dd665b7a15c3aee4b2c..24b575aae12f9f44c6a5c90e13b3a10ccce1c9ad 100644 (file)
@@ -2963,6 +2963,13 @@ fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> S
             normalized = normalized.replace("\\n", "\n");
         }
 
+        // If there are `$SRC_DIR` normalizations with line and column numbers, then replace them
+        // with placeholders as we do not want tests needing updated when compiler source code
+        // changes.
+        // eg. $SRC_DIR/libcore/mem.rs:323:14 becomes $SRC_DIR/libcore/mem.rs:LL:COL
+        normalized = Regex::new("SRC_DIR(.+):\\d+:\\d+").unwrap()
+            .replace_all(&normalized, "SRC_DIR$1:LL:COL").into_owned();
+
         normalized = normalized.replace("\\\\", "\\") // denormalize for paths on windows
               .replace("\\", "/") // normalize for paths on windows
               .replace("\r\n", "\n") // normalize for linebreaks on windows
index f76ea3ca16ed22dde8ef929db74a4b4df6f2f899..2a9b88b8b419d094fb2185c0ca31c28d31bdca00 160000 (submodule)
@@ -1 +1 @@
-Subproject commit f76ea3ca16ed22dde8ef929db74a4b4df6f2f899
+Subproject commit 2a9b88b8b419d094fb2185c0ca31c28d31bdca00
index 9e4d8d520390c6aeebc33260026c6ae2946c67ac..e67fd48f1aa2a31daee70dc3e80621077a31c52d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 9e4d8d520390c6aeebc33260026c6ae2946c67ac
+Subproject commit e67fd48f1aa2a31daee70dc3e80621077a31c52d
index 8c947bbbcddba2c30a6c2290cb6a9ef545c015c4..755b172dd1b2cb23e73fc13386e6753784de752b 100644 (file)
@@ -22,23 +22,28 @@ syn = { version = "0.14", features = ['extra-traits'] }
 [target.'cfg(windows)'.dependencies.winapi]
 version = "0.3"
 features = [
-  "profileapi",
+  "basetsd",
+  "consoleapi",
+  "errhandlingapi",
+  "jobapi",
+  "jobapi2",
+  "lmcons",
   "memoryapi",
   "minschannel",
-  "securitybaseapi",
-  "jobapi2",
-  "schannel",
-  "sysinfoapi",
-  "jobapi",
-  "synchapi",
-  "wincrypt",
-  "winbase",
   "minwinbase",
   "ntsecapi",
-  "basetsd",
   "ntstatus",
+  "profileapi",
+  "processenv",
   "psapi",
+  "schannel",
+  "securitybaseapi",
+  "shellapi",
+  "synchapi",
+  "sysinfoapi",
   "timezoneapi",
-  "lmcons",
+  "userenv",
+  "winbase",
   "wincon",
+  "wincrypt",
 ]
index 03bcda513fd8494ed60e599c468a6b55410175e4..68a4b7898575d0765135275d1904225e5c58fc1d 100644 (file)
@@ -50,6 +50,7 @@
     "colored",            // MPL-2.0, rustfmt
     "ordslice",           // Apache-2.0, rls
     "cloudabi",           // BSD-2-Clause, (rls -> crossbeam-channel 0.2 -> rand 0.5)
+    "ryu",                // Apache-2.0, rls/cargo/... (b/c of serde)
 ];
 
 /// Which crates to check against the whitelist?
     Crate("bitflags"),
     Crate("byteorder"),
     Crate("cc"),
+    Crate("cfg-if"),
     Crate("chalk-engine"),
     Crate("chalk-macros"),
-    Crate("cfg-if"),
+    Crate("cloudabi"),
     Crate("cmake"),
     Crate("crossbeam-deque"),
     Crate("crossbeam-epoch"),
     Crate("pkg-config"),
     Crate("quick-error"),
     Crate("rand"),
+    Crate("rand_core"),
     Crate("redox_syscall"),
     Crate("redox_termios"),
     Crate("regex"),
     Crate("unicode-width"),
     Crate("unreachable"),
     Crate("utf8-ranges"),
+    Crate("version_check"),
     Crate("void"),
     Crate("winapi"),
     Crate("winapi-build"),
index 1dc36221bd2898d4cbe3aea991e6464c7a1c9778..74f66c0a0516921deebd4d8d54e2993b4f35ecec 100644 (file)
@@ -252,7 +252,7 @@ pub fn collect_lib_features(base_src_path: &Path) -> Features {
     // add it to the set of known library features so we can still generate docs.
     lib_features.insert("compiler_builtins_lib".to_owned(), Feature {
         level: Status::Unstable,
-        since: "".to_owned(),
+        since: String::new(),
         has_gate_test: false,
         tracking_issue: None,
     });
index f2107f92debd2d915bcc01779f698bb3d9996d02..c4bd0bbd03ca3b195168b3fd1d7daba4860ff359 100644 (file)
@@ -76,8 +76,6 @@ fn filter_dirs(path: &Path) -> bool {
         "src/tools/miri",
         "src/tools/lld",
         "src/tools/lldb",
-        "src/librustc/mir/interpret",
-        "src/librustc_mir/interpret",
         "src/target",
         "src/stdsimd",
     ];
index f2f35f0f586023ba431d18a90a0c95bb8d5c7869..6b431ccda0883e9abc8d3a50bd12d86fc8857f4f 100644 (file)
@@ -17,7 +17,6 @@
 //! * No trailing whitespace
 //! * No CR characters
 //! * No `TODO` or `XXX` directives
-//! * A valid license header is at the top
 //! * No unexplained ` ```ignore ` or ` ```rust,ignore ` doc tests
 //!
 //! A number of these checks can be opted-out of with various directives like
 use std::path::Path;
 
 const COLS: usize = 100;
-const LICENSE: &'static str = "\
-Copyright <year> 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 UNEXPLAINED_IGNORE_DOCTEST_INFO: &str = r#"unexplained "```ignore" doctest; try one:
 
@@ -168,9 +157,6 @@ pub fn check(path: &Path, bad: &mut bool) {
                 trailing_new_lines = 0;
             }
         }
-        if !licenseck(file, &contents) {
-            tidy_error!(bad, "{}: incorrect license", file.display());
-        }
         match trailing_new_lines {
             0 => tidy_error!(bad, "{}: missing trailing newline", file.display()),
             1 | 2 => {}
@@ -178,42 +164,3 @@ pub fn check(path: &Path, bad: &mut bool) {
         };
     })
 }
-
-fn licenseck(file: &Path, contents: &str) -> bool {
-    if contents.contains("ignore-license") {
-        return true
-    }
-    let exceptions = [
-        "libstd/sync/mpsc/mpsc_queue.rs",
-        "libstd/sync/mpsc/spsc_queue.rs",
-    ];
-    if exceptions.iter().any(|f| file.ends_with(f)) {
-        return true
-    }
-
-    // Skip the BOM if it's there
-    let bom = "\u{feff}";
-    let contents = if contents.starts_with(bom) {&contents[3..]} else {contents};
-
-    // See if the license shows up in the first 100 lines
-    let lines = contents.lines().take(100).collect::<Vec<_>>();
-    lines.windows(LICENSE.lines().count()).any(|window| {
-        let offset = if window.iter().all(|w| w.starts_with("//")) {
-            2
-        } else if window.iter().all(|w| w.starts_with('#')) {
-            1
-        } else if window.iter().all(|w| w.starts_with(" *")) {
-            2
-        } else {
-            return false
-        };
-        window.iter().map(|a| a[offset..].trim())
-              .zip(LICENSE.lines()).all(|(a, b)| {
-            a == b || match b.find("<year>") {
-                Some(i) => a.starts_with(&b[..i]) && a.ends_with(&b[i+6..]),
-                None => false,
-            }
-        })
-    })
-
-}