]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #54257 - alexcrichton:wasm-math-symbols, r=TimNN
authorkennytm <kennytm@gmail.com>
Thu, 20 Sep 2018 13:36:21 +0000 (21:36 +0800)
committerGitHub <noreply@github.com>
Thu, 20 Sep 2018 13:36:21 +0000 (21:36 +0800)
Switch wasm math symbols to their original names

The names `Math_*` were given to help undefined symbol messages indicate how to
implement them, but these are all implemented in compiler-rt now so there's no
need to rename them! This change should make it so wasm binaries by default, no
matter the math symbols used, will not have unresolved symbols.

439 files changed:
src/Cargo.lock
src/bootstrap/builder.rs
src/bootstrap/check.rs
src/bootstrap/compile.rs
src/bootstrap/doc.rs
src/bootstrap/lib.rs
src/bootstrap/tool.rs
src/doc/README.md [deleted file]
src/doc/index.md
src/doc/unstable-book/src/language-features/self-struct-ctor.md [new file with mode: 0644]
src/liballoc/boxed.rs
src/liballoc/lib.rs
src/liballoc/pin.rs [deleted file]
src/liballoc/rc.rs
src/liballoc/sync.rs
src/liballoc/vec.rs
src/libcore/ffi.rs [new file with mode: 0644]
src/libcore/future/future.rs
src/libcore/future/future_obj.rs
src/libcore/lib.rs
src/libcore/marker.rs
src/libcore/nonzero.rs
src/libcore/option.rs
src/libcore/pin.rs
src/libcore/slice/mod.rs
src/libcore/tests/lib.rs
src/libcore/time.rs
src/libproc_macro/diagnostic.rs
src/libproc_macro/lib.rs
src/librustc/cfg/construct.rs
src/librustc/hir/check_attr.rs
src/librustc/hir/def.rs
src/librustc/hir/def_id.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/blocks.rs
src/librustc/hir/map/collector.rs
src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/definitions.rs
src/librustc/hir/map/hir_id_validator.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/ich/impls_hir.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs
src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
src/librustc/infer/error_reporting/nice_region_error/util.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/region.rs
src/librustc/middle/stability.rs
src/librustc/mir/traversal.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/select.rs
src/librustc/ty/context.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/query/mod.rs
src/librustc/ty/query/on_disk_cache.rs
src/librustc/ty/query/plumbing.rs
src/librustc/ty/sty.rs
src/librustc/util/ppaux.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
src/librustc_codegen_llvm/debuginfo/metadata.rs
src/librustc_codegen_llvm/debuginfo/type_names.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/librustc_codegen_llvm/mir/analyze.rs
src/librustc_codegen_llvm/mir/mod.rs
src/librustc_codegen_llvm/mir/rvalue.rs
src/librustc_data_structures/array_vec.rs [deleted file]
src/librustc_data_structures/bit_set.rs [new file with mode: 0644]
src/librustc_data_structures/bitslice.rs [deleted file]
src/librustc_data_structures/bitvec.rs [deleted file]
src/librustc_data_structures/flock.rs
src/librustc_data_structures/graph/implementation/mod.rs
src/librustc_data_structures/indexed_set.rs [deleted file]
src/librustc_data_structures/indexed_vec.rs
src/librustc_data_structures/lib.rs
src/librustc_data_structures/stable_hasher.rs
src/librustc_data_structures/transitive_relation.rs
src/librustc_data_structures/work_queue.rs
src/librustc_driver/driver.rs
src/librustc_driver/test.rs
src/librustc_errors/Cargo.toml
src/librustc_errors/diagnostic.rs
src/librustc_errors/diagnostic_builder.rs
src/librustc_errors/lib.rs
src/librustc_errors/lock.rs
src/librustc_lint/builtin.rs
src/librustc_lint/nonstandard_style.rs
src/librustc_lint/types.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/locator.rs
src/librustc_mir/borrow_check/borrow_set.rs
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/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/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/liveness/trace.rs
src/librustc_mir/build/block.rs
src/librustc_mir/build/cfg.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/matches/test.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/dataflow/at_location.rs
src/librustc_mir/dataflow/graphviz.rs
src/librustc_mir/dataflow/impls/borrowed_locals.rs
src/librustc_mir/dataflow/impls/borrows.rs
src/librustc_mir/dataflow/impls/mod.rs
src/librustc_mir/dataflow/impls/storage_liveness.rs
src/librustc_mir/dataflow/mod.rs
src/librustc_mir/dataflow/move_paths/mod.rs
src/librustc_mir/hair/cx/block.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/pattern/check_match.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/terminator.rs
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/item.rs
src/librustc_mir/transform/elaborate_drops.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/remove_noop_landing_pads.rs
src/librustc_mir/transform/rustc_peek.rs
src/librustc_mir/transform/simplify.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_mir/util/liveness.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/loops.rs
src/librustc_passes/rvalue_promotion.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/lib.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/intrinsic.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/lib.rs
src/librustdoc/clean/inline.rs
src/librustdoc/core.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/lib.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/visit_ast.rs
src/libserialize/json.rs
src/libserialize/opaque.rs
src/libserialize/serialize.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/table.rs
src/libstd/ffi/mod.rs
src/libstd/ffi/os_str.rs
src/libstd/future.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/net/addr.rs
src/libstd/os/raw/mod.rs
src/libstd/panic.rs
src/libstd/primitive_docs.rs
src/libstd/sys_common/net.rs
src/libstd/thread/mod.rs
src/libsyntax/config.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/feature_gate.rs
src/libsyntax/lib.rs
src/libsyntax/parse/parser.rs
src/libsyntax/ptr.rs
src/libsyntax_ext/format.rs
src/libsyntax_ext/test.rs
src/test/compile-fail-fulldeps/proc-macro/auxiliary/attr_proc_macro.rs [deleted file]
src/test/compile-fail-fulldeps/proc-macro/auxiliary/bang_proc_macro.rs [deleted file]
src/test/compile-fail-fulldeps/proc-macro/macro-use-attr.rs [deleted file]
src/test/compile-fail-fulldeps/proc-macro/macro-use-bang.rs [deleted file]
src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs
src/test/mir-opt/validate_1.rs
src/test/mir-opt/validate_3.rs
src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile
src/test/run-pass-fulldeps/newtype_index.rs [new file with mode: 0644]
src/test/run-pass/async-await.rs
src/test/run-pass/futures-api.rs
src/test/rustdoc-js/pinbox-new.js [deleted file]
src/test/rustdoc-js/vec-new.js
src/test/rustdoc/issue-53812.rs [new file with mode: 0644]
src/test/rustdoc/keyword.rs
src/test/ui-fulldeps/attribute-order-restricted.rs [new file with mode: 0644]
src/test/ui-fulldeps/attribute-order-restricted.stderr [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/auxiliary/attr_proc_macro.rs [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/auxiliary/bang_proc_macro.rs [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed-2.rs [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed.rs [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/auxiliary/multispan.rs [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/derive-helper-shadowed.rs [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.rs
src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr
src/test/ui-fulldeps/proc-macro/macro-use-attr.rs [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/macro-use-bang.rs [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/multispan.rs [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/multispan.stderr [new file with mode: 0644]
src/test/ui/E0596.ast.stderr
src/test/ui/asm/asm-out-assign-imm.nll.stderr
src/test/ui/assign-imm-local-twice.ast.nll.stderr
src/test/ui/assign-imm-local-twice.ast.stderr
src/test/ui/assign-imm-local-twice.mir.stderr
src/test/ui/assign-imm-local-twice.rs
src/test/ui/augmented-assignments.nll.stderr
src/test/ui/augmented-assignments.rs
src/test/ui/augmented-assignments.stderr
src/test/ui/bind-by-move/bind-by-move-no-guards.nll.stderr [new file with mode: 0644]
src/test/ui/bind-by-move/bind-by-move-no-guards.rs
src/test/ui/bind-by-move/bind-by-move-no-guards.stderr
src/test/ui/borrowck/borrowck-access-permissions.ast.stderr
src/test/ui/borrowck/borrowck-argument.stderr
src/test/ui/borrowck/borrowck-asm.ast.nll.stderr
src/test/ui/borrowck/borrowck-asm.mir.stderr
src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr
src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr
src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr
src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr
src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.nll.stderr
src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.nll.stderr
src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.nll.stderr
src/test/ui/borrowck/borrowck-match-binding-is-assignment.mir.stderr
src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr
src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr
src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr [new file with mode: 0644]
src/test/ui/borrowck/borrowck-overloaded-call.stderr
src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr
src/test/ui/borrowck/borrowck-unboxed-closures.stderr
src/test/ui/borrowck/immutable-arg.stderr
src/test/ui/borrowck/issue-41962.rs
src/test/ui/borrowck/issue-41962.stderr
src/test/ui/borrowck/mutability-errors.stderr
src/test/ui/borrowck/reassignment_immutable_fields.stderr
src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr
src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr
src/test/ui/codemap_tests/huge_multispan_highlight.stderr
src/test/ui/command-line-diagnostics.nll.stderr
src/test/ui/consts/const-eval/zst_operand_eval.rs [new file with mode: 0644]
src/test/ui/did_you_mean/issue-35937.stderr
src/test/ui/did_you_mean/issue-39544.stderr
src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs [new file with mode: 0644]
src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0008.nll.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0301.nll.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-dropck-ugeh-2.stderr
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-self-struct-ctor.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-self-struct-ctor.stderr [new file with mode: 0644]
src/test/ui/immut-function-arguments.ast.stderr
src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr
src/test/ui/invalid/invalid-crate-type.rs
src/test/ui/invalid/invalid-crate-type.stderr
src/test/ui/issue-53692.rs [new file with mode: 0644]
src/test/ui/issue-53692.stderr [new file with mode: 0644]
src/test/ui/issues/issue-11692-2.rs
src/test/ui/issues/issue-11692-2.stderr
src/test/ui/issues/issue-17385.nll.stderr
src/test/ui/issues/issue-36082.ast.nll.stderr
src/test/ui/issues/issue-36082.mir.stderr
src/test/ui/issues/issue-36082.rs
src/test/ui/issues/issue-36400.stderr
src/test/ui/issues/issue-45199.ast.nll.stderr
src/test/ui/issues/issue-45199.ast.stderr
src/test/ui/issues/issue-45199.mir.stderr
src/test/ui/issues/issue-45199.rs
src/test/ui/issues/issue-52489.rs
src/test/ui/issues/issue-52489.stderr
src/test/ui/issues/issue-53675-a-test-called-panic.rs [new file with mode: 0644]
src/test/ui/issues/issue-5500-1.ast.stderr
src/test/ui/issues/issue-5500-1.mir.stderr
src/test/ui/keyword/keyword-self-as-identifier.rs
src/test/ui/keyword/keyword-self-as-identifier.stderr
src/test/ui/lifetimes/borrowck-let-suggestion.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr
src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr
src/test/ui/lint/issue-54099-camel-case-underscore-types.rs [new file with mode: 0644]
src/test/ui/lint/lint-non-camel-case-types.rs
src/test/ui/lint/lint-non-camel-case-types.stderr
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.nll.stderr
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.stderr
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.mir.stderr
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.nll.stderr
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.stderr
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.mir.stderr
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.nll.stderr
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.stderr
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.mir.stderr
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.nll.stderr
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.stderr
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.mir.stderr
src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs
src/test/ui/liveness/liveness-move-in-while.nll.stderr
src/test/ui/macros/macro-path-prelude-fail-3.rs
src/test/ui/macros/macro-path-prelude-fail-3.stderr
src/test/ui/macros/macro-path-prelude-fail-4.rs [new file with mode: 0644]
src/test/ui/macros/macro-path-prelude-fail-4.stderr [new file with mode: 0644]
src/test/ui/macros/span-covering-argument-1.stderr
src/test/ui/mismatched_types/numeric-literal-cast.rs [new file with mode: 0644]
src/test/ui/mismatched_types/numeric-literal-cast.stderr [new file with mode: 0644]
src/test/ui/mut/mut-pattern-internal-mutability.ast.nll.stderr
src/test/ui/mut/mut-pattern-internal-mutability.mir.stderr
src/test/ui/mut/mut-suggestion.nll.stderr
src/test/ui/mut/mut-suggestion.rs
src/test/ui/mut/mut-suggestion.stderr
src/test/ui/mut/mutable-class-fields.ast.stderr
src/test/ui/nll/borrowed-temporary-error.stderr
src/test/ui/nll/issue-52669.rs [new file with mode: 0644]
src/test/ui/nll/issue-52669.stderr [new file with mode: 0644]
src/test/ui/nll/issue-53807.nll.stderr [new file with mode: 0644]
src/test/ui/nll/issue-53807.rs [new file with mode: 0644]
src/test/ui/nll/issue-53807.stderr [new file with mode: 0644]
src/test/ui/nll/move-subpaths-moves-root.rs [new file with mode: 0644]
src/test/ui/nll/move-subpaths-moves-root.stderr [new file with mode: 0644]
src/test/ui/no-capture-arc.nll.stderr
src/test/ui/no-reuse-move-arc.nll.stderr
src/test/ui/panic-implementation/panic-implementation-deprecated.stderr
src/test/ui/regions/regions-var-type-out-of-scope.nll.stderr
src/test/ui/resolve/tuple-struct-alias.rs
src/test/ui/resolve/tuple-struct-alias.stderr
src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs [new file with mode: 0644]
src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr [new file with mode: 0644]
src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr [new file with mode: 0644]
src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr [new file with mode: 0644]
src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr [new file with mode: 0644]
src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr [new file with mode: 0644]
src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs [new file with mode: 0644]
src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs [new file with mode: 0644]
src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs [new file with mode: 0644]
src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr [new file with mode: 0644]
src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs [new file with mode: 0644]
src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr [new file with mode: 0644]
src/test/ui/rfc-2126-extern-absolute-paths/meta.rs [new file with mode: 0644]
src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr [new file with mode: 0644]
src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs
src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr
src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs
src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr
src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs
src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr
src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs [new file with mode: 0644]
src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr [new file with mode: 0644]
src/test/ui/rfc-2126-extern-absolute-paths/single-segment.rs
src/test/ui/rfc-2126-extern-absolute-paths/single-segment.stderr
src/test/ui/rfc-2126-extern-in-paths/non-existent-1.rs
src/test/ui/rfc-2126-extern-in-paths/non-existent-1.stderr
src/test/ui/rfc-2126-extern-in-paths/non-existent-2.rs
src/test/ui/rfc-2126-extern-in-paths/non-existent-2.stderr
src/test/ui/rfc-2126-extern-in-paths/non-existent-3.rs
src/test/ui/rfc-2126-extern-in-paths/non-existent-3.stderr
src/test/ui/rfc-2126-extern-in-paths/single-segment.rs
src/test/ui/rfc-2126-extern-in-paths/single-segment.stderr
src/test/ui/run-pass/issues/issue-52140/main.rs
src/test/ui/run-pass/issues/issue-52141/main.rs
src/test/ui/run-pass/issues/issue-52705/main.rs
src/test/ui/run-pass/macros/macro-comma-support.rs
src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs
src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/extern.rs
src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/whitelisted.rs [new file with mode: 0644]
src/test/ui/run-pass/rfcs/rfc-2302-self-struct-ctor.rs [new file with mode: 0644]
src/test/ui/run-pass/uniform-paths/basic-nested.rs
src/test/ui/run-pass/uniform-paths/basic.rs
src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed
src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs
src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr
src/test/ui/rust-2018/extern-crate-idiomatic.fixed
src/test/ui/rust-2018/extern-crate-idiomatic.rs
src/test/ui/rust-2018/issue-54006.rs [new file with mode: 0644]
src/test/ui/rust-2018/issue-54006.stderr [new file with mode: 0644]
src/test/ui/rust-2018/remove-extern-crate.fixed
src/test/ui/rust-2018/remove-extern-crate.rs
src/test/ui/rust-2018/remove-extern-crate.stderr
src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs [new file with mode: 0644]
src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr [new file with mode: 0644]
src/test/ui/rust-2018/uniform-paths/issue-54253.rs [new file with mode: 0644]
src/test/ui/rust-2018/uniform-paths/issue-54253.stderr [new file with mode: 0644]
src/test/ui/self/self_type_keyword-2.rs
src/test/ui/self/self_type_keyword-2.stderr
src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr
src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr
src/test/ui/span/borrowck-let-suggestion-suffixes.nll.stderr
src/test/ui/span/borrowck-object-mutability.stderr
src/test/ui/span/borrowck-ref-into-rvalue.nll.stderr
src/test/ui/span/issue-15480.nll.stderr
src/test/ui/span/regions-close-over-borrowed-ref-in-obj.nll.stderr
src/test/ui/span/slice-borrow.nll.stderr
src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.stderr
src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr
src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr
src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr
src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr
src/test/ui/writing-to-immutable-vec.stderr
src/tools/clippy
src/tools/miri
src/tools/rls

index 989655ffb4f5c5b608b5541244d2d61d5feeacb7..5ac838cadc2a4bdfe501bb8e18cf845ca28d5eae 100644 (file)
@@ -12,7 +12,7 @@ version = "0.0.0"
 dependencies = [
  "compiler_builtins 0.0.0",
  "core 0.0.0",
- "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.5.5 (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.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
  "libc 0.0.0",
@@ -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.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -131,7 +131,7 @@ name = "bootstrap"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (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)",
@@ -198,7 +198,7 @@ dependencies = [
  "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)",
+ "libgit2-sys 0.7.8 (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)",
@@ -240,7 +240,7 @@ version = "0.1.0"
 
 [[package]]
 name = "cc"
-version = "1.0.22"
+version = "1.0.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -356,7 +356,7 @@ name = "cmake"
 version = "0.1.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -387,7 +387,7 @@ dependencies = [
 name = "compiler_builtins"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -433,7 +433,7 @@ dependencies = [
 name = "core"
 version = "0.0.0"
 dependencies = [
- "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -475,7 +475,7 @@ dependencies = [
  "crossbeam-epoch 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "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)",
+ "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -549,7 +549,7 @@ name = "curl"
 version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "curl-sys 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -561,12 +561,12 @@ dependencies = [
 
 [[package]]
 name = "curl-sys"
-version = "0.4.8"
+version = "0.4.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (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.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.22 (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.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -808,6 +808,16 @@ name = "getopts"
 version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "getset"
+version = "0.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "git2"
 version = "0.7.5"
@@ -815,7 +825,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "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)",
+ "libgit2-sys 0.7.8 (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)",
@@ -1063,27 +1073,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libgit2-sys"
-version = "0.7.7"
+version = "0.7.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "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)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.10 (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.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "libz-sys 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.22 (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.13 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "libssh2-sys"
-version = "0.2.10"
+version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (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.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.22 (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.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1091,10 +1100,10 @@ dependencies = [
 
 [[package]]
 name = "libz-sys"
-version = "1.0.20"
+version = "1.0.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (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.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1142,7 +1151,7 @@ name = "lzma-sys"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (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.13 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1246,7 +1255,7 @@ name = "miniz-sys"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1268,9 +1277,8 @@ dependencies = [
  "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.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)",
+ "vergen 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1356,7 +1364,7 @@ name = "openssl-src"
 version = "110.0.7+1.1.0i"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1364,7 +1372,7 @@ name = "openssl-sys"
 version = "0.9.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (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.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)",
@@ -1444,7 +1452,7 @@ version = "0.3.0"
 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.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.5.5 (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)",
 ]
@@ -1571,7 +1579,7 @@ dependencies = [
 name = "profiler_builtins"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
@@ -1644,7 +1652,7 @@ dependencies = [
 
 [[package]]
 name = "rand"
-version = "0.5.4"
+version = "0.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1767,6 +1775,7 @@ dependencies = [
  "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.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.5.5 (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.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-analysis 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2084,7 +2093,7 @@ dependencies = [
 name = "rustc_codegen_llvm"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "memmap 0.6.2 (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.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2173,6 +2182,7 @@ name = "rustc_errors"
 version = "0.0.0"
 dependencies = [
  "atty 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)",
  "rustc_cratesio_shim 0.0.0",
  "rustc_data_structures 0.0.0",
  "serialize 0.0.0",
@@ -2191,7 +2201,7 @@ version = "0.0.0"
 dependencies = [
  "graphviz 0.0.0",
  "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.5.5 (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",
@@ -2217,7 +2227,7 @@ name = "rustc_llvm"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2620,14 +2630,14 @@ dependencies = [
  "alloc_jemalloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (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.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_asan 0.0.0",
  "rustc_lsan 0.0.0",
  "rustc_msan 0.0.0",
@@ -2794,7 +2804,7 @@ 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.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.5.5 (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)",
@@ -3014,6 +3024,17 @@ name = "vec_map"
 version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "vergen"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getset 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "version_check"
 version = "0.1.4"
@@ -3123,7 +3144,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "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_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1"
-"checksum cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4a6007c146fdd28d4512a794b07ffe9d8e89e6bf86e2e0c4ddff2e1fb54a0007"
+"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16"
 "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"
@@ -3147,7 +3168,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "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.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 curl-sys 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2edeedbbd9c7cdccb14bfb5dfbcc108901f99d3411eb5bab3758789377c5bec4"
 "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"
@@ -3176,6 +3197,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c"
 "checksum fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34dd4c507af68d37ffef962063dfa1944ce0dd4d5b82043dbab1dabe088610c3"
 "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05"
+"checksum getset 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54c7f36a235738bb25904d6a2b3dbb28f6f5736cd3918c4bf80d6bb236200782"
 "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"
@@ -3201,9 +3223,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "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.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 libgit2-sys 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "44b1900be992dd5698bd3bb422921e336306d413e2860e6ba3b50e62e6219c4c"
+"checksum libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d"
+"checksum libz-sys 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "65ff614643d7635dfa2151913d95c4ee90ee1fe15d9e0980f4dcb1a7e5837c18"
 "checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54"
 "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
 "checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2"
@@ -3262,7 +3284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5"
 "checksum racer 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4bc3847329b20ff5ba56c298938c179ae9911af15c9c10553f683b65164533"
 "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 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
 "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"
 "checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8"
@@ -3348,6 +3370,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "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 vergen 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9a16834fc61e1492c07dae49b6c14b55f8b1d43a5f5f9e9a2ecc063f47b9f93c"
 "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.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "af464bc7be7b785c7ac72e266a6b67c4c9070155606f51655a650a6686204e35"
index 2f7f3058b04735bfb97b33af9e53291a7783ae8d..b842bc43f5baad82c2ca507f581d59c2b5ed9471 100644 (file)
@@ -708,6 +708,80 @@ pub fn cargo(
     ) -> Command {
         let mut cargo = Command::new(&self.initial_cargo);
         let out_dir = self.stage_out(compiler, mode);
+
+        // command specific path, we call clear_if_dirty with this
+        let mut my_out = match cmd {
+            "build" => self.cargo_out(compiler, mode, target),
+
+            // This is the intended out directory for crate documentation.
+            "doc" =>  self.crate_doc_out(target),
+
+            _ => self.stage_out(compiler, mode),
+        };
+
+        // This is for the original compiler, but if we're forced to use stage 1, then
+        // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since
+        // we copy the libs forward.
+        let cmp = if self.force_use_stage1(compiler, target) {
+            self.compiler(1, compiler.host)
+        } else {
+            compiler
+        };
+
+        let libstd_stamp = match cmd {
+            "check" => check::libstd_stamp(self, cmp, target),
+            _ => compile::libstd_stamp(self, cmp, target),
+        };
+
+        let libtest_stamp = match cmd {
+            "check" => check::libtest_stamp(self, cmp, target),
+            _ => compile::libstd_stamp(self, cmp, target),
+        };
+
+        let librustc_stamp = match cmd {
+            "check" => check::librustc_stamp(self, cmp, target),
+            _ => compile::librustc_stamp(self, cmp, target),
+        };
+
+        if cmd == "doc" {
+            if mode == Mode::Rustc || mode == Mode::ToolRustc || mode == Mode::Codegen {
+                // This is the intended out directory for compiler documentation.
+                my_out = self.compiler_doc_out(target);
+            }
+            let rustdoc = self.rustdoc(compiler.host);
+            self.clear_if_dirty(&my_out, &rustdoc);
+        } else if cmd != "test" {
+            match mode {
+                Mode::Std => {
+                    self.clear_if_dirty(&my_out, &self.rustc(compiler));
+                },
+                Mode::Test => {
+                    self.clear_if_dirty(&my_out, &libstd_stamp);
+                },
+                Mode::Rustc => {
+                    self.clear_if_dirty(&my_out, &self.rustc(compiler));
+                    self.clear_if_dirty(&my_out, &libstd_stamp);
+                    self.clear_if_dirty(&my_out, &libtest_stamp);
+                },
+                Mode::Codegen => {
+                    self.clear_if_dirty(&my_out, &librustc_stamp);
+                },
+                Mode::ToolBootstrap => { },
+                Mode::ToolStd => {
+                    self.clear_if_dirty(&my_out, &libstd_stamp);
+                },
+                Mode::ToolTest => {
+                    self.clear_if_dirty(&my_out, &libstd_stamp);
+                    self.clear_if_dirty(&my_out, &libtest_stamp);
+                },
+                Mode::ToolRustc => {
+                    self.clear_if_dirty(&my_out, &libstd_stamp);
+                    self.clear_if_dirty(&my_out, &libtest_stamp);
+                    self.clear_if_dirty(&my_out, &librustc_stamp);
+                },
+            }
+        }
+
         cargo
             .env("CARGO_TARGET_DIR", out_dir)
             .arg(cmd);
index 20cdfcb3d298134ebbab2d4900c741e70c7b8080..11463c1a056ec5e120961bcf6a0b7779542b8f83 100644 (file)
@@ -12,7 +12,7 @@
 
 use compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env, add_to_sysroot};
 use builder::{RunConfig, Builder, ShouldRun, Step};
-use tool::{self, prepare_tool_cargo, SourceType};
+use tool::{prepare_tool_cargo, SourceType};
 use {Compiler, Mode};
 use cache::{INTERNER, Interned};
 use std::path::PathBuf;
@@ -40,14 +40,11 @@ fn run(self, builder: &Builder) {
         let target = self.target;
         let compiler = builder.compiler(0, builder.config.build);
 
-        let out_dir = builder.stage_out(compiler, Mode::Std);
-        builder.clear_if_dirty(&out_dir, &builder.rustc(compiler));
-
         let mut cargo = builder.cargo(compiler, Mode::Std, target, "check");
         std_cargo(builder, &compiler, target, &mut cargo);
 
         let _folder = builder.fold_output(|| format!("stage{}-std", compiler.stage));
-        println!("Checking std artifacts ({} -> {})", &compiler.host, target);
+        builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
         run_cargo(builder,
                   &mut cargo,
                   vec![],
@@ -88,15 +85,13 @@ fn run(self, builder: &Builder) {
         let compiler = builder.compiler(0, builder.config.build);
         let target = self.target;
 
-        let stage_out = builder.stage_out(compiler, Mode::Rustc);
-        builder.clear_if_dirty(&stage_out, &libstd_stamp(builder, compiler, target));
-        builder.clear_if_dirty(&stage_out, &libtest_stamp(builder, compiler, target));
+        builder.ensure(Test { target });
 
         let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "check");
         rustc_cargo(builder, &mut cargo);
 
         let _folder = builder.fold_output(|| format!("stage{}-rustc", compiler.stage));
-        println!("Checking compiler artifacts ({} -> {})", &compiler.host, target);
+        builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target));
         run_cargo(builder,
                   &mut cargo,
                   vec![],
@@ -139,8 +134,7 @@ fn run(self, builder: &Builder) {
         let target = self.target;
         let backend = self.backend;
 
-        let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
-        builder.clear_if_dirty(&out_dir, &librustc_stamp(builder, compiler, target));
+        builder.ensure(Rustc { target });
 
         let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "check");
         cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
@@ -180,14 +174,13 @@ fn run(self, builder: &Builder) {
         let compiler = builder.compiler(0, builder.config.build);
         let target = self.target;
 
-        let out_dir = builder.stage_out(compiler, Mode::Test);
-        builder.clear_if_dirty(&out_dir, &libstd_stamp(builder, compiler, target));
+        builder.ensure(Std { target });
 
         let mut cargo = builder.cargo(compiler, Mode::Test, target, "check");
         test_cargo(builder, &compiler, target, &mut cargo);
 
         let _folder = builder.fold_output(|| format!("stage{}-test", compiler.stage));
-        println!("Checking test artifacts ({} -> {})", &compiler.host, target);
+        builder.info(&format!("Checking test artifacts ({} -> {})", &compiler.host, target));
         run_cargo(builder,
                   &mut cargo,
                   vec![],
@@ -223,10 +216,7 @@ fn run(self, builder: &Builder) {
         let compiler = builder.compiler(0, builder.config.build);
         let target = self.target;
 
-        let stage_out = builder.stage_out(compiler, Mode::ToolRustc);
-        builder.clear_if_dirty(&stage_out, &libstd_stamp(builder, compiler, target));
-        builder.clear_if_dirty(&stage_out, &libtest_stamp(builder, compiler, target));
-        builder.clear_if_dirty(&stage_out, &librustc_stamp(builder, compiler, target));
+        builder.ensure(Rustc { target });
 
         let mut cargo = prepare_tool_cargo(builder,
                                            compiler,
@@ -246,12 +236,7 @@ fn run(self, builder: &Builder) {
 
         let libdir = builder.sysroot_libdir(compiler, target);
         add_to_sysroot(&builder, &libdir, &rustdoc_stamp(builder, compiler, target));
-
-        builder.ensure(tool::CleanTools {
-            compiler,
-            target,
-            cause: Mode::Rustc,
-        });
+        builder.cargo(compiler, Mode::ToolRustc, target, "clean");
     }
 }
 
index c0661a773e3a71d900504f640025d69fd0ed2024..4205d5aebffa15dd967672ceaec79bd2c5eba874 100644 (file)
@@ -32,7 +32,6 @@
 use util::{exe, libdir, is_dylib, CiEnv};
 use {Compiler, Mode, GitRepo};
 use native;
-use tool;
 
 use cache::{INTERNER, Interned};
 use builder::{Step, RunConfig, ShouldRun, Builder};
@@ -107,8 +106,6 @@ fn run(self, builder: &Builder) {
             copy_musl_third_party_objects(builder, target, &libdir);
         }
 
-        let out_dir = builder.cargo_out(compiler, Mode::Std, target);
-        builder.clear_if_dirty(&out_dir, &builder.rustc(compiler));
         let mut cargo = builder.cargo(compiler, Mode::Std, target, "build");
         std_cargo(builder, &compiler, target, &mut cargo);
 
@@ -246,11 +243,7 @@ fn run(self, builder: &Builder) {
             copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir);
         }
 
-        builder.ensure(tool::CleanTools {
-            compiler: target_compiler,
-            target,
-            cause: Mode::Std,
-        });
+        builder.cargo(target_compiler, Mode::ToolStd, target, "clean");
     }
 }
 
@@ -387,8 +380,6 @@ fn run(self, builder: &Builder) {
             return;
         }
 
-        let out_dir = builder.cargo_out(compiler, Mode::Test, target);
-        builder.clear_if_dirty(&out_dir, &libstd_stamp(builder, compiler, target));
         let mut cargo = builder.cargo(compiler, Mode::Test, target, "build");
         test_cargo(builder, &compiler, target, &mut cargo);
 
@@ -448,11 +439,8 @@ fn run(self, builder: &Builder) {
                 target));
         add_to_sysroot(builder, &builder.sysroot_libdir(target_compiler, target),
                     &libtest_stamp(builder, compiler, target));
-        builder.ensure(tool::CleanTools {
-            compiler: target_compiler,
-            target,
-            cause: Mode::Test,
-        });
+
+        builder.cargo(target_compiler, Mode::ToolTest, target, "clean");
     }
 }
 
@@ -519,9 +507,6 @@ fn run(self, builder: &Builder) {
             compiler: builder.compiler(self.compiler.stage, builder.config.build),
             target: builder.config.build,
         });
-        let cargo_out = builder.cargo_out(compiler, Mode::Rustc, target);
-        builder.clear_if_dirty(&cargo_out, &libstd_stamp(builder, compiler, target));
-        builder.clear_if_dirty(&cargo_out, &libtest_stamp(builder, compiler, target));
 
         let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "build");
         rustc_cargo(builder, &mut cargo);
@@ -613,11 +598,7 @@ fn run(self, builder: &Builder) {
                  target));
         add_to_sysroot(builder, &builder.sysroot_libdir(target_compiler, target),
                        &librustc_stamp(builder, compiler, target));
-        builder.ensure(tool::CleanTools {
-            compiler: target_compiler,
-            target,
-            cause: Mode::Rustc,
-        });
+        builder.cargo(target_compiler, Mode::ToolRustc, target, "clean");
     }
 }
 
@@ -674,7 +655,6 @@ 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, "rustc");
         cargo.arg("--manifest-path")
index 9a5d78e58ea3fcfa7e529b87e56868dcb7de6aaa..17ccb04a7146d861a8eaaaccbad16e71a42bf07a 100644 (file)
@@ -455,7 +455,6 @@ fn run(self, builder: &Builder) {
         let out = builder.doc_out(target);
         t!(fs::create_dir_all(&out));
         let compiler = builder.compiler(stage, builder.config.build);
-        let rustdoc = builder.rustdoc(compiler.host);
         let compiler = if builder.force_use_stage1(compiler, target) {
             builder.compiler(1, compiler.host)
         } else {
@@ -480,7 +479,6 @@ fn run(self, builder: &Builder) {
         // This way rustdoc generates output directly into the output, and rustdoc
         // will also directly handle merging.
         let my_out = builder.crate_doc_out(target);
-        builder.clear_if_dirty(&my_out, &rustdoc);
         t!(symlink_dir_force(&builder.config, &my_out, &out_dir));
 
         let mut cargo = builder.cargo(compiler, Mode::Std, target, "doc");
@@ -535,7 +533,6 @@ fn run(self, builder: &Builder) {
         let out = builder.doc_out(target);
         t!(fs::create_dir_all(&out));
         let compiler = builder.compiler(stage, builder.config.build);
-        let rustdoc = builder.rustdoc(compiler.host);
         let compiler = if builder.force_use_stage1(compiler, target) {
             builder.compiler(1, compiler.host)
         } else {
@@ -551,7 +548,6 @@ fn run(self, builder: &Builder) {
 
         // See docs in std above for why we symlink
         let my_out = builder.crate_doc_out(target);
-        builder.clear_if_dirty(&my_out, &rustdoc);
         t!(symlink_dir_force(&builder.config, &my_out, &out_dir));
 
         let mut cargo = builder.cargo(compiler, Mode::Test, target, "doc");
@@ -603,7 +599,6 @@ fn run(self, builder: &Builder) {
         let out = builder.doc_out(target);
         t!(fs::create_dir_all(&out));
         let compiler = builder.compiler(stage, builder.config.build);
-        let rustdoc = builder.rustdoc(compiler.host);
         let compiler = if builder.force_use_stage1(compiler, target) {
             builder.compiler(1, compiler.host)
         } else {
@@ -619,7 +614,6 @@ fn run(self, builder: &Builder) {
 
         // See docs in std above for why we symlink
         let my_out = builder.crate_doc_out(target);
-        builder.clear_if_dirty(&my_out, &rustdoc);
         t!(symlink_dir_force(&builder.config, &my_out, &out_dir));
 
         let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc");
@@ -678,7 +672,6 @@ fn run(self, builder: &Builder) {
 
         // Get the correct compiler for this stage.
         let compiler = builder.compiler(stage, builder.config.build);
-        let rustdoc = builder.rustdoc(compiler.host);
         let compiler = if builder.force_use_stage1(compiler, target) {
             builder.compiler(1, compiler.host)
         } else {
@@ -699,7 +692,6 @@ fn run(self, builder: &Builder) {
         // We do not symlink to the same shared folder that already contains std library
         // documentation from previous steps as we do not want to include that.
         let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target).join("doc");
-        builder.clear_if_dirty(&out, &rustdoc);
         t!(symlink_dir_force(&builder.config, &out, &out_dir));
 
         // Build cargo command.
@@ -780,7 +772,6 @@ fn run(self, builder: &Builder) {
 
         // Get the correct compiler for this stage.
         let compiler = builder.compiler(stage, builder.config.build);
-        let rustdoc = builder.rustdoc(compiler.host);
         let compiler = if builder.force_use_stage1(compiler, target) {
             builder.compiler(1, compiler.host)
         } else {
@@ -803,7 +794,6 @@ fn run(self, builder: &Builder) {
             .join(target)
             .join("doc");
         t!(fs::create_dir_all(&out_dir));
-        builder.clear_if_dirty(&out, &rustdoc);
         t!(symlink_dir_force(&builder.config, &out, &out_dir));
 
         // Build cargo command.
index ed6a5f94d0d95fa1eb0adc2dd7a6d5a61066dbe4..6b88516bacd8a963481f4a8a80db03809b314f36 100644 (file)
@@ -352,6 +352,7 @@ pub enum Mode {
     /// Compile a tool which uses all libraries we compile (up to rustc).
     /// Doesn't use the stage0 compiler libraries like "other", and includes
     /// tools like rustdoc, cargo, rls, etc.
+    ToolTest,
     ToolStd,
     ToolRustc,
 }
@@ -572,6 +573,7 @@ fn stage_out(&self, compiler: Compiler, mode: Mode) -> PathBuf {
             Mode::Codegen => "-codegen",
             Mode::ToolBootstrap => "-bootstrap-tools",
             Mode::ToolStd => "-tools",
+            Mode::ToolTest => "-tools",
             Mode::ToolRustc => "-tools",
         };
         self.out.join(&*compiler.host)
index 04aaa970654730dd3c63a6aedbabddbb37b3d6d0..e5299761a159f76ef0dfa70d85d943b4faf1f3a0 100644 (file)
 use Compiler;
 use builder::{Step, RunConfig, ShouldRun, Builder};
 use util::{exe, add_lib_path};
-use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp};
+use compile;
 use native;
 use channel::GitInfo;
 use cache::Interned;
 use toolstate::ToolState;
 
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
-pub struct CleanTools {
-    pub compiler: Compiler,
-    pub target: Interned<String>,
-    pub cause: Mode,
-}
-
-impl Step for CleanTools {
-    type Output = ();
-
-    fn should_run(run: ShouldRun) -> ShouldRun {
-        run.never()
-    }
-
-    fn run(self, builder: &Builder) {
-        let compiler = self.compiler;
-        let target = self.target;
-        let cause = self.cause;
-
-        // This is for the original compiler, but if we're forced to use stage 1, then
-        // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since
-        // we copy the libs forward.
-        let tools_dir = builder.stage_out(compiler, Mode::ToolRustc);
-        let compiler = if builder.force_use_stage1(compiler, target) {
-            builder.compiler(1, compiler.host)
-        } else {
-            compiler
-        };
-
-        for &cur_mode in &[Mode::Std, Mode::Test, Mode::Rustc] {
-            let stamp = match cur_mode {
-                Mode::Std => libstd_stamp(builder, compiler, target),
-                Mode::Test => libtest_stamp(builder, compiler, target),
-                Mode::Rustc => librustc_stamp(builder, compiler, target),
-                _ => panic!(),
-            };
-
-            if builder.clear_if_dirty(&tools_dir, &stamp) {
-                break;
-            }
-
-            // If we are a rustc tool, and std changed, we also need to clear ourselves out -- our
-            // dependencies depend on std. Therefore, we iterate up until our own mode.
-            if cause == cur_mode {
-                break;
-            }
-        }
-    }
-}
-
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub enum SourceType {
     InTree,
diff --git a/src/doc/README.md b/src/doc/README.md
deleted file mode 100644 (file)
index 5f25894..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-# Rust documentations
-
-## Building
-
-To generate all the docs, follow the "Building Documentation" instructions in
-the README in the root of the repository. This will convert the distributed
-Markdown docs to HTML and generate HTML doc for the books, 'std' and 'extra'
-libraries.
-
-To generate HTML documentation from one source file/crate, do something like:
-
-~~~~text
-rustdoc --output html-doc/ --output-format html ../src/libstd/path.rs
-~~~~
-
-(This, of course, requires a working build of the `rustdoc` tool.)
-
-## Additional notes
-
-To generate an HTML version of a doc from Markdown manually, you can do
-something like:
-
-~~~~text
-rustdoc reference.md
-~~~~
-
-(`reference.md` being the Rust Reference Manual.)
-
-An overview of how to use the `rustdoc` command is available [in the docs][1].
-Further details are available from the command line by with `rustdoc --help`.
-
-[1]: https://github.com/rust-lang/rust/blob/master/src/doc/rustdoc/src/what-is-rustdoc.md
index 11313ba99e1a6ea8398908ba514b96db585f8897..b1788d8c32f02aa70d6c61d4c3e3b96776bc8044 100644 (file)
@@ -43,6 +43,13 @@ Rust's standard library has [extensive API documentation](std/index.html),
 with explanations of how to use various things, as well as example code for
 accomplishing various tasks.
 
+<div>
+  <form action="std/index.html" method="get">
+    <input type="search" name="search"/>
+    <button>Search</button>
+  </form>
+</div>
+
 ## The Rustc Book
 
 [The Rustc Book](rustc/index.html) describes the Rust compiler, `rustc`.
diff --git a/src/doc/unstable-book/src/language-features/self-struct-ctor.md b/src/doc/unstable-book/src/language-features/self-struct-ctor.md
new file mode 100644 (file)
index 0000000..b4742c4
--- /dev/null
@@ -0,0 +1,33 @@
+# `self_struct_ctor`
+
+The tracking issue for this feature is: [#51994]
+[#51994]: https://github.com/rust-lang/rust/issues/51994
+
+------------------------
+
+The `self_struct_ctor` feature gate lets you use the special `Self`
+identifier as a constructor and a pattern.
+
+A simple example is:
+
+```rust
+#![feature(self_struct_ctor)]
+
+struct ST(i32, i32);
+
+impl ST {
+    fn new() -> Self {
+        ST(0, 1)
+    }
+
+    fn ctor() -> Self {
+        Self(1,2)           // constructed by `Self`, it is the same as `ST(1, 2)`
+    }
+
+    fn pattern(self) {
+        match self {
+            Self(x, y) => println!("{} {}", x, y), // used as a pattern
+        }
+    }
+}
+```
index 29ba433bec7f52ed8a9791baf2a0c176e14c8856..11b91591593ee79747883f2dbd65ce5a019b7ffa 100644 (file)
 use core::iter::FusedIterator;
 use core::marker::{Unpin, Unsize};
 use core::mem;
-use core::pin::PinMut;
+use core::pin::Pin;
 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.
@@ -97,6 +96,12 @@ impl<T> Box<T> {
     pub fn new(x: T) -> Box<T> {
         box x
     }
+
+    #[unstable(feature = "pin", issue = "49150")]
+    #[inline(always)]
+    pub fn pinned(x: T) -> Pin<Box<T>> {
+        (box x).into()
+    }
 }
 
 impl<T: ?Sized> Box<T> {
@@ -427,6 +432,16 @@ fn from(t: T) -> Self {
     }
 }
 
+#[unstable(feature = "pin", issue = "49150")]
+impl<T> From<Box<T>> for Pin<Box<T>> {
+    fn from(boxed: Box<T>) -> Self {
+        // It's not possible to move or replace the insides of a `Pin<Box<T>>`
+        // when `T: !Unpin`,  so it's safe to pin it directly without any
+        // additional requirements.
+        unsafe { Pin::new_unchecked(boxed) }
+    }
+}
+
 #[stable(feature = "box_from_slice", since = "1.17.0")]
 impl<'a, T: Copy> From<&'a [T]> for Box<[T]> {
     fn from(slice: &'a [T]) -> Box<[T]> {
@@ -789,8 +804,8 @@ unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
 impl<F: ?Sized + Future + Unpin> Future for Box<F> {
     type Output = F::Output;
 
-    fn poll(mut self: PinMut<Self>, cx: &mut Context) -> Poll<Self::Output> {
-        PinMut::new(&mut **self).poll(cx)
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        F::poll(Pin::new(&mut *self), cx)
     }
 }
 
@@ -804,8 +819,8 @@ fn into_raw(self) -> *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)
+        let pin: Pin<&mut F> = Pin::new_unchecked(&mut *ptr);
+        F::poll(pin, cx)
     }
 
     unsafe fn drop(ptr: *mut ()) {
@@ -843,9 +858,16 @@ fn from(boxed: Box<F>) -> Self {
     }
 }
 
-#[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) }
+#[unstable(feature = "futures_api", issue = "50547")]
+impl<'a, F: Future<Output = ()> + Send + 'a> From<Pin<Box<F>>> for FutureObj<'a, ()> {
+    fn from(boxed: Pin<Box<F>>) -> Self {
+        FutureObj::new(boxed)
+    }
+}
+
+#[unstable(feature = "futures_api", issue = "50547")]
+impl<'a, F: Future<Output = ()> + 'a> From<Pin<Box<F>>> for LocalFutureObj<'a, ()> {
+    fn from(boxed: Pin<Box<F>>) -> Self {
+        LocalFutureObj::new(boxed)
     }
 }
index 2d271fd0dca8dcb0adc68f7c53cf4bf8e6dc02af..b2303a02cb2651bb4168a86bff7dbbdd1e8bacfb 100644 (file)
@@ -160,7 +160,6 @@ 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
deleted file mode 100644 (file)
index 17bbc98..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-//! 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 fcd683e5e87f85e5f47024509a513a15720eb88b..9d951691a34e76b4847498e18649ee5cb0746159 100644 (file)
 use core::mem::{self, align_of_val, forget, size_of_val};
 use core::ops::Deref;
 use core::ops::CoerceUnsized;
+use core::pin::Pin;
 use core::ptr::{self, NonNull};
 use core::convert::From;
 use core::usize;
@@ -321,6 +322,11 @@ pub fn new(value: T) -> Rc<T> {
         }
     }
 
+    #[unstable(feature = "pin", issue = "49150")]
+    pub fn pinned(value: T) -> Pin<Rc<T>> {
+        unsafe { Pin::new_unchecked(Rc::new(value)) }
+    }
+
     /// Returns the contained value, if the `Rc` has exactly one strong reference.
     ///
     /// Otherwise, an [`Err`][result] is returned with the same `Rc` that was
index 8b4231dbdf6f3202563d7874d73faec4a5d8d460..116393bdad195b54375dcba6e8266af802bc4386 100644 (file)
@@ -26,6 +26,7 @@
 use core::mem::{self, align_of_val, size_of_val};
 use core::ops::Deref;
 use core::ops::CoerceUnsized;
+use core::pin::Pin;
 use core::ptr::{self, NonNull};
 use core::marker::{Unpin, Unsize, PhantomData};
 use core::hash::{Hash, Hasher};
@@ -297,6 +298,11 @@ pub fn new(data: T) -> Arc<T> {
         Arc { ptr: Box::into_raw_non_null(x), phantom: PhantomData }
     }
 
+    #[unstable(feature = "pin", issue = "49150")]
+    pub fn pinned(data: T) -> Pin<Arc<T>> {
+        unsafe { Pin::new_unchecked(Arc::new(data)) }
+    }
+
     /// Returns the contained value, if the `Arc` has exactly one strong reference.
     ///
     /// Otherwise, an [`Err`][result] is returned with the same `Arc` that was
index e9c1a3df518913cb709004445ee46e740dda94ac..7fc4453fec5b07986fa108b0c5a82fec43b663e9 100644 (file)
@@ -2410,9 +2410,8 @@ fn next(&mut self) -> Option<T> {
                     // same pointer.
                     self.ptr = arith_offset(self.ptr as *const i8, 1) as *mut T;
 
-                    // Use a non-null pointer value
-                    // (self.ptr might be null because of wrapping)
-                    Some(ptr::read(1 as *mut T))
+                    // Make up a value of this ZST.
+                    Some(mem::zeroed())
                 } else {
                     let old = self.ptr;
                     self.ptr = self.ptr.offset(1);
@@ -2451,9 +2450,8 @@ fn next_back(&mut self) -> Option<T> {
                     // See above for why 'ptr.offset' isn't used
                     self.end = arith_offset(self.end as *const i8, -1) as *mut T;
 
-                    // Use a non-null pointer value
-                    // (self.end might be null because of wrapping)
-                    Some(ptr::read(1 as *mut T))
+                    // Make up a value of this ZST.
+                    Some(mem::zeroed())
                 } else {
                     self.end = self.end.offset(-1);
 
diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs
new file mode 100644 (file)
index 0000000..a03756f
--- /dev/null
@@ -0,0 +1,42 @@
+#![stable(feature = "", since = "1.30.0")]
+
+#![allow(non_camel_case_types)]
+
+//! Utilities related to FFI bindings.
+
+use ::fmt;
+
+/// Equivalent to C's `void` type when used as a [pointer].
+///
+/// In essence, `*const c_void` is equivalent to C's `const void*`
+/// and `*mut c_void` is equivalent to C's `void*`. That said, this is
+/// *not* the same as C's `void` return type, which is Rust's `()` type.
+///
+/// Ideally, this type would be equivalent to [`!`], but currently it may
+/// be more ideal to use `c_void` for FFI purposes.
+///
+/// [`!`]: ../../std/primitive.never.html
+/// [pointer]: ../../std/primitive.pointer.html
+// NB: For LLVM to recognize the void pointer type and by extension
+//     functions like malloc(), we need to have it represented as i8* in
+//     LLVM bitcode. The enum used here ensures this and prevents misuse
+//     of the "raw" type by only having private variants.. We need two
+//     variants, because the compiler complains about the repr attribute
+//     otherwise.
+#[repr(u8)]
+#[stable(feature = "raw_os", since = "1.1.0")]
+pub enum c_void {
+    #[unstable(feature = "c_void_variant", reason = "should not have to exist",
+               issue = "0")]
+    #[doc(hidden)] __variant1,
+    #[unstable(feature = "c_void_variant", reason = "should not have to exist",
+               issue = "0")]
+    #[doc(hidden)] __variant2,
+}
+
+#[stable(feature = "std_debug", since = "1.16.0")]
+impl fmt::Debug for c_void {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("c_void")
+    }
+}
index 520b6ebbbaaa59a072eda6529d6f22acd1e4249e..f4b5cf95e37fb89cb2c240403bc1b3fa3b48854c 100644 (file)
@@ -12,8 +12,9 @@
             reason = "futures in libcore are unstable",
             issue = "50547")]
 
-use pin::PinMut;
 use marker::Unpin;
+use ops;
+use pin::Pin;
 use task::{self, Poll};
 
 /// A future represents an asychronous computation.
@@ -92,21 +93,25 @@ pub trait Future {
     /// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending
     /// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready
     /// [`cx.waker()`]: ../task/struct.Context.html#method.waker
-    fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output>;
+    fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output>;
 }
 
 impl<'a, F: ?Sized + Future + Unpin> Future for &'a mut F {
     type Output = F::Output;
 
-    fn poll(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
-        F::poll(PinMut::new(&mut **self), cx)
+    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output> {
+        F::poll(Pin::new(&mut **self), cx)
     }
 }
 
-impl<'a, F: ?Sized + Future> Future for PinMut<'a, F> {
-    type Output = F::Output;
+impl<P> Future for Pin<P>
+where
+    P: ops::DerefMut,
+    P::Target: Future,
+{
+    type Output = <<P as ops::Deref>::Target as Future>::Output;
 
-    fn poll(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
-        F::poll((*self).reborrow(), cx)
+    fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output> {
+        Pin::get_mut(self).as_mut().poll(cx)
     }
 }
index 68fe461aeae86ebcb1e570a9796737fd5b034e6a..b335cac6c1d8ca4ca832412a225ee3fd23bd8c08 100644 (file)
@@ -15,7 +15,8 @@
 use fmt;
 use future::Future;
 use marker::{PhantomData, Unpin};
-use pin::PinMut;
+use ops;
+use pin::Pin;
 use task::{Context, Poll};
 
 /// A custom trait object for polling futures, roughly akin to
@@ -78,9 +79,9 @@ impl<'a, T> Future for LocalFutureObj<'a, T> {
     type Output = T;
 
     #[inline]
-    fn poll(self: PinMut<Self>, cx: &mut Context) -> Poll<T> {
+    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<T> {
         unsafe {
-            (self.poll_fn)(self.ptr, cx)
+            ((*self).poll_fn)((*self).ptr, cx)
         }
     }
 }
@@ -128,9 +129,11 @@ impl<'a, T> Future for FutureObj<'a, T> {
     type Output = T;
 
     #[inline]
-    fn poll(self: PinMut<Self>, cx: &mut Context) -> Poll<T> {
-        let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) };
-        pinned_field.poll(cx)
+    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<T> {
+        let pinned_field: Pin<&mut LocalFutureObj<'a, T>> = unsafe {
+            Pin::map_unchecked_mut(self, |x| &mut x.0)
+        };
+        LocalFutureObj::poll(pinned_field, cx)
     }
 }
 
@@ -175,7 +178,25 @@ fn into_raw(self) -> *mut () {
     }
 
     unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> {
-        PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx)
+        let p: Pin<&mut F> = Pin::new_unchecked(&mut *(ptr as *mut F));
+        F::poll(p, cx)
+    }
+
+    unsafe fn drop(_ptr: *mut ()) {}
+}
+
+#[unstable(feature = "futures_api", issue = "50547")]
+unsafe impl<'a, T, P, F> UnsafeFutureObj<'a, T> for Pin<P> where
+    P: ops::DerefMut<Target = F> + 'a,
+    F: Future<Output = T> + 'a,
+{
+    fn into_raw(mut self) -> *mut () {
+        unsafe { Pin::get_mut_unchecked(Pin::as_mut(&mut self)) as *mut F as *mut () }
+    }
+
+    unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> {
+        let future: Pin<&mut F> = Pin::new_unchecked(&mut *(ptr as *mut F));
+        F::poll(future, cx)
     }
 
     unsafe fn drop(_ptr: *mut ()) {}
index 763409327de2bd623b7e20a111dc9a2fa87e548e..675e73e952cc2ca011c055a949d38c75e99b18e2 100644 (file)
 pub mod option;
 pub mod raw;
 pub mod result;
+pub mod ffi;
 
 pub mod slice;
 pub mod str;
index dd57d2dd00910c4eee3062bc09ac6c20d626dc42..5572fe1512cbbaca498f2841d939e074c97053ae 100644 (file)
@@ -609,7 +609,7 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
 /// 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`],
+/// by controlling the behavior of pointers wrapped in the [`Pin`] wrapper,
 /// 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.
 ///
@@ -621,10 +621,10 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
 /// ```rust
 /// #![feature(pin)]
 /// use std::mem::replace;
-/// use std::pin::PinMut;
+/// use std::pin::Pin;
 ///
 /// let mut string = "this".to_string();
-/// let mut pinned_string = PinMut::new(&mut string);
+/// let mut pinned_string = Pin::new(&mut string);
 ///
 /// // dereferencing the pointer mutably is only possible because String implements Unpin
 /// replace(&mut *pinned_string, "other".to_string());
@@ -633,7 +633,7 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
 /// This trait is automatically implemented for almost every type.
 ///
 /// [`replace`]: ../../std/mem/fn.replace.html
-/// [`PinMut`]: ../pin/struct.PinMut.html
+/// [`Pin`]: ../pin/struct.Pin.html
 /// [`pin module`]: ../../std/pin/index.html
 #[unstable(feature = "pin", issue = "49150")]
 pub auto trait Unpin {}
index cc36ea7f71391ed99f9eabf697c9475c97b126bd..30067d7e163d21bf43e1f9ab466109c48a553efb 100644 (file)
@@ -14,7 +14,8 @@
 
 /// A wrapper type for raw pointers and integers that will never be
 /// NULL or 0 that might allow certain optimizations.
-#[lang = "non_zero"]
+#[cfg_attr(stage0, lang = "non_zero")]
+#[cfg_attr(not(stage0), rustc_layout_scalar_valid_range_start(1))]
 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
 #[repr(transparent)]
 pub(crate) struct NonZero<T>(pub(crate) T);
index 53cf626bb1ca02b93ef084b003de7c7138f538ba..58bf6be834d468e34936159be8293e2c4fd8d52b 100644 (file)
 
 use iter::{FromIterator, FusedIterator, TrustedLen};
 use {hint, mem, ops::{self, Deref}};
-use pin::PinMut;
+use pin::Pin;
 
 // 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
@@ -270,12 +270,22 @@ pub fn as_mut(&mut self) -> Option<&mut T> {
         }
     }
 
-    /// Converts from `Option<T>` to `Option<PinMut<'_, T>>`
+
+    /// Converts from `Pin<&Option<T>>` to `Option<Pin<&T>>`
+    #[inline]
+    #[unstable(feature = "pin", issue = "49150")]
+    pub fn as_pin_ref<'a>(self: Pin<&'a Option<T>>) -> Option<Pin<&'a T>> {
+        unsafe {
+            Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x))
+        }
+    }
+
+    /// Converts from `Pin<&mut Option<T>>` to `Option<Pin<&mut T>>`
     #[inline]
     #[unstable(feature = "pin", issue = "49150")]
-    pub fn as_pin_mut<'a>(self: PinMut<'a, Self>) -> Option<PinMut<'a, T>> {
+    pub fn as_pin_mut<'a>(self: Pin<&'a mut Option<T>>) -> Option<Pin<&'a mut T>> {
         unsafe {
-            PinMut::get_mut_unchecked(self).as_mut().map(|x| PinMut::new_unchecked(x))
+            Pin::get_mut_unchecked(self).as_mut().map(|x| Pin::new_unchecked(x))
         }
     }
 
@@ -1062,6 +1072,20 @@ fn from(val: T) -> Option<T> {
     }
 }
 
+#[stable(feature = "option_ref_from_ref_option", since = "1.30.0")]
+impl<'a, T> From<&'a Option<T>> for Option<&'a T> {
+    fn from(o: &'a Option<T>) -> Option<&'a T> {
+        o.as_ref()
+    }
+}
+
+#[stable(feature = "option_ref_from_ref_option", since = "1.30.0")]
+impl<'a, T> From<&'a mut Option<T>> for Option<&'a mut T> {
+    fn from(o: &'a mut Option<T>) -> Option<&'a mut T> {
+        o.as_mut()
+    }
+}
+
 /////////////////////////////////////////////////////////////////////////////
 // The Option Iterators
 /////////////////////////////////////////////////////////////////////////////
index e9001f86b3526b2648654d2d7191915d7372e104..d09a545aecfaf8a6072aedeada9e54f072d540c6 100644 (file)
 //! Types which pin data to its location in memory
 //!
-//! See the [standard library module] for more information.
+//! 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.
 //!
-//! [standard library module]: ../../std/pin/index.html
+//! 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 a pointer to the data in the [`Pin`] type. A pointer wrapped
+//! in a `Pin` is otherwise equivalent to its normal version, e.g. `Pin<Box<T>>`
+//! and `Box<T>` work the same way except that the first is pinning the value
+//! of `T` in place.
+//!
+//! 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.
+//!
+//! [`Pin`]: struct.Pin.html
+//! [`Unpin`]: trait.Unpin.html
+//! [`swap`]: ../../std/mem/fn.swap.html
+//! [`Box`]: ../../std/boxed/struct.Box.html
+//!
+//! # Examples
+//!
+//! ```rust
+//! #![feature(pin)]
+//!
+//! use std::pin::Pin;
+//! 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) -> Pin<Box<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 = Box::pinned(res);
+//!
+//!         let slice = NonNull::from(&boxed.data);
+//!         // we know this is safe because modifying a field doesn't move the whole struct
+//!         unsafe {
+//!             let mut_ref: Pin<&mut Self> = Pin::as_mut(&mut boxed);
+//!             Pin::get_mut_unchecked(mut_ref).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")]
 
 use fmt;
-use future::{Future, UnsafeFutureObj};
-use marker::{Sized, Unpin, Unsize};
-use task::{Context, Poll};
+use marker::Sized;
 use ops::{Deref, DerefMut, CoerceUnsized};
 
-/// A pinned reference.
+#[doc(inline)]
+pub use marker::Unpin;
+
+/// A pinned pointer.
 ///
-/// 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`].
+/// This is a wrapper around a kind of pointer which makes that pointer "pin" its
+/// value in place, preventing the value referenced by that pointer from being moved
+/// 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
+//
+// Note: the derives below are allowed because they all only use `&P`, so they
+// cannot move the value behind `pointer`.
 #[unstable(feature = "pin", issue = "49150")]
 #[fundamental]
-pub struct PinMut<'a, T: ?Sized + 'a> {
-    inner: &'a mut T,
+#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
+pub struct Pin<P> {
+    pointer: P,
 }
 
-#[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
+impl<P: Deref> Pin<P>
+where
+    P::Target: Unpin,
+{
+    /// Construct a new `Pin` around a pointer 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 }
+    #[inline(always)]
+    pub fn new(pointer: P) -> Pin<P> {
+        // Safety: the value pointed to is `Unpin`, and so has no requirements
+        // around pinning.
+        unsafe { Pin::new_unchecked(pointer) }
     }
+}
 
-    /// Get a mutable reference to the data inside of this `PinMut`.
+impl<P: Deref> Pin<P> {
+    /// Construct a new `Pin` around a reference to some data of a type that
+    /// may or may not implement `Unpin`.
+    ///
+    /// # Safety
+    ///
+    /// This constructor is unsafe because we cannot guarantee that the data
+    /// pointed to by `pointer` is pinned. If the constructed `Pin<P>` does
+    /// not guarantee that the data `P` points to is pinned, constructing a
+    /// `Pin<P>` is undefined behavior.
+    ///
+    /// If `pointer` dereferences to an `Unpin` type, `Pin::new` should be used
+    /// instead.
+    #[unstable(feature = "pin", issue = "49150")]
+    #[inline(always)]
+    pub unsafe fn new_unchecked(pointer: P) -> Pin<P> {
+        Pin { pointer }
+    }
+
+    /// Get a pinned shared reference from this pinned pointer.
     #[unstable(feature = "pin", issue = "49150")]
-    pub fn get_mut(this: PinMut<'a, T>) -> &'a mut T {
-        this.inner
+    #[inline(always)]
+    pub fn as_ref(self: &Pin<P>) -> Pin<&P::Target> {
+        unsafe { Pin::new_unchecked(&*self.pointer) }
     }
 }
 
+impl<P: DerefMut> Pin<P> {
+    /// Get a pinned mutable reference from this pinned pointer.
+    #[unstable(feature = "pin", issue = "49150")]
+    #[inline(always)]
+    pub fn as_mut(self: &mut Pin<P>) -> Pin<&mut P::Target> {
+        unsafe { Pin::new_unchecked(&mut *self.pointer) }
+    }
 
-#[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`.
+    /// Assign a new value to the memory behind the pinned reference.
+    #[unstable(feature = "pin", issue = "49150")]
+    #[inline(always)]
+    pub fn set(mut self: Pin<P>, value: P::Target)
+    where
+        P::Target: Sized,
+    {
+        *self.pointer = value;
+    }
+}
+
+impl<'a, T: ?Sized> Pin<&'a T> {
+    /// Construct a new pin by mapping the interior value.
     ///
-    /// 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.
+    /// For example, if you  wanted to get a `Pin` of a field of something,
+    /// you could use this to get access to that field in one line of code.
+    ///
+    /// # Safety
+    ///
+    /// 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 new_unchecked(reference: &'a mut T) -> PinMut<'a, T> {
-        PinMut { inner: reference }
+    pub unsafe fn map_unchecked<U, F>(this: Pin<&'a T>, func: F) -> Pin<&'a U> where
+        F: FnOnce(&T) -> &U,
+    {
+        let pointer = &*this.pointer;
+        let new_pointer = func(pointer);
+        Pin::new_unchecked(new_pointer)
     }
 
-    /// Reborrow a `PinMut` for a shorter lifetime.
+    /// Get a shared reference out of a pin.
     ///
-    /// For example, `PinMut::get_mut(x.reborrow())` (unsafely) returns a
-    /// short-lived mutable reference reborrowing from `x`.
+    /// Note: `Pin` also implements `Deref` to the target, which can be used
+    /// to access the inner value. However, `Deref` only provides a reference
+    /// that lives for as long as the borrow of the `Pin`, not the lifetime of
+    /// the `Pin` itself. This method allows turning the `Pin` into a reference
+    /// with the same lifetime as the original `Pin`.
     #[unstable(feature = "pin", issue = "49150")]
-    pub fn reborrow<'b>(&'b mut self) -> PinMut<'b, T> {
-        PinMut { inner: self.inner }
+    #[inline(always)]
+    pub fn get_ref(this: Pin<&'a T>) -> &'a T {
+        this.pointer
+    }
+}
+
+impl<'a, T: ?Sized> Pin<&'a mut T> {
+    /// Convert this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime.
+    #[unstable(feature = "pin", issue = "49150")]
+    #[inline(always)]
+    pub fn into_ref(this: Pin<&'a mut T>) -> Pin<&'a T> {
+        Pin { pointer: this.pointer }
+    }
+
+    /// Get a mutable reference to the data inside of this `Pin`.
+    ///
+    /// This requires that the data inside this `Pin` is `Unpin`.
+    ///
+    /// Note: `Pin` also implements `DerefMut` to the data, which can be used
+    /// to access the inner value. However, `DerefMut` only provides a reference
+    /// that lives for as long as the borrow of the `Pin`, not the lifetime of
+    /// the `Pin` itself. This method allows turning the `Pin` into a reference
+    /// with the same lifetime as the original `Pin`.
+    #[unstable(feature = "pin", issue = "49150")]
+    #[inline(always)]
+    pub fn get_mut(this: Pin<&'a mut T>) -> &'a mut T
+        where T: Unpin,
+    {
+        this.pointer
     }
 
-    /// Get a mutable reference to the data inside of this `PinMut`.
+    /// Get a mutable reference to the data inside of this `Pin`.
+    ///
+    /// # Safety
     ///
     /// 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.
+    /// function, so that the invariants on the `Pin` type can be upheld.
+    ///
+    /// If the underlying data is `Unpin`, `Pin::get_mut` should be used
+    /// instead.
     #[unstable(feature = "pin", issue = "49150")]
-    pub unsafe fn get_mut_unchecked(this: PinMut<'a, T>) -> &'a mut T {
-        this.inner
+    #[inline(always)]
+    pub unsafe fn get_mut_unchecked(this: Pin<&'a mut T>) -> &'a mut T {
+        this.pointer
     }
 
     /// Construct a new pin by mapping the interior value.
     ///
-    /// For example, if you  wanted to get a `PinMut` of a field of something,
+    /// For example, if you  wanted to get a `Pin` of a field of something,
     /// you could use this to get access to that field in one line of code.
     ///
+    /// # Safety
+    ///
     /// 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
+    pub unsafe fn map_unchecked_mut<U, F>(this: Pin<&'a mut T>, func: F) -> Pin<&'a mut 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;
+        let pointer = Pin::get_mut_unchecked(this);
+        let new_pointer = func(pointer);
+        Pin::new_unchecked(new_pointer)
     }
 }
 
 #[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized> Deref for PinMut<'a, T> {
-    type Target = T;
-
-    fn deref(&self) -> &T {
-        &*self.inner
+impl<P: Deref> Deref for Pin<P> {
+    type Target = P::Target;
+    fn deref(&self) -> &P::Target {
+        Pin::get_ref(Pin::as_ref(self))
     }
 }
 
 #[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized + Unpin> DerefMut for PinMut<'a, T> {
-    fn deref_mut(&mut self) -> &mut T {
-        self.inner
+impl<P: DerefMut> DerefMut for Pin<P>
+where
+    P::Target: Unpin
+{
+    fn deref_mut(&mut self) -> &mut P::Target {
+        Pin::get_mut(Pin::as_mut(self))
     }
 }
 
 #[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for PinMut<'a, T> {
+impl<'a, P: fmt::Debug> fmt::Debug for Pin<P> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(&**self, f)
+        fmt::Debug::fmt(&self.pointer, f)
     }
 }
 
 #[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: fmt::Display + ?Sized> fmt::Display for PinMut<'a, T> {
+impl<'a, P: fmt::Display> fmt::Display for Pin<P> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&**self, f)
+        fmt::Display::fmt(&self.pointer, f)
     }
 }
 
 #[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized> fmt::Pointer for PinMut<'a, T> {
+impl<'a, P: fmt::Pointer> fmt::Pointer for Pin<P> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Pointer::fmt(&(&*self.inner as *const T), f)
+        fmt::Pointer::fmt(&self.pointer, f)
     }
 }
 
+// Note: this means that any impl of `CoerceUnsized` that allows coercing from
+// a type that impls `Deref<Target=impl !Unpin>` to a type that impls
+// `Deref<Target=Unpin>` is unsound. Any such impl would probably be unsound
+// for other reasons, though, so we just need to take care not to allow such
+// impls to land in std.
 #[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinMut<'a, U>> for PinMut<'a, T> {}
+impl<'a, P, U> CoerceUnsized<Pin<U>> for Pin<P>
+where
+    P: CoerceUnsized<U>,
+{}
 
 #[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 ()) {}
-}
+impl<'a, P> Unpin for Pin<P> {}
index 62adaea168a3f97854f935c704331dad8c80701f..da4a56cfecd6e5323c8cfc92a16f4213bc71cfe3 100644 (file)
@@ -1739,8 +1739,9 @@ fn gcd(a: usize, b: usize) -> usize {
     /// maintained.
     ///
     /// This method splits the slice into three distinct slices: prefix, correctly aligned middle
-    /// slice of a new type, and the suffix slice. The middle slice will have the greatest length
-    /// possible for a given type and input slice.
+    /// slice of a new type, and the suffix slice. The method does a best effort to make the
+    /// middle slice the greatest length possible for a given type and input slice, but only
+    /// your algorithm's performance should depend on that, not its correctness.
     ///
     /// This method has no purpose when either input element `T` or output element `U` are
     /// zero-sized and will return the original slice without splitting anything.
@@ -1755,7 +1756,6 @@ fn gcd(a: usize, b: usize) -> usize {
     /// Basic usage:
     ///
     /// ```
-    /// # #![feature(slice_align_to)]
     /// unsafe {
     ///     let bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7];
     ///     let (prefix, shorts, suffix) = bytes.align_to::<u16>();
@@ -1764,7 +1764,7 @@ fn gcd(a: usize, b: usize) -> usize {
     ///     // less_efficient_algorithm_for_bytes(suffix);
     /// }
     /// ```
-    #[unstable(feature = "slice_align_to", issue = "44488")]
+    #[stable(feature = "slice_align_to", since = "1.30.0")]
     pub unsafe fn align_to<U>(&self) -> (&[T], &[U], &[T]) {
         // Note that most of this function will be constant-evaluated,
         if ::mem::size_of::<U>() == 0 || ::mem::size_of::<T>() == 0 {
@@ -1792,8 +1792,9 @@ pub unsafe fn align_to<U>(&self) -> (&[T], &[U], &[T]) {
     /// maintained.
     ///
     /// This method splits the slice into three distinct slices: prefix, correctly aligned middle
-    /// slice of a new type, and the suffix slice. The middle slice will have the greatest length
-    /// possible for a given type and input slice.
+    /// slice of a new type, and the suffix slice. The method does a best effort to make the
+    /// middle slice the greatest length possible for a given type and input slice, but only
+    /// your algorithm's performance should depend on that, not its correctness.
     ///
     /// This method has no purpose when either input element `T` or output element `U` are
     /// zero-sized and will return the original slice without splitting anything.
@@ -1808,7 +1809,6 @@ pub unsafe fn align_to<U>(&self) -> (&[T], &[U], &[T]) {
     /// Basic usage:
     ///
     /// ```
-    /// # #![feature(slice_align_to)]
     /// unsafe {
     ///     let mut bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7];
     ///     let (prefix, shorts, suffix) = bytes.align_to_mut::<u16>();
@@ -1817,7 +1817,7 @@ pub unsafe fn align_to<U>(&self) -> (&[T], &[U], &[T]) {
     ///     // less_efficient_algorithm_for_bytes(suffix);
     /// }
     /// ```
-    #[unstable(feature = "slice_align_to", issue = "44488")]
+    #[stable(feature = "slice_align_to", since = "1.30.0")]
     pub unsafe fn align_to_mut<U>(&mut self) -> (&mut [T], &mut [U], &mut [T]) {
         // Note that most of this function will be constant-evaluated,
         if ::mem::size_of::<U>() == 0 || ::mem::size_of::<T>() == 0 {
index e48f3b36c658675ddd8f48ff33c3842dcc9a482c..4f3086575c0cf2f0e89d494b125c81e1734874a4 100644 (file)
@@ -34,7 +34,6 @@
 #![feature(try_from)]
 #![feature(try_trait)]
 #![feature(exact_chunks)]
-#![feature(slice_align_to)]
 #![feature(align_offset)]
 #![feature(reverse_bits)]
 #![feature(inner_deref)]
index b58920224eb702217dd6009740fe5c11b0ea0ae7..1aed5a7b426fdd977f29f793ccc97e55a89fabd0 100644 (file)
@@ -21,7 +21,7 @@
 //! assert_eq!(Duration::new(5, 0), Duration::from_secs(5));
 //! ```
 
-use fmt;
+use {fmt, u64};
 use iter::Sum;
 use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign};
 
@@ -30,6 +30,7 @@
 const NANOS_PER_MICRO: u32 = 1_000;
 const MILLIS_PER_SEC: u64 = 1_000;
 const MICROS_PER_SEC: u64 = 1_000_000;
+const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f64;
 
 /// A `Duration` type to represent a span of time, typically used for system
 /// timeouts.
@@ -458,6 +459,115 @@ pub fn checked_div(self, rhs: u32) -> Option<Duration> {
             None
         }
     }
+
+    /// Returns the number of seconds contained by this `Duration` as `f64`.
+    ///
+    /// The returned value does include the fractional (nanosecond) part of the duration.
+    ///
+    /// # Examples
+    /// ```
+    /// #![feature(duration_float)]
+    /// use std::time::Duration;
+    ///
+    /// let dur = Duration::new(2, 700_000_000);
+    /// assert_eq!(dur.as_float_secs(), 2.7);
+    /// ```
+    #[unstable(feature = "duration_float", issue = "54361")]
+    #[inline]
+    pub fn as_float_secs(&self) -> f64 {
+        (self.secs as f64) + (self.nanos as f64) / (NANOS_PER_SEC as f64)
+    }
+
+    /// Creates a new `Duration` from the specified number of seconds.
+    ///
+    /// # Panics
+    /// This constructor will panic if `secs` is not finite, negative or overflows `Duration`.
+    ///
+    /// # Examples
+    /// ```
+    /// #![feature(duration_float)]
+    /// use std::time::Duration;
+    ///
+    /// let dur = Duration::from_float_secs(2.7);
+    /// assert_eq!(dur, Duration::new(2, 700_000_000));
+    /// ```
+    #[unstable(feature = "duration_float", issue = "54361")]
+    #[inline]
+    pub fn from_float_secs(secs: f64) -> Duration {
+        let nanos =  secs * (NANOS_PER_SEC as f64);
+        if !nanos.is_finite() {
+            panic!("got non-finite value when converting float to duration");
+        }
+        if nanos >= MAX_NANOS_F64 {
+            panic!("overflow when converting float to duration");
+        }
+        if nanos < 0.0 {
+            panic!("underflow when converting float to duration");
+        }
+        let nanos =  nanos as u128;
+        Duration {
+            secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
+            nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
+        }
+    }
+
+    /// Multiply `Duration` by `f64`.
+    ///
+    /// # Panics
+    /// This method will panic if result is not finite, negative or overflows `Duration`.
+    ///
+    /// # Examples
+    /// ```
+    /// #![feature(duration_float)]
+    /// use std::time::Duration;
+    ///
+    /// let dur = Duration::new(2, 700_000_000);
+    /// assert_eq!(dur.mul_f64(3.14), Duration::new(8, 478_000_000));
+    /// assert_eq!(dur.mul_f64(3.14e5), Duration::new(847_800, 0));
+    /// ```
+    #[unstable(feature = "duration_float", issue = "54361")]
+    #[inline]
+    pub fn mul_f64(self, rhs: f64) -> Duration {
+        Duration::from_float_secs(rhs * self.as_float_secs())
+    }
+
+    /// Divide `Duration` by `f64`.
+    ///
+    /// # Panics
+    /// This method will panic if result is not finite, negative or overflows `Duration`.
+    ///
+    /// # Examples
+    /// ```
+    /// #![feature(duration_float)]
+    /// use std::time::Duration;
+    ///
+    /// let dur = Duration::new(2, 700_000_000);
+    /// assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611));
+    /// // note that truncation is used, not rounding
+    /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_598));
+    /// ```
+    #[unstable(feature = "duration_float", issue = "54361")]
+    #[inline]
+    pub fn div_f64(self, rhs: f64) -> Duration {
+        Duration::from_float_secs(self.as_float_secs() / rhs)
+    }
+
+    /// Divide `Duration` by `Duration` and return `f64`.
+    ///
+    /// # Examples
+    /// ```
+    /// #![feature(duration_float)]
+    /// use std::time::Duration;
+    ///
+    /// let dur1 = Duration::new(2, 700_000_000);
+    /// let dur2 = Duration::new(5, 400_000_000);
+    /// assert_eq!(dur1.div_duration(dur2), 0.5);
+    /// ```
+    #[unstable(feature = "duration_float", issue = "54361")]
+    #[inline]
+    pub fn div_duration(self, rhs: Duration) -> f64 {
+        self.as_float_secs() / rhs.as_float_secs()
+    }
 }
 
 #[stable(feature = "duration", since = "1.3.0")]
@@ -501,6 +611,15 @@ fn mul(self, rhs: u32) -> Duration {
     }
 }
 
+#[stable(feature = "symmetric_u32_duration_mul", since = "1.31.0")]
+impl Mul<Duration> for u32 {
+    type Output = Duration;
+
+    fn mul(self, rhs: Duration) -> Duration {
+        rhs * self
+    }
+}
+
 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
 impl MulAssign<u32> for Duration {
     fn mul_assign(&mut self, rhs: u32) {
index af7790164183c7dbfed11cc9b671173b1876f2ae..bf23de394370237219007f7a0ad6cbe07572c17f 100644 (file)
 use Span;
 
 use rustc_errors as errors;
-use syntax_pos::MultiSpan;
 
 /// An enum representing a diagnostic level.
-#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
+#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
 #[derive(Copy, Clone, Debug)]
 #[non_exhaustive]
 pub enum Level {
@@ -28,30 +27,61 @@ pub enum Level {
     Help,
 }
 
+/// Trait implemented by types that can be converted into a set of `Span`s.
+#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
+pub trait MultiSpan {
+    /// Converts `self` into a `Vec<Span>`.
+    fn into_spans(self) -> Vec<Span>;
+}
+
+#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
+impl MultiSpan for Span {
+    fn into_spans(self) -> Vec<Span> {
+        vec![self]
+    }
+}
+
+#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
+impl MultiSpan for Vec<Span> {
+    fn into_spans(self) -> Vec<Span> {
+        self
+    }
+}
+
+#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
+impl<'a> MultiSpan for &'a [Span] {
+    fn into_spans(self) -> Vec<Span> {
+        self.to_vec()
+    }
+}
+
 /// A structure representing a diagnostic message and associated children
 /// messages.
-#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
+#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
 #[derive(Clone, Debug)]
 pub struct Diagnostic {
     level: Level,
     message: String,
-    span: Option<Span>,
+    spans: Vec<Span>,
     children: Vec<Diagnostic>
 }
 
 macro_rules! diagnostic_child_methods {
     ($spanned:ident, $regular:ident, $level:expr) => (
         /// Add a new child diagnostic message to `self` with the level
-        /// identified by this methods name with the given `span` and `message`.
-        #[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
-        pub fn $spanned<T: Into<String>>(mut self, span: Span, message: T) -> Diagnostic {
-            self.children.push(Diagnostic::spanned(span, $level, message));
+        /// identified by this method's name with the given `spans` and
+        /// `message`.
+        #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
+        pub fn $spanned<S, T>(mut self, spans: S, message: T) -> Diagnostic
+            where S: MultiSpan, T: Into<String>
+        {
+            self.children.push(Diagnostic::spanned(spans, $level, message));
             self
         }
 
         /// Add a new child diagnostic message to `self` with the level
         /// identified by this method's name with the given `message`.
-        #[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
+        #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
         pub fn $regular<T: Into<String>>(mut self, message: T) -> Diagnostic {
             self.children.push(Diagnostic::new($level, message));
             self
@@ -59,26 +89,43 @@ pub fn $regular<T: Into<String>>(mut self, message: T) -> Diagnostic {
     )
 }
 
+/// Iterator over the children diagnostics of a `Diagnostic`.
+#[derive(Debug, Clone)]
+#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
+pub struct Children<'a>(::std::slice::Iter<'a, Diagnostic>);
+
+#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
+impl<'a> Iterator for Children<'a> {
+    type Item = &'a Diagnostic;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
 impl Diagnostic {
     /// Create a new diagnostic with the given `level` and `message`.
-    #[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
+    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
     pub fn new<T: Into<String>>(level: Level, message: T) -> Diagnostic {
         Diagnostic {
             level: level,
             message: message.into(),
-            span: None,
+            spans: vec![],
             children: vec![]
         }
     }
 
     /// Create a new diagnostic with the given `level` and `message` pointing to
-    /// the given `span`.
-    #[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
-    pub fn spanned<T: Into<String>>(span: Span, level: Level, message: T) -> Diagnostic {
+    /// the given set of `spans`.
+    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
+    pub fn spanned<S, T>(spans: S, level: Level, message: T) -> Diagnostic
+        where S: MultiSpan, T: Into<String>
+    {
         Diagnostic {
             level: level,
             message: message.into(),
-            span: Some(span),
+            spans: spans.into_spans(),
             children: vec![]
         }
     }
@@ -89,25 +136,62 @@ pub fn spanned<T: Into<String>>(span: Span, level: Level, message: T) -> Diagnos
     diagnostic_child_methods!(span_help, help, Level::Help);
 
     /// Returns the diagnostic `level` for `self`.
-    #[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
+    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
     pub fn level(&self) -> Level {
         self.level
     }
 
+    /// Sets the level in `self` to `level`.
+    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
+    pub fn set_level(&mut self, level: Level) {
+        self.level = level;
+    }
+
+    /// Returns the message in `self`.
+    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
+    pub fn message(&self) -> &str {
+        &self.message
+    }
+
+    /// Sets the message in `self` to `message`.
+    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
+    pub fn set_message<T: Into<String>>(&mut self, message: T) {
+        self.message = message.into();
+    }
+
+    /// Returns the `Span`s in `self`.
+    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
+    pub fn spans(&self) -> &[Span] {
+        &self.spans
+    }
+
+    /// Sets the `Span`s in `self` to `spans`.
+    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
+    pub fn set_spans<S: MultiSpan>(&mut self, spans: S) {
+        self.spans = spans.into_spans();
+    }
+
+    /// Returns an iterator over the children diagnostics of `self`.
+    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
+    pub fn children(&self) -> Children {
+        Children(self.children.iter())
+    }
+
     /// Emit the diagnostic.
-    #[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
+    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
     pub fn emit(self) {
+        fn to_internal(spans: Vec<Span>) -> ::syntax_pos::MultiSpan {
+            let spans: Vec<_> = spans.into_iter().map(|s| s.0).collect();
+            ::syntax_pos::MultiSpan::from_spans(spans)
+        }
+
         let level = self.level.to_internal();
         let mut diag = errors::Diagnostic::new(level, &*self.message);
-
-        if let Some(span) = self.span {
-            diag.set_span(span.0);
-        }
+        diag.set_span(to_internal(self.spans));
 
         for child in self.children {
-            let span = child.span.map_or(MultiSpan::new(), |s| s.0.into());
             let level = child.level.to_internal();
-            diag.sub(level, &*child.message, span, None);
+            diag.sub(level, &*child.message, to_internal(child.spans), None);
         }
 
         ::__internal::with_sess(move |sess, _| {
index bb55661e45c75d7c854095219b2d3873245a093c..1a0dde3ccd7c3c331aaad23584145f8b9823733f 100644 (file)
@@ -47,7 +47,7 @@
 
 mod diagnostic;
 
-#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
+#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
 pub use diagnostic::{Diagnostic, Level};
 
 use std::{ascii, fmt, iter};
@@ -274,7 +274,7 @@ macro_rules! diagnostic_method {
     ($name:ident, $level:expr) => (
         /// Create a new `Diagnostic` with the given `message` at the span
         /// `self`.
-        #[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
+        #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
         pub fn $name<T: Into<String>>(self, message: T) -> Diagnostic {
             Diagnostic::spanned(self, $level, message)
         }
index 1b97480920321d6fafad010285a19ff258e95394..6b9c0aac52e79b370af16a0af500f90e56020828 100644 (file)
@@ -556,7 +556,10 @@ fn add_exiting_edge(&mut self,
                         target_scope: region::Scope,
                         to_index: CFGIndex) {
         let mut data = CFGEdgeData { exiting_scopes: vec![] };
-        let mut scope = region::Scope::Node(from_expr.hir_id.local_id);
+        let mut scope = region::Scope {
+            id: from_expr.hir_id.local_id,
+            data: region::ScopeData::Node
+        };
         let region_scope_tree = self.tcx.region_scope_tree(self.owner_def_id);
         while scope != target_scope {
             data.exiting_scopes.push(scope.item_local_id());
@@ -586,8 +589,11 @@ fn find_scope_edge(&self,
             Ok(loop_id) => {
                 for b in &self.breakable_block_scopes {
                     if b.block_expr_id == self.tcx.hir.node_to_hir_id(loop_id).local_id {
-                        let scope_id = self.tcx.hir.node_to_hir_id(loop_id).local_id;
-                        return (region::Scope::Node(scope_id), match scope_cf_kind {
+                        let scope = region::Scope {
+                            id: self.tcx.hir.node_to_hir_id(loop_id).local_id,
+                            data: region::ScopeData::Node
+                        };
+                        return (scope, match scope_cf_kind {
                             ScopeCfKind::Break => b.break_index,
                             ScopeCfKind::Continue => bug!("can't continue to block"),
                         });
@@ -595,8 +601,11 @@ fn find_scope_edge(&self,
                 }
                 for l in &self.loop_scopes {
                     if l.loop_id == self.tcx.hir.node_to_hir_id(loop_id).local_id {
-                        let scope_id = self.tcx.hir.node_to_hir_id(loop_id).local_id;
-                        return (region::Scope::Node(scope_id), match scope_cf_kind {
+                        let scope = region::Scope {
+                            id: self.tcx.hir.node_to_hir_id(loop_id).local_id,
+                            data: region::ScopeData::Node
+                        };
+                        return (scope, match scope_cf_kind {
                             ScopeCfKind::Break => l.break_index,
                             ScopeCfKind::Continue => l.continue_index,
                         });
index 9ded7bc28b30f83e43258e0fe4568dd73580e4ae..298ef67923a9c329e8c262657a676f30656d6c6e 100644 (file)
@@ -125,7 +125,7 @@ fn check_repr(&self, item: &hir::Item, target: Target) {
             .iter()
             .filter(|attr| attr.name() == "repr")
             .filter_map(|attr| attr.meta_item_list())
-            .flat_map(|hints| hints)
+            .flatten()
             .collect();
 
         let mut int_reprs = 0;
@@ -185,7 +185,7 @@ fn check_repr(&self, item: &hir::Item, target: Target) {
                         continue
                     }
                 }
-                "i8" | "u8" | "i16" | "u16" |
+                "i8"  | "u8"  | "i16" | "u16" |
                 "i32" | "u32" | "i64" | "u64" |
                 "isize" | "usize" => {
                     int_reprs += 1;
index b10f4785f16377d3e08cef3fdd7d12928e845048..4286b0628f5fff76f7054e69d74650287483850e 100644 (file)
@@ -69,6 +69,7 @@ pub enum Def {
     Static(DefId, bool /* is_mutbl */),
     StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor
     VariantCtor(DefId, CtorKind), // DefId refers to the enum variant
+    SelfCtor(DefId /* impl */),  // DefId refers to the impl
     Method(DefId),
     AssociatedConst(DefId),
 
@@ -272,7 +273,8 @@ 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::ForeignTy(id) => {
+            Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) |
+            Def::SelfCtor(id) => {
                 id
             }
 
@@ -309,6 +311,7 @@ pub fn kind_name(&self) -> &'static str {
             Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
             Def::StructCtor(.., CtorKind::Const) => "unit struct",
             Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
+            Def::SelfCtor(..) => "self constructor",
             Def::Union(..) => "union",
             Def::Trait(..) => "trait",
             Def::ForeignTy(..) => "foreign type",
index 420ffbcfee6cd29f1a6d5f20576a2a7cf132d13b..cd91b85689b30efede4c8b2efd738877960098d3 100644 (file)
 use std::u32;
 
 newtype_index! {
-    pub struct CrateNum {
+    pub struct CrateId {
         ENCODABLE = custom
-        DEBUG_FORMAT = "crate{}",
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum CrateNum {
+    /// Virtual crate for builtin macros
+    // FIXME(jseyfried): this is also used for custom derives until proc-macro crates get
+    // `CrateNum`s.
+    BuiltinMacros,
+    /// A CrateNum value that indicates that something is wrong.
+    Invalid,
+    /// A special CrateNum that we use for the tcx.rcache when decoding from
+    /// the incr. comp. cache.
+    ReservedForIncrCompCache,
+    Index(CrateId),
+}
+
+impl ::std::fmt::Debug for CrateNum {
+    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+        match self {
+            CrateNum::Index(id) => write!(fmt, "crate{}", id.private),
+            CrateNum::Invalid => write!(fmt, "invalid crate"),
+            CrateNum::BuiltinMacros => write!(fmt, "bultin macros crate"),
+            CrateNum::ReservedForIncrCompCache => write!(fmt, "crate for decoding incr comp cache"),
+        }
+    }
+}
 
-        /// Item definitions in the currently-compiled crate would have the CrateNum
-        /// LOCAL_CRATE in their DefId.
-        const LOCAL_CRATE = 0,
+/// Item definitions in the currently-compiled crate would have the CrateNum
+/// LOCAL_CRATE in their DefId.
+pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32_const(0));
 
-        /// Virtual crate for builtin macros
-        // FIXME(jseyfried): this is also used for custom derives until proc-macro crates get
-        // `CrateNum`s.
-        const BUILTIN_MACROS_CRATE = CrateNum::MAX_AS_U32,
 
-        /// A CrateNum value that indicates that something is wrong.
-        const INVALID_CRATE = CrateNum::MAX_AS_U32 - 1,
+impl Idx for CrateNum {
+    #[inline]
+    fn new(value: usize) -> Self {
+        CrateNum::Index(Idx::new(value))
+    }
 
-        /// A special CrateNum that we use for the tcx.rcache when decoding from
-        /// the incr. comp. cache.
-        const RESERVED_FOR_INCR_COMP_CACHE = CrateNum::MAX_AS_U32 - 2,
+    #[inline]
+    fn index(self) -> usize {
+        match self {
+            CrateNum::Index(idx) => Idx::index(idx),
+            _ => bug!("Tried to get crate index of {:?}", self),
+        }
     }
 }
 
@@ -43,12 +71,39 @@ pub fn new(x: usize) -> CrateNum {
         CrateNum::from_usize(x)
     }
 
+    pub fn from_usize(x: usize) -> CrateNum {
+        CrateNum::Index(CrateId::from_usize(x))
+    }
+
+    pub fn from_u32(x: u32) -> CrateNum {
+        CrateNum::Index(CrateId::from_u32(x))
+    }
+
+    pub fn as_usize(self) -> usize {
+        match self {
+            CrateNum::Index(id) => id.as_usize(),
+            _ => bug!("tried to get index of nonstandard crate {:?}", self),
+        }
+    }
+
+    pub fn as_u32(self) -> u32 {
+        match self {
+            CrateNum::Index(id) => id.as_u32(),
+            _ => bug!("tried to get index of nonstandard crate {:?}", self),
+        }
+    }
+
     pub fn as_def_id(&self) -> DefId { DefId { krate: *self, index: CRATE_DEF_INDEX } }
 }
 
 impl fmt::Display for CrateNum {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&self.as_u32(), f)
+        match self {
+            CrateNum::Index(id) => fmt::Display::fmt(&id.private, f),
+            CrateNum::Invalid => write!(f, "invalid crate"),
+            CrateNum::BuiltinMacros => write!(f, "bultin macros crate"),
+            CrateNum::ReservedForIncrCompCache => write!(f, "crate for decoding incr comp cache"),
+        }
     }
 }
 
index 8129cc18d46c2e08952b0753b8fcd691a90526b1..76c2ebc0e4a0e36ab5265924e527fdee83bbb329 100644 (file)
@@ -50,7 +50,6 @@
 
 use std::cmp;
 use std::u32;
-use std::result::Result::Err;
 
 #[derive(Copy, Clone)]
 pub enum FnKind<'a> {
@@ -1067,31 +1066,26 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
         ExprKind::Break(ref destination, ref opt_expr) => {
             if let Some(ref label) = destination.label {
                 visitor.visit_label(label);
-                match destination.target_id {
-                    Ok(node_id) => visitor.visit_def_mention(Def::Label(node_id)),
-                    Err(_) => {},
-                };
+                if let Ok(node_id) = destination.target_id {
+                    visitor.visit_def_mention(Def::Label(node_id))
+                }
             }
             walk_list!(visitor, visit_expr, opt_expr);
         }
         ExprKind::Continue(ref destination) => {
             if let Some(ref label) = destination.label {
                 visitor.visit_label(label);
-                match destination.target_id {
-                    Ok(node_id) => visitor.visit_def_mention(Def::Label(node_id)),
-                    Err(_) => {},
-                };
+                if let Ok(node_id) = destination.target_id {
+                    visitor.visit_def_mention(Def::Label(node_id))
+                }
             }
         }
         ExprKind::Ret(ref optional_expression) => {
             walk_list!(visitor, visit_expr, optional_expression);
         }
         ExprKind::InlineAsm(_, ref outputs, ref inputs) => {
-            for output in outputs {
-                visitor.visit_expr(output)
-            }
-            for input in inputs {
-                visitor.visit_expr(input)
+            for expr in outputs.iter().chain(inputs.iter()) {
+                visitor.visit_expr(expr)
             }
         }
         ExprKind::Yield(ref subexpression) => {
@@ -1156,7 +1150,6 @@ pub fn add(&mut self, id: NodeId) {
         self.min = cmp::min(self.min, id);
         self.max = cmp::max(self.max, NodeId::from_u32(id.as_u32() + 1));
     }
-
 }
 
 
index 34b3eb0a8c8bf64d1fd595377f2f028d89dcaf3f..bd8770abb135c55b0f77cc6ff0d21869a4e26af9 100644 (file)
@@ -67,6 +67,7 @@
 use syntax::ast::*;
 use syntax::errors;
 use syntax::ext::hygiene::{Mark, SyntaxContext};
+use syntax::feature_gate::{emit_feature_err, GateIssue};
 use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax::source_map::{self, respan, CompilerDesugaringKind, Spanned};
@@ -596,7 +597,7 @@ fn expect_full_def(&mut self, id: NodeId) -> Def {
         })
     }
 
-    fn expect_full_def_from_use(&mut self, id: NodeId) -> impl Iterator<Item=Def> {
+    fn expect_full_def_from_use(&mut self, id: NodeId) -> impl Iterator<Item = Def> {
         self.resolver.get_import(id).present_items().map(|pr| {
             if pr.unresolved_segments() != 0 {
                 bug!("path not fully resolved: {:?}", pr);
@@ -989,7 +990,7 @@ fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hi
             None => {
                 self.loop_scopes
                     .last()
-                    .map(|innermost_loop_id| *innermost_loop_id)
+                    .cloned()
                     .map(|id| Ok(self.lower_node_id(id).node_id))
                     .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))
                     .into()
@@ -3429,19 +3430,24 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                     ParamMode::Optional,
                     ImplTraitContext::Disallowed,
                 );
+                self.check_self_struct_ctor_feature(&qpath);
                 hir::PatKind::TupleStruct(
                     qpath,
                     pats.iter().map(|x| self.lower_pat(x)).collect(),
                     ddpos,
                 )
             }
-            PatKind::Path(ref qself, ref path) => hir::PatKind::Path(self.lower_qpath(
-                p.id,
-                qself,
-                path,
-                ParamMode::Optional,
-                ImplTraitContext::Disallowed,
-            )),
+            PatKind::Path(ref qself, ref path) => {
+                let qpath = self.lower_qpath(
+                    p.id,
+                    qself,
+                    path,
+                    ParamMode::Optional,
+                    ImplTraitContext::Disallowed,
+                );
+                self.check_self_struct_ctor_feature(&qpath);
+                hir::PatKind::Path(qpath)
+            }
             PatKind::Struct(ref path, ref fields, etc) => {
                 let qpath = self.lower_qpath(
                     p.id,
@@ -3828,13 +3834,17 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     attrs: e.attrs.clone(),
                 };
             }
-            ExprKind::Path(ref qself, ref path) => hir::ExprKind::Path(self.lower_qpath(
-                e.id,
-                qself,
-                path,
-                ParamMode::Optional,
-                ImplTraitContext::Disallowed,
-            )),
+            ExprKind::Path(ref qself, ref path) => {
+                let qpath = self.lower_qpath(
+                    e.id,
+                    qself,
+                    path,
+                    ParamMode::Optional,
+                    ImplTraitContext::Disallowed,
+                );
+                self.check_self_struct_ctor_feature(&qpath);
+                hir::ExprKind::Path(qpath)
+            }
             ExprKind::Break(opt_label, ref opt_expr) => {
                 let destination = if self.is_in_loop_condition && opt_label.is_none() {
                     hir::Destination {
@@ -4815,6 +4825,18 @@ fn wrap_in_try_constructor(
                                             ThinVec::new()));
         P(self.expr_call(e.span, from_err, hir_vec![e]))
     }
+
+    fn check_self_struct_ctor_feature(&self, qp: &hir::QPath) {
+        if let hir::QPath::Resolved(_, ref p) = qp {
+            if p.segments.len() == 1 &&
+               p.segments[0].ident.name == keywords::SelfType.name() &&
+               !self.sess.features_untracked().self_struct_ctor {
+                emit_feature_err(&self.sess.parse_sess, "self_struct_ctor",
+                                 p.span, GateIssue::Language,
+                                 "`Self` struct constructors are unstable");
+            }
+        }
+    }
 }
 
 fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body>) -> Vec<hir::BodyId> {
index eeb41682601f5798125be49567f819665b2f1ab2..c7824d411aac6366bf745568a31d88ec5832866f 100644 (file)
@@ -161,27 +161,27 @@ pub fn from_node(node: Node) -> Option<FnLikeNode> {
     }
 
     pub fn body(self) -> ast::BodyId {
-        self.handle(|i: ItemFnParts<'a>|  i.body,
-                    |_, _, _: &'a ast::MethodSig, _, body: ast::BodyId, _, _|  body,
+        self.handle(|i: ItemFnParts<'a>| i.body,
+                    |_, _, _: &'a ast::MethodSig, _, body: ast::BodyId, _, _| body,
                     |c: ClosureParts<'a>| c.body)
     }
 
     pub fn decl(self) -> &'a FnDecl {
-        self.handle(|i: ItemFnParts<'a>|  &*i.decl,
-                    |_, _, sig: &'a ast::MethodSig, _, _, _, _|  &sig.decl,
+        self.handle(|i: ItemFnParts<'a>| &*i.decl,
+                    |_, _, sig: &'a ast::MethodSig, _, _, _, _| &sig.decl,
                     |c: ClosureParts<'a>| c.decl)
     }
 
     pub fn span(self) -> Span {
-        self.handle(|i: ItemFnParts|     i.span,
+        self.handle(|i: ItemFnParts| i.span,
                     |_, _, _: &'a ast::MethodSig, _, _, span, _| span,
-                    |c: ClosureParts|    c.span)
+                    |c: ClosureParts| c.span)
     }
 
     pub fn id(self) -> NodeId {
-        self.handle(|i: ItemFnParts|     i.id,
+        self.handle(|i: ItemFnParts| i.id,
                     |id, _, _: &'a ast::MethodSig, _, _, _, _| id,
-                    |c: ClosureParts|    c.id)
+                    |c: ClosureParts| c.id)
     }
 
     pub fn constness(self) -> ast::Constness {
@@ -260,9 +260,7 @@ fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
                     ast::ImplItemKind::Method(ref sig, body) => {
                         method(ii.id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs)
                     }
-                    _ => {
-                        bug!("impl method FnLikeNode that is not fn-like")
-                    }
+                    _ => bug!("impl method FnLikeNode that is not fn-like")
                 }
             },
             map::Node::Expr(e) => match e.node {
index 30441c331e4cfea71cf9eabb835ff7b6ecb9d5fc..bd12a5e0cb4d8dccd87f2df68af588b3edf0e0ba 100644 (file)
@@ -67,7 +67,6 @@ pub(super) fn root(krate: &'hir Crate,
                 // them explicitly here.
                 ref attrs,
                 span,
-
                 // These fields are handled separately:
                 exported_macros: _,
                 items: _,
@@ -128,14 +127,14 @@ pub(super) fn finalize_and_compute_crate_hash(mut self,
                                                   cstore: &dyn CrateStore,
                                                   source_map: &SourceMap,
                                                   commandline_args_hash: u64)
-                                                  -> (Vec<Option<Entry<'hir>>>, Svh) {
-        self.hir_body_nodes
-            .sort_unstable_by(|&(ref d1, _), &(ref d2, _)| d1.cmp(d2));
+                                                  -> (Vec<Option<Entry<'hir>>>, Svh)
+    {
+        self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0);
 
         let node_hashes = self
             .hir_body_nodes
             .iter()
-            .fold(Fingerprint::ZERO, |fingerprint , &(def_path_hash, dep_node_index)| {
+            .fold(Fingerprint::ZERO, |fingerprint, &(def_path_hash, dep_node_index)| {
                 fingerprint.combine(
                     def_path_hash.0.combine(self.dep_graph.fingerprint_of(dep_node_index))
                 )
@@ -143,15 +142,12 @@ pub(super) fn finalize_and_compute_crate_hash(mut self,
 
         let mut upstream_crates: Vec<_> = cstore.crates_untracked().iter().map(|&cnum| {
             let name = cstore.crate_name_untracked(cnum).as_str();
-            let disambiguator = cstore.crate_disambiguator_untracked(cnum)
-                                      .to_fingerprint();
+            let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint();
             let hash = cstore.crate_hash_untracked(cnum);
             (name, disambiguator, hash)
         }).collect();
 
-        upstream_crates.sort_unstable_by(|&(name1, dis1, _), &(name2, dis2, _)| {
-            (name1, dis1).cmp(&(name2, dis2))
-        });
+        upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name, dis));
 
         // We hash the final, remapped names of all local source files so we
         // don't have to include the path prefix remapping commandline args.
@@ -229,7 +225,6 @@ fn insert(&mut self, id: NodeId, node: Node<'hir>) {
         }
 
         self.insert_entry(id, entry);
-
     }
 
     fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_id: NodeId, f: F) {
@@ -311,14 +306,11 @@ fn visit_item(&mut self, i: &'hir Item) {
         self.with_dep_node_owner(i.hir_id.owner, i, |this| {
             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(), Node::StructCtor(struct_def));
-                        }
+                if let ItemKind::Struct(ref struct_def, _) = i.node {
+                    // If this is a tuple-like struct, register the constructor.
+                    if !struct_def.is_struct() {
+                        this.insert(struct_def.id(), Node::StructCtor(struct_def));
                     }
-                    _ => {}
                 }
                 intravisit::walk_item(this, i);
             });
index cf832aee534d4cd6c1fb6e0cbf04cfcf7d4e98d1..57b3b43a338bb0a5e631132c65056c284539f15c 100644 (file)
@@ -348,13 +348,10 @@ fn visit_stmt(&mut self, stmt: &'a Stmt) {
 
     fn visit_token(&mut self, t: Token) {
         if let Token::Interpolated(nt) = t {
-            match nt.0 {
-                token::NtExpr(ref expr) => {
-                    if let ExprKind::Mac(..) = expr.node {
-                        self.visit_macro_invoc(expr.id);
-                    }
+            if let token::NtExpr(ref expr) = nt.0 {
+                if let ExprKind::Mac(..) = expr.node {
+                    self.visit_macro_invoc(expr.id);
                 }
-                _ => {}
             }
         }
     }
index 0b7fb5603cc40baf38a17236c025b1ae5ce265b7..c85cee736605533781bf9a876283e1b435737ecf 100644 (file)
@@ -317,10 +317,8 @@ pub enum DefPathData {
     // they are treated specially by the `def_path` function.
     /// The crate root (marker)
     CrateRoot,
-
     // Catch-all for random DefId things like DUMMY_NODE_ID
     Misc,
-
     // Different kinds of items and item-like things:
     /// An impl
     Impl,
@@ -342,7 +340,6 @@ pub enum DefPathData {
     MacroDef(InternedString),
     /// A closure expression
     ClosureExpr,
-
     // Subportions of items
     /// A type parameter (generic parameter)
     TypeParam(InternedString),
@@ -358,7 +355,6 @@ pub enum DefPathData {
     AnonConst,
     /// An `impl Trait` type node
     ImplTrait,
-
     /// GlobalMetaData identifies a piece of crate metadata that is global to
     /// a whole crate (as opposed to just one item). GlobalMetaData components
     /// are only supposed to show up right below the crate root.
@@ -656,10 +652,8 @@ pub fn as_interned_str(&self) -> InternedString {
             GlobalMetaData(name) => {
                 return name
             }
-
             // note that this does not show up in user printouts
             CrateRoot => "{{root}}",
-
             Impl => "{{impl}}",
             Misc => "{{?}}",
             ClosureExpr => "{{closure}}",
index a17c160c4d03e5340051d6597dd69ab1a7ed59cf..d61b5313444f37d23eecb2bae34fc573421da2d1 100644 (file)
@@ -100,8 +100,8 @@ fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self,
 
         if max != self.hir_ids_seen.len() - 1 {
             // Collect the missing ItemLocalIds
-            let missing: Vec<_> = (0 .. max + 1)
-              .filter(|&i| !self.hir_ids_seen.contains_key(&ItemLocalId(i as u32)))
+            let missing: Vec<_> = (0 .. max as u32 + 1)
+              .filter(|&i| !self.hir_ids_seen.contains_key(&ItemLocalId(i)))
               .collect();
 
             // Try to map those to something more useful
index 6fffde7cab50cdc578839693e0cde37c8b8028c6..31fba3ad97493158d9d3a879f514d81e0cea7dbf 100644 (file)
@@ -291,8 +291,7 @@ pub fn describe_def(&self, node_id: NodeId) -> Option<Def> {
                 };
 
                 match item.node {
-                    ItemKind::Static(_, m, _) => Some(Def::Static(def_id(),
-                                                            m == MutMutable)),
+                    ItemKind::Static(_, m, _) => Some(Def::Static(def_id(), m == MutMutable)),
                     ItemKind::Const(..) => Some(Def::Const(def_id())),
                     ItemKind::Fn(..) => Some(Def::Fn(def_id())),
                     ItemKind::Mod(..) => Some(Def::Mod(def_id())),
@@ -408,7 +407,7 @@ pub fn body(&self, id: BodyId) -> &'hir Body {
 
     pub fn fn_decl(&self, node_id: ast::NodeId) -> Option<FnDecl> {
         if let Some(entry) = self.find_entry(node_id) {
-            entry.fn_decl().map(|fd| fd.clone())
+            entry.fn_decl().cloned()
         } else {
             bug!("no entry for node_id `{}`", node_id)
         }
@@ -471,18 +470,13 @@ pub fn ty_param_owner(&self, id: NodeId) -> NodeId {
         match self.get(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))
-            }
+            _ => bug!("ty_param_owner: {} not a type parameter", self.node_to_string(id))
         }
     }
 
     pub fn ty_param_name(&self, id: NodeId) -> Name {
         match self.get(id) {
-            Node::Item(&Item { node: ItemKind::Trait(..), .. }) => {
-                keywords::SelfType.name()
-            }
+            Node::Item(&Item { node: ItemKind::Trait(..), .. }) => keywords::SelfType.name(),
             Node::GenericParam(param) => param.name.ident().name,
             _ => bug!("ty_param_name: {} not a type parameter", self.node_to_string(id)),
         }
@@ -521,10 +515,8 @@ pub fn krate_attrs(&self) -> &'hir [ast::Attribute] {
     /// Retrieve the Node corresponding to `id`, panicking if it cannot
     /// be found.
     pub fn get(&self, id: NodeId) -> Node<'hir> {
-        match self.find(id) {
-            Some(node) => node, // read recorded by `find`
-            None => bug!("couldn't find node id {} in the AST map", id)
-        }
+        // read recorded by `find`
+        self.find(id).unwrap_or_else(|| bug!("couldn't find node id {} in the AST map", id))
     }
 
     pub fn get_if_local(&self, id: DefId) -> Option<Node<'hir>> {
@@ -697,10 +689,7 @@ pub fn get_return_block(&self, id: NodeId) -> Option<NodeId> {
             }
         };
 
-        match self.walk_parent_nodes(id, match_fn, match_non_returning_block) {
-            Ok(id) => Some(id),
-            Err(_) => None,
-        }
+        self.walk_parent_nodes(id, match_fn, match_non_returning_block).ok()
     }
 
     /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no
@@ -738,17 +727,14 @@ pub fn get_module_parent(&self, id: NodeId) -> DefId {
     /// and associated types probably shouldn't, for example. Behavior in this
     /// 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 {
+        self.walk_parent_nodes(id, |node| match *node {
             Node::Item(_) |
             Node::ForeignItem(_) |
             Node::TraitItem(_) |
             Node::ImplItem(_) |
             Node::Block(_) => true,
             _ => false,
-        }, |_| false) {
-            Ok(id) => Some(id),
-            Err(_) => None,
-        }
+        }, |_| false).ok()
     }
 
     pub fn get_parent_did(&self, id: NodeId) -> DefId {
@@ -758,13 +744,11 @@ pub fn get_parent_did(&self, id: NodeId) -> DefId {
     pub fn get_foreign_abi(&self, id: NodeId) -> Abi {
         let parent = self.get_parent(id);
         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;
-                }
-                _ => {}
+            if let Entry {
+                node: Node::Item(Item { node: ItemKind::ForeignMod(ref nm), .. }), .. } = entry
+            {
+                self.read(id); // reveals some of the content of a node
+                return nm.abi;
             }
         }
         bug!("expected foreign mod or inlined parent, found {}", self.node_to_string(parent))
@@ -797,18 +781,12 @@ pub fn expect_variant_data(&self, id: NodeId) -> &'hir VariantData {
                 match i.node {
                     ItemKind::Struct(ref struct_def, _) |
                     ItemKind::Union(ref struct_def, _) => struct_def,
-                    _ => {
-                        bug!("struct ID bound to non-struct {}",
-                             self.node_to_string(id));
-                    }
+                    _ => bug!("struct ID bound to non-struct {}", self.node_to_string(id))
                 }
             }
             Some(Node::StructCtor(data)) => data,
             Some(Node::Variant(variant)) => &variant.node.data,
-            _ => {
-                bug!("expected struct or variant, found {}",
-                     self.node_to_string(id));
-            }
+            _ => bug!("expected struct or variant, found {}", self.node_to_string(id))
         }
     }
 
@@ -866,9 +844,7 @@ pub fn attrs(&self, id: NodeId) -> &'hir [ast::Attribute] {
             Some(Node::GenericParam(param)) => Some(&param.attrs[..]),
             // unit/tuple structs take the attributes straight from
             // the struct definition.
-            Some(Node::StructCtor(_)) => {
-                return self.attrs(self.get_parent(id));
-            }
+            Some(Node::StructCtor(_)) => return self.attrs(self.get_parent(id)),
             _ => None
         };
         attrs.unwrap_or(&[])
@@ -917,7 +893,6 @@ pub fn span(&self, id: NodeId) -> Span {
             Some(Node::Visibility(v)) => bug!("unexpected Visibility {:?}", v),
             Some(Node::Local(local)) => local.span,
             Some(Node::MacroDef(macro_def)) => macro_def.span,
-
             Some(Node::Crate) => self.forest.krate.span,
             None => bug!("hir::map::Map::span: id not in map: {:?}", id),
         }
@@ -976,10 +951,10 @@ fn suffix_matches(&self, parent: NodeId) -> bool {
         // chain, then returns `None`.
         fn find_first_mod_parent<'a>(map: &'a Map, mut id: NodeId) -> Option<(NodeId, Name)> {
             loop {
-                match map.find(id)? {
-                    Node::Item(item) if item_is_mod(&item) =>
-                        return Some((id, item.name)),
-                    _ => {}
+                if let Node::Item(item) = map.find(id)? {
+                    if item_is_mod(&item) {
+                        return Some((id, item.name))
+                    }
                 }
                 let parent = map.get_parent(id);
                 if parent == id { return None }
@@ -1041,7 +1016,6 @@ impl Named for StructField { fn name(&self) -> Name { self.ident.name } }
 impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } }
 impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } }
 
-
 pub fn map_crate<'hir>(sess: &::session::Session,
                        cstore: &dyn CrateStore,
                        forest: &'hir mut Forest,
@@ -1142,7 +1116,7 @@ pub fn print_node(&mut self, node: Node) -> io::Result<()> {
             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"),
+            Node::Crate           => bug!("cannot print Crate"),
         }
     }
 }
index 1b3103578737190b2c32a3886806940a6022af92..de9808ffe7001b66abfb0faaa23886d8a6a76902 100644 (file)
@@ -831,9 +831,10 @@ fn walk_<G>(&self, it: &mut G) -> bool
                 s.walk_(it)
             }
             PatKind::Slice(ref before, ref slice, ref after) => {
-                before.iter().all(|p| p.walk_(it)) &&
-                slice.iter().all(|p| p.walk_(it)) &&
-                after.iter().all(|p| p.walk_(it))
+                before.iter()
+                      .chain(slice.iter())
+                      .chain(after.iter())
+                      .all(|p| p.walk_(it))
             }
             PatKind::Wild |
             PatKind::Lit(_) |
@@ -872,23 +873,23 @@ pub struct FieldPat {
 /// inference.
 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
 pub enum BindingAnnotation {
-  /// No binding annotation given: this means that the final binding mode
-  /// will depend on whether we have skipped through a `&` reference
-  /// when matching. For example, the `x` in `Some(x)` will have binding
-  /// mode `None`; if you do `let Some(x) = &Some(22)`, it will
-  /// ultimately be inferred to be by-reference.
-  ///
-  /// Note that implicit reference skipping is not implemented yet (#42640).
-  Unannotated,
+    /// No binding annotation given: this means that the final binding mode
+    /// will depend on whether we have skipped through a `&` reference
+    /// when matching. For example, the `x` in `Some(x)` will have binding
+    /// mode `None`; if you do `let Some(x) = &Some(22)`, it will
+    /// ultimately be inferred to be by-reference.
+    ///
+    /// Note that implicit reference skipping is not implemented yet (#42640).
+    Unannotated,
 
-  /// Annotated with `mut x` -- could be either ref or not, similar to `None`.
-  Mutable,
+    /// Annotated with `mut x` -- could be either ref or not, similar to `None`.
+    Mutable,
 
-  /// Annotated as `ref`, like `ref x`
-  Ref,
+    /// Annotated as `ref`, like `ref x`
+    Ref,
 
-  /// Annotated as `ref mut x`.
-  RefMut,
+    /// Annotated as `ref mut x`.
+    RefMut,
 }
 
 #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
@@ -1658,7 +1659,6 @@ pub struct TypeBinding {
     pub span: Span,
 }
 
-
 #[derive(Clone, RustcEncodable, RustcDecodable)]
 pub struct Ty {
     pub id: NodeId,
@@ -2284,7 +2284,6 @@ pub struct TraitCandidate {
 // imported.
 pub type GlobMap = NodeMap<FxHashSet<Name>>;
 
-
 pub fn provide(providers: &mut Providers) {
     providers.describe_def = map::describe_def;
 }
index 55357095fb7596f10b6281af5f268493dab500bd..7638a2cc140c732f6e05ef7794ce075abc684f84 100644 (file)
@@ -251,6 +251,7 @@ pub fn bopen(&mut self) -> io::Result<()> {
     pub fn bclose_(&mut self, span: syntax_pos::Span, indented: usize) -> io::Result<()> {
         self.bclose_maybe_open(span, indented, true)
     }
+
     pub fn bclose_maybe_open(&mut self,
                              span: syntax_pos::Span,
                              indented: usize,
@@ -264,6 +265,7 @@ pub fn bclose_maybe_open(&mut self,
         }
         Ok(())
     }
+
     pub fn bclose(&mut self, span: syntax_pos::Span) -> io::Result<()> {
         self.bclose_(span, indent_unit)
     }
@@ -274,12 +276,14 @@ pub fn in_cbox(&self) -> bool {
             None => false,
         }
     }
+
     pub fn space_if_not_bol(&mut self) -> io::Result<()> {
         if !self.is_bol() {
             self.s.space()?;
         }
         Ok(())
     }
+
     pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) -> io::Result<()> {
         if !self.is_bol() {
             self.s.break_offset(n, off)
@@ -304,7 +308,6 @@ pub fn synth_comment(&mut self, text: String) -> io::Result<()> {
         self.s.word("*/")
     }
 
-
     pub fn commasep_cmnt<T, F, G>(&mut self,
                                   b: Breaks,
                                   elts: &[T],
@@ -689,20 +692,14 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                     self.s.space()?;
                 }
 
-                match polarity {
-                    hir::ImplPolarity::Negative => {
-                        self.s.word("!")?;
-                    }
-                    _ => {}
+                if let hir::ImplPolarity::Negative = polarity {
+                    self.s.word("!")?;
                 }
 
-                match opt_trait {
-                    &Some(ref t) => {
-                        self.print_trait_ref(t)?;
-                        self.s.space()?;
-                        self.word_space("for")?;
-                    }
-                    &None => {}
+                if let Some(ref t) = opt_trait {
+                    self.print_trait_ref(t)?;
+                    self.s.space()?;
+                    self.word_space("for")?;
                 }
 
                 self.print_type(&ty)?;
@@ -1061,13 +1058,10 @@ pub fn print_block_maybe_unclosed(&mut self,
         for st in &blk.stmts {
             self.print_stmt(st)?;
         }
-        match blk.expr {
-            Some(ref expr) => {
-                self.space_if_not_bol()?;
-                self.print_expr(&expr)?;
-                self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()))?;
-            }
-            _ => (),
+        if let Some(ref expr) = blk.expr {
+            self.space_if_not_bol()?;
+            self.print_expr(&expr)?;
+            self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()))?;
         }
         self.bclose_maybe_open(blk.span, indented, close_box)?;
         self.ann.post(self, AnnNode::Block(blk))
@@ -1479,12 +1473,9 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
             }
             hir::ExprKind::Ret(ref result) => {
                 self.s.word("return")?;
-                match *result {
-                    Some(ref expr) => {
-                        self.s.word(" ")?;
-                        self.print_expr_maybe_paren(&expr, parser::PREC_JUMP)?;
-                    }
-                    _ => (),
+                if let Some(ref expr) = *result {
+                    self.s.word(" ")?;
+                    self.print_expr_maybe_paren(&expr, parser::PREC_JUMP)?;
                 }
             }
             hir::ExprKind::InlineAsm(ref a, ref outputs, ref inputs) => {
index 3f1899bc54fb4c2e1e34b1c548cb51fcc3726e6b..bc2eb5f442b47df373d9173d2cea1f627a8a9f9e 100644 (file)
@@ -1021,6 +1021,7 @@ fn to_stable_hash_key(&self,
     Const(def_id),
     Static(def_id, is_mutbl),
     StructCtor(def_id, ctor_kind),
+    SelfCtor(impl_def_id),
     VariantCtor(def_id, ctor_kind),
     Method(def_id),
     AssociatedConst(def_id),
index 16175e159dd23e81baa6ca51e5eea10f8ea6065f..2bf1c79c8a43606dc5e0c120d359da8252e8f13c 100644 (file)
@@ -772,7 +772,15 @@ fn hash_stable<W: StableHasherResult>(&self,
     FnPtrAddrCast
 });
 
-impl_stable_hash_for!(struct ::middle::region::Scope { id, code });
+impl_stable_hash_for!(struct ::middle::region::Scope { id, data });
+
+impl_stable_hash_for!(enum ::middle::region::ScopeData {
+    Node,
+    CallSite,
+    Arguments,
+    Destruction,
+    Remainder(first_statement_index)
+});
 
 impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
     type KeyType = region::Scope;
@@ -783,11 +791,6 @@ fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope {
     }
 }
 
-impl_stable_hash_for!(struct ::middle::region::BlockRemainder {
-    block,
-    first_statement_index
-});
-
 impl_stable_hash_for!(struct ty::adjustment::CoerceUnsizedInfo {
     custom_kind
 });
index eabcf1ce4136361878b3879dc62df4271eee517d..cf76c3b7e02dfbb94185bdd6ff561e07c0b400ee 100644 (file)
@@ -118,18 +118,18 @@ pub fn note_and_explain_region(
                         return;
                     }
                 };
-                let scope_decorated_tag = match scope.data() {
-                    region::ScopeData::Node(_) => tag,
-                    region::ScopeData::CallSite(_) => "scope of call-site for function",
-                    region::ScopeData::Arguments(_) => "scope of function body",
-                    region::ScopeData::Destruction(_) => {
+                let scope_decorated_tag = match scope.data {
+                    region::ScopeData::Node => tag,
+                    region::ScopeData::CallSite => "scope of call-site for function",
+                    region::ScopeData::Arguments => "scope of function body",
+                    region::ScopeData::Destruction => {
                         new_string = format!("destruction scope surrounding {}", tag);
                         &new_string[..]
                     }
-                    region::ScopeData::Remainder(r) => {
+                    region::ScopeData::Remainder(first_statement_index) => {
                         new_string = format!(
                             "block suffix following statement {}",
-                            r.first_statement_index.index()
+                            first_statement_index.index()
                         );
                         &new_string[..]
                     }
index 168285b455f0a3c8c2ad4e846b8d156c6f52ce58..97b1978cb2eb2223af8e437504a15ee63945b470 100644 (file)
@@ -56,9 +56,9 @@ pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
         let (span, sub, sup) = self.get_regions();
 
         // Determine whether the sub and sup consist of both anonymous (elided) regions.
-        let anon_reg_sup = self.is_suitable_region(sup)?;
+        let anon_reg_sup = self.tcx.is_suitable_region(sup)?;
 
-        let anon_reg_sub = self.is_suitable_region(sub)?;
+        let anon_reg_sub = self.tcx.is_suitable_region(sub)?;
         let scope_def_id_sup = anon_reg_sup.def_id;
         let bregion_sup = anon_reg_sup.boundregion;
         let scope_def_id_sub = anon_reg_sub.def_id;
index e3faf755672a10c55916cd51f101faddd15de726..10a2d179dd564e4aef52f81f24da3c75b115956f 100644 (file)
@@ -36,7 +36,7 @@ pub(super) fn find_anon_type(
         region: Region<'tcx>,
         br: &ty::BoundRegion,
     ) -> Option<(&hir::Ty, &hir::FnDecl)> {
-        if let Some(anon_reg) = self.is_suitable_region(region) {
+        if let Some(anon_reg) = self.tcx.is_suitable_region(region) {
             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) {
index 4e26a4178b95d78748bf92ed5364d90f904a3589..6ff008919e52cab9a627165020d7a1b77ec92b22 100644 (file)
@@ -13,6 +13,7 @@
 use infer::error_reporting::nice_region_error::NiceRegionError;
 use ty;
 use util::common::ErrorReported;
+use errors::Applicability;
 
 impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
     /// When given a `ConcreteFailure` for a function with arguments containing a named region and
@@ -33,23 +34,23 @@ pub(super) fn try_report_named_anon_conflict(&self) -> Option<ErrorReported> {
         // version new_ty of its type where the anonymous region is replaced
         // with the named one.//scope_def_id
         let (named, anon, anon_arg_info, region_info) = if self.is_named_region(sub)
-            && self.is_suitable_region(sup).is_some()
+            && self.tcx.is_suitable_region(sup).is_some()
             && self.find_arg_with_region(sup, sub).is_some()
         {
             (
                 sub,
                 sup,
                 self.find_arg_with_region(sup, sub).unwrap(),
-                self.is_suitable_region(sup).unwrap(),
+                self.tcx.is_suitable_region(sup).unwrap(),
             )
-        } else if self.is_named_region(sup) && self.is_suitable_region(sub).is_some()
+        } else if self.is_named_region(sup) && self.tcx.is_suitable_region(sub).is_some()
             && self.find_arg_with_region(sub, sup).is_some()
         {
             (
                 sup,
                 sub,
                 self.find_arg_with_region(sub, sup).unwrap(),
-                self.is_suitable_region(sub).unwrap(),
+                self.tcx.is_suitable_region(sub).unwrap(),
             )
         } else {
             return None; // inapplicable
@@ -111,13 +112,14 @@ pub(super) fn try_report_named_anon_conflict(&self) -> Option<ErrorReported> {
             E0621,
             "explicit lifetime required in {}",
             error_var
-        ).span_suggestion(
+        ).span_suggestion_with_applicability(
             new_ty_span,
             &format!("add explicit lifetime `{}` to {}", named, span_label_var),
-            new_ty.to_string()
+            new_ty.to_string(),
+            Applicability::Unspecified,
         )
-            .span_label(span, format!("lifetime `{}` required", named))
-            .emit();
+        .span_label(span, format!("lifetime `{}` required", named))
+        .emit();
         return Some(ErrorReported);
     }
 
index d25dcd5b045ca30aef3918c86285e98cfec794c9..3393eb65089c05a55e3b6cf337ff6cd98b0860c0 100644 (file)
@@ -14,6 +14,7 @@
 use infer::lexical_region_resolve::RegionResolutionError;
 use ty::{BoundRegion, FreeRegion, RegionKind};
 use util::common::ErrorReported;
+use errors::Applicability;
 
 impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
     /// Print the error message for lifetime errors when the return type is a static impl Trait.
@@ -27,9 +28,9 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
                     sup_origin,
                     sup_r,
                 ) => {
-                    let anon_reg_sup = self.is_suitable_region(sup_r)?;
+                    let anon_reg_sup = self.tcx.is_suitable_region(sup_r)?;
                     if sub_r == &RegionKind::ReStatic &&
-                        self.is_return_type_impl_trait(anon_reg_sup.def_id)
+                        self.tcx.return_type_impl_trait(anon_reg_sup.def_id).is_some()
                     {
                         let sp = var_origin.span();
                         let return_sp = sub_origin.span();
@@ -61,7 +62,7 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
                             _ => "'_".to_owned(),
                         };
                         if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(return_sp) {
-                            err.span_suggestion(
+                            err.span_suggestion_with_applicability(
                                 return_sp,
                                 &format!(
                                     "you can add a constraint to the return type to make it last \
@@ -69,6 +70,7 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
                                     lifetime,
                                 ),
                                 format!("{} + {}", snippet, lifetime_name),
+                                Applicability::Unspecified,
                             );
                         }
                         err.emit();
index 30406f1fec55cd208ce6c56779f64c84deaa17b4..afc50fe1151665e3a37fb37549644f74013d5344 100644 (file)
@@ -15,7 +15,6 @@
 use infer::error_reporting::nice_region_error::NiceRegionError;
 use ty::{self, Region, Ty};
 use hir::def_id::DefId;
-use hir::Node;
 use syntax_pos::Span;
 
 // The struct contains the information about the anonymous region
@@ -35,18 +34,6 @@ pub(super) struct AnonymousArgInfo<'tcx> {
     pub is_first: bool,
 }
 
-// This struct contains information regarding the
-// Refree((FreeRegion) corresponding to lifetime conflict
-#[derive(Debug)]
-pub(super) struct FreeRegionInfo {
-    // def id corresponding to FreeRegion
-    pub def_id: DefId,
-    // the bound region corresponding to FreeRegion
-    pub boundregion: ty::BoundRegion,
-    // checks if bound region is in Impl Item
-    pub is_impl_item: bool,
-}
-
 impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
     // This method walks the Type of the function body arguments using
     // `fold_regions()` function and returns the
@@ -122,36 +109,6 @@ pub(super) fn find_arg_with_region(
         }
     }
 
-    // This method returns the DefId and the BoundRegion corresponding to the given region.
-    pub(super) fn is_suitable_region(&self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
-        let (suitable_region_binding_scope, bound_region) = match *region {
-            ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
-            ty::ReEarlyBound(ref ebr) => (
-                self.tcx.parent_def_id(ebr.def_id).unwrap(),
-                ty::BoundRegion::BrNamed(ebr.def_id, ebr.name),
-            ),
-            _ => return None, // not a free region
-        };
-
-        let node_id = self.tcx
-            .hir
-            .as_local_node_id(suitable_region_binding_scope)
-            .unwrap();
-        let is_impl_item = match self.tcx.hir.find(node_id) {
-            Some(Node::Item(..)) | Some(Node::TraitItem(..)) => false,
-            Some(Node::ImplItem(..)) => {
-                self.is_bound_region_in_impl_item(suitable_region_binding_scope)
-            }
-            _ => return None,
-        };
-
-        return Some(FreeRegionInfo {
-            def_id: suitable_region_binding_scope,
-            boundregion: bound_region,
-            is_impl_item: is_impl_item,
-        });
-    }
-
     // Here, we check for the case where the anonymous region
     // is in the return type.
     // FIXME(#42703) - Need to handle certain cases here.
@@ -176,22 +133,6 @@ pub(super) fn is_return_type_anon(
         None
     }
 
-    pub(super) fn is_return_type_impl_trait(
-        &self,
-        scope_def_id: DefId,
-    ) -> bool {
-        let ret_ty = self.tcx.type_of(scope_def_id);
-        match ret_ty.sty {
-            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();
-            }
-            _ => {}
-        }
-        false
-    }
-
     // Here we check for the case where anonymous region
     // corresponds to self and if yes, we display E0312.
     // FIXME(#42700) - Need to format self properly to
@@ -203,24 +144,4 @@ pub(super) fn is_self_anon(&self, is_first: bool, scope_def_id: DefId) -> bool {
                 .map(|i| i.method_has_self_argument) == Some(true)
     }
 
-    // Here we check if the bound region is in Impl Item.
-    pub(super) fn is_bound_region_in_impl_item(
-        &self,
-        suitable_region_binding_scope: DefId,
-    ) -> bool {
-        let container_id = self.tcx
-            .associated_item(suitable_region_binding_scope)
-            .container
-            .id();
-        if self.tcx.impl_trait_ref(container_id).is_some() {
-            // For now, we do not try to target impls of traits. This is
-            // because this message is going to suggest that the user
-            // change the fn signature, but they may not be free to do so,
-            // since the signature must match the trait.
-            //
-            // FIXME(#42706) -- in some cases, we could do better here.
-            return true;
-        }
-        false
-    }
 }
index 56096a5d423f33e986b4c47b03026929bb7a6377..c017c90b8955043ad0ab52fc285e09c98a57b0b7 100644 (file)
@@ -58,6 +58,8 @@
 #![feature(optin_builtin_traits)]
 #![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
+#![feature(rustc_attrs)]
+#![cfg_attr(stage0, feature(attr_literals))]
 #![feature(slice_patterns)]
 #![feature(slice_sort_by_cached_key)]
 #![feature(specialization)]
index 6783415619f983c1bdd3b0808d913b69c2cb1a72..e6452ad09278e45a7282490e0582a40d4c9efba2 100644 (file)
@@ -422,6 +422,7 @@ pub enum BuiltinLintDiagnostics {
     ProcMacroDeriveResolutionFallback(Span),
     MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
     ElidedLifetimesInPaths(usize, Span, bool, Span, String),
+    UnknownCrateTypes(Span, String, String),
 }
 
 impl BuiltinLintDiagnostics {
@@ -500,6 +501,14 @@ pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder) {
                     Applicability::MachineApplicable
                 );
             }
+            BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
+                db.span_suggestion_with_applicability(
+                    span,
+                    &note,
+                    sugg,
+                    Applicability::MaybeIncorrect
+                );
+            }
         }
     }
 }
index 356992b22146d67b02d63c409b07787c93b46774..469ae04c0fdc10bb70dc74c349f461d33ffb37f7 100644 (file)
@@ -317,7 +317,11 @@ pub fn consume_body(&mut self, body: &hir::Body) {
             debug!("consume_body: arg_ty = {:?}", arg_ty);
 
             let fn_body_scope_r =
-                self.tcx().mk_region(ty::ReScope(region::Scope::Node(body.value.hir_id.local_id)));
+                self.tcx().mk_region(ty::ReScope(
+                    region::Scope {
+                        id: body.value.hir_id.local_id,
+                        data: region::ScopeData::Node
+                    }));
             let arg_cmt = Rc::new(self.mc.cat_rvalue(
                 arg.hir_id,
                 arg.pat.span,
@@ -558,7 +562,10 @@ fn walk_callee(&mut self, call: &hir::Expr, callee: &hir::Expr) {
             _ => {
                 if let Some(def) = self.mc.tables.type_dependent_defs().get(call.hir_id) {
                     let def_id = def.def_id();
-                    let call_scope = region::Scope::Node(call.hir_id.local_id);
+                    let call_scope = region::Scope {
+                        id: call.hir_id.local_id,
+                        data: region::ScopeData::Node
+                    };
                     match OverloadedCallType::from_method_id(self.tcx(), def_id) {
                         FnMutOverloadedCall => {
                             let call_scope_r = self.tcx().mk_region(ty::ReScope(call_scope));
@@ -766,7 +773,10 @@ fn walk_autoref(&mut self,
                 // treated as borrowing it for the enclosing temporary
                 // scope.
                 let r = self.tcx().mk_region(ty::ReScope(
-                    region::Scope::Node(expr.hir_id.local_id)));
+                    region::Scope {
+                        id: expr.hir_id.local_id,
+                        data: region::ScopeData::Node
+                    }));
 
                 self.delegate.borrow(expr.id,
                                      expr.span,
index d92f856fa4dbff90445e78b1276bd011d5255b9b..bfde4e4a3aed8abb8d94d85aa8381f15908f1633 100644 (file)
@@ -326,8 +326,6 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
 
     PhantomDataItem,                 "phantom_data",            phantom_data;
 
-    NonZeroItem,                     "non_zero",                non_zero;
-
     ManuallyDropItem,                "manually_drop",           manually_drop;
 
     DebugTraitLangItem,              "debug_trait",             debug_trait;
index c34a0a654e6a9f7c1964b39b3fa0c4e411391010..13847fb48cee961e0d96e58006fee93c582dfc8d 100644 (file)
 //! methods.  It effectively does a reverse walk of the AST; whenever we
 //! reach a loop node, we iterate until a fixed point is reached.
 //!
-//! ## The `Users` struct
+//! ## The `users_*` fields
 //!
 //! At each live node `N`, we track three pieces of information for each
-//! variable `V` (these are encapsulated in the `Users` struct):
+//! variable `V` (these are in the `users_*` fields):
 //!
 //! - `reader`: the `LiveNode` ID of some node which will read the value
 //!    that `V` holds on entry to `N`.  Formally: a node `M` such
@@ -536,21 +536,6 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
 // Actually we compute just a bit more than just liveness, but we use
 // the same basic propagation framework in all cases.
 
-#[derive(Clone, Copy)]
-struct Users {
-    reader: LiveNode,
-    writer: LiveNode,
-    used: bool
-}
-
-fn invalid_users() -> Users {
-    Users {
-        reader: invalid_node(),
-        writer: invalid_node(),
-        used: false
-    }
-}
-
 #[derive(Copy, Clone)]
 struct Specials {
     exit_ln: LiveNode,
@@ -567,7 +552,14 @@ struct Liveness<'a, 'tcx: 'a> {
     tables: &'a ty::TypeckTables<'tcx>,
     s: Specials,
     successors: Vec<LiveNode>,
-    users: Vec<Users>,
+
+    // We used to have a single `users: Vec<Users>` field here, where `Users`
+    // had `reader`, `writer` and `used` fields. But the number of users can
+    // get very large, and it's more compact to store the data in three
+    // separate `Vec`s so that no space is wasted for padding.
+    users_reader: Vec<LiveNode>,
+    users_writer: Vec<LiveNode>,
+    users_used: Vec<bool>,
 
     // mappings from loop node ID to LiveNode
     // ("break" label should map to loop node ID,
@@ -592,13 +584,16 @@ fn new(ir: &'a mut IrMaps<'a, 'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> {
 
         let num_live_nodes = ir.num_live_nodes;
         let num_vars = ir.num_vars;
+        let num_users = num_live_nodes * num_vars;
 
         Liveness {
             ir,
             tables,
             s: specials,
             successors: vec![invalid_node(); num_live_nodes],
-            users: vec![invalid_users(); num_live_nodes * num_vars],
+            users_reader: vec![invalid_node(); num_users],
+            users_writer: vec![invalid_node(); num_users],
+            users_used: vec![false; num_users],
             break_ln: NodeMap(),
             cont_ln: NodeMap(),
         }
@@ -665,7 +660,7 @@ fn idx(&self, ln: LiveNode, var: Variable) -> usize {
     fn live_on_entry(&self, ln: LiveNode, var: Variable)
                       -> Option<LiveNodeKind> {
         assert!(ln.is_valid());
-        let reader = self.users[self.idx(ln, var)].reader;
+        let reader = self.users_reader[self.idx(ln, var)];
         if reader.is_valid() {Some(self.ir.lnk(reader))} else {None}
     }
 
@@ -680,13 +675,13 @@ fn live_on_exit(&self, ln: LiveNode, var: Variable)
 
     fn used_on_entry(&self, ln: LiveNode, var: Variable) -> bool {
         assert!(ln.is_valid());
-        self.users[self.idx(ln, var)].used
+        self.users_used[self.idx(ln, var)]
     }
 
     fn assigned_on_entry(&self, ln: LiveNode, var: Variable)
                          -> Option<LiveNodeKind> {
         assert!(ln.is_valid());
-        let writer = self.users[self.idx(ln, var)].writer;
+        let writer = self.users_writer[self.idx(ln, var)];
         if writer.is_valid() {Some(self.ir.lnk(writer))} else {None}
     }
 
@@ -730,9 +725,9 @@ fn ln_str(&self, ln: LiveNode) -> String {
         {
             let wr = &mut wr as &mut dyn Write;
             write!(wr, "[ln({:?}) of kind {:?} reads", ln.get(), self.ir.lnk(ln));
-            self.write_vars(wr, ln, |idx| self.users[idx].reader);
+            self.write_vars(wr, ln, |idx| self.users_reader[idx]);
             write!(wr, "  writes");
-            self.write_vars(wr, ln, |idx| self.users[idx].writer);
+            self.write_vars(wr, ln, |idx| self.users_writer[idx]);
             write!(wr, "  precedes {:?}]", self.successors[ln.get()]);
         }
         String::from_utf8(wr).unwrap()
@@ -747,7 +742,9 @@ fn init_empty(&mut self, ln: LiveNode, succ_ln: LiveNode) {
         // only grow during iterations.
         //
         // self.indices(ln) { |idx|
-        //     self.users[idx] = invalid_users();
+        //     self.users_reader[idx] = invalid_node();
+        //     self.users_writer[idx] = invalid_node();
+        //     self.users_used[idx] = false;
         // }
     }
 
@@ -756,7 +753,9 @@ fn init_from_succ(&mut self, ln: LiveNode, succ_ln: LiveNode) {
         self.successors[ln.get()] = succ_ln;
 
         self.indices2(ln, succ_ln, |this, idx, succ_idx| {
-            this.users[idx] = this.users[succ_idx]
+            this.users_reader[idx] = this.users_reader[succ_idx];
+            this.users_writer[idx] = this.users_writer[succ_idx];
+            this.users_used[idx] = this.users_used[succ_idx];
         });
         debug!("init_from_succ(ln={}, succ={})",
                self.ln_str(ln), self.ln_str(succ_ln));
@@ -771,12 +770,10 @@ fn merge_from_succ(&mut self,
 
         let mut changed = false;
         self.indices2(ln, succ_ln, |this, idx, succ_idx| {
-            changed |= copy_if_invalid(this.users[succ_idx].reader,
-                                       &mut this.users[idx].reader);
-            changed |= copy_if_invalid(this.users[succ_idx].writer,
-                                       &mut this.users[idx].writer);
-            if this.users[succ_idx].used && !this.users[idx].used {
-                this.users[idx].used = true;
+            changed |= copy_if_invalid(this.users_reader[succ_idx], &mut this.users_reader[idx]);
+            changed |= copy_if_invalid(this.users_writer[succ_idx], &mut this.users_writer[idx]);
+            if this.users_used[succ_idx] && !this.users_used[idx] {
+                this.users_used[idx] = true;
                 changed = true;
             }
         });
@@ -800,8 +797,8 @@ fn copy_if_invalid(src: LiveNode, dst: &mut LiveNode) -> bool {
     // this) so we just clear out all the data.
     fn define(&mut self, writer: LiveNode, var: Variable) {
         let idx = self.idx(writer, var);
-        self.users[idx].reader = invalid_node();
-        self.users[idx].writer = invalid_node();
+        self.users_reader[idx] = invalid_node();
+        self.users_writer[idx] = invalid_node();
 
         debug!("{:?} defines {:?} (idx={}): {}", writer, var,
                idx, self.ln_str(writer));
@@ -813,21 +810,20 @@ fn acc(&mut self, ln: LiveNode, var: Variable, acc: u32) {
                ln, acc, var, self.ln_str(ln));
 
         let idx = self.idx(ln, var);
-        let user = &mut self.users[idx];
 
         if (acc & ACC_WRITE) != 0 {
-            user.reader = invalid_node();
-            user.writer = ln;
+            self.users_reader[idx] = invalid_node();
+            self.users_writer[idx] = ln;
         }
 
         // Important: if we both read/write, must do read second
         // or else the write will override.
         if (acc & ACC_READ) != 0 {
-            user.reader = ln;
+            self.users_reader[idx] = ln;
         }
 
         if (acc & ACC_USE) != 0 {
-            user.used = true;
+            self.users_used[idx] = true;
         }
     }
 
index b63cde0f205f78031363d851a4e6d718291f8620..172511474710d6e47c6cf27b4eb6751c04fed669 100644 (file)
@@ -708,7 +708,7 @@ pub fn cat_def(&self,
 
         match def {
           Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) |
-          Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) => {
+          Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => {
                 Ok(self.cat_rvalue_node(hir_id, span, expr_ty))
           }
 
@@ -1288,7 +1288,7 @@ fn cat_pattern_<F>(&self, mut cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McR
                     (self.cat_downcast_if_needed(pat, cmt, def_id),
                      self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len())
                 }
-                Def::StructCtor(_, CtorKind::Fn) => {
+                Def::StructCtor(_, CtorKind::Fn) | Def::SelfCtor(..) => {
                     match self.pat_ty_unadjusted(&pat)?.sty {
                         ty::Adt(adt_def, _) => {
                             (cmt, adt_def.non_enum_variant().fields.len())
index f6a8f8dc172d4c0266b9b73b9547ef3380ede793..788fbcef17163581c6e5709b10cdb90ed2da018b 100644 (file)
@@ -20,8 +20,8 @@
 use util::nodemap::{FxHashMap, FxHashSet};
 use ty;
 
-use std::fmt;
 use std::mem;
+use std::fmt;
 use rustc_data_structures::sync::Lrc;
 use syntax::source_map;
 use syntax::ast;
@@ -51,7 +51,7 @@
 /// `DestructionScope`, but those that are `terminating_scopes` do;
 /// see discussion with `ScopeTree`.
 ///
-/// `Remainder(BlockRemainder { block, statement_index })` represents
+/// `Remainder { block, statement_index }` represents
 /// the scope of user code running immediately after the initializer
 /// expression for the indexed statement, until the end of the block.
 ///
 /// placate the same deriving in `ty::FreeRegion`, but we may want to
 /// actually attach a more meaningful ordering to scopes than the one
 /// generated via deriving here.
-///
-/// Scope is a bit-packed to save space - if `code` is SCOPE_DATA_REMAINDER_MAX
-/// or less, it is a `ScopeData::Remainder`, otherwise it is a type specified
-/// by the bitpacking.
 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, RustcEncodable, RustcDecodable)]
 pub struct Scope {
-    pub(crate) id: hir::ItemLocalId,
-    pub(crate) code: u32
+    pub id: hir::ItemLocalId,
+    pub data: ScopeData,
 }
 
-const SCOPE_DATA_NODE: u32 = !0;
-const SCOPE_DATA_CALLSITE: u32 = !1;
-const SCOPE_DATA_ARGUMENTS: u32 = !2;
-const SCOPE_DATA_DESTRUCTION: u32 = !3;
-const SCOPE_DATA_REMAINDER_MAX: u32 = !4;
+impl fmt::Debug for Scope {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        match self.data {
+            ScopeData::Node => write!(fmt, "Node({:?})", self.id),
+            ScopeData::CallSite => write!(fmt, "CallSite({:?})", self.id),
+            ScopeData::Arguments => write!(fmt, "Arguments({:?})", self.id),
+            ScopeData::Destruction => write!(fmt, "Destruction({:?})", self.id),
+            ScopeData::Remainder(fsi) => write!(
+                fmt,
+                "Remainder {{ block: {:?}, first_statement_index: {}}}",
+                self.id,
+                fsi.as_u32(),
+            ),
+        }
+    }
+}
 
 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)]
 pub enum ScopeData {
-    Node(hir::ItemLocalId),
+    Node,
 
     // Scope of the call-site for a function or closure
     // (outlives the arguments as well as the body).
-    CallSite(hir::ItemLocalId),
+    CallSite,
 
     // Scope of arguments passed to a function or closure
     // (they outlive its body).
-    Arguments(hir::ItemLocalId),
+    Arguments,
 
     // Scope of destructors for temporaries of node-id.
-    Destruction(hir::ItemLocalId),
+    Destruction,
 
     // Scope following a `let id = expr;` binding in a block.
-    Remainder(BlockRemainder)
+    Remainder(FirstStatementIndex)
 }
 
 /// Represents a subscope of `block` for a binding that is introduced
@@ -152,82 +159,18 @@ pub enum ScopeData {
 ///
 /// * the subscope with `first_statement_index == 1` is scope of `c`,
 ///   and thus does not include EXPR_2, but covers the `...`.
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable,
-         RustcDecodable, Debug, Copy)]
-pub struct BlockRemainder {
-    pub block: hir::ItemLocalId,
-    pub first_statement_index: FirstStatementIndex,
-}
 
 newtype_index! {
-    pub struct FirstStatementIndex {
-        MAX = SCOPE_DATA_REMAINDER_MAX
-    }
+    pub struct FirstStatementIndex { .. }
 }
 
 impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { private });
 
-impl From<ScopeData> for Scope {
-    #[inline]
-    fn from(scope_data: ScopeData) -> Self {
-        let (id, code) = match scope_data {
-            ScopeData::Node(id) => (id, SCOPE_DATA_NODE),
-            ScopeData::CallSite(id) => (id, SCOPE_DATA_CALLSITE),
-            ScopeData::Arguments(id) => (id, SCOPE_DATA_ARGUMENTS),
-            ScopeData::Destruction(id) => (id, SCOPE_DATA_DESTRUCTION),
-            ScopeData::Remainder(r) => (r.block, r.first_statement_index.index() as u32)
-        };
-        Self { id, code }
-    }
-}
-
-impl fmt::Debug for Scope {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(&self.data(), formatter)
-    }
-}
-
-#[allow(non_snake_case)]
-impl Scope {
-    #[inline]
-    pub fn data(self) -> ScopeData {
-        match self.code {
-            SCOPE_DATA_NODE => ScopeData::Node(self.id),
-            SCOPE_DATA_CALLSITE => ScopeData::CallSite(self.id),
-            SCOPE_DATA_ARGUMENTS => ScopeData::Arguments(self.id),
-            SCOPE_DATA_DESTRUCTION => ScopeData::Destruction(self.id),
-            idx => ScopeData::Remainder(BlockRemainder {
-                block: self.id,
-                first_statement_index: FirstStatementIndex::new(idx as usize)
-            })
-        }
-    }
-
-    #[inline]
-    pub fn Node(id: hir::ItemLocalId) -> Self {
-        Self::from(ScopeData::Node(id))
-    }
-
-    #[inline]
-    pub fn CallSite(id: hir::ItemLocalId) -> Self {
-        Self::from(ScopeData::CallSite(id))
-    }
-
-    #[inline]
-    pub fn Arguments(id: hir::ItemLocalId) -> Self {
-        Self::from(ScopeData::Arguments(id))
-    }
-
-    #[inline]
-    pub fn Destruction(id: hir::ItemLocalId) -> Self {
-        Self::from(ScopeData::Destruction(id))
-    }
-
-    #[inline]
-    pub fn Remainder(r: BlockRemainder) -> Self {
-        Self::from(ScopeData::Remainder(r))
-    }
-}
+// compilation error if size of `ScopeData` is not the same as a `u32`
+#[allow(dead_code)]
+// only works on stage 1 when the rustc_layout_scalar_valid_range attribute actually exists
+#[cfg(not(stage0))]
+static ASSERT: () = [()][!(mem::size_of::<ScopeData>() == 4) as usize];
 
 impl Scope {
     /// Returns a item-local id associated with this scope.
@@ -259,7 +202,7 @@ pub fn span(&self, tcx: TyCtxt, scope_tree: &ScopeTree) -> Span {
             return DUMMY_SP;
         }
         let span = tcx.hir.span(node_id);
-        if let ScopeData::Remainder(r) = self.data() {
+        if let ScopeData::Remainder(first_statement_index) = self.data {
             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
@@ -269,7 +212,7 @@ pub fn span(&self, tcx: TyCtxt, scope_tree: &ScopeTree) -> Span {
                 // (This is the special case aluded to in the
                 // doc-comment for this method)
 
-                let stmt_span = blk.stmts[r.first_statement_index.index()].span;
+                let stmt_span = blk.stmts[first_statement_index.index()].span;
 
                 // To avoid issues with macro-generated spans, the span
                 // of the statement must be nested in that of the block.
@@ -513,8 +456,8 @@ pub fn record_scope_parent(&mut self, child: Scope, parent: Option<(Scope, Scope
         }
 
         // record the destruction scopes for later so we can query them
-        if let ScopeData::Destruction(n) = child.data() {
-            self.destruction_scopes.insert(n, child);
+        if let ScopeData::Destruction = child.data {
+            self.destruction_scopes.insert(child.item_local_id(), child);
         }
     }
 
@@ -593,11 +536,11 @@ pub fn temporary_scope(&self, expr_id: hir::ItemLocalId) -> Option<Scope> {
         // if there's one. Static items, for instance, won't
         // have an enclosing scope, hence no scope will be
         // returned.
-        let mut id = Scope::Node(expr_id);
+        let mut id = Scope { id: expr_id, data: ScopeData::Node };
 
         while let Some(&(p, _)) = self.parent_map.get(&id) {
-            match p.data() {
-                ScopeData::Destruction(..) => {
+            match p.data {
+                ScopeData::Destruction => {
                     debug!("temporary_scope({:?}) = {:?} [enclosing]",
                            expr_id, id);
                     return Some(id);
@@ -652,8 +595,8 @@ pub fn is_subscope_of(&self,
     /// Returns the id of the innermost containing body
     pub fn containing_body(&self, mut scope: Scope)-> Option<hir::ItemLocalId> {
         loop {
-            if let ScopeData::CallSite(id) = scope.data() {
-                return Some(id);
+            if let ScopeData::CallSite = scope.data {
+                return Some(scope.item_local_id());
             }
 
             match self.opt_encl_scope(scope) {
@@ -745,7 +688,7 @@ pub fn early_free_scope<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
             self.root_body.unwrap().local_id
         });
 
-        Scope::CallSite(scope)
+        Scope { id: scope, data: ScopeData::CallSite }
     }
 
     /// Assuming that the provided region was defined within this `ScopeTree`,
@@ -765,7 +708,7 @@ pub fn free_scope<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, fr: &ty::FreeReg
 
         let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap();
         let body_id = tcx.hir.body_owned_by(param_owner_id);
-        Scope::CallSite(tcx.hir.body(body_id).value.hir_id.local_id)
+        Scope { id: tcx.hir.body(body_id).value.hir_id.local_id, data: ScopeData::CallSite }
     }
 
     /// Checks whether the given scope contains a `yield`. If so,
@@ -869,10 +812,10 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk:
                 // except for the first such subscope, which has the
                 // block itself as a parent.
                 visitor.enter_scope(
-                    Scope::Remainder(BlockRemainder {
-                        block: blk.hir_id.local_id,
-                        first_statement_index: FirstStatementIndex::new(i)
-                    })
+                    Scope {
+                        id: blk.hir_id.local_id,
+                        data: ScopeData::Remainder(FirstStatementIndex::new(i))
+                    }
                 );
                 visitor.cx.var_parent = visitor.cx.parent;
             }
@@ -897,7 +840,7 @@ fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, arm: &
 }
 
 fn resolve_pat<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, pat: &'tcx hir::Pat) {
-    visitor.record_child_scope(Scope::Node(pat.hir_id.local_id));
+    visitor.record_child_scope(Scope { id: pat.hir_id.local_id, data: ScopeData::Node });
 
     // If this is a binding then record the lifetime of that binding.
     if let PatKind::Binding(..) = pat.node {
@@ -1026,7 +969,7 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr:
 
     if let hir::ExprKind::Yield(..) = expr.node {
         // Mark this expr's scope and all parent scopes as containing `yield`.
-        let mut scope = Scope::Node(expr.hir_id.local_id);
+        let mut scope = Scope { id: expr.hir_id.local_id, data: ScopeData::Node };
         loop {
             visitor.scope_tree.yield_in_scope.insert(scope,
                 (expr.span, visitor.expr_and_pat_count));
@@ -1034,8 +977,8 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr:
             // Keep traversing up while we can.
             match visitor.scope_tree.parent_map.get(&scope) {
                 // Don't cross from closure bodies to their parent.
-                Some(&(superscope, _)) => match superscope.data() {
-                    ScopeData::CallSite(_) => break,
+                Some(&(superscope, _)) => match superscope.data {
+                    ScopeData::CallSite => break,
                     _ => scope = superscope
                 },
                 None => break
@@ -1298,9 +1241,9 @@ fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId) {
         // account for the destruction scope representing the scope of
         // the destructors that run immediately after it completes.
         if self.terminating_scopes.contains(&id) {
-            self.enter_scope(Scope::Destruction(id));
+            self.enter_scope(Scope { id, data: ScopeData::Destruction });
         }
-        self.enter_scope(Scope::Node(id));
+        self.enter_scope(Scope { id, data: ScopeData::Node });
     }
 }
 
@@ -1333,8 +1276,8 @@ fn visit_body(&mut self, body: &'tcx hir::Body) {
         }
         self.cx.root_id = Some(body.value.hir_id.local_id);
 
-        self.enter_scope(Scope::CallSite(body.value.hir_id.local_id));
-        self.enter_scope(Scope::Arguments(body.value.hir_id.local_id));
+        self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::CallSite });
+        self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::Arguments });
 
         // The arguments and `self` are parented to the fn.
         self.cx.var_parent = self.cx.parent.take();
index f237c5b397bd5263722c7ab089f0760ac12a605f..73a55265f009ac017844f2de1aa755f83ca36104 100644 (file)
@@ -783,7 +783,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
     fn visit_path(&mut self, path: &'tcx hir::Path, id: hir::HirId) {
         let id = self.tcx.hir.hir_to_node_id(id);
         match path.def {
-            Def::Local(..) | Def::Upvar(..) |
+            Def::Local(..) | Def::Upvar(..) | Def::SelfCtor(..) |
             Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => {}
             _ => self.tcx.check_stability(path.def.def_id(), Some(id), path.span)
         }
index c919793fe3e03c38aeca2e498e5d97f15659e3eb..db1bc3e7519c290e1304e77bbef013b48b031a25 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc_data_structures::bitvec::BitArray;
+use rustc_data_structures::bit_set::BitSet;
 
 use super::*;
 
@@ -32,7 +32,7 @@
 #[derive(Clone)]
 pub struct Preorder<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
-    visited: BitArray<BasicBlock>,
+    visited: BitSet<BasicBlock>,
     worklist: Vec<BasicBlock>,
 }
 
@@ -42,7 +42,7 @@ pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Preorder<'a, 'tcx> {
 
         Preorder {
             mir,
-            visited: BitArray::new(mir.basic_blocks().len()),
+            visited: BitSet::new_empty(mir.basic_blocks().len()),
             worklist,
         }
     }
@@ -104,7 +104,7 @@ impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {}
 /// A Postorder traversal of this graph is `D B C A` or `D C B A`
 pub struct Postorder<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
-    visited: BitArray<BasicBlock>,
+    visited: BitSet<BasicBlock>,
     visit_stack: Vec<(BasicBlock, Successors<'a>)>
 }
 
@@ -112,7 +112,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
     pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> {
         let mut po = Postorder {
             mir,
-            visited: BitArray::new(mir.basic_blocks().len()),
+            visited: BitSet::new_empty(mir.basic_blocks().len()),
             visit_stack: Vec::new()
         };
 
index 2a9732bf02c98616acee6bf36ba8baadf1f387a3..e4d633c3f2cf27ccb1e1bb4a2025f699f0145016 100644 (file)
@@ -275,18 +275,18 @@ pub fn should_codegen(&self) -> bool {
 // DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That
 // would break dependency tracking for commandline arguments.
 #[derive(Clone, Hash)]
-pub struct Externs(BTreeMap<String, BTreeSet<String>>);
+pub struct Externs(BTreeMap<String, BTreeSet<Option<String>>>);
 
 impl Externs {
-    pub fn new(data: BTreeMap<String, BTreeSet<String>>) -> Externs {
+    pub fn new(data: BTreeMap<String, BTreeSet<Option<String>>>) -> Externs {
         Externs(data)
     }
 
-    pub fn get(&self, key: &str) -> Option<&BTreeSet<String>> {
+    pub fn get(&self, key: &str) -> Option<&BTreeSet<Option<String>>> {
         self.0.get(key)
     }
 
-    pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet<String>> {
+    pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet<Option<String>>> {
         self.0.iter()
     }
 }
@@ -1331,6 +1331,8 @@ fn parse_cross_lang_lto(slot: &mut CrossLangLto, v: Option<&str>) -> bool {
         "disable user provided type assertion in NLL"),
     nll_dont_emit_read_for_match: bool = (false, parse_bool, [UNTRACKED],
         "in match codegen, do not include ReadForMatch statements (used by mir-borrowck)"),
+    dont_buffer_diagnostics: bool = (false, parse_bool, [UNTRACKED],
+        "emit diagnostics rather than buffering (breaks NLL error downgrading, sorting)."),
     polonius: bool = (false, parse_bool, [UNTRACKED],
         "enable polonius-based borrow-checker"),
     codegen_time_graph: bool = (false, parse_bool, [UNTRACKED],
@@ -2169,6 +2171,8 @@ pub fn build_session_options_and_crate_config(
     let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
     let test = matches.opt_present("test");
 
+    let is_unstable_enabled = nightly_options::is_unstable_enabled(matches);
+
     prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s {
         "crate-name" => PrintRequest::CrateName,
         "file-names" => PrintRequest::FileNames,
@@ -2182,15 +2186,13 @@ pub fn build_session_options_and_crate_config(
         "tls-models" => PrintRequest::TlsModels,
         "native-static-libs" => PrintRequest::NativeStaticLibs,
         "target-spec-json" => {
-            if nightly_options::is_unstable_enabled(matches) {
+            if is_unstable_enabled {
                 PrintRequest::TargetSpec
             } else {
                 early_error(
                     error_format,
-                    &format!(
-                        "the `-Z unstable-options` flag must also be passed to \
-                         enable the target-spec-json print option"
-                    ),
+                    "the `-Z unstable-options` flag must also be passed to \
+                     enable the target-spec-json print option",
                 );
             }
         }
@@ -2220,18 +2222,19 @@ pub fn build_session_options_and_crate_config(
             Some(s) => s,
             None => early_error(error_format, "--extern value must not be empty"),
         };
-        let location = match parts.next() {
-            Some(s) => s,
-            None => early_error(
+        let location = parts.next().map(|s| s.to_string());
+        if location.is_none() && !is_unstable_enabled {
+            early_error(
                 error_format,
-                "--extern value must be of the format `foo=bar`",
-            ),
+                "the `-Z unstable-options` flag must also be passed to \
+                 enable `--extern crate_name` without `=path`",
+            );
         };
 
         externs
             .entry(name.to_string())
             .or_default()
-            .insert(location.to_string());
+            .insert(location);
     }
 
     let crate_name = matches.opt_str("crate-name");
@@ -2687,33 +2690,33 @@ fn test_externs_tracking_hash_different_construction_order() {
         v1.externs = Externs::new(mk_map(vec![
             (
                 String::from("a"),
-                mk_set(vec![String::from("b"), String::from("c")]),
+                mk_set(vec![Some(String::from("b")), Some(String::from("c"))]),
             ),
             (
                 String::from("d"),
-                mk_set(vec![String::from("e"), String::from("f")]),
+                mk_set(vec![Some(String::from("e")), Some(String::from("f"))]),
             ),
         ]));
 
         v2.externs = Externs::new(mk_map(vec![
             (
                 String::from("d"),
-                mk_set(vec![String::from("e"), String::from("f")]),
+                mk_set(vec![Some(String::from("e")), Some(String::from("f"))]),
             ),
             (
                 String::from("a"),
-                mk_set(vec![String::from("b"), String::from("c")]),
+                mk_set(vec![Some(String::from("b")), Some(String::from("c"))]),
             ),
         ]));
 
         v3.externs = Externs::new(mk_map(vec![
             (
                 String::from("a"),
-                mk_set(vec![String::from("b"), String::from("c")]),
+                mk_set(vec![Some(String::from("b")), Some(String::from("c"))]),
             ),
             (
                 String::from("d"),
-                mk_set(vec![String::from("f"), String::from("e")]),
+                mk_set(vec![Some(String::from("f")), Some(String::from("e"))]),
             ),
         ]));
 
index 619262abb0bf5f5c749840bfbe481960a4701dff..7bf0d8ecec854264f4ee51fccb74b701c37b2897 100644 (file)
@@ -28,7 +28,7 @@
 use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock};
 
 use syntax::ast::NodeId;
-use errors::{self, DiagnosticBuilder, DiagnosticId};
+use errors::{self, DiagnosticBuilder, DiagnosticId, Applicability};
 use errors::emitter::{Emitter, EmitterWriter};
 use syntax::edition::Edition;
 use syntax::json::JsonEmitter;
@@ -431,8 +431,13 @@ fn diag_once<'a, 'b>(
                     diag_builder.span_note(span, message);
                 }
                 DiagnosticBuilderMethod::SpanSuggestion(suggestion) => {
-                    let span = span_maybe.expect("span_suggestion needs a span");
-                    diag_builder.span_suggestion(span, message, suggestion);
+                    let span = span_maybe.expect("span_suggestion_* needs a span");
+                    diag_builder.span_suggestion_with_applicability(
+                        span,
+                        message,
+                        suggestion,
+                        Applicability::Unspecified,
+                    );
                 }
             }
         }
@@ -1012,6 +1017,7 @@ pub fn build_session_with_source_map(
     let can_emit_warnings = !(warnings_allow || cap_lints_allow);
 
     let treat_err_as_bug = sopts.debugging_opts.treat_err_as_bug;
+    let dont_buffer_diagnostics = sopts.debugging_opts.dont_buffer_diagnostics;
     let report_delayed_bugs = sopts.debugging_opts.report_delayed_bugs;
 
     let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
@@ -1059,6 +1065,7 @@ pub fn build_session_with_source_map(
             can_emit_warnings,
             treat_err_as_bug,
             report_delayed_bugs,
+            dont_buffer_diagnostics,
             external_macro_backtrace,
             ..Default::default()
         },
index a7c697c1cbafdc8b35cf39469ba671b027911597..466d472cca338a92734ff8ee93dcc121a4a23c02 100644 (file)
@@ -661,7 +661,7 @@ pub fn report_selection_error(&self,
                         {
                             let predicate = trait_predicate.map_bound(|mut trait_pred| {
                                 trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
-                                    self.tcx.mk_nil(),
+                                    self.tcx.mk_unit(),
                                     &trait_pred.trait_ref.substs[1..],
                                 );
                                 trait_pred
index 232ef108537fefdb0ed634ad594e0db40bcf6940..85e7368bfdd1042f04b5be0e86804920081e1f7c 100644 (file)
@@ -44,8 +44,8 @@
 use middle::lang_items;
 use mir::interpret::{GlobalId};
 
+use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::sync::Lock;
-use rustc_data_structures::bitvec::BitArray;
 use std::iter;
 use std::cmp;
 use std::fmt;
@@ -3069,7 +3069,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 } else {
                     return Err(Unimplemented);
                 };
-                let mut ty_params = BitArray::new(substs_a.types().count());
+                let mut ty_params = BitSet::new_empty(substs_a.types().count());
                 let mut found = false;
                 for ty in field.walk() {
                     if let ty::Param(p) = ty.sty {
index 83d6b715e95bc4681c261bb4c707a198548933de..b7b0fdca2e6349c895c6b4556ea66e47252e5064 100644 (file)
@@ -17,7 +17,7 @@
 use session::config::{BorrowckMode, OutputFilenames};
 use session::config::CrateType;
 use middle;
-use hir::{TraitCandidate, HirId, ItemLocalId};
+use hir::{TraitCandidate, HirId, ItemLocalId, Node};
 use hir::def::{Def, Export};
 use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
 use hir::map as hir_map;
@@ -66,7 +66,7 @@
 use std::hash::{Hash, Hasher};
 use std::fmt;
 use std::mem;
-use std::ops::Deref;
+use std::ops::{Deref, Bound};
 use std::iter;
 use std::sync::mpsc;
 use std::sync::Arc;
@@ -829,10 +829,12 @@ fn hash_stable<W: StableHasherResult>(&self,
 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::TyKind>() <= 24);
-        #[cfg(target_pointer_width = "64")]
-        assert!(mem::size_of::<ty::TyS>() <= 32);
+        #[cfg(all(not(stage0), target_pointer_width = "64"))]
+        #[allow(dead_code)]
+        static ASSERT_TY_KIND: () = [()][!(::std::mem::size_of::<ty::TyKind>() <= 24) as usize];
+        #[cfg(all(not(stage0), target_pointer_width = "64"))]
+        #[allow(dead_code)]
+        static ASSERT_TYS: () = [()][!(::std::mem::size_of::<ty::TyS>() <= 32) as usize];
 
         let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty);
         let mk_region = |r| {
@@ -870,6 +872,18 @@ fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
     }
 }
 
+// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime
+// conflict.
+#[derive(Debug)]
+pub struct FreeRegionInfo {
+    // def id corresponding to FreeRegion
+    pub def_id: DefId,
+    // the bound region corresponding to FreeRegion
+    pub boundregion: ty::BoundRegion,
+    // checks if bound region is in Impl Item
+    pub is_impl_item: bool,
+}
+
 /// The central data structure of the compiler. It stores references
 /// to the various **arenas** and also houses the results of the
 /// various **compiler queries** that have been performed. See the
@@ -1083,6 +1097,26 @@ pub fn intern_layout(self, layout: LayoutDetails) -> &'gcx LayoutDetails {
         interned
     }
 
+    /// Returns a range of the start/end indices specified with the
+    /// `rustc_layout_scalar_valid_range` attribute.
+    pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) {
+        let attrs = self.get_attrs(def_id);
+        let get = |name| {
+            let attr = match attrs.iter().find(|a| a.check_name(name)) {
+                Some(attr) => attr,
+                None => return Bound::Unbounded,
+            };
+            for meta in attr.meta_item_list().expect("rustc_layout_scalar_valid_range takes args") {
+                match meta.literal().expect("attribute takes lit").node {
+                    ast::LitKind::Int(a, _) => return Bound::Included(a),
+                    _ => span_bug!(attr.span, "rustc_layout_scalar_valid_range expects int arg"),
+                }
+            }
+            span_bug!(attr.span, "no arguments to `rustc_layout_scalar_valid_range` attribute");
+        };
+        (get("rustc_layout_scalar_valid_range_start"), get("rustc_layout_scalar_valid_range_end"))
+    }
+
     pub fn lift<T: ?Sized + Lift<'tcx>>(self, value: &T) -> Option<T::Lifted> {
         value.lift_to_tcx(self)
     }
@@ -1225,7 +1259,11 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
                     .collect(),
             hir,
             def_path_hash_to_def_id,
-            queries: query::Queries::new(providers, on_disk_query_result_cache),
+            queries: query::Queries::new(
+                providers,
+                extern_providers,
+                on_disk_query_result_cache,
+            ),
             rcache: Lock::new(FxHashMap()),
             selection_cache: traits::SelectionCache::new(),
             evaluation_cache: traits::EvaluationCache::new(),
@@ -1410,10 +1448,37 @@ pub fn serialize_query_result_cache<E>(self,
         self.queries.on_disk_cache.serialize(self.global_tcx(), encoder)
     }
 
+    /// This checks whether one is allowed to have pattern bindings
+    /// that bind-by-move on a match arm that has a guard, e.g.:
+    ///
+    /// ```rust
+    /// match foo { A(inner) if { /* something */ } => ..., ... }
+    /// ```
+    ///
+    /// It is separate from check_for_mutation_in_guard_via_ast_walk,
+    /// because that method has a narrower effect that can be toggled
+    /// off via a separate `-Z` flag, at least for the short term.
+    pub fn allow_bind_by_move_patterns_with_guards(self) -> bool {
+        self.features().bind_by_move_pattern_guards && self.use_mir_borrowck()
+    }
+
     /// If true, we should use a naive AST walk to determine if match
     /// guard could perform bad mutations (or mutable-borrows).
     pub fn check_for_mutation_in_guard_via_ast_walk(self) -> bool {
-        !self.sess.opts.debugging_opts.disable_ast_check_for_mutation_in_guard
+        // If someone passes the `-Z` flag, they're asking for the footgun.
+        if self.sess.opts.debugging_opts.disable_ast_check_for_mutation_in_guard {
+            return false;
+        }
+
+        // If someone requests the feature, then be a little more
+        // careful and ensure that MIR-borrowck is enabled (which can
+        // happen via edition selection, via `feature(nll)`, or via an
+        // appropriate `-Z` flag) before disabling the mutation check.
+        if self.allow_bind_by_move_patterns_with_guards() {
+            return false;
+        }
+
+        return true;
     }
 
     /// If true, we should use the AST-based borrowck (we may *also* use
@@ -1545,6 +1610,74 @@ pub fn local_crate_exports_generics(self) -> bool {
             }
         })
     }
+
+    // This method returns the DefId and the BoundRegion corresponding to the given region.
+    pub fn is_suitable_region(&self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
+        let (suitable_region_binding_scope, bound_region) = match *region {
+            ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
+            ty::ReEarlyBound(ref ebr) => (
+                self.parent_def_id(ebr.def_id).unwrap(),
+                ty::BoundRegion::BrNamed(ebr.def_id, ebr.name),
+            ),
+            _ => return None, // not a free region
+        };
+
+        let node_id = self.hir
+            .as_local_node_id(suitable_region_binding_scope)
+            .unwrap();
+        let is_impl_item = match self.hir.find(node_id) {
+            Some(Node::Item(..)) | Some(Node::TraitItem(..)) => false,
+            Some(Node::ImplItem(..)) => {
+                self.is_bound_region_in_impl_item(suitable_region_binding_scope)
+            }
+            _ => return None,
+        };
+
+        return Some(FreeRegionInfo {
+            def_id: suitable_region_binding_scope,
+            boundregion: bound_region,
+            is_impl_item: is_impl_item,
+        });
+    }
+
+    pub fn return_type_impl_trait(
+        &self,
+        scope_def_id: DefId,
+    ) -> Option<Ty<'tcx>> {
+        let ret_ty = self.type_of(scope_def_id);
+        match ret_ty.sty {
+            ty::FnDef(_, _) => {
+                let sig = ret_ty.fn_sig(*self);
+                let output = self.erase_late_bound_regions(&sig.output());
+                if output.is_impl_trait() {
+                    Some(output)
+                } else {
+                    None
+                }
+            }
+            _ => None
+        }
+    }
+
+    // Here we check if the bound region is in Impl Item.
+    pub fn is_bound_region_in_impl_item(
+        &self,
+        suitable_region_binding_scope: DefId,
+    ) -> bool {
+        let container_id = self.associated_item(suitable_region_binding_scope)
+            .container
+            .id();
+        if self.impl_trait_ref(container_id).is_some() {
+            // For now, we do not try to target impls of traits. This is
+            // because this message is going to suggest that the user
+            // change the fn signature, but they may not be free to do so,
+            // since the signature must match the trait.
+            //
+            // FIXME(#42706) -- in some cases, we could do better here.
+            return true;
+        }
+        false
+    }
 }
 
 impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
@@ -2492,7 +2625,7 @@ pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> {
     }
 
     pub fn mk_nil_ptr(self) -> Ty<'tcx> {
-        self.mk_imm_ptr(self.mk_nil())
+        self.mk_imm_ptr(self.mk_unit())
     }
 
     pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
@@ -2511,7 +2644,7 @@ pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I) -> I::Output {
         iter.intern_with(|ts| self.mk_ty(Tuple(self.intern_type_list(ts))))
     }
 
-    pub fn mk_nil(self) -> Ty<'tcx> {
+    pub fn mk_unit(self) -> Ty<'tcx> {
         self.intern_tup(&[])
     }
 
index 17d613a2b181a14fb685d30c232ea4127a25af15..4e37a34a0c8a7f9af70d13a8f8d1cd8a790a3003 100644 (file)
@@ -20,6 +20,7 @@
 use std::i128;
 use std::iter;
 use std::mem;
+use std::ops::Bound;
 
 use ich::StableHashingContext;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
@@ -132,7 +133,7 @@ fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
             Int(i, signed) => i.to_ty(tcx, signed),
             Float(FloatTy::F32) => tcx.types.f32,
             Float(FloatTy::F64) => tcx.types.f64,
-            Pointer => tcx.mk_mut_ptr(tcx.mk_nil()),
+            Pointer => tcx.mk_mut_ptr(tcx.mk_unit()),
         }
     }
 }
@@ -761,17 +762,29 @@ enum StructKind {
 
                     let mut st = univariant_uninterned(&variants[v], &def.repr, kind)?;
                     st.variants = Variants::Single { index: v };
-                    // Exclude 0 from the range of a newtype ABI NonZero<T>.
-                    if Some(def.did) == self.tcx.lang_items().non_zero() {
-                        match st.abi {
-                            Abi::Scalar(ref mut scalar) |
-                            Abi::ScalarPair(ref mut scalar, _) => {
-                                if *scalar.valid_range.start() == 0 {
-                                    scalar.valid_range = 1..=*scalar.valid_range.end();
-                                }
+                    let (start, end) = self.tcx.layout_scalar_valid_range(def.did);
+                    match st.abi {
+                        Abi::Scalar(ref mut scalar) |
+                        Abi::ScalarPair(ref mut scalar, _) => {
+                            // the asserts ensure that we are not using the
+                            // `#[rustc_layout_scalar_valid_range(n)]`
+                            // attribute to widen the range of anything as that would probably
+                            // result in UB somewhere
+                            if let Bound::Included(start) = start {
+                                assert!(*scalar.valid_range.start() <= start);
+                                scalar.valid_range = start..=*scalar.valid_range.end();
+                            }
+                            if let Bound::Included(end) = end {
+                                assert!(*scalar.valid_range.end() >= end);
+                                scalar.valid_range = *scalar.valid_range.start()..=end;
                             }
-                            _ => {}
                         }
+                        _ => assert!(
+                            start == Bound::Unbounded && end == Bound::Unbounded,
+                            "nonscalar layout for layout_scalar_valid_range type {:?}: {:#?}",
+                            def,
+                            st,
+                        ),
                     }
                     return Ok(tcx.intern_layout(st));
                 }
@@ -1350,8 +1363,12 @@ pub fn compute(ty: Ty<'tcx>,
                 if def.variants.len() == 1 {
                     if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 {
                         return Ok(SizeSkeleton::Pointer {
-                            non_zero: non_zero ||
-                                Some(def.did) == tcx.lang_items().non_zero(),
+                            non_zero: non_zero || match tcx.layout_scalar_valid_range(def.did) {
+                                (Bound::Included(start), Bound::Unbounded) => start > 0,
+                                (Bound::Included(start), Bound::Included(end)) =>
+                                    0 < start && start < end,
+                                _ => false,
+                            },
                             tail,
                         });
                     } else {
@@ -1606,7 +1623,7 @@ fn field(this: TyLayout<'tcx>, cx: C, i: usize) -> C::TyLayout {
                 // (which may have no non-DST form), and will work as long
                 // as the `Abi` or `FieldPlacement` is checked by users.
                 if i == 0 {
-                    let nil = tcx.mk_nil();
+                    let nil = tcx.mk_unit();
                     let ptr_ty = if this.ty.is_unsafe_ptr() {
                         tcx.mk_mut_ptr(nil)
                     } else {
index a48aabc3cd7c7379c1f4a1a2de070fc89212e9e3..940da6099e0824704c792dbca67fad55bbc1c0f8 100644 (file)
@@ -80,7 +80,7 @@
 pub use self::binding::BindingMode;
 pub use self::binding::BindingMode::*;
 
-pub use self::context::{TyCtxt, GlobalArenas, AllArenas, tls, keep_local};
+pub use self::context::{TyCtxt, FreeRegionInfo, GlobalArenas, AllArenas, tls, keep_local};
 pub use self::context::{Lift, TypeckTables};
 
 pub use self::instance::{Instance, InstanceDef};
@@ -2134,7 +2134,8 @@ pub fn variant_of_def(&self, def: Def) -> &VariantDef {
         match def {
             Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid),
             Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
-            Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => self.non_enum_variant(),
+            Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) |
+            Def::SelfCtor(..) => self.non_enum_variant(),
             _ => bug!("unexpected def {:?} in variant_of_def", def)
         }
     }
index f0ca168e9e4679ce3db3ca4bcafeafcd13ec9b97..79c7e517273fc72c6764ba16303abeda4417beb4 100644 (file)
 use util::common::{ErrorReported};
 use util::profiling::ProfileCategory::*;
 
-use rustc_data_structures::indexed_set::IdxSet;
-use rustc_target::spec::PanicStrategy;
+use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::StableVec;
+use rustc_data_structures::sync::Lrc;
+use rustc_target::spec::PanicStrategy;
 
 use std::ops::Deref;
-use rustc_data_structures::sync::Lrc;
 use std::sync::Arc;
 use syntax_pos::{Span, DUMMY_SP};
 use syntax_pos::symbol::InternedString;
         /// 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<IdxSet<mir::Local>>),
+        [] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Lrc<BitSet<mir::Local>>),
 
         /// Fetch the MIR for a given def-id right after it's built - this includes
         /// unreachable code.
index 6e16d92ba0c8d91ef45e9bf0274530698de2f0af..0e4d2f1f64730c940c91846871eef34fc9b642bb 100644 (file)
@@ -11,8 +11,7 @@
 use dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
 use errors::Diagnostic;
 use hir;
-use hir::def_id::{CrateNum, DefIndex, DefId, LocalDefId,
-                  RESERVED_FOR_INCR_COMP_CACHE, LOCAL_CRATE};
+use hir::def_id::{CrateNum, DefIndex, DefId, LocalDefId, LOCAL_CRATE};
 use hir::map::definitions::DefPathHash;
 use ich::{CachingSourceMapView, Fingerprint};
 use mir::{self, interpret};
@@ -566,7 +565,7 @@ fn cached_ty_for_shorthand<F>(&mut self,
         let tcx = self.tcx();
 
         let cache_key = ty::CReaderCacheKey {
-            cnum: RESERVED_FOR_INCR_COMP_CACHE,
+            cnum: CrateNum::ReservedForIncrCompCache,
             pos: shorthand,
         };
 
@@ -1020,7 +1019,7 @@ impl<'enc, 'a, 'tcx, E> Encoder for CacheEncoder<'enc, 'a, 'tcx, E>
 {
     type Error = E::Error;
 
-    fn emit_nil(&mut self) -> Result<(), Self::Error> {
+    fn emit_unit(&mut self) -> Result<(), Self::Error> {
         Ok(())
     }
 
index 3c26732fbac6719668136be524de7daf92b496f5..25e72f462e680006634de0636a81e0e6e10b0181 100644 (file)
@@ -692,10 +692,12 @@ macro_rules! define_queries_inner {
         impl<$tcx> Queries<$tcx> {
             pub fn new(
                 providers: IndexVec<CrateNum, Providers<$tcx>>,
+                fallback_extern_providers: Providers<$tcx>,
                 on_disk_cache: OnDiskCache<'tcx>,
             ) -> Self {
                 Queries {
                     providers,
+                    fallback_extern_providers: Box::new(fallback_extern_providers),
                     on_disk_cache,
                     $($name: Lock::new(QueryCache::new())),*
                 }
@@ -818,7 +820,13 @@ fn to_dep_node(tcx: TyCtxt<'_, $tcx, '_>, key: &Self::Key) -> DepNode {
             #[inline]
             fn compute(tcx: TyCtxt<'_, 'tcx, '_>, key: Self::Key) -> Self::Value {
                 __query_compute::$name(move || {
-                    let provider = tcx.queries.providers[key.query_crate()].$name;
+                    let provider = tcx.queries.providers.get(key.query_crate())
+                        // HACK(eddyb) it's possible crates may be loaded after
+                        // the query engine is created, and because crate loading
+                        // is not yet integrated with the query engine, such crates
+                        // would be be missing appropriate entries in `providers`.
+                        .unwrap_or(&tcx.queries.fallback_extern_providers)
+                        .$name;
                     provider(tcx.global_tcx(), key)
                 })
             }
@@ -899,6 +907,7 @@ pub(crate) struct Queries<$tcx> {
             pub(crate) on_disk_cache: OnDiskCache<'tcx>,
 
             providers: IndexVec<CrateNum, Providers<$tcx>>,
+            fallback_extern_providers: Box<Providers<$tcx>>,
 
             $($(#[$attr])*  $name: Lock<QueryCache<$tcx, queries::$name<$tcx>>>,)*
         }
index 962b115f1877a8abd8a4d024d7bf86417b53a0da..ea547c592d048a2bf98dfeeae7301ea7c4202b59 100644 (file)
@@ -1458,7 +1458,7 @@ pub fn free_region_binding_scope(&self, tcx: TyCtxt<'_, '_, '_>) -> DefId {
 
 /// Type utilities
 impl<'a, 'gcx, 'tcx> TyS<'tcx> {
-    pub fn is_nil(&self) -> bool {
+    pub fn is_unit(&self) -> bool {
         match self.sty {
             Tuple(ref tys) => tys.is_empty(),
             _ => false,
index ddcc0fa9c9280d0ed609e2e93fe8eb05ae9cb822..9a1add26bb0b4bf24b80816145343ef97aba9e41 100644 (file)
@@ -11,7 +11,7 @@
 use hir::def_id::DefId;
 use hir::map::definitions::DefPathData;
 use mir::interpret::ConstValue;
-use middle::region::{self, BlockRemainder};
+use middle::region;
 use ty::subst::{self, Subst};
 use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
 use ty::{Bool, Char, Adt};
@@ -234,7 +234,7 @@ fn fn_sig<F: fmt::Write>(&mut self,
             }
         }
         write!(f, ")")?;
-        if !output.is_nil() {
+        if !output.is_unit() {
             print!(f, self, write(" -> "), print_display(output))?;
         }
 
@@ -769,18 +769,21 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     write!(f, "{}", br)
                 }
                 ty::ReScope(scope) if cx.identify_regions => {
-                    match scope.data() {
-                        region::ScopeData::Node(id) =>
-                            write!(f, "'{}s", id.as_usize()),
-                        region::ScopeData::CallSite(id) =>
-                            write!(f, "'{}cs", id.as_usize()),
-                        region::ScopeData::Arguments(id) =>
-                            write!(f, "'{}as", id.as_usize()),
-                        region::ScopeData::Destruction(id) =>
-                            write!(f, "'{}ds", id.as_usize()),
-                        region::ScopeData::Remainder(BlockRemainder
-                                                     { block, first_statement_index }) =>
-                            write!(f, "'{}_{}rs", block.as_usize(), first_statement_index.index()),
+                    match scope.data {
+                        region::ScopeData::Node =>
+                            write!(f, "'{}s", scope.item_local_id().as_usize()),
+                        region::ScopeData::CallSite =>
+                            write!(f, "'{}cs", scope.item_local_id().as_usize()),
+                        region::ScopeData::Arguments =>
+                            write!(f, "'{}as", scope.item_local_id().as_usize()),
+                        region::ScopeData::Destruction =>
+                            write!(f, "'{}ds", scope.item_local_id().as_usize()),
+                        region::ScopeData::Remainder(first_statement_index) => write!(
+                            f,
+                            "'{}_{}rs",
+                            scope.item_local_id().as_usize(),
+                            first_statement_index.index()
+                        ),
                     }
                 }
                 ty::ReVar(region_vid) if cx.identify_regions => {
index 1af117c97f569abbe829c82945a849bb40e262ed..40bfbf1596a478f5ce9b2593e49efa8dd80e34d9 100644 (file)
@@ -767,8 +767,12 @@ pub fn analyze_restrictions_on_use(&self,
 
         let mut ret = UseOk;
 
+        let scope = region::Scope {
+            id: expr_id,
+            data: region::ScopeData::Node
+        };
         self.each_in_scope_loan_affecting_path(
-            region::Scope::Node(expr_id), use_path, |loan| {
+            scope, use_path, |loan| {
             if !compatible_borrow_kinds(loan.kind, borrow_kind) {
                 ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span);
                 false
@@ -886,7 +890,10 @@ fn check_assignment(&self,
 
         // Check that we don't invalidate any outstanding loans
         if let Some(loan_path) = opt_loan_path(assignee_cmt) {
-            let scope = region::Scope::Node(assignment_id);
+            let scope = region::Scope {
+                id: assignment_id,
+                data: region::ScopeData::Node
+            };
             self.each_in_scope_loan_affecting_path(scope, &loan_path, |loan| {
                 self.report_illegal_mutation(assignment_span, &loan_path, loan);
                 false
index 6c83e2dd1c206608915927e42e141bd1dcd743c8..dc400c6ef3eadec1aca7a3306ca1c9e72383b890 100644 (file)
@@ -43,7 +43,10 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     let mut glcx = GatherLoanCtxt {
         bccx,
         all_loans: Vec::new(),
-        item_ub: region::Scope::Node(bccx.tcx.hir.body(body).value.hir_id.local_id),
+        item_ub: region::Scope {
+            id: bccx.tcx.hir.body(body).value.hir_id.local_id,
+            data: region::ScopeData::Node
+        },
         move_data: MoveData::default(),
         move_error_collector: move_error::MoveErrorCollector::new(),
     };
@@ -375,7 +378,10 @@ fn guarantee_valid(&mut self,
                 };
                 debug!("loan_scope = {:?}", loan_scope);
 
-                let borrow_scope = region::Scope::Node(borrow_id);
+                let borrow_scope = region::Scope {
+                    id: borrow_id,
+                    data: region::ScopeData::Node
+                };
                 let gen_scope = self.compute_gen_scope(borrow_scope, loan_scope);
                 debug!("gen_scope = {:?}", gen_scope);
 
index ad45c5429a512b3214a1a6544673f471f2150a88..fb8744e4d96d6ecb1d2685c3ed8ec9dcaad8bf03 100644 (file)
@@ -45,7 +45,7 @@
 use std::hash::{Hash, Hasher};
 use syntax::ast;
 use syntax_pos::{MultiSpan, Span};
-use errors::{DiagnosticBuilder, DiagnosticId};
+use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 
 use rustc::hir;
 use rustc::hir::intravisit::{self, Visitor};
@@ -441,7 +441,7 @@ pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::Scope {
             LpUpvar(upvar_id) => {
                 let block_id = closure_to_block(upvar_id.closure_expr_id, bccx.tcx);
                 let hir_id = bccx.tcx.hir.node_to_hir_id(block_id);
-                region::Scope::Node(hir_id.local_id)
+                region::Scope { id: hir_id.local_id, data: region::ScopeData::Node }
             }
             LpDowncast(ref base, _) |
             LpExtend(ref base, ..) => base.kill_scope(bccx),
@@ -867,10 +867,20 @@ fn report_bckerr(&self, err: &BckError<'a, 'tcx>) {
                                         }) = cmt.cat {
                                             db.note(fn_closure_msg);
                                         } else {
-                                            db.span_suggestion(sp, msg, suggestion);
+                                            db.span_suggestion_with_applicability(
+                                                sp,
+                                                msg,
+                                                suggestion,
+                                                Applicability::Unspecified,
+                                            );
                                         }
                                     } else {
-                                        db.span_suggestion(sp, msg, suggestion);
+                                        db.span_suggestion_with_applicability(
+                                            sp,
+                                            msg,
+                                            suggestion,
+                                            Applicability::Unspecified,
+                                        );
                                     }
                                 }
                                 _ => {
@@ -1236,10 +1246,16 @@ fn note_immutability_blame(&self,
                         let let_span = self.tcx.hir.span(node_id);
                         let suggestion = suggest_ref_mut(self.tcx, let_span);
                         if let Some(replace_str) = suggestion {
-                            db.span_suggestion(
+                            db.span_suggestion_with_applicability(
                                 let_span,
                                 "use a mutable reference instead",
                                 replace_str,
+                                // I believe this can be machine applicable,
+                                // but if there are multiple attempted uses of an immutable
+                                // reference, I don't know how rustfix handles it, it might
+                                // attempt fixing them multiple times.
+                                //                              @estebank
+                                Applicability::Unspecified,
                             );
                         }
                     }
@@ -1292,16 +1308,19 @@ fn note_immutable_local(&self,
                 )) = ty.map(|t| &t.node)
                 {
                     let borrow_expr_id = self.tcx.hir.get_parent_node(borrowed_node_id);
-                    db.span_suggestion(
+                    db.span_suggestion_with_applicability(
                         self.tcx.hir.span(borrow_expr_id),
                         "consider removing the `&mut`, as it is an \
                         immutable binding to a mutable reference",
-                        snippet
+                        snippet,
+                        Applicability::MachineApplicable,
                     );
                 } else {
-                    db.span_label(
+                    db.span_suggestion_with_applicability(
                         let_span,
-                        format!("consider changing this to `mut {}`", snippet),
+                        "make this binding mutable",
+                        format!("mut {}", snippet),
+                        Applicability::MachineApplicable,
                     );
                 }
             }
@@ -1324,12 +1343,15 @@ fn report_out_of_scope_escaping_closure_capture(&self,
                                                   &cmt_path_or_string,
                                                   capture_span,
                                                   Origin::Ast)
-            .span_suggestion(err.span,
-                             &format!("to force the closure to take ownership of {} \
-                                       (and any other referenced variables), \
-                                       use the `move` keyword",
-                                       cmt_path_or_string),
-                             suggestion)
+            .span_suggestion_with_applicability(
+                 err.span,
+                 &format!("to force the closure to take ownership of {} \
+                           (and any other referenced variables), \
+                           use the `move` keyword",
+                           cmt_path_or_string),
+                 suggestion,
+                 Applicability::MachineApplicable,
+            )
             .emit();
         self.signal_error();
     }
index a76f1d50fa7bf89551717ec1eb9164b44837c1f8..0484837a48d7debbdd0641afbdaa9c1c35351dc1 100644 (file)
@@ -21,7 +21,7 @@
 
 use syntax_pos::Pos;
 
-use rustc_data_structures::bitvec::BitArray;
+use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 
 use syntax_pos::BytePos;
@@ -64,7 +64,7 @@ pub fn create_mir_scopes(
     };
 
     // Find all the scopes with variables defined in them.
-    let mut has_variables = BitArray::new(mir.source_scopes.len());
+    let mut has_variables = BitSet::new_empty(mir.source_scopes.len());
     for var in mir.vars_iter() {
         let decl = &mir.local_decls[var];
         has_variables.insert(decl.visibility_scope);
@@ -81,7 +81,7 @@ pub fn create_mir_scopes(
 
 fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
                   mir: &Mir,
-                  has_variables: &BitArray<SourceScope>,
+                  has_variables: &BitSet<SourceScope>,
                   debug_context: &FunctionDebugContextData<'ll>,
                   scope: SourceScope,
                   scopes: &mut IndexVec<SourceScope, MirDebugScope<'ll>>) {
index 0221cfd9b2c28c3601eea39627cf22260f52b3e3..706568b544661cadde5156ff0409fa95323f78b5 100644 (file)
@@ -1803,13 +1803,7 @@ pub fn create_vtable_metadata(
         llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),
                                                     NO_SCOPE_METADATA,
                                                     name.as_ptr(),
-                                                    // LLVM 3.9
-                                                    // doesn't accept
-                                                    // null here, so
-                                                    // pass the name
-                                                    // as the linkage
-                                                    // name.
-                                                    name.as_ptr(),
+                                                    ptr::null(),
                                                     unknown_file_metadata(cx),
                                                     UNKNOWN_LINE_NUMBER,
                                                     vtable_type,
index 95a094bf909e1a3bc01451ec2f44ec4f3264d673..f9eb80a1988af469263c9df86cef856d7dd88ed6 100644 (file)
@@ -160,7 +160,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
             output.push(')');
 
-            if !sig.output().is_nil() {
+            if !sig.output().is_unit() {
                 output.push_str(" -> ");
                 push_debuginfo_type_name(cx, sig.output(), true, output);
             }
index 5d00e0807991e1d6607571237c0a8e7be911cb70..5ec934ebd066750458e51275d6e75e24a9606862 100644 (file)
@@ -968,7 +968,7 @@ fn get_rust_try_fn<'ll, 'tcx>(
     let i8p = tcx.mk_mut_ptr(tcx.types.i8);
     let fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
         iter::once(i8p),
-        tcx.mk_nil(),
+        tcx.mk_unit(),
         false,
         hir::Unsafety::Unsafe,
         Abi::Rust
index 6c2601bf1ef1255ec229b6533da9b8290bbd55dc..a5f4137c62b14e6e30c0bf3d7c91807ed602b243 100644 (file)
@@ -8,16 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// FIXME: Rename 'DIGlobalVariable' to 'DIGlobalVariableExpression'
-// once support for LLVM 3.9 is dropped.
-//
-// This method was changed in this LLVM patch:
-// https://reviews.llvm.org/D26769
-
 use super::debuginfo::{
     DIBuilder, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType,
     DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable,
-    DIGlobalVariable, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator,
+    DIGlobalVariableExpression, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator,
     DINameSpace, DIFlags,
 };
 
@@ -447,7 +441,7 @@ pub mod debuginfo {
     pub type DIDerivedType = DIType;
     pub type DICompositeType = DIDerivedType;
     pub type DIVariable = DIDescriptor;
-    pub type DIGlobalVariable = DIDescriptor;
+    pub type DIGlobalVariableExpression = DIDescriptor;
     pub type DIArray = DIDescriptor;
     pub type DISubrange = DIDescriptor;
     pub type DIEnumerator = DIDescriptor;
@@ -1330,7 +1324,7 @@ pub fn LLVMRustDIBuilderCreateStaticVariable(Builder: &DIBuilder<'a>,
                                                  Val: &'a Value,
                                                  Decl: Option<&'a DIDescriptor>,
                                                  AlignInBits: u32)
-                                                 -> &'a DIGlobalVariable;
+                                                 -> &'a DIGlobalVariableExpression;
 
     pub fn LLVMRustDIBuilderCreateVariable(Builder: &DIBuilder<'a>,
                                            Tag: c_uint,
index 0206744eb2b6b2daabc4f60f67cdb95a99d4f51f..c3e3785a724a2a7273f5b0f348f0aa7f7c2d8a4f 100644 (file)
@@ -11,7 +11,7 @@
 //! An analysis to determine which locals require allocas and
 //! which do not.
 
-use rustc_data_structures::bitvec::BitArray;
+use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc::mir::{self, Location, TerminatorKind};
@@ -22,7 +22,7 @@
 use type_of::LayoutLlvmExt;
 use super::FunctionCx;
 
-pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitArray<mir::Local> {
+pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitSet<mir::Local> {
     let mir = fx.mir;
     let mut analyzer = LocalAnalyzer::new(fx);
 
@@ -54,7 +54,7 @@ pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitArray<mir::Local> {
 struct LocalAnalyzer<'mir, 'a: 'mir, 'll: 'a, 'tcx: 'll> {
     fx: &'mir FunctionCx<'a, 'll, 'tcx>,
     dominators: Dominators<mir::BasicBlock>,
-    non_ssa_locals: BitArray<mir::Local>,
+    non_ssa_locals: BitSet<mir::Local>,
     // The location of the first visited direct assignment to each
     // local, or an invalid location (out of bounds `block` index).
     first_assignment: IndexVec<mir::Local, Location>
@@ -67,7 +67,7 @@ fn new(fx: &'mir FunctionCx<'a, 'll, 'tcx>) -> Self {
         let mut analyzer = LocalAnalyzer {
             fx,
             dominators: fx.mir.dominators(),
-            non_ssa_locals: BitArray::new(fx.mir.local_decls.len()),
+            non_ssa_locals: BitSet::new_empty(fx.mir.local_decls.len()),
             first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls)
         };
 
index 258fe643c3067cad32126a200fa6a4c2cce90378..c61a326e7c83937421f335ba169e0236f25d7136 100644 (file)
@@ -31,7 +31,7 @@
 
 use std::iter;
 
-use rustc_data_structures::bitvec::BitArray;
+use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::indexed_vec::IndexVec;
 
 pub use self::constant::codegen_static_initializer;
@@ -341,7 +341,7 @@ pub fn codegen_mir(
     debuginfo::start_emitting_source_locations(&fx.debug_context);
 
     let rpo = traversal::reverse_postorder(&mir);
-    let mut visited = BitArray::new(mir.basic_blocks().len());
+    let mut visited = BitSet::new_empty(mir.basic_blocks().len());
 
     // Codegen the body of each block using reverse postorder
     for (bb, _) in rpo {
@@ -435,7 +435,7 @@ fn arg_local_refs(
     bx: &Builder<'a, 'll, 'tcx>,
     fx: &FunctionCx<'a, 'll, 'tcx>,
     scopes: &IndexVec<mir::SourceScope, debuginfo::MirDebugScope<'ll>>,
-    memory_locals: &BitArray<mir::Local>,
+    memory_locals: &BitSet<mir::Local>,
 ) -> Vec<LocalRef<'ll, 'tcx>> {
     let mir = fx.mir;
     let tcx = bx.tcx();
index e301e5ae70be8a9723634bf56220f1d88badc838..c3ec347f60876c03dc846bbec04f75f546b8d75d 100644 (file)
@@ -566,7 +566,7 @@ pub fn codegen_scalar_binop(
     ) -> &'ll Value {
         let is_float = input_ty.is_fp();
         let is_signed = input_ty.is_signed();
-        let is_nil = input_ty.is_nil();
+        let is_unit = input_ty.is_unit();
         match op {
             mir::BinOp::Add => if is_float {
                 bx.fadd(lhs, rhs)
@@ -604,7 +604,7 @@ pub fn codegen_scalar_binop(
             mir::BinOp::Shl => common::build_unchecked_lshift(bx, lhs, rhs),
             mir::BinOp::Shr => common::build_unchecked_rshift(bx, input_ty, lhs, rhs),
             mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt |
-            mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => if is_nil {
+            mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => if is_unit {
                 C_bool(bx.cx, match op {
                     mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt => false,
                     mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => true,
diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs
deleted file mode 100644 (file)
index 45fb565..0000000
+++ /dev/null
@@ -1,305 +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 stack-allocated vector, allowing storage of N elements on the stack.
-
-use std::marker::Unsize;
-use std::iter::Extend;
-use std::ptr::{self, drop_in_place, NonNull};
-use std::ops::{Deref, DerefMut, Range};
-use std::hash::{Hash, Hasher};
-use std::slice;
-use std::fmt;
-use std::mem;
-use std::mem::ManuallyDrop;
-use std::ops::Bound::{Excluded, Included, Unbounded};
-use std::ops::RangeBounds;
-
-pub unsafe trait Array {
-    type Element;
-    type PartialStorage: Unsize<[ManuallyDrop<Self::Element>]>;
-    const LEN: usize;
-}
-
-unsafe impl<T> Array for [T; 1] {
-    type Element = T;
-    type PartialStorage = [ManuallyDrop<T>; 1];
-    const LEN: usize = 1;
-}
-
-unsafe impl<T> Array for [T; 8] {
-    type Element = T;
-    type PartialStorage = [ManuallyDrop<T>; 8];
-    const LEN: usize = 8;
-}
-
-unsafe impl<T> Array for [T; 32] {
-    type Element = T;
-    type PartialStorage = [ManuallyDrop<T>; 32];
-    const LEN: usize = 32;
-}
-
-pub struct ArrayVec<A: Array> {
-    count: usize,
-    values: A::PartialStorage
-}
-
-impl<A> Hash for ArrayVec<A>
-    where A: Array,
-          A::Element: Hash {
-    fn hash<H>(&self, state: &mut H) where H: Hasher {
-        (&self[..]).hash(state);
-    }
-}
-
-impl<A> Clone for ArrayVec<A>
-    where A: Array,
-          A::Element: Clone {
-    fn clone(&self) -> Self {
-        let mut v = ArrayVec::new();
-        v.extend(self.iter().cloned());
-        v
-    }
-}
-
-impl<A: Array> ArrayVec<A> {
-    pub fn new() -> Self {
-        ArrayVec {
-            count: 0,
-            values: unsafe { ::std::mem::uninitialized() },
-        }
-    }
-
-    pub fn len(&self) -> usize {
-        self.count
-    }
-
-    pub unsafe fn set_len(&mut self, len: usize) {
-        self.count = len;
-    }
-
-    /// Panics when the stack vector is full.
-    pub fn push(&mut self, el: A::Element) {
-        let arr = &mut self.values as &mut [ManuallyDrop<_>];
-        arr[self.count] = ManuallyDrop::new(el);
-        self.count += 1;
-    }
-
-    pub fn pop(&mut self) -> Option<A::Element> {
-        if self.count > 0 {
-            let arr = &mut self.values as &mut [ManuallyDrop<_>];
-            self.count -= 1;
-            unsafe {
-                let value = ptr::read(&*arr[self.count]);
-                Some(value)
-            }
-        } else {
-            None
-        }
-    }
-
-    pub fn drain<R>(&mut self, range: R) -> Drain<A>
-        where R: RangeBounds<usize>
-    {
-        // Memory safety
-        //
-        // When the Drain is first created, it shortens the length of
-        // the source vector to make sure no uninitialized or moved-from elements
-        // are accessible at all if the Drain's destructor never gets to run.
-        //
-        // Drain will ptr::read out the values to remove.
-        // When finished, remaining tail of the vec is copied back to cover
-        // the hole, and the vector length is restored to the new length.
-        //
-        let len = self.len();
-        let start = match range.start_bound() {
-            Included(&n) => n,
-            Excluded(&n) => n + 1,
-            Unbounded    => 0,
-        };
-        let end = match range.end_bound() {
-            Included(&n) => n + 1,
-            Excluded(&n) => n,
-            Unbounded    => len,
-        };
-        assert!(start <= end);
-        assert!(end <= len);
-
-        unsafe {
-            // set self.vec length's to start, to be safe in case Drain is leaked
-            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 = {
-                let arr = &mut self.values as &mut [ManuallyDrop<<A as Array>::Element>];
-                slice::from_raw_parts_mut(arr.as_mut_ptr().add(start),
-                                          end - start)
-            };
-            Drain {
-                tail_start: end,
-                tail_len: len - end,
-                iter: range_slice.iter(),
-                array_vec: NonNull::from(self),
-            }
-        }
-    }
-}
-
-impl<A> Default for ArrayVec<A>
-    where A: Array {
-    fn default() -> Self {
-        ArrayVec::new()
-    }
-}
-
-impl<A> fmt::Debug for ArrayVec<A>
-    where A: Array,
-          A::Element: fmt::Debug {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self[..].fmt(f)
-    }
-}
-
-impl<A: Array> Deref for ArrayVec<A> {
-    type Target = [A::Element];
-    fn deref(&self) -> &Self::Target {
-        unsafe {
-            slice::from_raw_parts(&self.values as *const _ as *const A::Element, self.count)
-        }
-    }
-}
-
-impl<A: Array> DerefMut for ArrayVec<A> {
-    fn deref_mut(&mut self) -> &mut [A::Element] {
-        unsafe {
-            slice::from_raw_parts_mut(&mut self.values as *mut _ as *mut A::Element, self.count)
-        }
-    }
-}
-
-impl<A: Array> Drop for ArrayVec<A> {
-    fn drop(&mut self) {
-        unsafe {
-            drop_in_place(&mut self[..])
-        }
-    }
-}
-
-impl<A: Array> Extend<A::Element> for ArrayVec<A> {
-    fn extend<I>(&mut self, iter: I) where I: IntoIterator<Item=A::Element> {
-        for el in iter {
-            self.push(el);
-        }
-    }
-}
-
-pub struct Iter<A: Array> {
-    indices: Range<usize>,
-    store: A::PartialStorage,
-}
-
-impl<A: Array> Drop for Iter<A> {
-    fn drop(&mut self) {
-        self.for_each(drop);
-    }
-}
-
-impl<A: Array> Iterator for Iter<A> {
-    type Item = A::Element;
-
-    fn next(&mut self) -> Option<A::Element> {
-        let arr = &self.store as &[ManuallyDrop<_>];
-        unsafe {
-            self.indices.next().map(|i| ptr::read(&*arr[i]))
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.indices.size_hint()
-    }
-}
-
-pub struct Drain<'a, A: Array>
-        where A::Element: 'a
-{
-    tail_start: usize,
-    tail_len: usize,
-    iter: slice::Iter<'a, ManuallyDrop<A::Element>>,
-    array_vec: NonNull<ArrayVec<A>>,
-}
-
-impl<'a, A: Array> Iterator for Drain<'a, A> {
-    type Item = A::Element;
-
-    #[inline]
-    fn next(&mut self) -> Option<A::Element> {
-        self.iter.next().map(|elt| unsafe { ptr::read(&**elt) })
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-impl<'a, A: Array> Drop for Drain<'a, A> {
-    fn drop(&mut self) {
-        // exhaust self first
-        self.for_each(drop);
-
-        if self.tail_len > 0 {
-            unsafe {
-                let source_array_vec: &mut ArrayVec<A> = self.array_vec.as_mut();
-                // memmove back untouched tail, update to new length
-                let start = source_array_vec.len();
-                let tail = self.tail_start;
-                {
-                    let arr =
-                        &mut source_array_vec.values as &mut [ManuallyDrop<<A as Array>::Element>];
-                    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);
-            }
-        }
-    }
-}
-
-impl<A: Array> IntoIterator for ArrayVec<A> {
-    type Item = A::Element;
-    type IntoIter = Iter<A>;
-    fn into_iter(self) -> Self::IntoIter {
-        let store = unsafe {
-            ptr::read(&self.values)
-        };
-        let indices = 0..self.count;
-        mem::forget(self);
-        Iter {
-            indices,
-            store,
-        }
-    }
-}
-
-impl<'a, A: Array> IntoIterator for &'a ArrayVec<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 ArrayVec<A> {
-    type Item = &'a mut A::Element;
-    type IntoIter = slice::IterMut<'a, A::Element>;
-    fn into_iter(self) -> Self::IntoIter {
-        self.iter_mut()
-    }
-}
diff --git a/src/librustc_data_structures/bit_set.rs b/src/librustc_data_structures/bit_set.rs
new file mode 100644 (file)
index 0000000..9eb8d0a
--- /dev/null
@@ -0,0 +1,1172 @@
+// 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 indexed_vec::{Idx, IndexVec};
+use rustc_serialize;
+use smallvec::SmallVec;
+use std::fmt;
+use std::iter;
+use std::marker::PhantomData;
+use std::mem;
+use std::slice;
+
+pub type Word = u64;
+pub const WORD_BYTES: usize = mem::size_of::<Word>();
+pub const WORD_BITS: usize = WORD_BYTES * 8;
+
+/// A fixed-size bitset type with a dense representation. It does not support
+/// resizing after creation; use `GrowableBitSet` for that.
+///
+/// `T` is an index type, typically a newtyped `usize` wrapper, but it can also
+/// just be `usize`.
+#[derive(Clone, Eq, PartialEq)]
+pub struct BitSet<T: Idx> {
+    words: Vec<Word>,
+    marker: PhantomData<T>,
+}
+
+impl<T: Idx> BitSet<T> {
+    #[inline]
+    pub fn new_empty(domain_size: usize) -> BitSet<T> {
+        let num_words = num_words(domain_size);
+        BitSet {
+            words: vec![0; num_words],
+            marker: PhantomData,
+        }
+    }
+
+    #[inline]
+    pub fn new_filled(domain_size: usize) -> BitSet<T> {
+        let num_words = num_words(domain_size);
+        let mut result = BitSet {
+            words: vec![!0; num_words],
+            marker: PhantomData,
+        };
+        result.clear_above(domain_size);
+        result
+    }
+
+    #[inline]
+    pub fn clear(&mut self) {
+        for word in &mut self.words {
+            *word = 0;
+        }
+    }
+
+    /// Sets all elements up to and including `size`.
+    pub fn set_up_to(&mut self, elem: usize) {
+        for word in &mut self.words {
+            *word = !0;
+        }
+        self.clear_above(elem);
+    }
+
+    /// Clear all elements above `elem`.
+    fn clear_above(&mut self, elem: usize) {
+        let first_clear_block = elem / WORD_BITS;
+
+        if first_clear_block < self.words.len() {
+            // Within `first_clear_block`, the `elem % WORD_BITS` LSBs should
+            // remain.
+            let mask = (1 << (elem % WORD_BITS)) - 1;
+            self.words[first_clear_block] &= mask;
+
+            // All the blocks above `first_clear_block` are fully cleared.
+            for word in &mut self.words[first_clear_block + 1..] {
+                *word = 0;
+            }
+        }
+    }
+
+    /// Efficiently overwrite `self` with `other`. Panics if `self` and `other`
+    /// don't have the same length.
+    pub fn overwrite(&mut self, other: &BitSet<T>) {
+        self.words.clone_from_slice(&other.words);
+    }
+
+    /// Count the number of set bits in the set.
+    pub fn count(&self) -> usize {
+        self.words.iter().map(|e| e.count_ones() as usize).sum()
+    }
+
+    /// True if `self` contains `elem`.
+    #[inline]
+    pub fn contains(&self, elem: T) -> bool {
+        let (word_index, mask) = word_index_and_mask(elem);
+        (self.words[word_index] & mask) != 0
+    }
+
+    /// True if `self` is a (non-strict) superset of `other`.
+    ///
+    /// The two sets must have the same domain_size.
+    #[inline]
+    pub fn superset(&self, other: &BitSet<T>) -> bool {
+        assert_eq!(self.words.len(), other.words.len());
+        self.words.iter().zip(&other.words).all(|(a, b)| (a & b) == *b)
+    }
+
+    /// Is the set empty?
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        self.words.iter().all(|a| *a == 0)
+    }
+
+    /// Insert `elem`. Returns true if the set has changed.
+    #[inline]
+    pub fn insert(&mut self, elem: T) -> bool {
+        let (word_index, mask) = word_index_and_mask(elem);
+        let word_ref = &mut self.words[word_index];
+        let word = *word_ref;
+        let new_word = word | mask;
+        *word_ref = new_word;
+        new_word != word
+    }
+
+    /// Sets all bits to true.
+    pub fn insert_all(&mut self) {
+        for word in &mut self.words {
+            *word = !0;
+        }
+    }
+
+    /// Returns true if the set has changed.
+    #[inline]
+    pub fn remove(&mut self, elem: T) -> bool {
+        let (word_index, mask) = word_index_and_mask(elem);
+        let word_ref = &mut self.words[word_index];
+        let word = *word_ref;
+        let new_word = word & !mask;
+        *word_ref = new_word;
+        new_word != word
+    }
+
+    /// Set `self = self | other` and return true if `self` changed
+    /// (i.e., if new bits were added).
+    pub fn union(&mut self, other: &impl UnionIntoBitSet<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: &impl SubtractFromBitSet<T>) -> bool {
+        other.subtract_from(self)
+    }
+
+    /// Set `self = self & other` and return true if `self` changed.
+    /// (i.e., if any bits were removed).
+    pub fn intersect(&mut self, other: &BitSet<T>) -> bool {
+        bitwise(&mut self.words, &other.words, |a, b| { a & b })
+    }
+
+    /// Get a slice of the underlying words.
+    pub fn words(&self) -> &[Word] {
+        &self.words
+    }
+
+    /// Iterates over the indices of set bits in a sorted order.
+    #[inline]
+    pub fn iter<'a>(&'a self) -> BitIter<'a, T> {
+        BitIter {
+            cur: None,
+            iter: self.words.iter().enumerate(),
+            marker: PhantomData,
+        }
+    }
+
+    /// Duplicates the set as a hybrid set.
+    pub fn to_hybrid(&self) -> HybridBitSet<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 domain_size = self.words.len() * WORD_BITS;
+
+        // Note: we currently don't bother trying to make a Sparse set.
+        HybridBitSet::Dense(self.to_owned(), domain_size)
+    }
+
+    pub fn to_string(&self, bits: usize) -> String {
+        let mut result = String::new();
+        let mut sep = '[';
+
+        // Note: this is a little endian printout of bytes.
+
+        // i tracks how many bits we have printed so far.
+        let mut i = 0;
+        for word in &self.words {
+            let mut word = *word;
+            for _ in 0..WORD_BYTES { // for each byte in `word`:
+                let remain = bits - i;
+                // If less than a byte remains, then mask just that many bits.
+                let mask = if remain <= 8 { (1 << remain) - 1 } else { 0xFF };
+                assert!(mask <= 0xFF);
+                let byte = word & mask;
+
+                result.push_str(&format!("{}{:02x}", sep, byte));
+
+                if remain <= 8 { break; }
+                word >>= 8;
+                i += 8;
+                sep = '-';
+            }
+            sep = '|';
+        }
+        result.push(']');
+
+        result
+    }
+}
+
+/// This is implemented by all the bitsets so that BitSet::union() can be
+/// passed any type of bitset.
+pub trait UnionIntoBitSet<T: Idx> {
+    // Performs `other = other | self`.
+    fn union_into(&self, other: &mut BitSet<T>) -> bool;
+}
+
+/// This is implemented by all the bitsets so that BitSet::subtract() can be
+/// passed any type of bitset.
+pub trait SubtractFromBitSet<T: Idx> {
+    // Performs `other = other - self`.
+    fn subtract_from(&self, other: &mut BitSet<T>) -> bool;
+}
+
+impl<T: Idx> UnionIntoBitSet<T> for BitSet<T> {
+    fn union_into(&self, other: &mut BitSet<T>) -> bool {
+        bitwise(&mut other.words, &self.words, |a, b| { a | b })
+    }
+}
+
+impl<T: Idx> SubtractFromBitSet<T> for BitSet<T> {
+    fn subtract_from(&self, other: &mut BitSet<T>) -> bool {
+        bitwise(&mut other.words, &self.words, |a, b| { a & !b })
+    }
+}
+
+impl<T: Idx> fmt::Debug for BitSet<T> {
+    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
+        w.debug_list()
+         .entries(self.iter())
+         .finish()
+    }
+}
+
+impl<T: Idx> rustc_serialize::Encodable for BitSet<T> {
+    fn encode<E: rustc_serialize::Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
+        self.words.encode(encoder)
+    }
+}
+
+impl<T: Idx> rustc_serialize::Decodable for BitSet<T> {
+    fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<BitSet<T>, D::Error> {
+        let words: Vec<Word> = rustc_serialize::Decodable::decode(d)?;
+        Ok(BitSet {
+            words,
+            marker: PhantomData,
+        })
+    }
+}
+
+pub struct BitIter<'a, T: Idx> {
+    cur: Option<(Word, usize)>,
+    iter: iter::Enumerate<slice::Iter<'a, Word>>,
+    marker: PhantomData<T>
+}
+
+impl<'a, T: Idx> Iterator for BitIter<'a, T> {
+    type Item = T;
+    fn next(&mut self) -> Option<T> {
+        loop {
+            if let Some((ref mut word, offset)) = self.cur {
+                let bit_pos = word.trailing_zeros() as usize;
+                if bit_pos != WORD_BITS {
+                    let bit = 1 << bit_pos;
+                    *word ^= bit;
+                    return Some(T::new(bit_pos + offset))
+                }
+            }
+
+            let (i, word) = self.iter.next()?;
+            self.cur = Some((*word, WORD_BITS * i));
+        }
+    }
+}
+
+pub trait BitSetOperator {
+    /// Combine one bitset into another.
+    fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool;
+}
+
+#[inline]
+fn bitwise<Op>(out_vec: &mut [Word], in_vec: &[Word], op: Op) -> bool
+    where Op: Fn(Word, Word) -> Word
+{
+    assert_eq!(out_vec.len(), in_vec.len());
+    let mut changed = false;
+    for (out_elem, in_elem) in out_vec.iter_mut().zip(in_vec.iter()) {
+        let old_val = *out_elem;
+        let new_val = op(old_val, *in_elem);
+        *out_elem = new_val;
+        changed |= old_val != new_val;
+    }
+    changed
+}
+
+const SPARSE_MAX: usize = 8;
+
+/// A fixed-size bitset type with a sparse representation and a maximum of
+/// `SPARSE_MAX` elements. The elements are stored as a sorted `SmallVec` with
+/// no duplicates; although `SmallVec` can spill its elements to the heap, that
+/// never happens within this type because of the `SPARSE_MAX` limit.
+///
+/// This type is used by `HybridBitSet`; do not use directly.
+#[derive(Clone, Debug)]
+pub struct SparseBitSet<T: Idx>(SmallVec<[T; SPARSE_MAX]>);
+
+impl<T: Idx> SparseBitSet<T> {
+    fn new_empty() -> Self {
+        SparseBitSet(SmallVec::new())
+    }
+
+    fn len(&self) -> usize {
+        self.0.len()
+    }
+
+    fn is_empty(&self) -> bool {
+        self.0.len() == 0
+    }
+
+    fn contains(&self, elem: T) -> bool {
+        self.0.contains(&elem)
+    }
+
+    fn insert(&mut self, elem: T) -> bool {
+        assert!(self.len() < SPARSE_MAX);
+        if let Some(i) = self.0.iter().position(|&e| e >= elem) {
+            if self.0[i] == elem {
+                // `elem` is already in the set.
+                false
+            } else {
+                // `elem` is smaller than one or more existing elements.
+                self.0.insert(i, elem);
+                true
+            }
+        } else {
+            // `elem` is larger than all existing elements.
+            self.0.push(elem);
+            true
+        }
+    }
+
+    fn remove(&mut self, elem: T) -> bool {
+        if let Some(i) = self.0.iter().position(|&e| e == elem) {
+            self.0.remove(i);
+            true
+        } else {
+            false
+        }
+    }
+
+    fn to_dense(&self, domain_size: usize) -> BitSet<T> {
+        let mut dense = BitSet::new_empty(domain_size);
+        for elem in self.0.iter() {
+            dense.insert(*elem);
+        }
+        dense
+    }
+
+    fn iter(&self) -> slice::Iter<T> {
+        self.0.iter()
+    }
+}
+
+impl<T: Idx> UnionIntoBitSet<T> for SparseBitSet<T> {
+    fn union_into(&self, other: &mut BitSet<T>) -> bool {
+        let mut changed = false;
+        for elem in self.iter() {
+            changed |= other.insert(*elem);
+        }
+        changed
+    }
+}
+
+impl<T: Idx> SubtractFromBitSet<T> for SparseBitSet<T> {
+    fn subtract_from(&self, other: &mut BitSet<T>) -> bool {
+        let mut changed = false;
+        for elem in self.iter() {
+            changed |= other.remove(*elem);
+        }
+        changed
+    }
+}
+
+/// A fixed-size bitset type with a hybrid representation: sparse when there
+/// are up to a `SPARSE_MAX` elements in the set, but dense when there are more
+/// than `SPARSE_MAX`.
+///
+/// This type is especially efficient for sets that typically have a small
+/// number of elements, but a large `domain_size`, and are cleared frequently.
+///
+/// `T` is an index type, typically a newtyped `usize` wrapper, but it can also
+/// just be `usize`.
+#[derive(Clone, Debug)]
+pub enum HybridBitSet<T: Idx> {
+    Sparse(SparseBitSet<T>, usize),
+    Dense(BitSet<T>, usize),
+}
+
+impl<T: Idx> HybridBitSet<T> {
+    // FIXME: This function is used in conjunction with `mem::replace()` in
+    // several pieces of awful code below. I can't work out how else to appease
+    // the borrow checker.
+    fn dummy() -> Self {
+        // The cheapest HybridBitSet to construct, which is only used to get
+        // around the borrow checker.
+        HybridBitSet::Sparse(SparseBitSet::new_empty(), 0)
+    }
+
+    pub fn new_empty(domain_size: usize) -> Self {
+        HybridBitSet::Sparse(SparseBitSet::new_empty(), domain_size)
+    }
+
+    pub fn domain_size(&self) -> usize {
+        match *self {
+            HybridBitSet::Sparse(_, size) => size,
+            HybridBitSet::Dense(_, size) => size,
+        }
+    }
+
+    pub fn clear(&mut self) {
+        let domain_size = self.domain_size();
+        *self = HybridBitSet::new_empty(domain_size);
+    }
+
+    pub fn contains(&self, elem: T) -> bool {
+        match self {
+            HybridBitSet::Sparse(sparse, _) => sparse.contains(elem),
+            HybridBitSet::Dense(dense, _) => dense.contains(elem),
+        }
+    }
+
+    pub fn superset(&self, other: &HybridBitSet<T>) -> bool {
+        match (self, other) {
+            (HybridBitSet::Dense(self_dense, _), HybridBitSet::Dense(other_dense, _)) => {
+                self_dense.superset(other_dense)
+            }
+            _ => other.iter().all(|elem| self.contains(elem)),
+        }
+    }
+
+    pub fn is_empty(&self) -> bool {
+        match self {
+            HybridBitSet::Sparse(sparse, _) => sparse.is_empty(),
+            HybridBitSet::Dense(dense, _) => dense.is_empty(),
+        }
+    }
+
+    pub fn insert(&mut self, elem: T) -> bool {
+        match self {
+            HybridBitSet::Sparse(sparse, _) if sparse.len() < SPARSE_MAX => {
+                // The set is sparse and has space for `elem`.
+                sparse.insert(elem)
+            }
+            HybridBitSet::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
+            }
+            HybridBitSet::Sparse(_, _) => {
+                // The set is sparse and full. Convert to a dense set.
+                match mem::replace(self, HybridBitSet::dummy()) {
+                    HybridBitSet::Sparse(sparse, domain_size) => {
+                        let mut dense = sparse.to_dense(domain_size);
+                        let changed = dense.insert(elem);
+                        assert!(changed);
+                        *self = HybridBitSet::Dense(dense, domain_size);
+                        changed
+                    }
+                    _ => unreachable!()
+                }
+            }
+
+            HybridBitSet::Dense(dense, _) => dense.insert(elem),
+        }
+    }
+
+    pub fn insert_all(&mut self) {
+        let domain_size = self.domain_size();
+        match self {
+            HybridBitSet::Sparse(_, _) => {
+                let dense = BitSet::new_filled(domain_size);
+                *self = HybridBitSet::Dense(dense, domain_size);
+            }
+            HybridBitSet::Dense(dense, _) => dense.insert_all(),
+        }
+    }
+
+    pub fn remove(&mut self, elem: T) -> bool {
+        // Note: we currently don't bother going from Dense back to Sparse.
+        match self {
+            HybridBitSet::Sparse(sparse, _) => sparse.remove(elem),
+            HybridBitSet::Dense(dense, _) => dense.remove(elem),
+        }
+    }
+
+    pub fn union(&mut self, other: &HybridBitSet<T>) -> bool {
+        match self {
+            HybridBitSet::Sparse(_, _) => {
+                match other {
+                    HybridBitSet::Sparse(other_sparse, _) => {
+                        // Both sets are sparse. Add the elements in
+                        // `other_sparse` to `self_hybrid` one at a time. This
+                        // may or may not cause `self_hybrid` to be densified.
+                        let mut self_hybrid = mem::replace(self, HybridBitSet::dummy());
+                        let mut changed = false;
+                        for elem in other_sparse.iter() {
+                            changed |= self_hybrid.insert(*elem);
+                        }
+                        *self = self_hybrid;
+                        changed
+                    }
+                    HybridBitSet::Dense(other_dense, _) => {
+                        // `self` is sparse and `other` is dense. Densify
+                        // `self` and then do the bitwise union.
+                        match mem::replace(self, HybridBitSet::dummy()) {
+                            HybridBitSet::Sparse(self_sparse, self_domain_size) => {
+                                let mut new_dense = self_sparse.to_dense(self_domain_size);
+                                let changed = new_dense.union(other_dense);
+                                *self = HybridBitSet::Dense(new_dense, self_domain_size);
+                                changed
+                            }
+                            _ => unreachable!()
+                        }
+                    }
+                }
+            }
+
+            HybridBitSet::Dense(self_dense, _) => self_dense.union(other),
+        }
+    }
+
+    /// Converts to a dense set, consuming itself in the process.
+    pub fn to_dense(self) -> BitSet<T> {
+        match self {
+            HybridBitSet::Sparse(sparse, domain_size) => sparse.to_dense(domain_size),
+            HybridBitSet::Dense(dense, _) => dense,
+        }
+    }
+
+    pub fn iter(&self) -> HybridIter<T> {
+        match self {
+            HybridBitSet::Sparse(sparse, _) => HybridIter::Sparse(sparse.iter()),
+            HybridBitSet::Dense(dense, _) => HybridIter::Dense(dense.iter()),
+        }
+    }
+}
+
+impl<T: Idx> UnionIntoBitSet<T> for HybridBitSet<T> {
+    fn union_into(&self, other: &mut BitSet<T>) -> bool {
+        match self {
+            HybridBitSet::Sparse(sparse, _) => sparse.union_into(other),
+            HybridBitSet::Dense(dense, _) => dense.union_into(other),
+        }
+    }
+}
+
+impl<T: Idx> SubtractFromBitSet<T> for HybridBitSet<T> {
+    fn subtract_from(&self, other: &mut BitSet<T>) -> bool {
+        match self {
+            HybridBitSet::Sparse(sparse, _) => sparse.subtract_from(other),
+            HybridBitSet::Dense(dense, _) => dense.subtract_from(other),
+        }
+    }
+}
+
+pub enum HybridIter<'a, T: Idx> {
+    Sparse(slice::Iter<'a, T>),
+    Dense(BitIter<'a, T>),
+}
+
+impl<'a, T: Idx> Iterator for HybridIter<'a, T> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        match self {
+            HybridIter::Sparse(sparse) => sparse.next().map(|e| *e),
+            HybridIter::Dense(dense) => dense.next(),
+        }
+    }
+}
+
+/// A resizable bitset type with a dense representation.
+///
+/// `T` is an index type, typically a newtyped `usize` wrapper, but it can also
+/// just be `usize`.
+#[derive(Clone, Debug, PartialEq)]
+pub struct GrowableBitSet<T: Idx> {
+    bit_set: BitSet<T>,
+}
+
+impl<T: Idx> GrowableBitSet<T> {
+    pub fn grow(&mut self, domain_size: T) {
+        let num_words = num_words(domain_size);
+        if self.bit_set.words.len() <= num_words {
+            self.bit_set.words.resize(num_words + 1, 0)
+        }
+    }
+
+    pub fn new_empty() -> GrowableBitSet<T> {
+        GrowableBitSet { bit_set: BitSet::new_empty(0) }
+    }
+
+    pub fn with_capacity(bits: usize) -> GrowableBitSet<T> {
+        GrowableBitSet { bit_set: BitSet::new_empty(bits) }
+    }
+
+    /// Returns true if the set has changed.
+    #[inline]
+    pub fn insert(&mut self, elem: T) -> bool {
+        self.grow(elem);
+        self.bit_set.insert(elem)
+    }
+
+    #[inline]
+    pub fn contains(&self, elem: T) -> bool {
+        let (word_index, mask) = word_index_and_mask(elem);
+        if let Some(word) = self.bit_set.words.get(word_index) {
+            (word & mask) != 0
+        } else {
+            false
+        }
+    }
+}
+
+/// A fixed-size 2D bit matrix type with a dense representation.
+///
+/// `R` and `C` are index types used to identify rows and columns respectively;
+/// typically newtyped `usize` wrappers, but they can also just be `usize`.
+///
+#[derive(Clone, Debug)]
+pub struct BitMatrix<R: Idx, C: Idx> {
+    columns: usize,
+    words: Vec<Word>,
+    marker: PhantomData<(R, C)>,
+}
+
+impl<R: Idx, C: Idx> BitMatrix<R, C> {
+    /// Create a new `rows x columns` matrix, initially empty.
+    pub fn new(rows: usize, columns: usize) -> BitMatrix<R, C> {
+        // For every element, we need one bit for every other
+        // element. Round up to an even number of words.
+        let words_per_row = num_words(columns);
+        BitMatrix {
+            columns,
+            words: vec![0; rows * words_per_row],
+            marker: PhantomData,
+        }
+    }
+
+    /// The range of bits for a given row.
+    fn range(&self, row: R) -> (usize, usize) {
+        let row = row.index();
+        let words_per_row = num_words(self.columns);
+        let start = row * words_per_row;
+        (start, start + words_per_row)
+    }
+
+    /// Sets the cell at `(row, column)` to true. Put another way, insert
+    /// `column` to the bitset for `row`.
+    ///
+    /// Returns true if this changed the matrix, and false otherwise.
+    pub fn insert(&mut self, row: R, column: R) -> bool {
+        let (start, _) = self.range(row);
+        let (word_index, mask) = word_index_and_mask(column);
+        let words = &mut self.words[..];
+        let word = words[start + word_index];
+        let new_word = word | mask;
+        words[start + word_index] = new_word;
+        word != new_word
+    }
+
+    /// Do the bits from `row` contain `column`? Put another way, is
+    /// the matrix cell at `(row, column)` true?  Put yet another way,
+    /// if the matrix represents (transitive) reachability, can
+    /// `row` reach `column`?
+    pub fn contains(&self, row: R, column: R) -> bool {
+        let (start, _) = self.range(row);
+        let (word_index, mask) = word_index_and_mask(column);
+        (self.words[start + word_index] & mask) != 0
+    }
+
+    /// Returns those indices that are true in rows `a` and `b`.  This
+    /// is an O(n) operation where `n` is the number of elements
+    /// (somewhat independent from the actual size of the
+    /// intersection, in particular).
+    pub fn intersect_rows(&self, a: R, b: R) -> Vec<C> {
+        let (a_start, a_end) = self.range(a);
+        let (b_start, b_end) = self.range(b);
+        let mut result = Vec::with_capacity(self.columns);
+        for (base, (i, j)) in (a_start..a_end).zip(b_start..b_end).enumerate() {
+            let mut v = self.words[i] & self.words[j];
+            for bit in 0..WORD_BITS {
+                if v == 0 {
+                    break;
+                }
+                if v & 0x1 != 0 {
+                    result.push(C::new(base * WORD_BITS + bit));
+                }
+                v >>= 1;
+            }
+        }
+        result
+    }
+
+    /// Add the bits from row `read` to the bits from row `write`,
+    /// return true if anything changed.
+    ///
+    /// This is used when computing transitive reachability because if
+    /// you have an edge `write -> read`, because in that case
+    /// `write` can reach everything that `read` can (and
+    /// potentially more).
+    pub fn union_rows(&mut self, read: R, write: R) -> bool {
+        let (read_start, read_end) = self.range(read);
+        let (write_start, write_end) = self.range(write);
+        let words = &mut self.words[..];
+        let mut changed = false;
+        for (read_index, write_index) in (read_start..read_end).zip(write_start..write_end) {
+            let word = words[write_index];
+            let new_word = word | words[read_index];
+            words[write_index] = new_word;
+            changed |= word != new_word;
+        }
+        changed
+    }
+
+    /// Iterates through all the columns set to true in a given row of
+    /// the matrix.
+    pub fn iter<'a>(&'a self, row: R) -> BitIter<'a, C> {
+        let (start, end) = self.range(row);
+        BitIter {
+            cur: None,
+            iter: self.words[start..end].iter().enumerate(),
+            marker: PhantomData,
+        }
+    }
+}
+
+/// A fixed-column-size, variable-row-size 2D bit matrix with a moderately
+/// sparse representation.
+///
+/// Initially, every row has no explicit representation. If any bit within a
+/// row is set, the entire row is instantiated as `Some(<HybridBitSet>)`.
+/// 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.
+///
+/// `R` and `C` are index types used to identify rows and columns respectively;
+/// typically newtyped `usize` wrappers, but they can also just be `usize`.
+#[derive(Clone, Debug)]
+pub struct SparseBitMatrix<R, C>
+where
+    R: Idx,
+    C: Idx,
+{
+    num_columns: usize,
+    rows: IndexVec<R, Option<HybridBitSet<C>>>,
+}
+
+impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
+    /// Create a new empty sparse bit matrix with no rows or columns.
+    pub fn new(num_columns: usize) -> Self {
+        Self {
+            num_columns,
+            rows: IndexVec::new(),
+        }
+    }
+
+    fn ensure_row(&mut self, row: R) -> &mut HybridBitSet<C> {
+        // Instantiate any missing rows up to and including row `row` with an
+        // empty HybridBitSet.
+        self.rows.ensure_contains_elem(row, || None);
+
+        // Then replace row `row` with a full HybridBitSet if necessary.
+        let num_columns = self.num_columns;
+        self.rows[row].get_or_insert_with(|| HybridBitSet::new_empty(num_columns))
+    }
+
+    /// Sets the cell at `(row, column)` to true. Put another way, insert
+    /// `column` to the bitset for `row`.
+    ///
+    /// Returns true if this changed the matrix, and false otherwise.
+    pub fn insert(&mut self, row: R, column: C) -> bool {
+        self.ensure_row(row).insert(column)
+    }
+
+    /// Do the bits from `row` contain `column`? Put another way, is
+    /// the matrix cell at `(row, column)` true?  Put yet another way,
+    /// if the matrix represents (transitive) reachability, can
+    /// `row` reach `column`?
+    pub fn contains(&self, row: R, column: C) -> bool {
+        self.row(row).map_or(false, |r| r.contains(column))
+    }
+
+    /// Add the bits from row `read` to the bits from row `write`,
+    /// return true if anything changed.
+    ///
+    /// This is used when computing transitive reachability because if
+    /// you have an edge `write -> read`, because in that case
+    /// `write` can reach everything that `read` can (and
+    /// potentially more).
+    pub fn union_rows(&mut self, read: R, write: R) -> bool {
+        if read == write || self.row(read).is_none() {
+            return false;
+        }
+
+        self.ensure_row(write);
+        if let (Some(read_row), Some(write_row)) = self.rows.pick2_mut(read, write) {
+            write_row.union(read_row)
+        } else {
+            unreachable!()
+        }
+    }
+
+    /// Union a row, `from`, into the `into` row.
+    pub fn union_into_row(&mut self, into: R, from: &HybridBitSet<C>) -> bool {
+        self.ensure_row(into).union(from)
+    }
+
+    /// Insert all bits in the given row.
+    pub fn insert_all_into_row(&mut self, row: R) {
+        self.ensure_row(row).insert_all();
+    }
+
+    pub fn rows(&self) -> impl Iterator<Item = R> {
+        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.row(row).into_iter().flat_map(|r| r.iter())
+    }
+
+    pub fn row(&self, row: R) -> Option<&HybridBitSet<C>> {
+        if let Some(Some(row)) = self.rows.get(row) {
+            Some(row)
+        } else {
+            None
+        }
+    }
+}
+
+#[inline]
+fn num_words<T: Idx>(elements: T) -> usize {
+    (elements.index() + WORD_BITS - 1) / WORD_BITS
+}
+
+#[inline]
+fn word_index_and_mask<T: Idx>(index: T) -> (usize, Word) {
+    let index = index.index();
+    let word_index = index / WORD_BITS;
+    let mask = 1 << (index % WORD_BITS);
+    (word_index, mask)
+}
+
+#[test]
+fn test_clear_above() {
+    use std::cmp;
+
+    for i in 0..256 {
+        let mut idx_buf: BitSet<usize> = BitSet::new_filled(128);
+        idx_buf.clear_above(i);
+
+        let elems: Vec<usize> = idx_buf.iter().collect();
+        let expected: Vec<usize> = (0..cmp::min(i, 128)).collect();
+        assert_eq!(elems, expected);
+    }
+}
+
+#[test]
+fn test_set_up_to() {
+    for i in 0..128 {
+        for mut idx_buf in
+            vec![BitSet::new_empty(128), BitSet::new_filled(128)].into_iter()
+        {
+            idx_buf.set_up_to(i);
+
+            let elems: Vec<usize> = idx_buf.iter().collect();
+            let expected: Vec<usize> = (0..i).collect();
+            assert_eq!(elems, expected);
+        }
+    }
+}
+
+#[test]
+fn test_new_filled() {
+    for i in 0..128 {
+        let idx_buf = BitSet::new_filled(i);
+        let elems: Vec<usize> = idx_buf.iter().collect();
+        let expected: Vec<usize> = (0..i).collect();
+        assert_eq!(elems, expected);
+    }
+}
+
+#[test]
+fn bitset_iter_works() {
+    let mut bitset: BitSet<usize> = BitSet::new_empty(100);
+    bitset.insert(1);
+    bitset.insert(10);
+    bitset.insert(19);
+    bitset.insert(62);
+    bitset.insert(63);
+    bitset.insert(64);
+    bitset.insert(65);
+    bitset.insert(66);
+    bitset.insert(99);
+    assert_eq!(
+        bitset.iter().collect::<Vec<_>>(),
+        [1, 10, 19, 62, 63, 64, 65, 66, 99]
+    );
+}
+
+#[test]
+fn bitset_iter_works_2() {
+    let mut bitset: BitSet<usize> = BitSet::new_empty(319);
+    bitset.insert(0);
+    bitset.insert(127);
+    bitset.insert(191);
+    bitset.insert(255);
+    bitset.insert(319);
+    assert_eq!(bitset.iter().collect::<Vec<_>>(), [0, 127, 191, 255, 319]);
+}
+
+#[test]
+fn union_two_sets() {
+    let mut set1: BitSet<usize> = BitSet::new_empty(65);
+    let mut set2: BitSet<usize> = BitSet::new_empty(65);
+    assert!(set1.insert(3));
+    assert!(!set1.insert(3));
+    assert!(set2.insert(5));
+    assert!(set2.insert(64));
+    assert!(set1.union(&set2));
+    assert!(!set1.union(&set2));
+    assert!(set1.contains(3));
+    assert!(!set1.contains(4));
+    assert!(set1.contains(5));
+    assert!(!set1.contains(63));
+    assert!(set1.contains(64));
+}
+
+#[test]
+fn hybrid_bitset() {
+    let mut sparse038: HybridBitSet<usize> = HybridBitSet::new_empty(256);
+    assert!(sparse038.is_empty());
+    assert!(sparse038.insert(0));
+    assert!(sparse038.insert(1));
+    assert!(sparse038.insert(8));
+    assert!(sparse038.insert(3));
+    assert!(!sparse038.insert(3));
+    assert!(sparse038.remove(1));
+    assert!(!sparse038.is_empty());
+    assert_eq!(sparse038.iter().collect::<Vec<_>>(), [0, 3, 8]);
+
+    for i in 0..256 {
+        if i == 0 || i == 3 || i == 8 {
+            assert!(sparse038.contains(i));
+        } else {
+            assert!(!sparse038.contains(i));
+        }
+    }
+
+    let mut sparse01358 = sparse038.clone();
+    assert!(sparse01358.insert(1));
+    assert!(sparse01358.insert(5));
+    assert_eq!(sparse01358.iter().collect::<Vec<_>>(), [0, 1, 3, 5, 8]);
+
+    let mut dense10 = HybridBitSet::new_empty(256);
+    for i in 0..10 {
+        assert!(dense10.insert(i));
+    }
+    assert!(!dense10.is_empty());
+    assert_eq!(dense10.iter().collect::<Vec<_>>(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+
+    let mut dense256 = HybridBitSet::new_empty(256);
+    assert!(dense256.is_empty());
+    dense256.insert_all();
+    assert!(!dense256.is_empty());
+    for i in 0..256 {
+        assert!(dense256.contains(i));
+    }
+
+    assert!(sparse038.superset(&sparse038));    // sparse + sparse (self)
+    assert!(sparse01358.superset(&sparse038));  // sparse + sparse
+    assert!(dense10.superset(&sparse038));      // dense + sparse
+    assert!(dense10.superset(&dense10));        // dense + dense (self)
+    assert!(dense256.superset(&dense10));       // dense + dense
+
+    let mut hybrid = sparse038;
+    assert!(!sparse01358.union(&hybrid));       // no change
+    assert!(hybrid.union(&sparse01358));
+    assert!(hybrid.superset(&sparse01358) && sparse01358.superset(&hybrid));
+    assert!(!dense10.union(&sparse01358));
+    assert!(!dense256.union(&dense10));
+    let mut dense = dense10;
+    assert!(dense.union(&dense256));
+    assert!(dense.superset(&dense256) && dense256.superset(&dense));
+    assert!(hybrid.union(&dense256));
+    assert!(hybrid.superset(&dense256) && dense256.superset(&hybrid));
+
+    assert_eq!(dense256.iter().count(), 256);
+    let mut dense0 = dense256;
+    for i in 0..256 {
+        assert!(dense0.remove(i));
+    }
+    assert!(!dense0.remove(0));
+    assert!(dense0.is_empty());
+}
+
+#[test]
+fn grow() {
+    let mut set: GrowableBitSet<usize> = GrowableBitSet::with_capacity(65);
+    for index in 0..65 {
+        assert!(set.insert(index));
+        assert!(!set.insert(index));
+    }
+    set.grow(128);
+
+    // Check if the bits set before growing are still set
+    for index in 0..65 {
+        assert!(set.contains(index));
+    }
+
+    // Check if the new bits are all un-set
+    for index in 65..128 {
+        assert!(!set.contains(index));
+    }
+
+    // Check that we can set all new bits without running out of bounds
+    for index in 65..128 {
+        assert!(set.insert(index));
+        assert!(!set.insert(index));
+    }
+}
+
+#[test]
+fn matrix_intersection() {
+    let mut matrix: BitMatrix<usize, usize> = BitMatrix::new(200, 200);
+
+    // (*) Elements reachable from both 2 and 65.
+
+    matrix.insert(2, 3);
+    matrix.insert(2, 6);
+    matrix.insert(2, 10); // (*)
+    matrix.insert(2, 64); // (*)
+    matrix.insert(2, 65);
+    matrix.insert(2, 130);
+    matrix.insert(2, 160); // (*)
+
+    matrix.insert(64, 133);
+
+    matrix.insert(65, 2);
+    matrix.insert(65, 8);
+    matrix.insert(65, 10); // (*)
+    matrix.insert(65, 64); // (*)
+    matrix.insert(65, 68);
+    matrix.insert(65, 133);
+    matrix.insert(65, 160); // (*)
+
+    let intersection = matrix.intersect_rows(2, 64);
+    assert!(intersection.is_empty());
+
+    let intersection = matrix.intersect_rows(2, 65);
+    assert_eq!(intersection, &[10, 64, 160]);
+}
+
+#[test]
+fn matrix_iter() {
+    let mut matrix: BitMatrix<usize, usize> = BitMatrix::new(64, 100);
+    matrix.insert(3, 22);
+    matrix.insert(3, 75);
+    matrix.insert(2, 99);
+    matrix.insert(4, 0);
+    matrix.union_rows(3, 5);
+
+    let expected = [99];
+    let mut iter = expected.iter();
+    for i in matrix.iter(2) {
+        let j = *iter.next().unwrap();
+        assert_eq!(i, j);
+    }
+    assert!(iter.next().is_none());
+
+    let expected = [22, 75];
+    let mut iter = expected.iter();
+    for i in matrix.iter(3) {
+        let j = *iter.next().unwrap();
+        assert_eq!(i, j);
+    }
+    assert!(iter.next().is_none());
+
+    let expected = [0];
+    let mut iter = expected.iter();
+    for i in matrix.iter(4) {
+        let j = *iter.next().unwrap();
+        assert_eq!(i, j);
+    }
+    assert!(iter.next().is_none());
+
+    let expected = [22, 75];
+    let mut iter = expected.iter();
+    for i in matrix.iter(5) {
+        let j = *iter.next().unwrap();
+        assert_eq!(i, j);
+    }
+    assert!(iter.next().is_none());
+}
+
+#[test]
+fn sparse_matrix_iter() {
+    let mut matrix: SparseBitMatrix<usize, usize> = SparseBitMatrix::new(100);
+    matrix.insert(3, 22);
+    matrix.insert(3, 75);
+    matrix.insert(2, 99);
+    matrix.insert(4, 0);
+    matrix.union_rows(3, 5);
+
+    let expected = [99];
+    let mut iter = expected.iter();
+    for i in matrix.iter(2) {
+        let j = *iter.next().unwrap();
+        assert_eq!(i, j);
+    }
+    assert!(iter.next().is_none());
+
+    let expected = [22, 75];
+    let mut iter = expected.iter();
+    for i in matrix.iter(3) {
+        let j = *iter.next().unwrap();
+        assert_eq!(i, j);
+    }
+    assert!(iter.next().is_none());
+
+    let expected = [0];
+    let mut iter = expected.iter();
+    for i in matrix.iter(4) {
+        let j = *iter.next().unwrap();
+        assert_eq!(i, j);
+    }
+    assert!(iter.next().is_none());
+
+    let expected = [22, 75];
+    let mut iter = expected.iter();
+    for i in matrix.iter(5) {
+        let j = *iter.next().unwrap();
+        assert_eq!(i, j);
+    }
+    assert!(iter.next().is_none());
+}
diff --git a/src/librustc_data_structures/bitslice.rs b/src/librustc_data_structures/bitslice.rs
deleted file mode 100644 (file)
index a63033c..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright 2012-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.
-
-// FIXME: merge with `bitvec`
-
-use std::mem;
-
-pub type Word = usize;
-
-/// `BitSlice` provides helper methods for treating a `[Word]`
-/// as a bitvector.
-pub trait BitSlice {
-    fn clear_bit(&mut self, idx: usize) -> bool;
-    fn set_bit(&mut self, idx: usize) -> bool;
-    fn get_bit(&self, idx: usize) -> bool;
-}
-
-impl BitSlice for [Word] {
-    /// Clears bit at `idx` to 0; returns true iff this changed `self.`
-    #[inline]
-    fn clear_bit(&mut self, idx: usize) -> bool {
-        let words = self;
-        debug!("clear_bit: words={} idx={}",
-               bits_to_string(words, words.len() * mem::size_of::<Word>() * 8), idx);
-        let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx);
-        debug!("word={} bit_in_word={} bit_mask=0x{:x}", word, bit_in_word, bit_mask);
-        let oldv = words[word];
-        let newv = oldv & !bit_mask;
-        words[word] = newv;
-        oldv != newv
-    }
-
-    /// Sets bit at `idx` to 1; returns true iff this changed `self.`
-    #[inline]
-    fn set_bit(&mut self, idx: usize) -> bool {
-        let words = self;
-        debug!("set_bit: words={} idx={}",
-               bits_to_string(words, words.len() * mem::size_of::<Word>() * 8), idx);
-        let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx);
-        debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask);
-        let oldv = words[word];
-        let newv = oldv | bit_mask;
-        words[word] = newv;
-        oldv != newv
-    }
-
-    /// Extracts value of bit at `idx` in `self`.
-    #[inline]
-    fn get_bit(&self, idx: usize) -> bool {
-        let words = self;
-        let BitLookup { word, bit_mask, .. } = bit_lookup(idx);
-        (words[word] & bit_mask) != 0
-    }
-}
-
-struct BitLookup {
-    /// An index of the word holding the bit in original `[Word]` of query.
-    word: usize,
-    /// Index of the particular bit within the word holding the bit.
-    bit_in_word: usize,
-    /// Word with single 1-bit set corresponding to where the bit is located.
-    bit_mask: Word,
-}
-
-#[inline]
-fn bit_lookup(bit: usize) -> BitLookup {
-    let word_bits = mem::size_of::<Word>() * 8;
-    let word = bit / word_bits;
-    let bit_in_word = bit % word_bits;
-    let bit_mask = 1 << bit_in_word;
-    BitLookup { word, bit_in_word, bit_mask }
-}
-
-pub fn bits_to_string(words: &[Word], bits: usize) -> String {
-    let mut result = String::new();
-    let mut sep = '[';
-
-    // Note: this is a little endian printout of bytes.
-
-    // i tracks how many bits we have printed so far.
-    let mut i = 0;
-    for &word in words.iter() {
-        let mut v = word;
-        for _ in 0..mem::size_of::<Word>() { // for each byte in `v`:
-            let remain = bits - i;
-            // If less than a byte remains, then mask just that many bits.
-            let mask = if remain <= 8 { (1 << remain) - 1 } else { 0xFF };
-            assert!(mask <= 0xFF);
-            let byte = v & mask;
-
-            result.push_str(&format!("{}{:02x}", sep, byte));
-
-            if remain <= 8 { break; }
-            v >>= 8;
-            i += 8;
-            sep = '-';
-        }
-        sep = '|';
-    }
-    result.push(']');
-
-    result
-}
-
-#[inline]
-pub fn bitwise<Op:BitwiseOperator>(out_vec: &mut [Word],
-                                   in_vec: &[Word],
-                                   op: &Op) -> bool {
-    assert_eq!(out_vec.len(), in_vec.len());
-    let mut changed = false;
-    for (out_elt, in_elt) in out_vec.iter_mut().zip(in_vec) {
-        let old_val = *out_elt;
-        let new_val = op.join(old_val, *in_elt);
-        *out_elt = new_val;
-        changed |= old_val != new_val;
-    }
-    changed
-}
-
-pub trait BitwiseOperator {
-    /// Applies some bit-operation pointwise to each of the bits in the two inputs.
-    fn join(&self, pred1: Word, pred2: Word) -> Word;
-}
-
-pub struct Intersect;
-impl BitwiseOperator for Intersect {
-    #[inline]
-    fn join(&self, a: Word, b: Word) -> Word { a & b }
-}
-pub struct Union;
-impl BitwiseOperator for Union {
-    #[inline]
-    fn join(&self, a: Word, b: Word) -> Word { a | b }
-}
-pub struct Subtract;
-impl BitwiseOperator for Subtract {
-    #[inline]
-    fn join(&self, a: Word, b: Word) -> Word { a & !b }
-}
diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs
deleted file mode 100644 (file)
index 642d24f..0000000
+++ /dev/null
@@ -1,621 +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 indexed_vec::{Idx, IndexVec};
-use std::marker::PhantomData;
-
-type Word = u128;
-const WORD_BITS: usize = 128;
-
-/// A very simple BitArray type.
-///
-/// It does not support resizing after creation; use `BitVector` for that.
-#[derive(Clone, Debug, PartialEq)]
-pub struct BitArray<C: Idx> {
-    data: Vec<Word>,
-    marker: PhantomData<C>,
-}
-
-#[derive(Clone, Debug, PartialEq)]
-pub struct BitVector<C: Idx> {
-    data: BitArray<C>,
-}
-
-impl<C: Idx> BitVector<C> {
-    pub fn grow(&mut self, num_bits: C) {
-        self.data.grow(num_bits)
-    }
-
-    pub fn new() -> BitVector<C> {
-        BitVector {
-            data: BitArray::new(0),
-        }
-    }
-
-    pub fn with_capacity(bits: usize) -> BitVector<C> {
-        BitVector {
-            data: BitArray::new(bits),
-        }
-    }
-
-    /// Returns true if the bit has changed.
-    #[inline]
-    pub fn insert(&mut self, bit: C) -> bool {
-        self.grow(bit);
-        self.data.insert(bit)
-    }
-
-    #[inline]
-    pub fn contains(&self, bit: C) -> bool {
-        let (word, mask) = word_mask(bit);
-        if let Some(word) = self.data.data.get(word) {
-            (word & mask) != 0
-        } else {
-            false
-        }
-    }
-}
-
-impl<C: Idx> BitArray<C> {
-    // Do not make this method public, instead switch your use case to BitVector.
-    #[inline]
-    fn grow(&mut self, num_bits: C) {
-        let num_words = words(num_bits);
-        if self.data.len() <= num_words {
-            self.data.resize(num_words + 1, 0)
-        }
-    }
-
-    #[inline]
-    pub fn new(num_bits: usize) -> BitArray<C> {
-        let num_words = words(num_bits);
-        BitArray {
-            data: vec![0; num_words],
-            marker: PhantomData,
-        }
-    }
-
-    #[inline]
-    pub fn clear(&mut self) {
-        for p in &mut self.data {
-            *p = 0;
-        }
-    }
-
-    pub fn count(&self) -> usize {
-        self.data.iter().map(|e| e.count_ones() as usize).sum()
-    }
-
-    /// True if `self` contains the bit `bit`.
-    #[inline]
-    pub fn contains(&self, bit: C) -> bool {
-        let (word, mask) = word_mask(bit);
-        (self.data[word] & mask) != 0
-    }
-
-    /// True if `self` contains all the bits in `other`.
-    ///
-    /// The two vectors must have the same length.
-    #[inline]
-    pub fn contains_all(&self, other: &BitArray<C>) -> bool {
-        assert_eq!(self.data.len(), other.data.len());
-        self.data.iter().zip(&other.data).all(|(a, b)| (a & b) == *b)
-    }
-
-    #[inline]
-    pub fn is_empty(&self) -> bool {
-        self.data.iter().all(|a| *a == 0)
-    }
-
-    /// Returns true if the bit has changed.
-    #[inline]
-    pub fn insert(&mut self, bit: C) -> bool {
-        let (word, mask) = word_mask(bit);
-        let data = &mut self.data[word];
-        let value = *data;
-        let new_value = value | mask;
-        *data = new_value;
-        new_value != value
-    }
-
-    /// Sets all bits to true.
-    pub fn insert_all(&mut self) {
-        for data in &mut self.data {
-            *data = u128::max_value();
-        }
-    }
-
-    /// Returns true if the bit has changed.
-    #[inline]
-    pub fn remove(&mut self, bit: C) -> bool {
-        let (word, mask) = word_mask(bit);
-        let data = &mut self.data[word];
-        let value = *data;
-        let new_value = value & !mask;
-        *data = new_value;
-        new_value != value
-    }
-
-    #[inline]
-    pub fn merge(&mut self, all: &BitArray<C>) -> bool {
-        assert!(self.data.len() == all.data.len());
-        let mut changed = false;
-        for (i, j) in self.data.iter_mut().zip(&all.data) {
-            let value = *i;
-            *i = value | *j;
-            if value != *i {
-                changed = true;
-            }
-        }
-        changed
-    }
-
-    /// Iterates over indexes of set bits in a sorted order
-    #[inline]
-    pub fn iter<'a>(&'a self) -> BitIter<'a, C> {
-        BitIter {
-            iter: self.data.iter(),
-            current: 0,
-            idx: 0,
-            marker: PhantomData,
-        }
-    }
-}
-
-pub struct BitIter<'a, C: Idx> {
-    iter: ::std::slice::Iter<'a, Word>,
-    current: Word,
-    idx: usize,
-    marker: PhantomData<C>
-}
-
-impl<'a, C: Idx> Iterator for BitIter<'a, C> {
-    type Item = C;
-    fn next(&mut self) -> Option<C> {
-        while self.current == 0 {
-            self.current = if let Some(&i) = self.iter.next() {
-                if i == 0 {
-                    self.idx += WORD_BITS;
-                    continue;
-                } else {
-                    self.idx = words(self.idx) * WORD_BITS;
-                    i
-                }
-            } else {
-                return None;
-            }
-        }
-        let offset = self.current.trailing_zeros() as usize;
-        self.current >>= offset;
-        self.current >>= 1; // shift otherwise overflows for 0b1000_0000_…_0000
-        self.idx += offset + 1;
-
-        Some(C::new(self.idx - 1))
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (_, upper) = self.iter.size_hint();
-        (0, upper)
-    }
-}
-
-/// A "bit matrix" is basically a matrix of booleans represented as
-/// one gigantic bitvector. In other words, it is as if you have
-/// `rows` bitvectors, each of length `columns`.
-#[derive(Clone, Debug)]
-pub struct BitMatrix<R: Idx, C: Idx> {
-    columns: usize,
-    vector: Vec<Word>,
-    phantom: PhantomData<(R, C)>,
-}
-
-impl<R: Idx, C: Idx> BitMatrix<R, C> {
-    /// Create a new `rows x columns` matrix, initially empty.
-    pub fn new(rows: usize, columns: usize) -> BitMatrix<R, C> {
-        // For every element, we need one bit for every other
-        // element. Round up to an even number of words.
-        let words_per_row = words(columns);
-        BitMatrix {
-            columns,
-            vector: vec![0; rows * words_per_row],
-            phantom: PhantomData,
-        }
-    }
-
-    /// The range of bits for a given row.
-    fn range(&self, row: R) -> (usize, usize) {
-        let row = row.index();
-        let words_per_row = words(self.columns);
-        let start = row * words_per_row;
-        (start, start + words_per_row)
-    }
-
-    /// Sets the cell at `(row, column)` to true. Put another way, add
-    /// `column` to the bitset for `row`.
-    ///
-    /// Returns true if this changed the matrix, and false otherwise.
-    pub fn add(&mut self, row: R, column: R) -> bool {
-        let (start, _) = self.range(row);
-        let (word, mask) = word_mask(column);
-        let vector = &mut self.vector[..];
-        let v1 = vector[start + word];
-        let v2 = v1 | mask;
-        vector[start + word] = v2;
-        v1 != v2
-    }
-
-    /// Do the bits from `row` contain `column`? Put another way, is
-    /// the matrix cell at `(row, column)` true?  Put yet another way,
-    /// if the matrix represents (transitive) reachability, can
-    /// `row` reach `column`?
-    pub fn contains(&self, row: R, column: R) -> bool {
-        let (start, _) = self.range(row);
-        let (word, mask) = word_mask(column);
-        (self.vector[start + word] & mask) != 0
-    }
-
-    /// Returns those indices that are true in rows `a` and `b`.  This
-    /// is an O(n) operation where `n` is the number of elements
-    /// (somewhat independent from the actual size of the
-    /// intersection, in particular).
-    pub fn intersection(&self, a: R, b: R) -> Vec<C> {
-        let (a_start, a_end) = self.range(a);
-        let (b_start, b_end) = self.range(b);
-        let mut result = Vec::with_capacity(self.columns);
-        for (base, (i, j)) in (a_start..a_end).zip(b_start..b_end).enumerate() {
-            let mut v = self.vector[i] & self.vector[j];
-            for bit in 0..WORD_BITS {
-                if v == 0 {
-                    break;
-                }
-                if v & 0x1 != 0 {
-                    result.push(C::new(base * WORD_BITS + bit));
-                }
-                v >>= 1;
-            }
-        }
-        result
-    }
-
-    /// Add the bits from row `read` to the bits from row `write`,
-    /// return true if anything changed.
-    ///
-    /// This is used when computing transitive reachability because if
-    /// you have an edge `write -> read`, because in that case
-    /// `write` can reach everything that `read` can (and
-    /// potentially more).
-    pub fn merge(&mut self, read: R, write: R) -> bool {
-        let (read_start, read_end) = self.range(read);
-        let (write_start, write_end) = self.range(write);
-        let vector = &mut self.vector[..];
-        let mut changed = false;
-        for (read_index, write_index) in (read_start..read_end).zip(write_start..write_end) {
-            let v1 = vector[write_index];
-            let v2 = v1 | vector[read_index];
-            vector[write_index] = v2;
-            changed |= v1 != v2;
-        }
-        changed
-    }
-
-    /// Iterates through all the columns set to true in a given row of
-    /// the matrix.
-    pub fn iter<'a>(&'a self, row: R) -> BitIter<'a, C> {
-        let (start, end) = self.range(row);
-        BitIter {
-            iter: self.vector[start..end].iter(),
-            current: 0,
-            idx: 0,
-            marker: PhantomData,
-        }
-    }
-}
-
-/// 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,
-{
-    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(num_columns: usize) -> Self {
-        Self {
-            num_columns,
-            rows: IndexVec::new(),
-        }
-    }
-
-    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
-    /// `column` to the bitset for `row`.
-    ///
-    /// Returns true if this changed the matrix, and false otherwise.
-    pub fn add(&mut self, row: R, column: C) -> bool {
-        self.ensure_row(row).insert(column)
-    }
-
-    /// Do the bits from `row` contain `column`? Put another way, is
-    /// the matrix cell at `(row, column)` true?  Put yet another way,
-    /// if the matrix represents (transitive) reachability, can
-    /// `row` reach `column`?
-    pub fn contains(&self, row: R, column: C) -> bool {
-        self.row(row).map_or(false, |r| r.contains(column))
-    }
-
-    /// Add the bits from row `read` to the bits from row `write`,
-    /// return true if anything changed.
-    ///
-    /// This is used when computing transitive reachability because if
-    /// you have an edge `write -> read`, because in that case
-    /// `write` can reach everything that `read` can (and
-    /// potentially more).
-    pub fn merge(&mut self, read: R, write: R) -> bool {
-        if read == write || self.row(read).is_none() {
-            return false;
-        }
-
-        self.ensure_row(write);
-        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).merge(from)
-    }
-
-    /// Add all bits to the given row.
-    pub fn add_all(&mut self, row: R) {
-        self.ensure_row(row).insert_all();
-    }
-
-    pub fn rows(&self) -> impl Iterator<Item = R> {
-        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.row(row).into_iter().flat_map(|r| r.iter())
-    }
-
-    pub fn row(&self, row: R) -> Option<&BitArray<C>> {
-        if let Some(Some(row)) = self.rows.get(row) {
-            Some(row)
-        } else {
-            None
-        }
-    }
-}
-
-#[inline]
-fn words<C: Idx>(elements: C) -> usize {
-    (elements.index() + WORD_BITS - 1) / WORD_BITS
-}
-
-#[inline]
-fn word_mask<C: Idx>(index: C) -> (usize, Word) {
-    let index = index.index();
-    let word = index / WORD_BITS;
-    let mask = 1 << (index % WORD_BITS);
-    (word, mask)
-}
-
-#[test]
-fn bitvec_iter_works() {
-    let mut bitvec: BitArray<usize> = BitArray::new(100);
-    bitvec.insert(1);
-    bitvec.insert(10);
-    bitvec.insert(19);
-    bitvec.insert(62);
-    bitvec.insert(63);
-    bitvec.insert(64);
-    bitvec.insert(65);
-    bitvec.insert(66);
-    bitvec.insert(99);
-    assert_eq!(
-        bitvec.iter().collect::<Vec<_>>(),
-        [1, 10, 19, 62, 63, 64, 65, 66, 99]
-    );
-}
-
-#[test]
-fn bitvec_iter_works_2() {
-    let mut bitvec: BitArray<usize> = BitArray::new(319);
-    bitvec.insert(0);
-    bitvec.insert(127);
-    bitvec.insert(191);
-    bitvec.insert(255);
-    bitvec.insert(319);
-    assert_eq!(bitvec.iter().collect::<Vec<_>>(), [0, 127, 191, 255, 319]);
-}
-
-#[test]
-fn union_two_vecs() {
-    let mut vec1: BitArray<usize> = BitArray::new(65);
-    let mut vec2: BitArray<usize> = BitArray::new(65);
-    assert!(vec1.insert(3));
-    assert!(!vec1.insert(3));
-    assert!(vec2.insert(5));
-    assert!(vec2.insert(64));
-    assert!(vec1.merge(&vec2));
-    assert!(!vec1.merge(&vec2));
-    assert!(vec1.contains(3));
-    assert!(!vec1.contains(4));
-    assert!(vec1.contains(5));
-    assert!(!vec1.contains(63));
-    assert!(vec1.contains(64));
-}
-
-#[test]
-fn grow() {
-    let mut vec1: BitVector<usize> = BitVector::with_capacity(65);
-    for index in 0..65 {
-        assert!(vec1.insert(index));
-        assert!(!vec1.insert(index));
-    }
-    vec1.grow(128);
-
-    // Check if the bits set before growing are still set
-    for index in 0..65 {
-        assert!(vec1.contains(index));
-    }
-
-    // Check if the new bits are all un-set
-    for index in 65..128 {
-        assert!(!vec1.contains(index));
-    }
-
-    // Check that we can set all new bits without running out of bounds
-    for index in 65..128 {
-        assert!(vec1.insert(index));
-        assert!(!vec1.insert(index));
-    }
-}
-
-#[test]
-fn matrix_intersection() {
-    let mut vec1: BitMatrix<usize, usize> = BitMatrix::new(200, 200);
-
-    // (*) Elements reachable from both 2 and 65.
-
-    vec1.add(2, 3);
-    vec1.add(2, 6);
-    vec1.add(2, 10); // (*)
-    vec1.add(2, 64); // (*)
-    vec1.add(2, 65);
-    vec1.add(2, 130);
-    vec1.add(2, 160); // (*)
-
-    vec1.add(64, 133);
-
-    vec1.add(65, 2);
-    vec1.add(65, 8);
-    vec1.add(65, 10); // (*)
-    vec1.add(65, 64); // (*)
-    vec1.add(65, 68);
-    vec1.add(65, 133);
-    vec1.add(65, 160); // (*)
-
-    let intersection = vec1.intersection(2, 64);
-    assert!(intersection.is_empty());
-
-    let intersection = vec1.intersection(2, 65);
-    assert_eq!(intersection, &[10, 64, 160]);
-}
-
-#[test]
-fn matrix_iter() {
-    let mut matrix: BitMatrix<usize, usize> = BitMatrix::new(64, 100);
-    matrix.add(3, 22);
-    matrix.add(3, 75);
-    matrix.add(2, 99);
-    matrix.add(4, 0);
-    matrix.merge(3, 5);
-
-    let expected = [99];
-    let mut iter = expected.iter();
-    for i in matrix.iter(2) {
-        let j = *iter.next().unwrap();
-        assert_eq!(i, j);
-    }
-    assert!(iter.next().is_none());
-
-    let expected = [22, 75];
-    let mut iter = expected.iter();
-    for i in matrix.iter(3) {
-        let j = *iter.next().unwrap();
-        assert_eq!(i, j);
-    }
-    assert!(iter.next().is_none());
-
-    let expected = [0];
-    let mut iter = expected.iter();
-    for i in matrix.iter(4) {
-        let j = *iter.next().unwrap();
-        assert_eq!(i, j);
-    }
-    assert!(iter.next().is_none());
-
-    let expected = [22, 75];
-    let mut iter = expected.iter();
-    for i in matrix.iter(5) {
-        let j = *iter.next().unwrap();
-        assert_eq!(i, j);
-    }
-    assert!(iter.next().is_none());
-}
-
-#[test]
-fn sparse_matrix_iter() {
-    let mut matrix: SparseBitMatrix<usize, usize> = SparseBitMatrix::new(100);
-    matrix.add(3, 22);
-    matrix.add(3, 75);
-    matrix.add(2, 99);
-    matrix.add(4, 0);
-    matrix.merge(3, 5);
-
-    let expected = [99];
-    let mut iter = expected.iter();
-    for i in matrix.iter(2) {
-        let j = *iter.next().unwrap();
-        assert_eq!(i, j);
-    }
-    assert!(iter.next().is_none());
-
-    let expected = [22, 75];
-    let mut iter = expected.iter();
-    for i in matrix.iter(3) {
-        let j = *iter.next().unwrap();
-        assert_eq!(i, j);
-    }
-    assert!(iter.next().is_none());
-
-    let expected = [0];
-    let mut iter = expected.iter();
-    for i in matrix.iter(4) {
-        let j = *iter.next().unwrap();
-        assert_eq!(i, j);
-    }
-    assert!(iter.next().is_none());
-
-    let expected = [22, 75];
-    let mut iter = expected.iter();
-    for i in matrix.iter(5) {
-        let j = *iter.next().unwrap();
-        assert_eq!(i, j);
-    }
-    assert!(iter.next().is_none());
-}
index f10a9a68bed5b3a73d2354b2e6a2e61b34572fd5..38ce331051fecc81b029a2bd460a0406963e8644 100644 (file)
 //! librustdoc, it is not production quality at all.
 
 #![allow(non_camel_case_types)]
-use std::path::Path;
-
-pub use self::imp::Lock;
+#![allow(nonstandard_style)]
 
-#[cfg(unix)]
-mod imp {
-    use std::ffi::{CString, OsStr};
-    use std::os::unix::prelude::*;
-    use std::path::Path;
-    use std::io;
-    use libc;
+use std::io;
+use std::path::Path;
 
-    #[cfg(any(target_os = "linux", target_os = "android"))]
-    mod os {
+cfg_if! {
+    if #[cfg(unix)] {
+        use std::ffi::{CString, OsStr};
+        use std::os::unix::prelude::*;
         use libc;
 
-        #[repr(C)]
-        pub struct flock {
-            pub l_type: libc::c_short,
-            pub l_whence: libc::c_short,
-            pub l_start: libc::off_t,
-            pub l_len: libc::off_t,
-            pub l_pid: libc::pid_t,
-
-            // not actually here, but brings in line with freebsd
-            pub l_sysid: libc::c_int,
-        }
+        #[cfg(any(target_os = "linux", target_os = "android"))]
+        mod os {
+            use libc;
 
-        pub const F_RDLCK: libc::c_short = 0;
-        pub const F_WRLCK: libc::c_short = 1;
-        pub const F_UNLCK: libc::c_short = 2;
-        pub const F_SETLK: libc::c_int = 6;
-        pub const F_SETLKW: libc::c_int = 7;
-    }
+            #[repr(C)]
+            pub struct flock {
+                pub l_type: libc::c_short,
+                pub l_whence: libc::c_short,
+                pub l_start: libc::off_t,
+                pub l_len: libc::off_t,
+                pub l_pid: libc::pid_t,
 
-    #[cfg(target_os = "freebsd")]
-    mod os {
-        use libc;
+                // not actually here, but brings in line with freebsd
+                pub l_sysid: libc::c_int,
+            }
 
-        #[repr(C)]
-        pub struct flock {
-            pub l_start: libc::off_t,
-            pub l_len: libc::off_t,
-            pub l_pid: libc::pid_t,
-            pub l_type: libc::c_short,
-            pub l_whence: libc::c_short,
-            pub l_sysid: libc::c_int,
+            pub const F_RDLCK: libc::c_short = 0;
+            pub const F_WRLCK: libc::c_short = 1;
+            pub const F_UNLCK: libc::c_short = 2;
+            pub const F_SETLK: libc::c_int = 6;
+            pub const F_SETLKW: libc::c_int = 7;
         }
 
-        pub const F_RDLCK: libc::c_short = 1;
-        pub const F_UNLCK: libc::c_short = 2;
-        pub const F_WRLCK: libc::c_short = 3;
-        pub const F_SETLK: libc::c_int = 12;
-        pub const F_SETLKW: libc::c_int = 13;
-    }
-
-    #[cfg(any(target_os = "dragonfly",
-              target_os = "bitrig",
-              target_os = "netbsd",
-              target_os = "openbsd"))]
-    mod os {
-        use libc;
+        #[cfg(target_os = "freebsd")]
+        mod os {
+            use libc;
+
+            #[repr(C)]
+            pub struct flock {
+                pub l_start: libc::off_t,
+                pub l_len: libc::off_t,
+                pub l_pid: libc::pid_t,
+                pub l_type: libc::c_short,
+                pub l_whence: libc::c_short,
+                pub l_sysid: libc::c_int,
+            }
 
-        #[repr(C)]
-        pub struct flock {
-            pub l_start: libc::off_t,
-            pub l_len: libc::off_t,
-            pub l_pid: libc::pid_t,
-            pub l_type: libc::c_short,
-            pub l_whence: libc::c_short,
-
-            // not actually here, but brings in line with freebsd
-            pub l_sysid: libc::c_int,
+            pub const F_RDLCK: libc::c_short = 1;
+            pub const F_UNLCK: libc::c_short = 2;
+            pub const F_WRLCK: libc::c_short = 3;
+            pub const F_SETLK: libc::c_int = 12;
+            pub const F_SETLKW: libc::c_int = 13;
         }
 
-        pub const F_RDLCK: libc::c_short = 1;
-        pub const F_UNLCK: libc::c_short = 2;
-        pub const F_WRLCK: libc::c_short = 3;
-        pub const F_SETLK: libc::c_int = 8;
-        pub const F_SETLKW: libc::c_int = 9;
-    }
-
-    #[cfg(target_os = "haiku")]
-    mod os {
-        use libc;
+        #[cfg(any(target_os = "dragonfly",
+                  target_os = "bitrig",
+                  target_os = "netbsd",
+                  target_os = "openbsd"))]
+        mod os {
+            use libc;
+
+            #[repr(C)]
+            pub struct flock {
+                pub l_start: libc::off_t,
+                pub l_len: libc::off_t,
+                pub l_pid: libc::pid_t,
+                pub l_type: libc::c_short,
+                pub l_whence: libc::c_short,
+
+                // not actually here, but brings in line with freebsd
+                pub l_sysid: libc::c_int,
+            }
 
-        #[repr(C)]
-        pub struct flock {
-            pub l_type: libc::c_short,
-            pub l_whence: libc::c_short,
-            pub l_start: libc::off_t,
-            pub l_len: libc::off_t,
-            pub l_pid: libc::pid_t,
-
-            // not actually here, but brings in line with freebsd
-            pub l_sysid: libc::c_int,
+            pub const F_RDLCK: libc::c_short = 1;
+            pub const F_UNLCK: libc::c_short = 2;
+            pub const F_WRLCK: libc::c_short = 3;
+            pub const F_SETLK: libc::c_int = 8;
+            pub const F_SETLKW: libc::c_int = 9;
         }
 
-        pub const F_RDLCK: libc::c_short = 0x0040;
-        pub const F_UNLCK: libc::c_short = 0x0200;
-        pub const F_WRLCK: libc::c_short = 0x0400;
-        pub const F_SETLK: libc::c_int = 0x0080;
-        pub const F_SETLKW: libc::c_int = 0x0100;
-    }
+        #[cfg(target_os = "haiku")]
+        mod os {
+            use libc;
 
-    #[cfg(any(target_os = "macos", target_os = "ios"))]
-    mod os {
-        use libc;
+            #[repr(C)]
+            pub struct flock {
+                pub l_type: libc::c_short,
+                pub l_whence: libc::c_short,
+                pub l_start: libc::off_t,
+                pub l_len: libc::off_t,
+                pub l_pid: libc::pid_t,
 
-        #[repr(C)]
-        pub struct flock {
-            pub l_start: libc::off_t,
-            pub l_len: libc::off_t,
-            pub l_pid: libc::pid_t,
-            pub l_type: libc::c_short,
-            pub l_whence: libc::c_short,
-
-            // not actually here, but brings in line with freebsd
-            pub l_sysid: libc::c_int,
+                // not actually here, but brings in line with freebsd
+                pub l_sysid: libc::c_int,
+            }
+
+            pub const F_RDLCK: libc::c_short = 0x0040;
+            pub const F_UNLCK: libc::c_short = 0x0200;
+            pub const F_WRLCK: libc::c_short = 0x0400;
+            pub const F_SETLK: libc::c_int = 0x0080;
+            pub const F_SETLKW: libc::c_int = 0x0100;
         }
 
-        pub const F_RDLCK: libc::c_short = 1;
-        pub const F_UNLCK: libc::c_short = 2;
-        pub const F_WRLCK: libc::c_short = 3;
-        pub const F_SETLK: libc::c_int = 8;
-        pub const F_SETLKW: libc::c_int = 9;
-    }
+        #[cfg(any(target_os = "macos", target_os = "ios"))]
+        mod os {
+            use libc;
 
-    #[cfg(target_os = "solaris")]
-    mod os {
-        use libc;
+            #[repr(C)]
+            pub struct flock {
+                pub l_start: libc::off_t,
+                pub l_len: libc::off_t,
+                pub l_pid: libc::pid_t,
+                pub l_type: libc::c_short,
+                pub l_whence: libc::c_short,
 
-        #[repr(C)]
-        pub struct flock {
-            pub l_type: libc::c_short,
-            pub l_whence: libc::c_short,
-            pub l_start: libc::off_t,
-            pub l_len: libc::off_t,
-            pub l_sysid: libc::c_int,
-            pub l_pid: libc::pid_t,
+                // not actually here, but brings in line with freebsd
+                pub l_sysid: libc::c_int,
+            }
+
+            pub const F_RDLCK: libc::c_short = 1;
+            pub const F_UNLCK: libc::c_short = 2;
+            pub const F_WRLCK: libc::c_short = 3;
+            pub const F_SETLK: libc::c_int = 8;
+            pub const F_SETLKW: libc::c_int = 9;
         }
 
-        pub const F_RDLCK: libc::c_short = 1;
-        pub const F_WRLCK: libc::c_short = 2;
-        pub const F_UNLCK: libc::c_short = 3;
-        pub const F_SETLK: libc::c_int = 6;
-        pub const F_SETLKW: libc::c_int = 7;
-    }
+        #[cfg(target_os = "solaris")]
+        mod os {
+            use libc;
+
+            #[repr(C)]
+            pub struct flock {
+                pub l_type: libc::c_short,
+                pub l_whence: libc::c_short,
+                pub l_start: libc::off_t,
+                pub l_len: libc::off_t,
+                pub l_sysid: libc::c_int,
+                pub l_pid: libc::pid_t,
+            }
 
-    #[derive(Debug)]
-    pub struct Lock {
-        fd: libc::c_int,
-    }
+            pub const F_RDLCK: libc::c_short = 1;
+            pub const F_WRLCK: libc::c_short = 2;
+            pub const F_UNLCK: libc::c_short = 3;
+            pub const F_SETLK: libc::c_int = 6;
+            pub const F_SETLKW: libc::c_int = 7;
+        }
 
-    impl Lock {
-        pub fn new(p: &Path,
-                   wait: bool,
-                   create: bool,
-                   exclusive: bool)
-                   -> io::Result<Lock> {
-            let os: &OsStr = p.as_ref();
-            let buf = CString::new(os.as_bytes()).unwrap();
-            let open_flags = if create {
-                libc::O_RDWR | libc::O_CREAT
-            } else {
-                libc::O_RDWR
-            };
-
-            let fd = unsafe {
-                libc::open(buf.as_ptr(), open_flags,
-                           libc::S_IRWXU as libc::c_int)
-            };
-
-            if fd < 0 {
-                return Err(io::Error::last_os_error());
-            }
+        #[derive(Debug)]
+        pub struct Lock {
+            fd: libc::c_int,
+        }
 
-            let lock_type = if exclusive {
-                os::F_WRLCK
-            } else {
-                os::F_RDLCK
-            };
-
-            let flock = os::flock {
-                l_start: 0,
-                l_len: 0,
-                l_pid: 0,
-                l_whence: libc::SEEK_SET as libc::c_short,
-                l_type: lock_type,
-                l_sysid: 0,
-            };
-            let cmd = if wait { os::F_SETLKW } else { os::F_SETLK };
-            let ret = unsafe {
-                libc::fcntl(fd, cmd, &flock)
-            };
-            if ret == -1 {
-                let err = io::Error::last_os_error();
-                unsafe { libc::close(fd); }
-                Err(err)
-            } else {
-                Ok(Lock { fd: fd })
+        impl Lock {
+            pub fn new(p: &Path,
+                       wait: bool,
+                       create: bool,
+                       exclusive: bool)
+                       -> io::Result<Lock> {
+                let os: &OsStr = p.as_ref();
+                let buf = CString::new(os.as_bytes()).unwrap();
+                let open_flags = if create {
+                    libc::O_RDWR | libc::O_CREAT
+                } else {
+                    libc::O_RDWR
+                };
+
+                let fd = unsafe {
+                    libc::open(buf.as_ptr(), open_flags,
+                               libc::S_IRWXU as libc::c_int)
+                };
+
+                if fd < 0 {
+                    return Err(io::Error::last_os_error());
+                }
+
+                let lock_type = if exclusive {
+                    os::F_WRLCK
+                } else {
+                    os::F_RDLCK
+                };
+
+                let flock = os::flock {
+                    l_start: 0,
+                    l_len: 0,
+                    l_pid: 0,
+                    l_whence: libc::SEEK_SET as libc::c_short,
+                    l_type: lock_type,
+                    l_sysid: 0,
+                };
+                let cmd = if wait { os::F_SETLKW } else { os::F_SETLK };
+                let ret = unsafe {
+                    libc::fcntl(fd, cmd, &flock)
+                };
+                if ret == -1 {
+                    let err = io::Error::last_os_error();
+                    unsafe { libc::close(fd); }
+                    Err(err)
+                } else {
+                    Ok(Lock { fd: fd })
+                }
             }
         }
-    }
 
-    impl Drop for Lock {
-        fn drop(&mut self) {
-            let flock = os::flock {
-                l_start: 0,
-                l_len: 0,
-                l_pid: 0,
-                l_whence: libc::SEEK_SET as libc::c_short,
-                l_type: os::F_UNLCK,
-                l_sysid: 0,
-            };
-            unsafe {
-                libc::fcntl(self.fd, os::F_SETLK, &flock);
-                libc::close(self.fd);
+        impl Drop for Lock {
+            fn drop(&mut self) {
+                let flock = os::flock {
+                    l_start: 0,
+                    l_len: 0,
+                    l_pid: 0,
+                    l_whence: libc::SEEK_SET as libc::c_short,
+                    l_type: os::F_UNLCK,
+                    l_sysid: 0,
+                };
+                unsafe {
+                    libc::fcntl(self.fd, os::F_SETLK, &flock);
+                    libc::close(self.fd);
+                }
             }
         }
-    }
-}
+    } else if #[cfg(windows)] {
+        use std::mem;
+        use std::os::windows::prelude::*;
+        use std::os::windows::raw::HANDLE;
+        use std::fs::{File, OpenOptions};
+        use std::os::raw::{c_ulong, c_int};
 
-#[cfg(windows)]
-#[allow(nonstandard_style)]
-mod imp {
-    use std::io;
-    use std::mem;
-    use std::os::windows::prelude::*;
-    use std::os::windows::raw::HANDLE;
-    use std::path::Path;
-    use std::fs::{File, OpenOptions};
-    use std::os::raw::{c_ulong, c_int};
-
-    type DWORD = c_ulong;
-    type BOOL = c_int;
-    type ULONG_PTR = usize;
-
-    type LPOVERLAPPED = *mut OVERLAPPED;
-    const LOCKFILE_EXCLUSIVE_LOCK: DWORD = 0x0000_0002;
-    const LOCKFILE_FAIL_IMMEDIATELY: DWORD = 0x0000_0001;
-
-    const FILE_SHARE_DELETE: DWORD = 0x4;
-    const FILE_SHARE_READ: DWORD = 0x1;
-    const FILE_SHARE_WRITE: DWORD = 0x2;
-
-    #[repr(C)]
-    struct OVERLAPPED {
-        Internal: ULONG_PTR,
-        InternalHigh: ULONG_PTR,
-        Offset: DWORD,
-        OffsetHigh: DWORD,
-        hEvent: HANDLE,
-    }
+        type DWORD = c_ulong;
+        type BOOL = c_int;
+        type ULONG_PTR = usize;
 
-    extern "system" {
-        fn LockFileEx(hFile: HANDLE,
-                      dwFlags: DWORD,
-                      dwReserved: DWORD,
-                      nNumberOfBytesToLockLow: DWORD,
-                      nNumberOfBytesToLockHigh: DWORD,
-                      lpOverlapped: LPOVERLAPPED) -> BOOL;
-    }
+        type LPOVERLAPPED = *mut OVERLAPPED;
+        const LOCKFILE_EXCLUSIVE_LOCK: DWORD = 0x0000_0002;
+        const LOCKFILE_FAIL_IMMEDIATELY: DWORD = 0x0000_0001;
 
-    #[derive(Debug)]
-    pub struct Lock {
-        _file: File,
-    }
+        const FILE_SHARE_DELETE: DWORD = 0x4;
+        const FILE_SHARE_READ: DWORD = 0x1;
+        const FILE_SHARE_WRITE: DWORD = 0x2;
 
-    impl Lock {
-        pub fn new(p: &Path,
-                   wait: bool,
-                   create: bool,
-                   exclusive: bool)
-                   -> io::Result<Lock> {
-            assert!(p.parent().unwrap().exists(),
-                "Parent directory of lock-file must exist: {}",
-                p.display());
-
-            let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
-
-            let mut open_options = OpenOptions::new();
-            open_options.read(true)
-                        .share_mode(share_mode);
-
-            if create {
-                open_options.create(true)
-                            .write(true);
-            }
+        #[repr(C)]
+        struct OVERLAPPED {
+            Internal: ULONG_PTR,
+            InternalHigh: ULONG_PTR,
+            Offset: DWORD,
+            OffsetHigh: DWORD,
+            hEvent: HANDLE,
+        }
 
-            debug!("Attempting to open lock file `{}`", p.display());
-            let file = match open_options.open(p) {
-                Ok(file) => {
-                    debug!("Lock file opened successfully");
-                    file
-                }
-                Err(err) => {
-                    debug!("Error opening lock file: {}", err);
-                    return Err(err)
-                }
-            };
+        extern "system" {
+            fn LockFileEx(hFile: HANDLE,
+                          dwFlags: DWORD,
+                          dwReserved: DWORD,
+                          nNumberOfBytesToLockLow: DWORD,
+                          nNumberOfBytesToLockHigh: DWORD,
+                          lpOverlapped: LPOVERLAPPED) -> BOOL;
+        }
 
-            let ret = unsafe {
-                let mut overlapped: OVERLAPPED = mem::zeroed();
+        #[derive(Debug)]
+        pub struct Lock {
+            _file: File,
+        }
 
-                let mut dwFlags = 0;
-                if !wait {
-                    dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
+        impl Lock {
+            pub fn new(p: &Path,
+                       wait: bool,
+                       create: bool,
+                       exclusive: bool)
+                       -> io::Result<Lock> {
+                assert!(p.parent().unwrap().exists(),
+                    "Parent directory of lock-file must exist: {}",
+                    p.display());
+
+                let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
+
+                let mut open_options = OpenOptions::new();
+                open_options.read(true)
+                            .share_mode(share_mode);
+
+                if create {
+                    open_options.create(true)
+                                .write(true);
                 }
 
-                if exclusive {
-                    dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
+                debug!("Attempting to open lock file `{}`", p.display());
+                let file = match open_options.open(p) {
+                    Ok(file) => {
+                        debug!("Lock file opened successfully");
+                        file
+                    }
+                    Err(err) => {
+                        debug!("Error opening lock file: {}", err);
+                        return Err(err)
+                    }
+                };
+
+                let ret = unsafe {
+                    let mut overlapped: OVERLAPPED = mem::zeroed();
+
+                    let mut dwFlags = 0;
+                    if !wait {
+                        dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
+                    }
+
+                    if exclusive {
+                        dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
+                    }
+
+                    debug!("Attempting to acquire lock on lock file `{}`",
+                           p.display());
+                    LockFileEx(file.as_raw_handle(),
+                               dwFlags,
+                               0,
+                               0xFFFF_FFFF,
+                               0xFFFF_FFFF,
+                               &mut overlapped)
+                };
+                if ret == 0 {
+                    let err = io::Error::last_os_error();
+                    debug!("Failed acquiring file lock: {}", err);
+                    Err(err)
+                } else {
+                    debug!("Successfully acquired lock.");
+                    Ok(Lock { _file: file })
                 }
+            }
+        }
 
-                debug!("Attempting to acquire lock on lock file `{}`",
-                       p.display());
-                LockFileEx(file.as_raw_handle(),
-                           dwFlags,
-                           0,
-                           0xFFFF_FFFF,
-                           0xFFFF_FFFF,
-                           &mut overlapped)
-            };
-            if ret == 0 {
-                let err = io::Error::last_os_error();
-                debug!("Failed acquiring file lock: {}", err);
-                Err(err)
-            } else {
-                debug!("Successfully acquired lock.");
-                Ok(Lock { _file: file })
+        // Note that we don't need a Drop impl on the Windows: The file is unlocked
+        // automatically when it's closed.
+    } else {
+        #[derive(Debug)]
+        pub struct Lock(());
+
+        impl Lock {
+            pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool)
+                -> io::Result<Lock>
+            {
+                let msg = "file locks not supported on this platform";
+                Err(io::Error::new(io::ErrorKind::Other, msg))
             }
         }
     }
-
-    // Note that we don't need a Drop impl on the Windows: The file is unlocked
-    // automatically when it's closed.
 }
 
-impl imp::Lock {
+impl Lock {
     pub fn panicking_new(p: &Path,
                          wait: bool,
                          create: bool,
index baac75658686545e0eddd4f3ee84b7163b4fc7eb..c31321fa374a48cc7d7a678f39797bc2867f3753 100644 (file)
@@ -30,7 +30,7 @@
 //! the field `next_edge`). Each of those fields is an array that should
 //! be indexed by the direction (see the type `Direction`).
 
-use bitvec::BitArray;
+use bit_set::BitSet;
 use std::fmt::Debug;
 use std::usize;
 use snapshot_vec::{SnapshotVec, SnapshotVecDelegate};
@@ -266,7 +266,7 @@ pub fn nodes_in_postorder(
         direction: Direction,
         entry_node: NodeIndex,
     ) -> Vec<NodeIndex> {
-        let mut visited = BitArray::new(self.len_nodes());
+        let mut visited = BitSet::new_empty(self.len_nodes());
         let mut stack = vec![];
         let mut result = Vec::with_capacity(self.len_nodes());
         let mut push_node = |stack: &mut Vec<_>, node: NodeIndex| {
@@ -348,7 +348,7 @@ pub struct DepthFirstTraversal<'g, N, E>
 {
     graph: &'g Graph<N, E>,
     stack: Vec<NodeIndex>,
-    visited: BitArray<usize>,
+    visited: BitSet<usize>,
     direction: Direction,
 }
 
@@ -358,7 +358,7 @@ pub fn with_start_node(
         start_node: NodeIndex,
         direction: Direction,
     ) -> Self {
-        let mut visited = BitArray::new(graph.len_nodes());
+        let mut visited = BitSet::new_empty(graph.len_nodes());
         visited.insert(start_node.node_id());
         DepthFirstTraversal {
             graph,
diff --git a/src/librustc_data_structures/indexed_set.rs b/src/librustc_data_structures/indexed_set.rs
deleted file mode 100644 (file)
index 65fdf10..0000000
+++ /dev/null
@@ -1,498 +0,0 @@
-// Copyright 2012-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 array_vec::ArrayVec;
-use std::fmt;
-use std::iter;
-use std::marker::PhantomData;
-use std::mem;
-use std::slice;
-use bitslice::{BitSlice, Word};
-use bitslice::{bitwise, Union, Subtract, Intersect};
-use indexed_vec::Idx;
-use rustc_serialize;
-
-/// 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 IdxSet<T: Idx> {
-    _pd: PhantomData<fn(&T)>,
-    bits: Vec<Word>,
-}
-
-impl<T: Idx> Clone for IdxSet<T> {
-    fn clone(&self) -> Self {
-        IdxSet { _pd: PhantomData, bits: self.bits.clone() }
-    }
-}
-
-impl<T: Idx> rustc_serialize::Encodable for IdxSet<T> {
-    fn encode<E: rustc_serialize::Encoder>(&self,
-                                     encoder: &mut E)
-                                     -> Result<(), E::Error> {
-        self.bits.encode(encoder)
-    }
-}
-
-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(IdxSet {
-            _pd: PhantomData,
-            bits: words,
-        })
-    }
-}
-
-const BITS_PER_WORD: usize = mem::size_of::<Word>() * 8;
-
-impl<T: Idx> fmt::Debug for IdxSet<T> {
-    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
-        w.debug_list()
-         .entries(self.iter())
-         .finish()
-    }
-}
-
-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..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(domain_size: usize) -> Self {
-        Self::new(0, domain_size)
-    }
-
-    /// Duplicates as a hybrid set.
-    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 domain_size = self.bits.len() * BITS_PER_WORD;
-
-        // Note: we currently don't bother trying to make a Sparse set.
-        HybridIdxSet::Dense(self.to_owned(), domain_size)
-    }
-
-    /// Removes all elements
-    pub fn clear(&mut self) {
-        for b in &mut self.bits {
-            *b = 0;
-        }
-    }
-
-    /// 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(domain_size);
-    }
-
-    /// 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 = domain_size / BITS_PER_WORD;
-
-        // all the blocks above it have to be completely cleared.
-        if trim_block < self.bits.len() {
-            for b in &mut self.bits[trim_block+1..] {
-                *b = 0;
-            }
-
-            // at that block, the `domain_size % BITS_PER_WORD` LSBs
-            // should remain.
-            let remaining_bits = domain_size % BITS_PER_WORD;
-            let mask = (1<<remaining_bits)-1;
-            self.bits[trim_block] &= mask;
-        }
-    }
-
-    /// Removes `elem` from the set `self`; returns true iff this changed `self`.
-    pub fn remove(&mut self, elem: &T) -> bool {
-        self.bits.clear_bit(elem.index())
-    }
-
-    /// Adds `elem` to the set `self`; returns true iff this changed `self`.
-    pub fn add(&mut self, elem: &T) -> bool {
-        self.bits.set_bit(elem.index())
-    }
-
-    /// Returns true iff set `self` contains `elem`.
-    pub fn contains(&self, elem: &T) -> bool {
-        self.bits.get_bit(elem.index())
-    }
-
-    pub fn words(&self) -> &[Word] {
-        &self.bits
-    }
-
-    pub fn words_mut(&mut self) -> &mut [Word] {
-        &mut self.bits
-    }
-
-    /// Efficiently overwrite `self` with `other`. Panics if `self` and `other`
-    /// don't have the same length.
-    pub fn overwrite(&mut self, other: &IdxSet<T>) {
-        self.words_mut().clone_from_slice(other.words());
-    }
-
-    /// Set `self = self | other` and return true if `self` changed
-    /// (i.e., if new bits were added).
-    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: &impl SubtractFromIdxSet<T>) -> bool {
-        other.subtract_from(self)
-    }
-
-    /// Set `self = self & other` and return true if `self` changed.
-    /// (i.e., if any bits were removed).
-    pub fn intersect(&mut self, other: &IdxSet<T>) -> bool {
-        bitwise(self.words_mut(), other.words(), &Intersect)
-    }
-
-    pub fn iter(&self) -> Iter<T> {
-        Iter {
-            cur: None,
-            iter: self.words().iter().enumerate(),
-            _pd: PhantomData,
-        }
-    }
-}
-
-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>>,
-    _pd: PhantomData<fn(&T)>,
-}
-
-impl<'a, T: Idx> Iterator for Iter<'a, T> {
-    type Item = T;
-
-    fn next(&mut self) -> Option<T> {
-        loop {
-            if let Some((ref mut word, offset)) = self.cur {
-                let bit_pos = word.trailing_zeros() as usize;
-                if bit_pos != BITS_PER_WORD {
-                    let bit = 1 << bit_pos;
-                    *word ^= bit;
-                    return Some(T::new(bit_pos + offset))
-                }
-            }
-
-            let (i, word) = self.iter.next()?;
-            self.cur = Some((*word, BITS_PER_WORD * i));
-        }
-    }
-}
-
-const SPARSE_MAX: usize = 8;
-
-/// A sparse index set with a maximum of SPARSE_MAX elements. Used by
-/// HybridIdxSet; do not use directly.
-///
-/// The elements are stored as an unsorted vector with no duplicates.
-#[derive(Clone, Debug)]
-pub struct SparseIdxSet<T: Idx>(ArrayVec<[T; SPARSE_MAX]>);
-
-impl<T: Idx> SparseIdxSet<T> {
-    fn new() -> Self {
-        SparseIdxSet(ArrayVec::new())
-    }
-
-    fn len(&self) -> usize {
-        self.0.len()
-    }
-
-    fn contains(&self, elem: &T) -> bool {
-        self.0.contains(elem)
-    }
-
-    fn add(&mut self, elem: &T) -> bool {
-        // Ensure there are no duplicates.
-        if self.0.contains(elem) {
-            false
-        } else {
-            self.0.push(*elem);
-            true
-        }
-    }
-
-    fn remove(&mut self, elem: &T) -> bool {
-        if let Some(i) = self.0.iter().position(|e| e == elem) {
-            // Swap the found element to the end, then pop it.
-            let len = self.0.len();
-            self.0.swap(i, len - 1);
-            self.0.pop();
-            true
-        } else {
-            false
-        }
-    }
-
-    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);
-        }
-        dense
-    }
-
-    fn iter(&self) -> SparseIter<T> {
-        SparseIter {
-            iter: self.0.iter(),
-        }
-    }
-}
-
-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>,
-}
-
-impl<'a, T: Idx> Iterator for SparseIter<'a, T> {
-    type Item = T;
-
-    fn next(&mut self) -> Option<T> {
-        self.iter.next().map(|e| *e)
-    }
-}
-
-/// 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 `domain_size`, and are cleared frequently.
-#[derive(Clone, Debug)]
-pub enum HybridIdxSet<T: Idx> {
-    Sparse(SparseIdxSet<T>, usize),
-    Dense(IdxSet<T>, usize),
-}
-
-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 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 {
-            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 {
-            HybridIdxSet::Sparse(sparse, _) if sparse.len() < SPARSE_MAX => {
-                // The set is sparse and has space for `elem`.
-                sparse.add(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
-            }
-            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 = HybridIdxSet::Sparse(SparseIdxSet::new(), 0);
-                match mem::replace(self, dummy) {
-                    HybridIdxSet::Sparse(sparse, domain_size) => {
-                        let mut dense = sparse.to_dense(domain_size);
-                        let changed = dense.add(elem);
-                        assert!(changed);
-                        mem::replace(self, HybridIdxSet::Dense(dense, domain_size));
-                        changed
-                    }
-                    _ => panic!("impossible"),
-                }
-            }
-
-            HybridIdxSet::Dense(dense, _) => dense.add(elem),
-        }
-    }
-
-    /// Removes `elem` from the set `self`.
-    pub fn remove(&mut self, elem: &T) -> bool {
-        // Note: we currently don't bother going from Dense back to Sparse.
-        match self {
-            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) -> IdxSet<T> {
-        match self {
-            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 {
-            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),
-        }
-    }
-}
-
-pub enum HybridIter<'a, T: Idx> {
-    Sparse(SparseIter<'a, T>),
-    Dense(Iter<'a, T>),
-}
-
-impl<'a, T: Idx> Iterator for HybridIter<'a, T> {
-    type Item = T;
-
-    fn next(&mut self) -> Option<T> {
-        match self {
-            HybridIter::Sparse(sparse) => sparse.next(),
-            HybridIter::Dense(dense) => dense.next(),
-        }
-    }
-}
-
-#[test]
-fn test_trim_to() {
-    use std::cmp;
-
-    for i in 0..256 {
-        let mut idx_buf: IdxSet<usize> = IdxSet::new_filled(128);
-        idx_buf.trim_to(i);
-
-        let elems: Vec<usize> = idx_buf.iter().collect();
-        let expected: Vec<usize> = (0..cmp::min(i, 128)).collect();
-        assert_eq!(elems, expected);
-    }
-}
-
-#[test]
-fn test_set_up_to() {
-    for i in 0..128 {
-        for mut idx_buf in
-            vec![IdxSet::new_empty(128), IdxSet::new_filled(128)]
-            .into_iter()
-        {
-            idx_buf.set_up_to(i);
-
-            let elems: Vec<usize> = idx_buf.iter().collect();
-            let expected: Vec<usize> = (0..i).collect();
-            assert_eq!(elems, expected);
-        }
-    }
-}
-
-#[test]
-fn test_new_filled() {
-    for i in 0..128 {
-        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 186bc6d43ccc560a0afb47d0fd27ee926167357a..2f11fea46d69a6c6db09c10ea0a5c0d32e4a6546 100644 (file)
@@ -72,7 +72,8 @@ macro_rules! newtype_index {
         newtype_index!(
             // Leave out derives marker so we can use its absence to ensure it comes first
             @type         [$name]
-            @max          [::std::u32::MAX - 1]
+            // shave off 256 indices at the end to allow space for packing these indices into enums
+            @max          [0xFFFF_FF00]
             @vis          [$v]
             @debug_format ["{}"]);
     );
@@ -82,7 +83,8 @@ macro_rules! newtype_index {
         newtype_index!(
             // Leave out derives marker so we can use its absence to ensure it comes first
             @type         [$name]
-            @max          [::std::u32::MAX - 1]
+            // shave off 256 indices at the end to allow space for packing these indices into enums
+            @max          [0xFFFF_FF00]
             @vis          [$v]
             @debug_format ["{}"]
                           $($tokens)+);
@@ -97,6 +99,7 @@ macro_rules! newtype_index {
      @vis          [$v:vis]
      @debug_format [$debug_format:tt]) => (
         #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, $($derives),*)]
+        #[rustc_layout_scalar_valid_range_end($max)]
         $v struct $type {
             private: u32
         }
index 87a033138c32e1e49be0e416e19097e3d1c4e5ce..70b960ac351c0031069b153b00cff8cedfb5402d 100644 (file)
 pub use rustc_serialize::hex::ToHex;
 
 pub mod svh;
-pub mod array_vec;
 pub mod base_n;
-pub mod bitslice;
-pub mod bitvec;
+pub mod bit_set;
 pub mod const_cstr;
 pub mod flock;
 pub mod fx;
 pub mod graph;
-pub mod indexed_set;
 pub mod indexed_vec;
 pub mod obligation_forest;
 pub mod owning_ref;
index 215c44dec6913365cef39f528e2e005e0d4dbb1a..c85d771a1810671f997ed5487aa0798e8c4c0ff3 100644 (file)
@@ -457,7 +457,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 
-impl<I: ::indexed_vec::Idx, CTX> HashStable<CTX> for ::indexed_set::IdxSet<I>
+impl<I: ::indexed_vec::Idx, CTX> HashStable<CTX> for ::bit_set::BitSet<I>
 {
     fn hash_stable<W: StableHasherResult>(&self,
                                           ctx: &mut CTX,
index 2acc29acb0caafd0325520d054fd1c18969d3127..1512b30eeadaa932175c7382305f022989ab1ca8 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use bitvec::BitMatrix;
+use bit_set::BitMatrix;
 use fx::FxHashMap;
 use sync::Lock;
 use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
@@ -279,7 +279,7 @@ pub fn minimal_upper_bounds(&self, a: &T, b: &T) -> Vec<&T> {
             //
             // This same algorithm is used in `parents` below.
 
-            let mut candidates = closure.intersection(a.0, b.0); // (1)
+            let mut candidates = closure.intersect_rows(a.0, b.0); // (1)
             pare_down(&mut candidates, closure); // (2)
             candidates.reverse(); // (3a)
             pare_down(&mut candidates, closure); // (3b)
@@ -321,7 +321,7 @@ pub fn parents(&self, a: &T) -> Vec<&T> {
         // with a slight tweak. In the case where `a R a`, we remove
         // that from the set of candidates.
         let ancestors = self.with_closure(|closure| {
-            let mut ancestors = closure.intersection(a.0, a.0);
+            let mut ancestors = closure.intersect_rows(a.0, a.0);
 
             // Remove anything that can reach `a`. If this is a
             // reflexive relation, this will include `a` itself.
@@ -366,10 +366,10 @@ fn compute_closure(&self) -> BitMatrix<usize, usize> {
             changed = false;
             for edge in &self.edges {
                 // add an edge from S -> T
-                changed |= matrix.add(edge.source.0, edge.target.0);
+                changed |= matrix.insert(edge.source.0, edge.target.0);
 
                 // add all outgoing edges from T into S
-                changed |= matrix.merge(edge.target.0, edge.source.0);
+                changed |= matrix.union_rows(edge.target.0, edge.source.0);
             }
         }
         matrix
index 0c8ec753a18f6e6e126e7d263d4fce910c7c5506..af9ed9306ebb2f29be1396d21a22a64c9a097db8 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use indexed_set::IdxSet;
+use bit_set::BitSet;
 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: IdxSet<T>,
+    set: BitSet<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: IdxSet::new_filled(len),
+            set: BitSet::new_filled(len),
         }
     }
 
@@ -38,14 +38,14 @@ pub fn with_all(len: usize) -> Self {
     pub fn with_none(len: usize) -> Self {
         WorkQueue {
             deque: VecDeque::with_capacity(len),
-            set: IdxSet::new_empty(len),
+            set: BitSet::new_empty(len),
         }
     }
 
     /// Attempt to enqueue `element` in the work queue. Returns false if it was already present.
     #[inline]
     pub fn insert(&mut self, element: T) -> bool {
-        if self.set.add(&element) {
+        if self.set.insert(element) {
             self.deque.push_back(element);
             true
         } else {
@@ -57,7 +57,7 @@ pub fn insert(&mut self, element: T) -> bool {
     #[inline]
     pub fn pop(&mut self) -> Option<T> {
         if let Some(element) = self.deque.pop_front() {
-            self.set.remove(&element);
+            self.set.remove(element);
             Some(element)
         } else {
             None
index d27b0856c1533358ba39d074ebc286d1b85a1239..7fb66ea97f26ba05a92e3f60a0140f0cbdc07777 100644 (file)
@@ -57,6 +57,8 @@
 use syntax::fold::Folder;
 use syntax::parse::{self, PResult};
 use syntax::util::node_count::NodeCounter;
+use syntax::util::lev_distance::find_best_match_for_name;
+use syntax::symbol::Symbol;
 use syntax_pos::{FileName, hygiene};
 use syntax_ext;
 
@@ -1508,13 +1510,45 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
                     Some(ref n) if *n == "staticlib" => Some(config::CrateType::Staticlib),
                     Some(ref n) if *n == "proc-macro" => Some(config::CrateType::ProcMacro),
                     Some(ref n) if *n == "bin" => Some(config::CrateType::Executable),
-                    Some(_) => {
-                        session.buffer_lint(
-                            lint::builtin::UNKNOWN_CRATE_TYPES,
-                            ast::CRATE_NODE_ID,
-                            a.span,
-                            "invalid `crate_type` value",
-                        );
+                    Some(ref n) => {
+                        let crate_types = vec![
+                            Symbol::intern("rlib"),
+                            Symbol::intern("dylib"),
+                            Symbol::intern("cdylib"),
+                            Symbol::intern("lib"),
+                            Symbol::intern("staticlib"),
+                            Symbol::intern("proc-macro"),
+                            Symbol::intern("bin")
+                        ];
+                        if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().node {
+                            let span = spanned.span;
+                            let lev_candidate = find_best_match_for_name(
+                                crate_types.iter(),
+                                &n.as_str(),
+                                None
+                            );
+                            if let Some(candidate) = lev_candidate {
+                                session.buffer_lint_with_diagnostic(
+                                    lint::builtin::UNKNOWN_CRATE_TYPES,
+                                    ast::CRATE_NODE_ID,
+                                    span,
+                                    "invalid `crate_type` value",
+                                    lint::builtin::BuiltinLintDiagnostics::
+                                        UnknownCrateTypes(
+                                            span,
+                                            "did you mean".to_string(),
+                                            format!("\"{}\"", candidate)
+                                        )
+                                );
+                            } else {
+                                session.buffer_lint(
+                                    lint::builtin::UNKNOWN_CRATE_TYPES,
+                                    ast::CRATE_NODE_ID,
+                                    span,
+                                    "invalid `crate_type` value"
+                                );
+                            }
+                        }
                         None
                     }
                     _ => {
index 57c00f252ef16f0caa647db89595d5453f776283..0a7bd3d97022dbc241b4d023be2a1b66cff00bee 100644 (file)
@@ -198,7 +198,7 @@ pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
 
     pub fn create_region_hierarchy(&mut self, rh: &RH,
                                    parent: (region::Scope, region::ScopeDepth)) {
-        let me = region::Scope::Node(rh.id);
+        let me = region::Scope { id: rh.id, data: region::ScopeData::Node };
         self.region_scope_tree.record_scope_parent(me, Some(parent));
         for child_rh in rh.sub {
             self.create_region_hierarchy(child_rh, (me, parent.1 + 1));
@@ -209,7 +209,10 @@ pub fn create_simple_region_hierarchy(&mut self) {
         // creates a region hierarchy where 1 is root, 10 and 11 are
         // children of 1, etc
 
-        let dscope = region::Scope::Destruction(hir::ItemLocalId(1));
+        let dscope = region::Scope {
+            id: hir::ItemLocalId(1),
+            data: region::ScopeData::Destruction
+        };
         self.region_scope_tree.record_scope_parent(dscope, None);
         self.create_region_hierarchy(&RH {
             id: hir::ItemLocalId(1),
@@ -309,7 +312,7 @@ pub fn t_fn(&self, input_tys: &[Ty<'tcx>], output_ty: Ty<'tcx>) -> Ty<'tcx> {
     }
 
     pub fn t_nil(&self) -> Ty<'tcx> {
-        self.infcx.tcx.mk_nil()
+        self.infcx.tcx.mk_unit()
     }
 
     pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> {
@@ -355,7 +358,10 @@ pub fn t_rptr_late_bound_with_debruijn(&self,
     }
 
     pub fn t_rptr_scope(&self, id: u32) -> Ty<'tcx> {
-        let r = ty::ReScope(region::Scope::Node(hir::ItemLocalId(id)));
+        let r = ty::ReScope(region::Scope {
+            id: hir::ItemLocalId(id),
+            data: region::ScopeData::Node
+        });
         self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize)
     }
 
index 101ca0650c8a4247d281eb8d06534c52c3105b99..b24f8ddf4d9f7371621d5897a3573eb4bbc3a915 100644 (file)
@@ -9,6 +9,7 @@ path = "lib.rs"
 crate-type = ["dylib"]
 
 [dependencies]
+log = "0.4"
 serialize = { path = "../libserialize" }
 syntax_pos = { path = "../libsyntax_pos" }
 rustc_data_structures = { path = "../librustc_data_structures" }
index 825e31539c8bedfe511056858a3182fc10836e3c..2799f2cc81f5ab0648d078f0d19d6fdc387356ce 100644 (file)
@@ -232,6 +232,7 @@ pub fn span_help<S: Into<MultiSpan>>(&mut self,
     /// inline it will only show the text message and not the text.
     ///
     /// See `CodeSuggestion` for more information.
+    #[deprecated(note = "Use `span_suggestion_short_with_applicability`")]
     pub fn span_suggestion_short(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
         self.suggestions.push(CodeSuggestion {
             substitutions: vec![Substitution {
@@ -263,6 +264,7 @@ pub fn span_suggestion_short(&mut self, sp: Span, msg: &str, suggestion: String)
     /// * may contain a name of a function, variable or type, but not whole expressions
     ///
     /// See `CodeSuggestion` for more information.
+    #[deprecated(note = "Use `span_suggestion_with_applicability`")]
     pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
         self.suggestions.push(CodeSuggestion {
             substitutions: vec![Substitution {
@@ -278,10 +280,11 @@ pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &m
         self
     }
 
-    pub fn multipart_suggestion(
+    pub fn multipart_suggestion_with_applicability(
         &mut self,
         msg: &str,
         suggestion: Vec<(Span, String)>,
+        applicability: Applicability,
     ) -> &mut Self {
         self.suggestions.push(CodeSuggestion {
             substitutions: vec![Substitution {
@@ -292,12 +295,26 @@ pub fn multipart_suggestion(
             }],
             msg: msg.to_owned(),
             show_code_when_inline: true,
-            applicability: Applicability::Unspecified,
+            applicability,
         });
         self
     }
 
+    #[deprecated(note = "Use `multipart_suggestion_with_applicability`")]
+    pub fn multipart_suggestion(
+        &mut self,
+        msg: &str,
+        suggestion: Vec<(Span, String)>,
+    ) -> &mut Self {
+        self.multipart_suggestion_with_applicability(
+            msg,
+            suggestion,
+            Applicability::Unspecified,
+        )
+    }
+
     /// Prints out a message with multiple suggested edits of the code.
+    #[deprecated(note = "Use `span_suggestions_with_applicability`")]
     pub fn span_suggestions(&mut self, sp: Span, msg: &str, suggestions: Vec<String>) -> &mut Self {
         self.suggestions.push(CodeSuggestion {
             substitutions: suggestions.into_iter().map(|snippet| Substitution {
index 1b34898b99084e20f6ddf15b46080f1666d3d8fe..60a68b1e496620a64106ff82659a8a90ebf1867e 100644 (file)
 use syntax_pos::{MultiSpan, Span};
 
 /// Used for emitting structured error messages and other diagnostic information.
+///
+/// If there is some state in a downstream crate you would like to
+/// access in the methods of `DiagnosticBuilder` here, consider
+/// extending `HandlerFlags`, accessed via `self.handler.flags`.
 #[must_use]
 #[derive(Clone)]
 pub struct DiagnosticBuilder<'a> {
@@ -39,16 +43,18 @@ pub struct DiagnosticBuilder<'a> {
 /// it easy to declare such methods on the builder.
 macro_rules! forward {
     // Forward pattern for &self -> &Self
-    (pub fn $n:ident(&self, $($name:ident: $ty:ty),*) -> &Self) => {
+    (pub fn $n:ident(&self, $($name:ident: $ty:ty),* $(,)*) -> &Self) => {
         pub fn $n(&self, $($name: $ty),*) -> &Self {
+            #[allow(deprecated)]
             self.diagnostic.$n($($name),*);
             self
         }
     };
 
     // Forward pattern for &mut self -> &mut Self
-    (pub fn $n:ident(&mut self, $($name:ident: $ty:ty),*) -> &mut Self) => {
+    (pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)*) -> &mut Self) => {
         pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
+            #[allow(deprecated)]
             self.diagnostic.$n($($name),*);
             self
         }
@@ -56,8 +62,12 @@ pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
 
     // Forward pattern for &mut self -> &mut Self, with S: Into<MultiSpan>
     // type parameter. No obvious way to make this more generic.
-    (pub fn $n:ident<S: Into<MultiSpan>>(&mut self, $($name:ident: $ty:ty),*) -> &mut Self) => {
+    (pub fn $n:ident<S: Into<MultiSpan>>(
+                    &mut self,
+                    $($name:ident: $ty:ty),*
+                    $(,)*) -> &mut Self) => {
         pub fn $n<S: Into<MultiSpan>>(&mut self, $($name: $ty),*) -> &mut Self {
+            #[allow(deprecated)]
             self.diagnostic.$n($($name),*);
             self
         }
@@ -89,8 +99,14 @@ pub fn emit(&mut self) {
         self.cancel();
     }
 
-    /// Buffers the diagnostic for later emission.
-    pub fn buffer(self, buffered_diagnostics: &mut Vec<Diagnostic>) {
+    /// Buffers the diagnostic for later emission, unless handler
+    /// has disabled such buffering.
+    pub fn buffer(mut self, buffered_diagnostics: &mut Vec<Diagnostic>) {
+        if self.handler.flags.dont_buffer_diagnostics || self.handler.flags.treat_err_as_bug {
+            self.emit();
+            return;
+        }
+
         // We need to use `ptr::read` because `DiagnosticBuilder`
         // implements `Drop`.
         let diagnostic;
@@ -98,6 +114,9 @@ pub fn buffer(self, buffered_diagnostics: &mut Vec<Diagnostic>) {
             diagnostic = ::std::ptr::read(&self.diagnostic);
             ::std::mem::forget(self);
         };
+        // Logging here is useful to help track down where in logs an error was
+        // actually emitted.
+        debug!("buffer: diagnostic={:?}", diagnostic);
         buffered_diagnostics.push(diagnostic);
     }
 
@@ -144,49 +163,75 @@ pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self
     forward!(pub fn note_expected_found(&mut self,
                                         label: &dyn fmt::Display,
                                         expected: DiagnosticStyledString,
-                                        found: DiagnosticStyledString)
-                                        -> &mut Self);
+                                        found: DiagnosticStyledString,
+                                        -> &mut Self);
 
     forward!(pub fn note_expected_found_extra(&mut self,
                                               label: &dyn fmt::Display,
                                               expected: DiagnosticStyledString,
                                               found: DiagnosticStyledString,
                                               expected_extra: &dyn fmt::Display,
-                                              found_extra: &dyn fmt::Display)
-                                              -> &mut Self);
+                                              found_extra: &dyn fmt::Display,
+                                              -> &mut Self);
 
     forward!(pub fn note(&mut self, msg: &str) -> &mut Self);
     forward!(pub fn span_note<S: Into<MultiSpan>>(&mut self,
                                                   sp: S,
-                                                  msg: &str)
-                                                  -> &mut Self);
+                                                  msg: &str,
+                                                  -> &mut Self);
     forward!(pub fn warn(&mut self, msg: &str) -> &mut Self);
     forward!(pub fn span_warn<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self);
     forward!(pub fn help(&mut self , msg: &str) -> &mut Self);
     forward!(pub fn span_help<S: Into<MultiSpan>>(&mut self,
                                                   sp: S,
-                                                  msg: &str)
-                                                  -> &mut Self);
-    forward!(pub fn span_suggestion_short(&mut self,
-                                          sp: Span,
-                                          msg: &str,
-                                          suggestion: String)
-                                          -> &mut Self);
+                                                  msg: &str,
+                                                  ) -> &mut Self);
+
+    #[deprecated(note = "Use `span_suggestion_short_with_applicability`")]
+    forward!(pub fn span_suggestion_short(
+                                      &mut self,
+                                      sp: Span,
+                                      msg: &str,
+                                      suggestion: String,
+                                      ) -> &mut Self);
+
+    #[deprecated(note = "Use `multipart_suggestion_with_applicability`")]
     forward!(pub fn multipart_suggestion(
         &mut self,
         msg: &str,
-        suggestion: Vec<(Span, String)>
+        suggestion: Vec<(Span, String)>,
     ) -> &mut Self);
+
+    #[deprecated(note = "Use `span_suggestion_with_applicability`")]
     forward!(pub fn span_suggestion(&mut self,
                                     sp: Span,
                                     msg: &str,
-                                    suggestion: String)
-                                    -> &mut Self);
+                                    suggestion: String,
+                                    ) -> &mut Self);
+
+    #[deprecated(note = "Use `span_suggestions_with_applicability`")]
     forward!(pub fn span_suggestions(&mut self,
                                      sp: Span,
                                      msg: &str,
-                                     suggestions: Vec<String>)
-                                     -> &mut Self);
+                                     suggestions: Vec<String>,
+                                     ) -> &mut Self);
+
+    pub fn multipart_suggestion_with_applicability(&mut self,
+                                              msg: &str,
+                                              suggestion: Vec<(Span, String)>,
+                                              applicability: Applicability,
+                                              ) -> &mut Self {
+        if !self.allow_suggestions {
+            return self
+        }
+        self.diagnostic.multipart_suggestion_with_applicability(
+            msg,
+            suggestion,
+            applicability,
+        );
+        self
+    }
+
     pub fn span_suggestion_with_applicability(&mut self,
                                               sp: Span,
                                               msg: &str,
index 3582c2359c8b9f653f5ed5d27148f2845e18e801..266aa3269816895dc8fbdf3c3fbc9f0983f2d4fc 100644 (file)
@@ -23,6 +23,8 @@
 extern crate termcolor;
 #[cfg(unix)]
 extern crate libc;
+#[macro_use]
+extern crate log;
 extern crate rustc_data_structures;
 extern crate serialize as rustc_serialize;
 extern crate syntax_pos;
@@ -303,9 +305,20 @@ fn default_track_diagnostic(_: &Diagnostic) {}
 
 #[derive(Default)]
 pub struct HandlerFlags {
+    /// If false, warning-level lints are suppressed.
+    /// (rustc: see `--allow warnings` and `--cap-lints`)
     pub can_emit_warnings: bool,
+    /// If true, error-level diagnostics are upgraded to bug-level.
+    /// (rustc: see `-Z treat-err-as-bug`)
     pub treat_err_as_bug: bool,
+    /// If true, immediately emit diagnostics that would otherwise be buffered.
+    /// (rustc: see `-Z dont-buffer-diagnostics` and `-Z treat-err-as-bug`)
+    pub dont_buffer_diagnostics: bool,
+    /// If true, immediately print bugs registered with `delay_span_bug`.
+    /// (rustc: see `-Z report-delayed-bugs`)
     pub report_delayed_bugs: bool,
+    /// show macro backtraces even for non-local macros.
+    /// (rustc: see `-Z external-macro-backtrace`)
     pub external_macro_backtrace: bool,
 }
 
index e5baf93b00064abf32a50b65f3cd1ea70a0de1af..ff323073c6235eb40da49f36e75d1e4f82127827 100644 (file)
@@ -109,7 +109,7 @@ fn drop(&mut self) {
     }
 }
 
-#[cfg(unix)]
+#[cfg(not(windows))]
 pub fn acquire_global_lock(_name: &str) -> Box<dyn Any> {
     Box::new(())
 }
index b662b825013937a055422d7792e2c652d9e5603c..f9e717f8d456ec9b5da4a2d3184d2fd341449b8c 100644 (file)
@@ -783,7 +783,7 @@ impl EarlyLintPass for DeprecatedAttr {
     fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
         for &&(n, _, ref g) in &self.depr_attrs {
             if attr.name() == n {
-                if let &AttributeGate::Gated(Stability::Deprecated(link),
+                if let &AttributeGate::Gated(Stability::Deprecated(link, suggestion),
                                              ref name,
                                              ref reason,
                                              _) = g {
@@ -792,7 +792,7 @@ fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
                     let mut err = cx.struct_span_lint(DEPRECATED, attr.span, &msg);
                     err.span_suggestion_short_with_applicability(
                         attr.span,
-                        "remove this attribute",
+                        suggestion.unwrap_or("remove this attribute"),
                         String::new(),
                         Applicability::MachineApplicable
                     );
index 09871c0e84049d801888014eafc012a400faa67f..56d204f15d935897bc36d68324032baf38256f36 100644 (file)
@@ -59,10 +59,10 @@ fn char_has_case(c: char) -> bool {
 
         fn is_camel_case(name: ast::Name) -> bool {
             let name = name.as_str();
+            let name = name.trim_matches('_');
             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)
index 33181bd80e9374799400dea020e17a14ca1b6412..2bec9203e9ee5ff7021c1cd0830f83dd1d7fbba3 100644 (file)
@@ -691,7 +691,7 @@ fn check_type_for_ffi(&self,
                 }
 
                 let sig = cx.erase_late_bound_regions(&sig);
-                if !sig.output().is_nil() {
+                if !sig.output().is_unit() {
                     let r = self.check_type_for_ffi(cache, sig.output());
                     match r {
                         FfiSafe => {}
@@ -767,7 +767,7 @@ fn check_foreign_fn(&mut self, id: ast::NodeId, decl: &hir::FnDecl) {
 
         if let hir::Return(ref ret_hir) = decl.output {
             let ret_ty = sig.output();
-            if !ret_ty.is_nil() {
+            if !ret_ty.is_unit() {
                 self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty);
             }
         }
index 5eb541952150f06cb3955f5089ea1f18a905657e..6eef2397f9c6ed9b0cb28e0bd0ca9048aed2c27d 100644 (file)
@@ -100,6 +100,18 @@ enum LoadResult {
     Loaded(Library),
 }
 
+enum LoadError<'a> {
+    LocatorError(locator::Context<'a>),
+}
+
+impl<'a> LoadError<'a> {
+    fn report(self) -> ! {
+        match self {
+            LoadError::LocatorError(mut locate_ctxt) => locate_ctxt.report_errs(),
+        }
+    }
+}
+
 impl<'a> CrateLoader<'a> {
     pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Self {
         CrateLoader {
@@ -132,7 +144,8 @@ fn existing_match(&self, name: Symbol, hash: Option<&Svh>, kind: PathKind)
             // from the strings on the command line.
             let source = &self.cstore.get_crate_data(cnum).source;
             if let Some(locs) = self.sess.opts.externs.get(&*name.as_str()) {
-                let found = locs.iter().any(|l| {
+                // Only use `--extern crate_name=path` here, not `--extern crate_name`.
+                let found = locs.iter().filter_map(|l| l.as_ref()).any(|l| {
                     let l = fs::canonicalize(l).ok();
                     source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
                     source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
@@ -267,16 +280,17 @@ fn register_crate(&mut self,
         (cnum, cmeta)
     }
 
-    fn resolve_crate(&mut self,
-                     root: &Option<CratePaths>,
-                     ident: Symbol,
-                     name: Symbol,
-                     hash: Option<&Svh>,
-                     extra_filename: Option<&str>,
-                     span: Span,
-                     path_kind: PathKind,
-                     mut dep_kind: DepKind)
-                     -> (CrateNum, Lrc<cstore::CrateMetadata>) {
+    fn resolve_crate<'b>(
+        &'b mut self,
+        root: &'b Option<CratePaths>,
+        ident: Symbol,
+        name: Symbol,
+        hash: Option<&'b Svh>,
+        extra_filename: Option<&'b str>,
+        span: Span,
+        path_kind: PathKind,
+        mut dep_kind: DepKind,
+    ) -> Result<(CrateNum, Lrc<cstore::CrateMetadata>), LoadError<'b>> {
         info!("resolving crate `extern crate {} as {}`", name, ident);
         let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) {
             LoadResult::Previous(cnum)
@@ -320,7 +334,7 @@ fn resolve_crate(&mut self,
                 };
 
                 self.load(&mut proc_macro_locator)
-            }).unwrap_or_else(|| locate_ctxt.report_errs())
+            }).ok_or_else(move || LoadError::LocatorError(locate_ctxt))?
         };
 
         match result {
@@ -332,10 +346,10 @@ fn resolve_crate(&mut self,
                 data.dep_kind.with_lock(|data_dep_kind| {
                     *data_dep_kind = cmp::max(*data_dep_kind, dep_kind);
                 });
-                (cnum, data)
+                Ok((cnum, data))
             }
             LoadResult::Loaded(library) => {
-                self.register_crate(root, ident, span, library, dep_kind)
+                Ok(self.register_crate(root, ident, span, library, dep_kind))
             }
         }
     }
@@ -440,7 +454,7 @@ fn resolve_crate_deps(&mut self,
             let (local_cnum, ..) = self.resolve_crate(
                 root, dep.name, dep.name, Some(&dep.hash), Some(&dep.extra_filename), span,
                 PathKind::Dependency, dep_kind,
-            );
+            ).unwrap_or_else(|err| err.report());
             local_cnum
         })).collect()
     }
@@ -694,7 +708,8 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
 
         let dep_kind = DepKind::Implicit;
         let (cnum, data) =
-            self.resolve_crate(&None, name, name, None, None, DUMMY_SP, PathKind::Crate, dep_kind);
+            self.resolve_crate(&None, name, name, None, None, DUMMY_SP, PathKind::Crate, dep_kind)
+                .unwrap_or_else(|err| err.report());
 
         // Sanity check the loaded crate to ensure it is indeed a panic runtime
         // and the panic strategy is indeed what we thought it was.
@@ -802,7 +817,8 @@ fn inject_sanitizer_runtime(&mut self) {
                 let dep_kind = DepKind::Explicit;
                 let (_, data) =
                     self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP,
-                                       PathKind::Crate, dep_kind);
+                                       PathKind::Crate, dep_kind)
+                        .unwrap_or_else(|err| err.report());
 
                 // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime
                 if !data.root.sanitizer_runtime {
@@ -825,7 +841,8 @@ fn inject_profiler_runtime(&mut self) {
             let dep_kind = DepKind::Implicit;
             let (_, data) =
                 self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP,
-                                   PathKind::Crate, dep_kind);
+                                   PathKind::Crate, dep_kind)
+                    .unwrap_or_else(|err| err.report());
 
             // Sanity check the loaded crate to ensure it is indeed a profiler runtime
             if !data.root.profiler_runtime {
@@ -945,7 +962,8 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
                                                               None,
                                                               DUMMY_SP,
                                                               PathKind::Crate,
-                                                              DepKind::Implicit);
+                                                              DepKind::Implicit)
+                            .unwrap_or_else(|err| err.report());
                         self.sess.injected_allocator.set(Some(cnum));
                         data
                     })
@@ -1102,7 +1120,7 @@ pub fn process_extern_crate(
                 let (cnum, ..) = self.resolve_crate(
                     &None, item.ident.name, orig_name, None, None,
                     item.span, PathKind::Crate, dep_kind,
-                );
+                ).unwrap_or_else(|err| err.report());
 
                 let def_id = definitions.opt_local_def_id(item.id).unwrap();
                 let path_len = definitions.def_path(def_id.index).data.len();
@@ -1130,7 +1148,7 @@ pub fn process_path_extern(
     ) -> CrateNum {
         let cnum = self.resolve_crate(
             &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit
-        ).0;
+        ).unwrap_or_else(|err| err.report()).0;
 
         self.update_extern_crate(
             cnum,
@@ -1146,4 +1164,28 @@ pub fn process_path_extern(
 
         cnum
     }
+
+    pub fn maybe_process_path_extern(
+        &mut self,
+        name: Symbol,
+        span: Span,
+    ) -> Option<CrateNum> {
+        let cnum = self.resolve_crate(
+            &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit
+        ).ok()?.0;
+
+        self.update_extern_crate(
+            cnum,
+            ExternCrate {
+                src: ExternCrateSource::Path,
+                span,
+                // to have the least priority in `update_extern_crate`
+                path_len: usize::max_value(),
+                direct: true,
+            },
+            &mut FxHashSet(),
+        );
+
+        Some(cnum)
+    }
 }
index 87a32b5a53e7a0d4365b4c1407dd0817c42d6b03..d2285e8cbf1bea5ac1884b1bffdf2453c5023751 100644 (file)
@@ -42,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::IdxSet;
+use rustc_data_structures::bit_set::BitSet;
 use rustc::hir;
 
 macro_rules! provide {
@@ -141,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(IdxSet::new_empty(0)))
+        (cdata.mir_const_qualif(def_id.index), Lrc::new(BitSet::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)) }
index aae45c17c6771bd134b95bafcb22eef9d7ecb64f..56b38cfbc872a2711e0b7912f27a556bdfdc7830 100644 (file)
@@ -75,7 +75,7 @@ macro_rules! encoder_methods {
 impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
     type Error = <opaque::Encoder as Encoder>::Error;
 
-    fn emit_nil(&mut self) -> Result<(), Self::Error> {
+    fn emit_unit(&mut self) -> Result<(), Self::Error> {
         Ok(())
     }
 
index 9492385957eabe79f7571b120bbfde0a5f868f72..adff34af61ed8e9bd98a0566409d185849f55408 100644 (file)
@@ -438,7 +438,12 @@ fn find_library_crate(&mut self,
         if self.hash.is_none() {
             self.should_match_name = false;
             if let Some(s) = self.sess.opts.externs.get(&self.crate_name.as_str()) {
-                return self.find_commandline_library(s.iter());
+                // Only use `--extern crate_name=path` here, not `--extern crate_name`.
+                if s.iter().any(|l| l.is_some()) {
+                    return self.find_commandline_library(
+                        s.iter().filter_map(|l| l.as_ref()),
+                    );
+                }
             }
             self.should_match_name = true;
         }
@@ -617,7 +622,7 @@ fn extract_one(&mut self,
                         }
                     }
                     Err(err) => {
-                        info!("no metadata found: {}", err);
+                        warn!("no metadata found: {}", err);
                         continue;
                     }
                 };
index 8ddcfa054321e38ebc9cb3edd6d5d88935625e56..bb70b4b76c27784c0c312c68d6874fc868fb1ce4 100644 (file)
@@ -17,7 +17,7 @@
 use rustc::ty::{Region, TyCtxt};
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_data_structures::bitvec::BitArray;
+use rustc_data_structures::bit_set::BitSet;
 use std::fmt;
 use std::hash::Hash;
 use std::ops::Index;
@@ -102,7 +102,7 @@ fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
 
 crate enum LocalsStateAtExit {
     AllAreInvalidated,
-    SomeAreInvalidated { has_storage_dead_or_moved: BitArray<Local> }
+    SomeAreInvalidated { has_storage_dead_or_moved: BitSet<Local> }
 }
 
 impl LocalsStateAtExit {
@@ -111,7 +111,7 @@ fn build(
         mir: &Mir<'tcx>,
         move_data: &MoveData<'tcx>
     ) -> Self {
-        struct HasStorageDead(BitArray<Local>);
+        struct HasStorageDead(BitSet<Local>);
 
         impl<'tcx> Visitor<'tcx> for HasStorageDead {
             fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) {
@@ -124,7 +124,7 @@ fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) {
         if locals_are_invalidated_at_exit {
             LocalsStateAtExit::AllAreInvalidated
         } else {
-            let mut has_storage_dead = HasStorageDead(BitArray::new(mir.local_decls.len()));
+            let mut has_storage_dead = HasStorageDead(BitSet::new_empty(mir.local_decls.len()));
             has_storage_dead.visit_mir(mir);
             let mut has_storage_dead_or_moved = has_storage_dead.0;
             for move_out in &move_data.moves {
index 3f8cd03660c43ab6708420f79eb03509076453cf..9187cb97e69e52f387e37605ae3df7a00b780aa1 100644 (file)
 use rustc::ty;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use syntax_pos::Span;
 
 use super::borrow_set::BorrowData;
 use super::{Context, MirBorrowckCtxt};
 use super::{InitializationRequiringAction, PrefixSet};
 
+use borrow_check::nll::explain_borrow::BorrowContainsPointReason;
 use dataflow::drop_flag_effects;
 use dataflow::move_paths::indexes::MoveOutIndex;
 use dataflow::move_paths::MovePathIndex;
@@ -37,6 +38,12 @@ pub(super) fn report_use_of_moved_or_uninitialized(
         (place, span): (&Place<'tcx>, Span),
         mpi: MovePathIndex,
     ) {
+        debug!(
+            "report_use_of_moved_or_uninitialized: context={:?} desired_action={:?} place={:?} \
+            span={:?} mpi={:?}",
+            context, desired_action, place, span, mpi
+        );
+
         let use_spans = self
             .move_spans(place, context.loc)
             .or_else(|| self.borrow_spans(span, context.loc));
@@ -48,7 +55,7 @@ pub(super) fn report_use_of_moved_or_uninitialized(
         if mois.is_empty() {
             let root_place = self.prefixes(&place, PrefixSet::All).last().unwrap();
 
-            if self.moved_error_reported.contains(&root_place.clone()) {
+            if self.uninitialized_error_reported.contains(&root_place.clone()) {
                 debug!(
                     "report_use_of_moved_or_uninitialized place: error about {:?} suppressed",
                     root_place
@@ -56,7 +63,7 @@ pub(super) fn report_use_of_moved_or_uninitialized(
                 return;
             }
 
-            self.moved_error_reported.insert(root_place.clone());
+            self.uninitialized_error_reported.insert(root_place.clone());
 
             let item_msg = match self.describe_place_with_options(place, IncludingDowncast(true)) {
                 Some(name) => format!("`{}`", name),
@@ -79,6 +86,14 @@ pub(super) fn report_use_of_moved_or_uninitialized(
 
             err.buffer(&mut self.errors_buffer);
         } else {
+            if let Some((reported_place, _)) = self.move_error_reported.get(&mois) {
+                if self.prefixes(&reported_place, PrefixSet::All).any(|p| p == place) {
+                    debug!("report_use_of_moved_or_uninitialized place: error suppressed \
+                           mois={:?}", mois);
+                    return;
+                }
+            }
+
             let msg = ""; //FIXME: add "partially " or "collaterally "
 
             let mut err = self.tcx.cannot_act_on_moved_value(
@@ -166,7 +181,13 @@ pub(super) fn report_use_of_moved_or_uninitialized(
                 }
             }
 
-            err.buffer(&mut self.errors_buffer);
+            if let Some((_, mut old_err)) = self.move_error_reported.insert(
+                mois,
+                (place.clone(), err)
+            ) {
+                // Cancel the old error so it doesn't ICE.
+                old_err.cancel();
+            }
         }
     }
 
@@ -409,6 +430,8 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
         self.access_place_error_reported
             .insert((root_place.clone(), borrow_span));
 
+        let borrow_reason = self.find_why_borrow_contains_point(context, borrow);
+
         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)
@@ -418,17 +441,17 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
                 name,
                 &scope_tree,
                 &borrow,
+                borrow_reason,
                 drop_span,
                 borrow_span,
-                proper_span,
                 kind.map(|k| (k, place_span.0)),
             ),
             None => self.report_temporary_value_does_not_live_long_enough(
                 context,
                 &scope_tree,
                 &borrow,
+                borrow_reason,
                 drop_span,
-                borrow_span,
                 proper_span,
             ),
         };
@@ -444,16 +467,16 @@ fn report_local_value_does_not_live_long_enough(
         name: &String,
         scope_tree: &Lrc<ScopeTree>,
         borrow: &BorrowData<'tcx>,
+        reason: BorrowContainsPointReason<'tcx>,
         drop_span: Span,
         borrow_span: Span,
-        _proper_span: Span,
         kind_place: Option<(WriteKind, &Place<'tcx>)>,
     ) -> DiagnosticBuilder<'cx> {
         debug!(
             "report_local_value_does_not_live_long_enough(\
-             {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\
+             {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\
              )",
-            context, name, scope_tree, borrow, drop_span, borrow_span
+            context, name, scope_tree, borrow, reason, drop_span, borrow_span
         );
 
         let mut err = self.tcx.path_does_not_live_long_enough(
@@ -468,7 +491,7 @@ fn report_local_value_does_not_live_long_enough(
             format!("`{}` dropped here while still borrowed", name),
         );
 
-        self.explain_why_borrow_contains_point(context, borrow, kind_place, &mut err);
+        self.report_why_borrow_contains_point(&mut err, reason, kind_place);
         err
     }
 
@@ -501,15 +524,15 @@ fn report_temporary_value_does_not_live_long_enough(
         context: Context,
         scope_tree: &Lrc<ScopeTree>,
         borrow: &BorrowData<'tcx>,
+        reason: BorrowContainsPointReason<'tcx>,
         drop_span: Span,
-        _borrow_span: Span,
         proper_span: Span,
     ) -> DiagnosticBuilder<'cx> {
         debug!(
             "report_temporary_value_does_not_live_long_enough(\
-             {:?}, {:?}, {:?}, {:?}, {:?}\
+             {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\
              )",
-            context, scope_tree, borrow, drop_span, proper_span
+            context, scope_tree, borrow, reason, drop_span, proper_span
         );
 
         let tcx = self.tcx;
@@ -518,7 +541,16 @@ fn report_temporary_value_does_not_live_long_enough(
         err.span_label(proper_span, "temporary value does not live long enough");
         err.span_label(drop_span, "temporary value only lives until here");
 
-        self.explain_why_borrow_contains_point(context, borrow, None, &mut err);
+        // Only give this note and suggestion if they could be relevant
+        match reason {
+            BorrowContainsPointReason::Liveness {..}
+            | BorrowContainsPointReason::DropLiveness {..} => {
+                err.note("consider using a `let` binding to create a longer lived value");
+            }
+            BorrowContainsPointReason::OutlivesFreeRegion {..} => (),
+        }
+
+        self.report_why_borrow_contains_point(&mut err, reason, None);
         err
     }
 
@@ -552,9 +584,20 @@ fn get_moved_indexes(&mut self, context: Context, mpi: MovePathIndex) -> Vec<Mov
                 // created by `StorageDead` and at the beginning
                 // of a function.
             } else {
+                // If we are found a use of a.b.c which was in error, then we want to look for
+                // moves not only of a.b.c but also a.b and a.
+                //
+                // Note that the moves data already includes "parent" paths, so we don't have to
+                // worry about the other case: that is, if there is a move of a.b.c, it is already
+                // marked as a move of a.b and a as well, so we will generate the correct errors
+                // there.
+                let mut mpis = vec![mpi];
+                let move_paths = &self.move_data.move_paths;
+                mpis.extend(move_paths[mpi].parents(move_paths));
+
                 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 {
+                    if mpis.contains(&self.move_data.moves[*moi].path) {
                         debug!("report_use_of_moved_or_uninitialized: found");
                         result.push(*moi);
 
@@ -690,9 +733,11 @@ pub(super) fn report_illegal_reassignment(
         if let Some(decl) = local_decl {
             if let Some(name) = decl.name {
                 if decl.can_be_made_mutable() {
-                    err.span_label(
+                    err.span_suggestion_with_applicability(
                         decl.source_info.span,
-                        format!("consider changing this to `mut {}`", name),
+                        "make this binding mutable",
+                        format!("mut {}", name),
+                        Applicability::MachineApplicable,
                     );
                 }
             }
index 6b964fec74fdd1417b1145de05f44ed2df3b696e..16bb1ef78dc6f85c2000609280aa2f35b8e1e966 100644 (file)
@@ -15,7 +15,7 @@
 
 use rustc::mir::{BasicBlock, Location};
 use rustc::ty::RegionVid;
-use rustc_data_structures::indexed_set::Iter;
+use rustc_data_structures::bit_set::BitIter;
 
 use borrow_check::location::LocationIndex;
 
@@ -67,7 +67,7 @@ impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
         }
     }
 
-    crate fn with_outgoing_borrows(&self, op: impl FnOnce(Iter<BorrowIndex>)) {
+    crate fn with_outgoing_borrows(&self, op: impl FnOnce(BitIter<BorrowIndex>)) {
         self.borrows.with_iter_outgoing(op)
     }
 }
index 60aeb92d91a6f30b7cf2075a365ebe53b8bf0ab4..c7e53714e3e847a5ed8bdacd25d6bc68e8a6bb71 100644 (file)
 use rustc::ty::{self, ParamEnv, TyCtxt, Ty};
 
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, Level};
-use rustc_data_structures::graph::dominators::Dominators;
+use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::indexed_set::IdxSet;
+use rustc_data_structures::graph::dominators::Dominators;
 use rustc_data_structures::indexed_vec::Idx;
 use smallvec::SmallVec;
 
 use std::rc::Rc;
+use std::collections::BTreeMap;
 
 use syntax_pos::Span;
 
 use dataflow::indexes::BorrowIndex;
 use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MoveError, MovePathIndex};
+use dataflow::move_paths::indexes::MoveOutIndex;
 use dataflow::Borrows;
 use dataflow::DataflowResultsConsumer;
 use dataflow::FlowAtLocation;
@@ -167,7 +169,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         _ => Some(tcx.hir.body_owned_by(id)),
     };
 
-    let dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len());
+    let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
     let mut flow_inits = FlowAtLocation::new(do_dataflow(
         tcx,
         mir,
@@ -177,24 +179,6 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         MaybeInitializedPlaces::new(tcx, mir, &mdpe),
         |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
     ));
-    let flow_uninits = FlowAtLocation::new(do_dataflow(
-        tcx,
-        mir,
-        id,
-        &attributes,
-        &dead_unwinds,
-        MaybeUninitializedPlaces::new(tcx, mir, &mdpe),
-        |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
-    ));
-    let flow_ever_inits = FlowAtLocation::new(do_dataflow(
-        tcx,
-        mir,
-        id,
-        &attributes,
-        &dead_unwinds,
-        EverInitializedPlaces::new(tcx, mir, &mdpe),
-        |bd, i| DebugFormatted::new(&bd.move_data().inits[i]),
-    ));
 
     let locals_are_invalidated_at_exit = match tcx.hir.body_owner_kind(id) {
             hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false,
@@ -216,6 +200,12 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         &borrow_set,
         &mut errors_buffer,
     );
+
+    // The various `flow_*` structures can be large. We drop `flow_inits` here
+    // so it doesn't overlap with the others below. This reduces peak memory
+    // usage significantly on some benchmarks.
+    drop(flow_inits);
+
     let regioncx = Rc::new(regioncx);
 
     let flow_borrows = FlowAtLocation::new(do_dataflow(
@@ -227,6 +217,24 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         Borrows::new(tcx, mir, regioncx.clone(), def_id, body_id, &borrow_set),
         |rs, i| DebugFormatted::new(&rs.location(i)),
     ));
+    let flow_uninits = FlowAtLocation::new(do_dataflow(
+        tcx,
+        mir,
+        id,
+        &attributes,
+        &dead_unwinds,
+        MaybeUninitializedPlaces::new(tcx, mir, &mdpe),
+        |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
+    ));
+    let flow_ever_inits = FlowAtLocation::new(do_dataflow(
+        tcx,
+        mir,
+        id,
+        &attributes,
+        &dead_unwinds,
+        EverInitializedPlaces::new(tcx, mir, &mdpe),
+        |bd, i| DebugFormatted::new(&bd.move_data().inits[i]),
+    ));
 
     let movable_generator = match tcx.hir.get(id) {
         Node::Expr(&hir::Expr {
@@ -249,7 +257,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         locals_are_invalidated_at_exit,
         access_place_error_reported: FxHashSet(),
         reservation_error_reported: FxHashSet(),
-        moved_error_reported: FxHashSet(),
+        move_error_reported: BTreeMap::new(),
+        uninitialized_error_reported: FxHashSet(),
         errors_buffer,
         nonlexical_regioncx: regioncx,
         used_mut: FxHashSet(),
@@ -327,6 +336,11 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         }
     }
 
+    // Buffer any move errors that we collected and de-duplicated.
+    for (_, (_, diag)) in mbcx.move_error_reported {
+        diag.buffer(&mut mbcx.errors_buffer);
+    }
+
     if mbcx.errors_buffer.len() > 0 {
         mbcx.errors_buffer.sort_by_key(|diag| diag.span.primary_span());
 
@@ -402,9 +416,24 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     /// but it is currently inconvenient to track down the BorrowIndex
     /// at the time we detect and report a reservation error.
     reservation_error_reported: FxHashSet<Place<'tcx>>,
-    /// This field keeps track of errors reported in the checking of moved variables,
+    /// This field keeps track of move errors that are to be reported for given move indicies.
+    ///
+    /// There are situations where many errors can be reported for a single move out (see #53807)
+    /// and we want only the best of those errors.
+    ///
+    /// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the
+    /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of the
+    /// `Place` of the previous most diagnostic. This happens instead of buffering the error. Once
+    /// all move errors have been reported, any diagnostics in this map are added to the buffer
+    /// to be emitted.
+    ///
+    /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary
+    /// when errors in the map are being re-added to the error buffer so that errors with the
+    /// same primary span come out in a consistent order.
+    move_error_reported: BTreeMap<Vec<MoveOutIndex>, (Place<'tcx>, DiagnosticBuilder<'cx>)>,
+    /// This field keeps track of errors reported in the checking of uninitialized variables,
     /// so that we don't report seemingly duplicate errors.
-    moved_error_reported: FxHashSet<Place<'tcx>>,
+    uninitialized_error_reported: FxHashSet<Place<'tcx>>,
     /// Errors to be reported buffer
     errors_buffer: Vec<Diagnostic>,
     /// This field keeps track of all the local variables that are declared mut and are mutated.
@@ -795,7 +824,7 @@ enum LocalMutationIsAllowed {
     No,
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 enum InitializationRequiringAction {
     Update,
     Borrow,
@@ -1589,7 +1618,7 @@ fn check_if_reassignment_to_immutable_state(
         // Check if any of the initializiations of `local` have happened yet:
         let mpi = self.move_data.rev_lookup.find_local(local);
         let init_indices = &self.move_data.init_path_map[mpi];
-        let first_init_index = init_indices.iter().find(|ii| flow_state.ever_inits.contains(ii));
+        let first_init_index = init_indices.iter().find(|&ii| flow_state.ever_inits.contains(*ii));
         if let Some(&init_index) = first_init_index {
             // And, if so, report an error.
             let init = &self.move_data.inits[init_index];
@@ -1647,7 +1676,7 @@ fn check_if_full_path_is_moved(
         debug!("check_if_full_path_is_moved place: {:?}", place_span.0);
         match self.move_path_closest_to(place_span.0) {
             Ok(mpi) => {
-                if maybe_uninits.contains(&mpi) {
+                if maybe_uninits.contains(mpi) {
                     self.report_use_of_moved_or_uninitialized(
                         context,
                         desired_action,
@@ -1963,7 +1992,7 @@ fn add_used_mut<'d>(
                     // keyword, since the mutation may be a possible reassignment.
                     let mpi = self.move_data.rev_lookup.find_local(*local);
                     let ii = &self.move_data.init_path_map[mpi];
-                    for index in ii {
+                    for &index in ii {
                         if flow_state.ever_inits.contains(index) {
                             self.used_mut.insert(*local);
                             break;
index 290c7032388053f0b1376b35e1d22295e8a4ae58..52d051ebe7ba0cf13ce648519b26b13ef9c0e97c 100644 (file)
@@ -11,7 +11,7 @@
 use core::unicode::property::Pattern_White_Space;
 use rustc::mir::*;
 use rustc::ty;
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{DiagnosticBuilder,Applicability};
 use syntax_pos::Span;
 
 use borrow_check::MirBorrowckCtxt;
@@ -350,16 +350,18 @@ fn add_move_hints(
                     // expressions `a[b]`, which roughly desugar to
                     // `*Index::index(&a, b)` or
                     // `*IndexMut::index_mut(&mut a, b)`.
-                    err.span_suggestion(
+                    err.span_suggestion_with_applicability(
                         span,
                         "consider removing the `*`",
                         snippet[1..].to_owned(),
+                        Applicability::Unspecified,
                     );
                 } else {
-                    err.span_suggestion(
+                    err.span_suggestion_with_applicability(
                         span,
                         "consider borrowing here",
                         format!("&{}", snippet),
+                        Applicability::Unspecified,
                     );
                 }
 
@@ -420,10 +422,11 @@ fn add_move_error_suggestions(
         suggestions.sort_unstable_by_key(|&(span, _, _)| span);
         suggestions.dedup_by_key(|&mut (span, _, _)| span);
         for (span, to_remove, suggestion) in suggestions {
-            err.span_suggestion(
+            err.span_suggestion_with_applicability(
                 span,
                 &format!("consider removing the `{}`", to_remove),
-                suggestion
+                suggestion,
+                Applicability::MachineApplicable,
             );
         }
     }
index 78ab772d9ad5b2f3ed5fd9cbd2cbf26d62f53c50..a078aa59a7d5b4bf37624ba5eaa2735d1c69b253 100644 (file)
@@ -22,6 +22,7 @@
 use util::borrowck_errors::{BorrowckErrors, Origin};
 use util::collect_writes::FindAssignments;
 use util::suggest_ref_mut;
+use rustc_errors::Applicability;
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub(super) enum AccessKind {
@@ -227,10 +228,11 @@ pub(super) fn report_mutability_error(
                 assert_eq!(local_decl.mutability, Mutability::Not);
 
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
-                err.span_suggestion(
+                err.span_suggestion_with_applicability(
                     local_decl.source_info.span,
                     "consider changing this to be mutable",
                     format!("mut {}", local_decl.name.unwrap()),
+                    Applicability::MachineApplicable,
                 );
             }
 
@@ -257,10 +259,11 @@ pub(super) fn report_mutability_error(
                         _,
                     ) = pat.node
                     {
-                        err.span_suggestion(
+                        err.span_suggestion_with_applicability(
                             upvar_ident.span,
                             "consider changing this to be mutable",
                             format!("mut {}", upvar_ident.name),
+                            Applicability::MachineApplicable,
                         );
                     }
                 }
@@ -351,10 +354,11 @@ pub(super) fn report_mutability_error(
                 };
 
                 if let Some((err_help_span, suggested_code)) = suggestion {
-                    err.span_suggestion(
+                    err.span_suggestion_with_applicability(
                         err_help_span,
                         &format!("consider changing this to be a mutable {}", pointer_desc),
                         suggested_code,
+                        Applicability::MachineApplicable,
                     );
                 }
 
index 5098b24adc367507e756324a682e14f7234122ec..414cb1d6f05c2589f88a1f093fd2010c81590067 100644 (file)
 use borrow_check::borrow_set::BorrowData;
 use borrow_check::nll::region_infer::Cause;
 use borrow_check::{Context, MirBorrowckCtxt, WriteKind};
-use rustc::mir::{Location, Place, TerminatorKind};
+use rustc::mir::{Local, Location, Place, TerminatorKind};
 use rustc_errors::DiagnosticBuilder;
+use rustc::ty::Region;
 
 mod find_use;
 
+#[derive(Copy, Clone, Debug)]
+pub enum BorrowContainsPointReason<'tcx> {
+    Liveness {
+        local: Local,
+        location: Location,
+        in_loop: bool,
+    },
+    DropLiveness {
+        local: Local,
+        location: Location,
+    },
+    OutlivesFreeRegion {
+        outlived_region: Option<Region<'tcx>>,
+    },
+}
+
 impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     /// Adds annotations to `err` explaining *why* the borrow contains the
     /// point from `context`. This is key for the "3-point errors"
@@ -32,15 +49,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     ///
     /// [d]: https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points
     pub(in borrow_check) fn explain_why_borrow_contains_point(
-        &mut self,
+        &self,
         context: Context,
         borrow: &BorrowData<'tcx>,
         kind_place: Option<(WriteKind, &Place<'tcx>)>,
         err: &mut DiagnosticBuilder<'_>,
     ) {
+        let reason = self.find_why_borrow_contains_point(context, borrow);
+        self.report_why_borrow_contains_point(err, reason, kind_place);
+    }
+
+    /// Finds the reason that [explain_why_borrow_contains_point] will report
+    /// but doesn't add it to any message. This is a separate function in case
+    /// the caller wants to change the error they report based on the reason
+    /// that will be reported.
+    pub(in borrow_check) fn find_why_borrow_contains_point(
+        &self,
+        context: Context,
+        borrow: &BorrowData<'tcx>
+    ) -> BorrowContainsPointReason<'tcx> {
+        use self::BorrowContainsPointReason::*;
+
         debug!(
-            "explain_why_borrow_contains_point(context={:?}, borrow={:?}, kind_place={:?})",
-            context, borrow, kind_place,
+            "find_why_borrow_contains_point(context={:?}, borrow={:?})",
+            context, borrow,
         );
 
         let regioncx = &self.nonlexical_regioncx;
@@ -62,11 +94,45 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
         );
 
         match find_use::find(mir, regioncx, tcx, region_sub, context.loc) {
-            Some(Cause::LiveVar(local, location)) => {
+            Some(Cause::LiveVar(local, location)) => Liveness {
+                local,
+                location,
+                in_loop: self.is_borrow_location_in_loop(context.loc),
+            },
+            Some(Cause::DropVar(local, location)) => DropLiveness {
+                local,
+                location,
+            },
+            None => OutlivesFreeRegion {
+                outlived_region: regioncx.to_error_region(region_sub),
+            },
+        }
+    }
+
+    /// Adds annotations to `err` for the explanation `reason`. This is a
+    /// separate method so that the caller can change their error message based
+    /// on the reason that is going to be reported.
+    pub (in borrow_check) fn report_why_borrow_contains_point(
+        &self,
+        err: &mut DiagnosticBuilder,
+        reason: BorrowContainsPointReason<'tcx>,
+        kind_place: Option<(WriteKind, &Place<'tcx>)>,
+    ) {
+        use self::BorrowContainsPointReason::*;
+
+        debug!(
+            "find_why_borrow_contains_point(reason={:?}, kind_place={:?})",
+            reason, kind_place,
+        );
+
+        let mir = self.mir;
+
+        match reason {
+            Liveness { local, location, in_loop } => {
                 let span = mir.source_info(location).span;
                 let spans = self.move_spans(&Place::Local(local), location)
                     .or_else(|| self.borrow_spans(span, location));
-                let message = if self.is_borrow_location_in_loop(context.loc) {
+                let message = if in_loop {
                     if spans.for_closure() {
                         "borrow captured here by closure in later iteration of loop"
                     } else {
@@ -81,8 +147,7 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
                 };
                 err.span_label(spans.var_or_use(), message);
             }
-
-            Some(Cause::DropVar(local, location)) => match &mir.local_decls[local].name {
+            DropLiveness { local, location } => match &mir.local_decls[local].name {
                 Some(local_name) => {
                     err.span_label(
                         mir.source_info(location).span,
@@ -93,12 +158,12 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
                         if let Place::Local(borrowed_local) = place {
                             let dropped_local_scope = mir.local_decls[local].visibility_scope;
                             let borrowed_local_scope =
-                                mir.local_decls[*borrowed_local].visibility_scope;
+                            mir.local_decls[*borrowed_local].visibility_scope;
 
                             if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope) {
                                 err.note(
-                                    "values in a scope are dropped \
-                                     in the opposite order they are defined",
+                                "values in a scope are dropped \
+                                                     in the opposite order they are defined",
                                 );
                             }
                         }
@@ -106,18 +171,16 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
                 }
 
                 None => {}
-            },
-
-            None => {
-                if let Some(region) = regioncx.to_error_region(region_sub) {
-                    self.tcx.note_and_explain_free_region(
-                        err,
-                        "borrowed value must be valid for ",
-                        region,
-                        "...",
-                    );
-                }
             }
+            OutlivesFreeRegion { outlived_region: Some(region) } => {
+                self.tcx.note_and_explain_free_region(
+                    err,
+                    "borrowed value must be valid for ",
+                    region,
+                    "...",
+                );
+            }
+            OutlivesFreeRegion { outlived_region: None } => (),
         }
     }
 
@@ -193,3 +256,4 @@ fn is_borrow_location_in_loop(
         false
     }
 }
+
index 0b9b9b33b3f154577bda5fa1edff3c0998b1899a..dfed41cb1defd5de4bcf145a0f116dc8da4bcd7d 100644 (file)
 use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
 use rustc::infer::InferCtxt;
 use rustc::mir::{self, Location, Mir, Place, Rvalue, StatementKind, TerminatorKind};
-use rustc::ty::{TyCtxt, RegionVid};
+use rustc::ty::{self, TyCtxt, RegionVid};
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_errors::Diagnostic;
+use rustc_errors::{Diagnostic, DiagnosticBuilder};
 use std::collections::VecDeque;
 use std::fmt;
+use syntax::symbol::keywords;
 use syntax_pos::Span;
 
 mod region_name;
 mod var_name;
 
+use self::region_name::RegionName;
+
 /// Constraints that are considered interesting can be categorized to
 /// determine why they are interesting. Order of variants indicates
 /// sort order of the category, thereby influencing diagnostic output.
@@ -356,9 +359,9 @@ pub(super) fn report_error(
             self.universal_regions.is_local_free_region(fr),
             self.universal_regions.is_local_free_region(outlived_fr),
         );
+
         debug!("report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}",
                fr_is_local, outlived_fr_is_local, category);
-
         match (category, fr_is_local, outlived_fr_is_local) {
             (ConstraintCategory::Assignment, true, false) |
             (ConstraintCategory::CallArgument, true, false) =>
@@ -465,9 +468,93 @@ fn report_general_error(
             },
         }
 
+        self.add_static_impl_trait_suggestion(
+            infcx, &mut diag, fr, fr_name, outlived_fr,
+        );
+
         diag.buffer(errors_buffer);
     }
 
+    fn add_static_impl_trait_suggestion(
+        &self,
+        infcx: &InferCtxt<'_, '_, 'tcx>,
+        diag: &mut DiagnosticBuilder<'_>,
+        fr: RegionVid,
+        // We need to pass `fr_name` - computing it again will label it twice.
+        fr_name: RegionName,
+        outlived_fr: RegionVid,
+    ) {
+        if let (
+            Some(f),
+            Some(ty::RegionKind::ReStatic)
+        ) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
+            if let Some(ty::TyS {
+                sty: ty::TyKind::Opaque(did, substs),
+                ..
+            }) = infcx.tcx.is_suitable_region(f)
+                    .map(|r| r.def_id)
+                    .map(|id| infcx.tcx.return_type_impl_trait(id))
+                    .unwrap_or(None)
+            {
+                // Check whether or not the impl trait return type is intended to capture
+                // data with the static lifetime.
+                //
+                // eg. check for `impl Trait + 'static` instead of `impl Trait`.
+                let has_static_predicate = {
+                    let predicates_of = infcx.tcx.predicates_of(*did);
+                    let bounds = predicates_of.instantiate(infcx.tcx, substs);
+
+                    let mut found = false;
+                    for predicate in bounds.predicates {
+                        if let ty::Predicate::TypeOutlives(binder) = predicate {
+                            if let ty::OutlivesPredicate(
+                                _,
+                                ty::RegionKind::ReStatic
+                            ) = binder.skip_binder() {
+                                found = true;
+                                break;
+                            }
+                        }
+                    }
+
+                    found
+                };
+
+                debug!("add_static_impl_trait_suggestion: has_static_predicate={:?}",
+                       has_static_predicate);
+                let static_str = keywords::StaticLifetime.name();
+                // If there is a static predicate, then the only sensible suggestion is to replace
+                // fr with `'static`.
+                if has_static_predicate {
+                    diag.help(
+                        &format!(
+                            "consider replacing `{}` with `{}`",
+                            fr_name, static_str,
+                        ),
+                    );
+                } else {
+                    // Otherwise, we should suggest adding a constraint on the return type.
+                    let span = infcx.tcx.def_span(*did);
+                    if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(span) {
+                        let suggestable_fr_name = match fr_name {
+                            RegionName::Named(name) => format!("{}", name),
+                            RegionName::Synthesized(_) => "'_".to_string(),
+                        };
+                        diag.span_suggestion(
+                            span,
+                            &format!(
+                                "to allow this impl Trait to capture borrowed data with lifetime \
+                                 `{}`, add `{}` as a constraint",
+                                fr_name, suggestable_fr_name,
+                            ),
+                            format!("{} + {}", snippet, suggestable_fr_name),
+                        );
+                    }
+                }
+            }
+        }
+    }
+
     // Finds some region R such that `fr1: R` and `R` is live at
     // `elem`.
     crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
index 5ae123bdc18d16b45f81733cea4a71244af9cf03..857f1dae7ab5175c27e347630c3e743a5a8938f9 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::fmt::{self, Display};
 use borrow_check::nll::region_infer::RegionInferenceContext;
 use borrow_check::nll::universal_regions::DefiningTy;
 use borrow_check::nll::ToRegionVid;
 use rustc_errors::DiagnosticBuilder;
 use syntax::ast::{Name, DUMMY_NODE_ID};
 use syntax::symbol::keywords;
+use syntax_pos::Span;
 use syntax_pos::symbol::InternedString;
 
+/// Name of a region used in error reporting. Variants denote the source of the region name -
+/// whether it was synthesized for the error message and therefore should not be used in
+/// suggestions; or whether it was found from the region.
+#[derive(Debug)]
+pub(crate) enum RegionName {
+    Named(InternedString),
+    Synthesized(InternedString),
+}
+
+impl RegionName {
+    fn as_interned_string(&self) -> &InternedString {
+        match self {
+            RegionName::Named(name) | RegionName::Synthesized(name) => name,
+        }
+    }
+}
+
+impl Display for RegionName {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            RegionName::Named(name) | RegionName::Synthesized(name) =>
+                write!(f, "{}", name),
+        }
+    }
+}
+
 impl<'tcx> RegionInferenceContext<'tcx> {
     /// Maps from an internal MIR region vid to something that we can
     /// report to the user. In some cases, the region vids will map
@@ -57,7 +85,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         fr: RegionVid,
         counter: &mut usize,
         diag: &mut DiagnosticBuilder,
-    ) -> InternedString {
+    ) -> RegionName {
         debug!("give_region_a_name(fr={:?}, counter={})", fr, counter);
 
         assert!(self.universal_regions.is_universal_region(fr));
@@ -95,27 +123,31 @@ fn give_name_from_error_region(
         fr: RegionVid,
         counter: &mut usize,
         diag: &mut DiagnosticBuilder<'_>,
-    ) -> Option<InternedString> {
+    ) -> Option<RegionName> {
         let error_region = self.to_error_region(fr)?;
 
         debug!("give_region_a_name: error_region = {:?}", error_region);
         match error_region {
             ty::ReEarlyBound(ebr) => {
                 if ebr.has_name() {
-                    self.highlight_named_span(tcx, error_region, &ebr.name, diag);
-                    Some(ebr.name)
+                    let name = RegionName::Named(ebr.name);
+                    self.highlight_named_span(tcx, error_region, &name, diag);
+                    Some(name)
                 } else {
                     None
                 }
             }
 
-            ty::ReStatic => Some(keywords::StaticLifetime.name().as_interned_str()),
+            ty::ReStatic => Some(RegionName::Named(
+                keywords::StaticLifetime.name().as_interned_str()
+            )),
 
             ty::ReFree(free_region) => match free_region.bound_region {
                 ty::BoundRegion::BrNamed(_, name) => {
+                    let name = RegionName::Named(name);
                     self.highlight_named_span(tcx, error_region, &name, diag);
                     Some(name)
-                }
+                },
 
                 ty::BoundRegion::BrEnv => {
                     let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).expect("non-local mir");
@@ -132,7 +164,10 @@ fn give_name_from_error_region(
                         let region_name = self.synthesize_region_name(counter);
                         diag.span_label(
                             args_span,
-                            format!("lifetime `{}` represents this closure's body", region_name),
+                            format!(
+                                "lifetime `{}` represents this closure's body",
+                                region_name
+                            ),
                         );
 
                         let closure_kind_ty = substs.closure_kind_ty(def_id, tcx);
@@ -174,6 +209,26 @@ fn give_name_from_error_region(
         }
     }
 
+    /// Get the span of a named region.
+    pub(super) fn get_span_of_named_region(
+        &self,
+        tcx: TyCtxt<'_, '_, 'tcx>,
+        error_region: &RegionKind,
+        name: &RegionName,
+    ) -> Span {
+        let scope = error_region.free_region_binding_scope(tcx);
+        let node = tcx.hir.as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID);
+
+        let span = tcx.sess.source_map().def_span(tcx.hir.span(node));
+        if let Some(param) = tcx.hir.get_generics(scope).and_then(|generics| {
+            generics.get_named(name.as_interned_string())
+        }) {
+            param.span
+        } else {
+            span
+        }
+    }
+
     /// Highlight a named span to provide context for error messages that
     /// mention that span, for example:
     ///
@@ -192,23 +247,15 @@ fn highlight_named_span(
         &self,
         tcx: TyCtxt<'_, '_, 'tcx>,
         error_region: &RegionKind,
-        name: &InternedString,
+        name: &RegionName,
         diag: &mut DiagnosticBuilder<'_>,
     ) {
-        let cm = tcx.sess.source_map();
+        let span = self.get_span_of_named_region(tcx, error_region, name);
 
-        let scope = error_region.free_region_binding_scope(tcx);
-        let node = tcx.hir.as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID);
-
-        let mut sp = cm.def_span(tcx.hir.span(node));
-        if let Some(param) = tcx.hir
-            .get_generics(scope)
-            .and_then(|generics| generics.get_named(name))
-        {
-            sp = param.span;
-        }
-
-        diag.span_label(sp, format!("lifetime `{}` defined here", name));
+        diag.span_label(
+            span,
+            format!("lifetime `{}` defined here", name),
+        );
     }
 
     /// Find an argument that contains `fr` and label it with a fully
@@ -227,7 +274,7 @@ fn give_name_if_anonymous_region_appears_in_arguments(
         fr: RegionVid,
         counter: &mut usize,
         diag: &mut DiagnosticBuilder<'_>,
-    ) -> Option<InternedString> {
+    ) -> Option<RegionName> {
         let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
         let argument_index = self.get_argument_index_for_region(infcx.tcx, fr)?;
 
@@ -259,7 +306,7 @@ fn give_name_if_we_can_match_hir_ty_from_argument(
         argument_index: usize,
         counter: &mut usize,
         diag: &mut DiagnosticBuilder<'_>,
-    ) -> Option<InternedString> {
+    ) -> Option<RegionName> {
         let mir_node_id = infcx.tcx.hir.as_local_node_id(mir_def_id)?;
         let fn_decl = infcx.tcx.hir.fn_decl(mir_node_id)?;
         let argument_hir_ty: &hir::Ty = &fn_decl.inputs[argument_index];
@@ -306,7 +353,7 @@ fn give_name_if_we_cannot_match_hir_ty(
         argument_ty: Ty<'tcx>,
         counter: &mut usize,
         diag: &mut DiagnosticBuilder<'_>,
-    ) -> Option<InternedString> {
+    ) -> Option<RegionName> {
         let type_name = with_highlight_region(needle_fr, *counter, || {
             infcx.extract_type_name(&argument_ty)
         });
@@ -361,7 +408,7 @@ fn give_name_if_we_can_match_hir_ty(
         argument_hir_ty: &hir::Ty,
         counter: &mut usize,
         diag: &mut DiagnosticBuilder<'_>,
-    ) -> Option<InternedString> {
+    ) -> Option<RegionName> {
         let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty)> = &mut Vec::new();
 
         search_stack.push((argument_ty, argument_hir_ty));
@@ -457,7 +504,7 @@ fn match_adt_and_segment<'hir>(
         counter: &mut usize,
         diag: &mut DiagnosticBuilder<'_>,
         search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty)>,
-    ) -> Option<InternedString> {
+    ) -> Option<RegionName> {
         // Did the user give explicit arguments? (e.g., `Foo<..>`)
         let args = last_segment.args.as_ref()?;
         let lifetime = self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
@@ -467,7 +514,10 @@ fn match_adt_and_segment<'hir>(
             | hir::LifetimeName::Underscore => {
                 let region_name = self.synthesize_region_name(counter);
                 let ampersand_span = lifetime.span;
-                diag.span_label(ampersand_span, format!("let's call this `{}`", region_name));
+                diag.span_label(
+                    ampersand_span,
+                    format!("let's call this `{}`", region_name)
+                );
                 return Some(region_name);
             }
 
@@ -544,7 +594,7 @@ fn give_name_if_anonymous_region_appears_in_upvars(
         fr: RegionVid,
         counter: &mut usize,
         diag: &mut DiagnosticBuilder<'_>,
-    ) -> Option<InternedString> {
+    ) -> Option<RegionName> {
         let upvar_index = self.get_upvar_index_for_region(tcx, fr)?;
         let (upvar_name, upvar_span) =
             self.get_upvar_name_and_span_for_region(tcx, mir, upvar_index);
@@ -573,7 +623,7 @@ fn give_name_if_anonymous_region_appears_in_output(
         fr: RegionVid,
         counter: &mut usize,
         diag: &mut DiagnosticBuilder<'_>,
-    ) -> Option<InternedString> {
+    ) -> Option<RegionName> {
         let tcx = infcx.tcx;
 
         let return_ty = self.universal_regions.unnormalized_output_ty;
@@ -622,10 +672,10 @@ fn give_name_if_anonymous_region_appears_in_output(
 
     /// Create a synthetic region named `'1`, incrementing the
     /// counter.
-    fn synthesize_region_name(&self, counter: &mut usize) -> InternedString {
+    fn synthesize_region_name(&self, counter: &mut usize) -> RegionName {
         let c = *counter;
         *counter += 1;
 
-        Name::intern(&format!("'{:?}", c)).as_interned_str()
+        RegionName::Synthesized(Name::intern(&format!("'{:?}", c)).as_interned_str())
     }
 }
index 214628600b370675e5708a51baa90ece318b7a96..d1713a520a79c7178767ae275c7cb2cd3c081320 100644 (file)
@@ -26,8 +26,8 @@
 };
 use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
 use rustc::util::common;
+use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::graph::scc::Sccs;
-use rustc_data_structures::indexed_set::IdxSet;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_errors::{DiagnosticBuilder, Diagnostic};
 
@@ -477,7 +477,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 IdxSet::new_empty(self.constraint_sccs.num_sccs());
+        let visited = &mut BitSet::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);
         }
@@ -487,9 +487,9 @@ fn propagate_constraints(&mut self, _mir: &Mir<'tcx>) {
     fn propagate_constraint_sccs_if_new(
         &mut self,
         scc_a: ConstraintSccIndex,
-        visited: &mut IdxSet<ConstraintSccIndex>,
+        visited: &mut BitSet<ConstraintSccIndex>,
     ) {
-        if visited.add(&scc_a) {
+        if visited.insert(scc_a) {
             self.propagate_constraint_sccs_new(scc_a, visited);
         }
     }
@@ -497,7 +497,7 @@ fn propagate_constraint_sccs_if_new(
     fn propagate_constraint_sccs_new(
         &mut self,
         scc_a: ConstraintSccIndex,
-        visited: &mut IdxSet<ConstraintSccIndex>,
+        visited: &mut BitSet<ConstraintSccIndex>,
     ) {
         let constraint_sccs = self.constraint_sccs.clone();
 
index 3dafab2f5a9f4da0ddd8e8b3b0b7fd50a9583ee6..8dc41a9b2d32d13df61fc6af0403527c6b51a8d9 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc::mir::{BasicBlock, Location, Mir};
 use rustc::ty::{self, RegionVid};
-use rustc_data_structures::bitvec::{BitArray, SparseBitMatrix};
+use rustc_data_structures::bit_set::{HybridBitSet, SparseBitMatrix};
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::indexed_vec::IndexVec;
 use std::fmt::Debug;
@@ -179,19 +179,19 @@ impl<N: Idx> LivenessValues<N> {
     crate fn add_element(&mut self, row: N, location: Location) -> bool {
         debug!("LivenessValues::add(r={:?}, location={:?})", row, location);
         let index = self.elements.point_from_location(location);
-        self.points.add(row, index)
+        self.points.insert(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 {
+    crate fn add_elements(&mut self, row: N, locations: &HybridBitSet<PointIndex>) -> bool {
         debug!("LivenessValues::add_elements(row={:?}, locations={:?})", row, locations);
-        self.points.merge_into(row, locations)
+        self.points.union_into_row(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);
+        self.points.insert_all_into_row(row);
     }
 
     /// True if the region `r` contains the given element.
@@ -270,15 +270,15 @@ impl<N: Idx> RegionValues<N> {
 
     /// Adds all the control-flow points to the values for `r`.
     crate fn add_all_points(&mut self, r: N) {
-        self.points.add_all(r);
+        self.points.insert_all_into_row(r);
     }
 
     /// Add all elements in `r_from` to `r_to` (because e.g. `r_to:
     /// r_from`).
     crate fn add_region(&mut self, r_to: N, r_from: N) -> bool {
-        self.points.merge(r_from, r_to)
-            | self.free_regions.merge(r_from, r_to)
-            | self.placeholders.merge(r_from, r_to)
+        self.points.union_rows(r_from, r_to)
+            | self.free_regions.union_rows(r_from, r_to)
+            | self.placeholders.union_rows(r_from, r_to)
     }
 
     /// True if the region `r` contains the given element.
@@ -291,7 +291,7 @@ impl<N: Idx> RegionValues<N> {
     /// the region `to` in `self`.
     crate fn merge_liveness<M: Idx>(&mut self, to: N, from: M, values: &LivenessValues<M>) {
         if let Some(set) = values.points.row(from) {
-            self.points.merge_into(to, set);
+            self.points.union_into_row(to, set);
         }
     }
 
@@ -300,7 +300,7 @@ impl<N: Idx> RegionValues<N> {
     crate fn contains_points(&self, sup_region: N, sub_region: N) -> bool {
         if let Some(sub_row) = self.points.row(sub_region) {
             if let Some(sup_row) = self.points.row(sup_region) {
-                sup_row.contains_all(sub_row)
+                sup_row.superset(sub_row)
             } else {
                 // sup row is empty, so sub row must be empty
                 sub_row.is_empty()
@@ -378,7 +378,7 @@ impl<N: Idx> RegionValues<N> {
 impl ToElementIndex for Location {
     fn add_to_row<N: Idx>(self, values: &mut RegionValues<N>, row: N) -> bool {
         let index = values.elements.point_from_location(self);
-        values.points.add(row, index)
+        values.points.insert(row, index)
     }
 
     fn contained_in_row<N: Idx>(self, values: &RegionValues<N>, row: N) -> bool {
@@ -389,7 +389,7 @@ fn contained_in_row<N: Idx>(self, values: &RegionValues<N>, row: N) -> bool {
 
 impl ToElementIndex for RegionVid {
     fn add_to_row<N: Idx>(self, values: &mut RegionValues<N>, row: N) -> bool {
-        values.free_regions.add(row, self)
+        values.free_regions.insert(row, self)
     }
 
     fn contained_in_row<N: Idx>(self, values: &RegionValues<N>, row: N) -> bool {
@@ -400,7 +400,7 @@ fn contained_in_row<N: Idx>(self, values: &RegionValues<N>, row: N) -> bool {
 impl ToElementIndex for ty::UniverseIndex {
     fn add_to_row<N: Idx>(self, values: &mut RegionValues<N>, row: N) -> bool {
         let index = PlaceholderIndex::new(self.as_usize() - 1);
-        values.placeholders.add(row, index)
+        values.placeholders.insert(row, index)
     }
 
     fn contained_in_row<N: Idx>(self, values: &RegionValues<N>, row: N) -> bool {
index 79589ce973372b551387dd9d9273f7edc8b1bcd6..47e6ce05cec1ff9cdc9485ba0d8d8796300b0ee7 100644 (file)
@@ -22,7 +22,7 @@
 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::bit_set::HybridBitSet;
 use rustc_data_structures::fx::FxHashMap;
 use std::rc::Rc;
 use util::liveness::LiveVariableMap;
@@ -121,16 +121,16 @@ struct LivenessResults<'me, 'typeck, 'flow, 'gcx, 'tcx>
     cx: LivenessContext<'me, 'typeck, 'flow, 'gcx, 'tcx>,
 
     /// Set of points that define the current local.
-    defs: BitArray<PointIndex>,
+    defs: HybridBitSet<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>,
+    use_live_at: HybridBitSet<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>,
+    drop_live_at: HybridBitSet<PointIndex>,
 
     /// Locations where drops may occur.
     drop_locations: Vec<Location>,
@@ -144,9 +144,9 @@ 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),
+            defs: HybridBitSet::new_empty(num_points),
+            use_live_at: HybridBitSet::new_empty(num_points),
+            drop_live_at: HybridBitSet::new_empty(num_points),
             drop_locations: vec![],
             stack: vec![],
         }
@@ -448,7 +448,7 @@ fn initialized_at_exit(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool
     fn add_use_live_facts_for(
         &mut self,
         value: impl TypeFoldable<'tcx>,
-        live_at: &BitArray<PointIndex>,
+        live_at: &HybridBitSet<PointIndex>,
     ) {
         debug!("add_use_live_facts_for(value={:?})", value);
 
@@ -465,7 +465,7 @@ fn add_drop_live_facts_for(
         dropped_local: Local,
         dropped_ty: Ty<'tcx>,
         drop_locations: &[Location],
-        live_at: &BitArray<PointIndex>,
+        live_at: &HybridBitSet<PointIndex>,
     ) {
         debug!(
             "add_drop_live_constraint(\
@@ -508,7 +508,7 @@ fn make_all_regions_live(
         elements: &RegionValueElements,
         typeck: &mut TypeChecker<'_, '_, 'tcx>,
         value: impl TypeFoldable<'tcx>,
-        live_at: &BitArray<PointIndex>,
+        live_at: &HybridBitSet<PointIndex>,
     ) {
         debug!("make_all_regions_live(value={:?})", value);
         debug!(
index bfb6daee6041ea80f58e2a80a2bbf5e18ad284ac..c4cb7958fd3c35865cf6eef19165b5c206227ff0 100644 (file)
@@ -167,7 +167,7 @@ fn ast_block_stmts(&mut self,
             // the case of `!`, no return value is required, as the block will never return.
             let tcx = this.hir.tcx();
             let ty = destination.ty(&this.local_decls, tcx).to_ty(tcx);
-            if ty.is_nil() {
+            if ty.is_unit() {
                 // We only want to assign an implicit `()` as the return value of the block if the
                 // block does not diverge. (Otherwise, we may try to assign a unit to a `!`-type.)
                 this.cfg.push_assign_unit(block, source_info, destination);
index 1ed8289d4418469544d5cd7400a6b718584516c6..8e40fd19941b3dc01fc94e5e56dbb936bb013c3a 100644 (file)
@@ -51,7 +51,7 @@ pub fn push_end_region<'a, 'gcx:'a+'tcx>(&mut self,
                                              source_info: SourceInfo,
                                              region_scope: region::Scope) {
         if tcx.emit_end_regions() {
-            if let region::ScopeData::CallSite(_) = region_scope.data() {
+            if let region::ScopeData::CallSite = region_scope.data {
                 // The CallSite scope (aka the root scope) is sort of weird, in that it is
                 // supposed to "separate" the "interior" and "exterior" of a closure. Being
                 // that, it is not really a part of the region hierarchy, but for some
index cef1fb77e5c9e68ade18b997619af33cf5a4e207..49c4ed874bbe971c9b775476e035d228a54764f8 100644 (file)
@@ -21,7 +21,7 @@
 use rustc::hir;
 use rustc::mir::*;
 use rustc::ty::{self, CanonicalTy, Ty};
-use rustc_data_structures::bitvec::BitArray;
+use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::fx::FxHashMap;
 use syntax::ast::{Name, NodeId};
 use syntax_pos::Span;
@@ -635,7 +635,7 @@ enum TestKind<'tcx> {
     // test the branches of enum
     Switch {
         adt_def: &'tcx ty::AdtDef,
-        variants: BitArray<usize>,
+        variants: BitSet<usize>,
     },
 
     // test the branches of enum
index 373c8e039f8de36a4479e144a4b992779dd26a98..caef3ef80dbc2c43ef26420a10f9943faa360656 100644 (file)
@@ -18,8 +18,8 @@
 use build::Builder;
 use build::matches::{Candidate, MatchPair, Test, TestKind};
 use hair::*;
+use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::bitvec::BitArray;
 use rustc::ty::{self, Ty};
 use rustc::ty::util::IntTypeExt;
 use rustc::mir::*;
@@ -38,7 +38,7 @@ pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
                     span: match_pair.pattern.span,
                     kind: TestKind::Switch {
                         adt_def: adt_def.clone(),
-                        variants: BitArray::new(adt_def.variants.len()),
+                        variants: BitSet::new_empty(adt_def.variants.len()),
                     },
                 }
             }
@@ -152,7 +152,7 @@ pub fn add_cases_to_switch<'pat>(&mut self,
     pub fn add_variants_to_switch<'pat>(&mut self,
                                         test_place: &Place<'tcx>,
                                         candidate: &Candidate<'pat, 'tcx>,
-                                        variants: &mut BitArray<usize>)
+                                        variants: &mut BitSet<usize>)
                                         -> bool
     {
         let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
index 576c91a02b08daed34dd64fb31da5371800ad30a..d2061d8eecf5f3d79667430fea1c4d0d0167b400 100644 (file)
@@ -550,8 +550,14 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
         upvar_decls);
 
     let fn_def_id = tcx.hir.local_def_id(fn_id);
-    let call_site_scope = region::Scope::CallSite(body.value.hir_id.local_id);
-    let arg_scope = region::Scope::Arguments(body.value.hir_id.local_id);
+    let call_site_scope = region::Scope {
+        id: body.value.hir_id.local_id,
+        data: region::ScopeData::CallSite
+    };
+    let arg_scope = region::Scope {
+        id: body.value.hir_id.local_id,
+        data: region::ScopeData::Arguments
+    };
     let mut block = START_BLOCK;
     let source_info = builder.source_info(span);
     let call_site_s = (call_site_scope, source_info);
index 38e0854bcd61eddabdd00c694f9efc45018d9a43..cc5b08f2a90474776ee07ef381c9b0f06d8fdb0e 100644 (file)
@@ -565,8 +565,8 @@ pub fn region_scope_of_return_scope(&self) -> region::Scope {
         // The outermost scope (`scopes[0]`) will be the `CallSiteScope`.
         // We want `scopes[1]`, which is the `ParameterScope`.
         assert!(self.scopes.len() >= 2);
-        assert!(match self.scopes[1].region_scope.data() {
-            region::ScopeData::Arguments(_) => true,
+        assert!(match self.scopes[1].region_scope.data {
+            region::ScopeData::Arguments => true,
             _ => false,
         });
         self.scopes[1].region_scope
index 1dc91cd05b33e9c7aeef0457942904c43ea47117..d815bfedc3713237ea72d6ae3102a50d940d4b1d 100644 (file)
@@ -12,7 +12,7 @@
 //! locations.
 
 use rustc::mir::{BasicBlock, Location};
-use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet, Iter};
+use rustc_data_structures::bit_set::{BitIter, BitSet, HybridBitSet};
 
 use dataflow::{BitDenotation, BlockSets, DataflowResults};
 use dataflow::move_paths::{HasMoveData, MovePathIndex};
@@ -75,9 +75,9 @@ pub struct FlowAtLocation<BD>
     BD: BitDenotation,
 {
     base_results: DataflowResults<BD>,
-    curr_state: IdxSet<BD::Idx>,
-    stmt_gen: HybridIdxSet<BD::Idx>,
-    stmt_kill: HybridIdxSet<BD::Idx>,
+    curr_state: BitSet<BD::Idx>,
+    stmt_gen: HybridBitSet<BD::Idx>,
+    stmt_kill: HybridBitSet<BD::Idx>,
 }
 
 impl<BD> FlowAtLocation<BD>
@@ -104,9 +104,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 = IdxSet::new_empty(bits_per_block);
-        let stmt_gen = HybridIdxSet::new_empty(bits_per_block);
-        let stmt_kill = HybridIdxSet::new_empty(bits_per_block);
+        let curr_state = BitSet::new_empty(bits_per_block);
+        let stmt_gen = HybridBitSet::new_empty(bits_per_block);
+        let stmt_kill = HybridBitSet::new_empty(bits_per_block);
         FlowAtLocation {
             base_results: results,
             curr_state: curr_state,
@@ -120,12 +120,12 @@ pub fn operator(&self) -> &BD {
         self.base_results.operator()
     }
 
-    pub fn contains(&self, x: &BD::Idx) -> bool {
+    pub fn contains(&self, x: BD::Idx) -> bool {
         self.curr_state.contains(x)
     }
 
     /// Returns an iterator over the elements present in the current state.
-    pub fn iter_incoming(&self) -> iter::Peekable<Iter<BD::Idx>> {
+    pub fn iter_incoming(&self) -> iter::Peekable<BitIter<BD::Idx>> {
         self.curr_state.iter().peekable()
     }
 
@@ -134,7 +134,7 @@ pub fn iter_incoming(&self) -> iter::Peekable<Iter<BD::Idx>> {
     /// Invokes `f` with an iterator over the resulting state.
     pub fn with_iter_outgoing<F>(&self, f: F)
     where
-        F: FnOnce(Iter<BD::Idx>),
+        F: FnOnce(BitIter<BD::Idx>),
     {
         let mut curr_state = self.curr_state.clone();
         curr_state.union(&self.stmt_gen);
@@ -223,7 +223,7 @@ pub fn has_any_child_of(&self, mpi: T::Idx) -> Option<T::Idx> {
         //   siblings);
         // - ~99% of the time the loop isn't reached, and this code is hot, so
         //   we don't want to allocate `todo` unnecessarily.
-        if self.contains(&mpi) {
+        if self.contains(mpi) {
             return Some(mpi);
         }
         let move_data = self.operator().move_data();
@@ -235,7 +235,7 @@ pub fn has_any_child_of(&self, mpi: T::Idx) -> Option<T::Idx> {
         };
 
         while let Some(mpi) = todo.pop() {
-            if self.contains(&mpi) {
+            if self.contains(mpi) {
                 return Some(mpi);
             }
             let move_path = &move_data.move_paths[mpi];
index 2b5d26c748704f1655ff225b08b859d82b5f9788..45baab844abc35cdcf1e517e6bbe84223f1ee2b3 100644 (file)
@@ -12,7 +12,6 @@
 
 use syntax::ast::NodeId;
 use rustc::mir::{BasicBlock, Mir};
-use rustc_data_structures::bitslice::bits_to_string;
 
 use dot;
 use dot::IntoCow;
@@ -223,7 +222,7 @@ fn node_label_final_row<W: io::Write>(&self,
 
         // Entry
         let set = flow.sets.on_entry_set_for(i);
-        write!(w, "<td>{:?}</td>", dot::escape_html(&bits_to_string(set.words(), bits_per_block)))?;
+        write!(w, "<td>{:?}</td>", dot::escape_html(&set.to_string(bits_per_block)))?;
 
         // Terminator
         write!(w, "<td>")?;
index c8c41c13b0fbb684fbaa8967689f6fb12f9a3508..8d186597b142c32517a3ccd680549971c9595780 100644 (file)
@@ -43,7 +43,7 @@ fn bits_per_block(&self) -> usize {
         self.mir.local_decls.len()
     }
 
-    fn start_block_effect(&self, _sets: &mut IdxSet<Local>) {
+    fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
         // Nothing is borrowed on function entry
     }
 
@@ -58,7 +58,7 @@ fn statement_effect(&self,
 
         // StorageDead invalidates all borrows and raw pointers to a local
         match stmt.kind {
-            StatementKind::StorageDead(l) => sets.kill(&l),
+            StatementKind::StorageDead(l) => sets.kill(l),
             _ => (),
         }
     }
@@ -72,7 +72,7 @@ fn terminator_effect(&self,
     }
 
     fn propagate_call_return(&self,
-                             _in_out: &mut IdxSet<Local>,
+                             _in_out: &mut BitSet<Local>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              _dest_place: &mir::Place) {
@@ -80,10 +80,10 @@ fn propagate_call_return(&self,
     }
 }
 
-impl<'a, 'tcx> BitwiseOperator for HaveBeenBorrowedLocals<'a, 'tcx> {
+impl<'a, 'tcx> BitSetOperator for HaveBeenBorrowedLocals<'a, 'tcx> {
     #[inline]
-    fn join(&self, pred1: Word, pred2: Word) -> Word {
-        pred1 | pred2 // "maybe" means we union effects of both preds
+    fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
+        inout_set.union(in_set) // "maybe" means we union effects of both preds
     }
 }
 
@@ -118,7 +118,7 @@ fn visit_rvalue(&mut self,
                     location: Location) {
         if let Rvalue::Ref(_, _, ref place) = *rvalue {
             if let Some(local) = find_local(place) {
-                self.sets.gen(&local);
+                self.sets.gen(local);
             }
         }
 
index cc92cdecc60768fab8d657ca7b1c3ee78ecef0a2..010ffafc4bd60db7e057529b301a01cf478ec368 100644 (file)
 use rustc::ty::{RegionKind, RegionVid};
 use rustc::ty::RegionKind::ReScope;
 
-use rustc_data_structures::bitslice::{BitwiseOperator, Word};
+use rustc_data_structures::bit_set::{BitSet, BitSetOperator};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::indexed_set::IdxSet;
-use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::sync::Lrc;
 
 use dataflow::{BitDenotation, BlockSets, InitialFlow};
@@ -157,7 +156,10 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
     ) -> Self {
         let scope_tree = tcx.region_scope_tree(def_id);
         let root_scope = body_id.map(|body_id| {
-            region::Scope::CallSite(tcx.hir.body(body_id).value.hir_id.local_id)
+            region::Scope {
+                id: tcx.hir.body(body_id).value.hir_id.local_id,
+                data: region::ScopeData::CallSite
+            }
         });
 
         let mut borrows_out_of_scope_at_location = FxHashMap();
@@ -227,7 +229,7 @@ fn bits_per_block(&self) -> usize {
         self.borrow_set.borrows.len() * 2
     }
 
-    fn start_block_effect(&self, _entry_set: &mut IdxSet<BorrowIndex>) {
+    fn start_block_effect(&self, _entry_set: &mut BitSet<BorrowIndex>) {
         // no borrows of code region_scopes have been taken prior to
         // function execution, so this method has no effect on
         // `_sets`.
@@ -286,7 +288,7 @@ fn statement_effect(&self, sets: &mut BlockSets<BorrowIndex>, location: Location
                         debug!("Borrows::statement_effect_on_borrows \
                                 location: {:?} stmt: {:?} has empty region, killing {:?}",
                                location, stmt.kind, index);
-                        sets.kill(&index);
+                        sets.kill(*index);
                         return
                     } else {
                         debug!("Borrows::statement_effect_on_borrows location: {:?} stmt: {:?}",
@@ -296,7 +298,7 @@ fn statement_effect(&self, sets: &mut BlockSets<BorrowIndex>, location: Location
                     assert!(self.borrow_set.region_map.get(region).unwrap_or_else(|| {
                         panic!("could not find BorrowIndexs for region {:?}", region);
                     }).contains(&index));
-                    sets.gen(&index);
+                    sets.gen(*index);
 
                     // Issue #46746: Two-phase borrows handles
                     // stmts of form `Tmp = &mut Borrow` ...
@@ -308,7 +310,7 @@ fn statement_effect(&self, sets: &mut BlockSets<BorrowIndex>, location: Location
                             // e.g. `box (&mut _)`. Current
                             // conservative solution: force
                             // immediate activation here.
-                            sets.gen(&index);
+                            sets.gen(*index);
                         }
                     }
                 }
@@ -378,7 +380,7 @@ fn terminator_effect(&self, sets: &mut BlockSets<BorrowIndex>, location: Locatio
                             if *scope != root_scope &&
                                 self.scope_tree.is_subscope_of(*scope, root_scope)
                             {
-                                sets.kill(&borrow_index);
+                                sets.kill(borrow_index);
                             }
                         }
                     }
@@ -399,7 +401,7 @@ fn terminator_effect(&self, sets: &mut BlockSets<BorrowIndex>, location: Locatio
     }
 
     fn propagate_call_return(&self,
-                             _in_out: &mut IdxSet<BorrowIndex>,
+                             _in_out: &mut BitSet<BorrowIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              _dest_place: &mir::Place) {
@@ -411,10 +413,10 @@ fn propagate_call_return(&self,
     }
 }
 
-impl<'a, 'gcx, 'tcx> BitwiseOperator for Borrows<'a, 'gcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitSetOperator for Borrows<'a, 'gcx, 'tcx> {
     #[inline]
-    fn join(&self, pred1: Word, pred2: Word) -> Word {
-        pred1 | pred2 // union effects of preds when computing reservations
+    fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
+        inout_set.union(in_set) // "maybe" means we union effects of both preds
     }
 }
 
index 62c6018809f39ef161b8407d8b0c26b0c4c657c1..984d1f686d987bfeb645d3ce1e15b8004fe5add2 100644 (file)
@@ -14,8 +14,7 @@
 
 use rustc::ty::TyCtxt;
 use rustc::mir::{self, Mir, Location};
-use rustc_data_structures::bitslice::{BitwiseOperator, Word};
-use rustc_data_structures::indexed_set::{IdxSet};
+use rustc_data_structures::bit_set::{BitSet, BitSetOperator};
 use rustc_data_structures::indexed_vec::Idx;
 
 use super::MoveDataParamEnv;
@@ -266,8 +265,8 @@ fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
                    state: DropFlagState)
     {
         match state {
-            DropFlagState::Absent => sets.kill(&path),
-            DropFlagState::Present => sets.gen(&path),
+            DropFlagState::Absent => sets.kill(path),
+            DropFlagState::Present => sets.gen(path),
         }
     }
 }
@@ -277,8 +276,8 @@ fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
                    state: DropFlagState)
     {
         match state {
-            DropFlagState::Absent => sets.gen(&path),
-            DropFlagState::Present => sets.kill(&path),
+            DropFlagState::Absent => sets.gen(path),
+            DropFlagState::Present => sets.kill(path),
         }
     }
 }
@@ -288,8 +287,8 @@ fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
                    state: DropFlagState)
     {
         match state {
-            DropFlagState::Absent => sets.kill(&path),
-            DropFlagState::Present => sets.gen(&path),
+            DropFlagState::Absent => sets.kill(path),
+            DropFlagState::Present => sets.gen(path),
         }
     }
 }
@@ -301,12 +300,12 @@ fn bits_per_block(&self) -> usize {
         self.move_data().move_paths.len()
     }
 
-    fn start_block_effect(&self, entry_set: &mut IdxSet<MovePathIndex>) {
+    fn start_block_effect(&self, entry_set: &mut BitSet<MovePathIndex>) {
         drop_flag_effects_for_function_entry(
             self.tcx, self.mir, self.mdpe,
             |path, s| {
                 assert!(s == DropFlagState::Present);
-                entry_set.add(&path);
+                entry_set.insert(path);
             });
     }
 
@@ -333,7 +332,7 @@ fn terminator_effect(&self,
     }
 
     fn propagate_call_return(&self,
-                             in_out: &mut IdxSet<MovePathIndex>,
+                             in_out: &mut BitSet<MovePathIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              dest_place: &mir::Place) {
@@ -341,7 +340,7 @@ fn propagate_call_return(&self,
         // the bits for that dest_place to 1 (initialized).
         on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
                               self.move_data().rev_lookup.find(dest_place),
-                              |mpi| { in_out.add(&mpi); });
+                              |mpi| { in_out.insert(mpi); });
     }
 }
 
@@ -353,7 +352,7 @@ fn bits_per_block(&self) -> usize {
     }
 
     // sets on_entry bits for Arg places
-    fn start_block_effect(&self, entry_set: &mut IdxSet<MovePathIndex>) {
+    fn start_block_effect(&self, entry_set: &mut BitSet<MovePathIndex>) {
         // set all bits to 1 (uninit) before gathering counterevidence
         entry_set.set_up_to(self.bits_per_block());
 
@@ -361,7 +360,7 @@ fn start_block_effect(&self, entry_set: &mut IdxSet<MovePathIndex>) {
             self.tcx, self.mir, self.mdpe,
             |path, s| {
                 assert!(s == DropFlagState::Present);
-                entry_set.remove(&path);
+                entry_set.remove(path);
             });
     }
 
@@ -388,7 +387,7 @@ fn terminator_effect(&self,
     }
 
     fn propagate_call_return(&self,
-                             in_out: &mut IdxSet<MovePathIndex>,
+                             in_out: &mut BitSet<MovePathIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              dest_place: &mir::Place) {
@@ -396,7 +395,7 @@ fn propagate_call_return(&self,
         // the bits for that dest_place to 0 (initialized).
         on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
                               self.move_data().rev_lookup.find(dest_place),
-                              |mpi| { in_out.remove(&mpi); });
+                              |mpi| { in_out.remove(mpi); });
     }
 }
 
@@ -408,14 +407,14 @@ fn bits_per_block(&self) -> usize {
     }
 
     // sets on_entry bits for Arg places
-    fn start_block_effect(&self, entry_set: &mut IdxSet<MovePathIndex>) {
+    fn start_block_effect(&self, entry_set: &mut BitSet<MovePathIndex>) {
         entry_set.clear();
 
         drop_flag_effects_for_function_entry(
             self.tcx, self.mir, self.mdpe,
             |path, s| {
                 assert!(s == DropFlagState::Present);
-                entry_set.add(&path);
+                entry_set.insert(path);
             });
     }
 
@@ -442,7 +441,7 @@ fn terminator_effect(&self,
     }
 
     fn propagate_call_return(&self,
-                             in_out: &mut IdxSet<MovePathIndex>,
+                             in_out: &mut BitSet<MovePathIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              dest_place: &mir::Place) {
@@ -450,7 +449,7 @@ fn propagate_call_return(&self,
         // the bits for that dest_place to 1 (initialized).
         on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
                               self.move_data().rev_lookup.find(dest_place),
-                              |mpi| { in_out.add(&mpi); });
+                              |mpi| { in_out.insert(mpi); });
     }
 }
 
@@ -461,9 +460,9 @@ fn bits_per_block(&self) -> usize {
         self.move_data().inits.len()
     }
 
-    fn start_block_effect(&self, entry_set: &mut IdxSet<InitIndex>) {
+    fn start_block_effect(&self, entry_set: &mut BitSet<InitIndex>) {
         for arg_init in 0..self.mir.arg_count {
-            entry_set.add(&InitIndex::new(arg_init));
+            entry_set.insert(InitIndex::new(arg_init));
         }
     }
 
@@ -531,7 +530,7 @@ fn terminator_effect(&self,
     }
 
     fn propagate_call_return(&self,
-                             in_out: &mut IdxSet<InitIndex>,
+                             in_out: &mut BitSet<InitIndex>,
                              call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              _dest_place: &mir::Place) {
@@ -545,36 +544,36 @@ fn propagate_call_return(&self,
         };
         for init_index in &init_loc_map[call_loc] {
             assert!(init_index.index() < bits_per_block);
-            in_out.add(init_index);
+            in_out.insert(*init_index);
         }
     }
 }
 
-impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeInitializedPlaces<'a, 'gcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitSetOperator for MaybeInitializedPlaces<'a, 'gcx, 'tcx> {
     #[inline]
-    fn join(&self, pred1: Word, pred2: Word) -> Word {
-        pred1 | pred2 // "maybe" means we union effects of both preds
+    fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
+        inout_set.union(in_set) // "maybe" means we union effects of both preds
     }
 }
 
-impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitSetOperator for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> {
     #[inline]
-    fn join(&self, pred1: Word, pred2: Word) -> Word {
-        pred1 | pred2 // "maybe" means we union effects of both preds
+    fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
+        inout_set.union(in_set) // "maybe" means we union effects of both preds
     }
 }
 
-impl<'a, 'gcx, 'tcx> BitwiseOperator for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitSetOperator for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> {
     #[inline]
-    fn join(&self, pred1: Word, pred2: Word) -> Word {
-        pred1 & pred2 // "definitely" means we intersect effects of both preds
+    fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
+        inout_set.intersect(in_set) // "definitely" means we intersect effects of both preds
     }
 }
 
-impl<'a, 'gcx, 'tcx> BitwiseOperator for EverInitializedPlaces<'a, 'gcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitSetOperator for EverInitializedPlaces<'a, 'gcx, 'tcx> {
     #[inline]
-    fn join(&self, pred1: Word, pred2: Word) -> Word {
-        pred1 | pred2 // inits from both preds are in scope
+    fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
+        inout_set.union(in_set) // inits from both preds are in scope
     }
 }
 
index 29548051a4d927e73b36c74af845fa84671a3a92..ab03ace23d7b4ef635a9c39f6e82bee7da5dc15e 100644 (file)
@@ -36,7 +36,7 @@ fn bits_per_block(&self) -> usize {
         self.mir.local_decls.len()
     }
 
-    fn start_block_effect(&self, _sets: &mut IdxSet<Local>) {
+    fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
         // Nothing is live on function entry
     }
 
@@ -46,8 +46,8 @@ fn statement_effect(&self,
         let stmt = &self.mir[loc.block].statements[loc.statement_index];
 
         match stmt.kind {
-            StatementKind::StorageLive(l) => sets.gen(&l),
-            StatementKind::StorageDead(l) => sets.kill(&l),
+            StatementKind::StorageLive(l) => sets.gen(l),
+            StatementKind::StorageDead(l) => sets.kill(l),
             _ => (),
         }
     }
@@ -59,7 +59,7 @@ fn terminator_effect(&self,
     }
 
     fn propagate_call_return(&self,
-                             _in_out: &mut IdxSet<Local>,
+                             _in_out: &mut BitSet<Local>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              _dest_place: &mir::Place) {
@@ -67,10 +67,10 @@ fn propagate_call_return(&self,
     }
 }
 
-impl<'a, 'tcx> BitwiseOperator for MaybeStorageLive<'a, 'tcx> {
+impl<'a, 'tcx> BitSetOperator for MaybeStorageLive<'a, 'tcx> {
     #[inline]
-    fn join(&self, pred1: Word, pred2: Word) -> Word {
-        pred1 | pred2 // "maybe" means we union effects of both preds
+    fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
+        inout_set.union(in_set) // "maybe" means we union effects of both preds
     }
 }
 
index d6874e290d4f6cb7398fff416d826d55c70338ab..1e362e6f0dccfeb55b816d62192216370f1d1589 100644 (file)
@@ -10,8 +10,7 @@
 
 use syntax::ast::{self, MetaItem};
 
-use rustc_data_structures::bitslice::{bitwise, BitwiseOperator};
-use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet};
+use rustc_data_structures::bit_set::{BitSet, BitSetOperator, HybridBitSet};
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::work_queue::WorkQueue;
 
@@ -125,7 +124,7 @@ pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                                  mir: &'a Mir<'tcx>,
                                                  node_id: ast::NodeId,
                                                  attributes: &[ast::Attribute],
-                                                 dead_unwinds: &IdxSet<BasicBlock>,
+                                                 dead_unwinds: &BitSet<BasicBlock>,
                                                  bd: BD,
                                                  p: P)
                                                  -> DataflowResults<BD>
@@ -182,7 +181,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 = IdxSet::new_empty(self.flow_state.sets.bits_per_block);
+        let mut temp = BitSet::new_empty(self.flow_state.sets.bits_per_block);
         let mut propcx = PropagationContext {
             builder: self,
         };
@@ -231,7 +230,7 @@ fn build_sets(&mut self) {
 
 impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> where BD: BitDenotation
 {
-    fn walk_cfg(&mut self, in_out: &mut IdxSet<BD::Idx>) {
+    fn walk_cfg(&mut self, in_out: &mut BitSet<BD::Idx>) {
         let mut dirty_queue: WorkQueue<mir::BasicBlock> =
             WorkQueue::with_all(self.builder.mir.basic_blocks().len());
         let mir = self.builder.mir;
@@ -352,7 +351,7 @@ pub fn state_for_location<'tcx, T: BitDenotation>(loc: Location,
                                                   analysis: &T,
                                                   result: &DataflowResults<T>,
                                                   mir: &Mir<'tcx>)
-    -> IdxSet<T::Idx> {
+    -> BitSet<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();
@@ -385,7 +384,7 @@ pub fn state_for_location<'tcx, T: BitDenotation>(loc: Location,
 pub struct DataflowAnalysis<'a, 'tcx: 'a, O> where O: BitDenotation
 {
     flow_state: DataflowState<O>,
-    dead_unwinds: &'a IdxSet<mir::BasicBlock>,
+    dead_unwinds: &'a BitSet<mir::BasicBlock>,
     mir: &'a Mir<'tcx>,
 }
 
@@ -426,7 +425,7 @@ pub struct DataflowState<O: BitDenotation>
 impl<O: BitDenotation> DataflowState<O> {
     pub(crate) fn interpret_set<'c, P>(&self,
                                        o: &'c O,
-                                       set: &IdxSet<O::Idx>,
+                                       set: &BitSet<O::Idx>,
                                        render_idx: &P)
                                        -> Vec<DebugFormatted>
         where P: Fn(&O, O::Idx) -> DebugFormatted
@@ -436,7 +435,7 @@ pub(crate) fn interpret_set<'c, P>(&self,
 
     pub(crate) fn interpret_hybrid_set<'c, P>(&self,
                                               o: &'c O,
-                                              set: &HybridIdxSet<O::Idx>,
+                                              set: &HybridBitSet<O::Idx>,
                                               render_idx: &P)
                                               -> Vec<DebugFormatted>
         where P: Fn(&O, O::Idx) -> DebugFormatted
@@ -451,21 +450,21 @@ pub struct AllSets<E: Idx> {
     bits_per_block: usize,
 
     /// For each block, bits valid on entry to the block.
-    on_entry_sets: Vec<IdxSet<E>>,
+    on_entry_sets: Vec<BitSet<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>>,
+    gen_sets: Vec<HybridBitSet<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>>,
+    kill_sets: Vec<HybridBitSet<E>>,
 }
 
 /// Triple of sets associated with a given block.
@@ -485,20 +484,20 @@ pub struct AllSets<E: Idx> {
 #[derive(Debug)]
 pub struct BlockSets<'a, E: Idx> {
     /// Dataflow state immediately before control flow enters the given block.
-    pub(crate) on_entry: &'a mut IdxSet<E>,
+    pub(crate) on_entry: &'a mut BitSet<E>,
 
     /// 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 HybridIdxSet<E>,
+    pub(crate) gen_set: &'a mut HybridBitSet<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 HybridIdxSet<E>,
+    pub(crate) kill_set: &'a mut HybridBitSet<E>,
 }
 
 impl<'a, E:Idx> BlockSets<'a, E> {
-    fn gen(&mut self, e: &E) {
-        self.gen_set.add(e);
+    fn gen(&mut self, e: E) {
+        self.gen_set.insert(e);
         self.kill_set.remove(e);
     }
     fn gen_all<I>(&mut self, i: I)
@@ -506,13 +505,13 @@ fn gen_all<I>(&mut self, i: I)
               I::Item: Borrow<E>
     {
         for j in i {
-            self.gen(j.borrow());
+            self.gen(*j.borrow());
         }
     }
 
-    fn kill(&mut self, e: &E) {
+    fn kill(&mut self, e: E) {
         self.gen_set.remove(e);
-        self.kill_set.add(e);
+        self.kill_set.insert(e);
     }
 
     fn kill_all<I>(&mut self, i: I)
@@ -520,7 +519,7 @@ fn kill_all<I>(&mut self, i: I)
               I::Item: Borrow<E>
     {
         for j in i {
-            self.kill(j.borrow());
+            self.kill(*j.borrow());
         }
     }
 
@@ -540,13 +539,13 @@ pub fn for_block(&mut self, block_idx: usize) -> BlockSets<E> {
         }
     }
 
-    pub fn on_entry_set_for(&self, block_idx: usize) -> &IdxSet<E> {
+    pub fn on_entry_set_for(&self, block_idx: usize) -> &BitSet<E> {
         &self.on_entry_sets[block_idx]
     }
-    pub fn gen_set_for(&self, block_idx: usize) -> &HybridIdxSet<E> {
+    pub fn gen_set_for(&self, block_idx: usize) -> &HybridBitSet<E> {
         &self.gen_sets[block_idx]
     }
-    pub fn kill_set_for(&self, block_idx: usize) -> &HybridIdxSet<E> {
+    pub fn kill_set_for(&self, block_idx: usize) -> &HybridBitSet<E> {
         &self.kill_sets[block_idx]
     }
 }
@@ -562,7 +561,7 @@ pub trait InitialFlow {
     fn bottom_value() -> bool;
 }
 
-pub trait BitDenotation: BitwiseOperator {
+pub trait BitDenotation: BitSetOperator {
     /// Specifies what index type is used to access the bitvector.
     type Idx: Idx;
 
@@ -609,7 +608,7 @@ fn accumulates_intrablock_state() -> bool { false }
     /// these won't be accounted for correctly.
     ///
     /// (For example, establishing the call arguments.)
-    fn start_block_effect(&self, entry_set: &mut IdxSet<Self::Idx>);
+    fn start_block_effect(&self, entry_set: &mut BitSet<Self::Idx>);
 
     /// Similar to `statement_effect`, except it applies
     /// *just before* the statement rather than *just after* it.
@@ -689,7 +688,7 @@ fn terminator_effect(&self,
     /// kill-sets associated with each edge coming out of the basic
     /// block.
     fn propagate_call_return(&self,
-                             in_out: &mut IdxSet<Self::Idx>,
+                             in_out: &mut BitSet<Self::Idx>,
                              call_bb: mir::BasicBlock,
                              dest_bb: mir::BasicBlock,
                              dest_place: &mir::Place);
@@ -698,17 +697,17 @@ fn propagate_call_return(&self,
 impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
 {
     pub fn new(mir: &'a Mir<'tcx>,
-               dead_unwinds: &'a IdxSet<mir::BasicBlock>,
+               dead_unwinds: &'a BitSet<mir::BasicBlock>,
                denotation: D) -> Self where D: InitialFlow {
         let bits_per_block = denotation.bits_per_block();
         let num_blocks = mir.basic_blocks().len();
 
         let on_entry_sets = if D::bottom_value() {
-            vec![IdxSet::new_filled(bits_per_block); num_blocks]
+            vec![BitSet::new_filled(bits_per_block); num_blocks]
         } else {
-            vec![IdxSet::new_empty(bits_per_block); num_blocks]
+            vec![BitSet::new_empty(bits_per_block); num_blocks]
         };
-        let gen_sets = vec![HybridIdxSet::new_empty(bits_per_block); num_blocks];
+        let gen_sets = vec![HybridBitSet::new_empty(bits_per_block); num_blocks];
         let kill_sets = gen_sets.clone();
 
         DataflowAnalysis {
@@ -727,7 +726,7 @@ pub fn new(mir: &'a Mir<'tcx>,
     }
 
     pub fn new_from_sets(mir: &'a Mir<'tcx>,
-                         dead_unwinds: &'a IdxSet<mir::BasicBlock>,
+                         dead_unwinds: &'a BitSet<mir::BasicBlock>,
                          sets: AllSets<D::Idx>,
                          denotation: D) -> Self {
         DataflowAnalysis {
@@ -758,7 +757,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
     /// unwind target).
     fn propagate_bits_into_graph_successors_of(
         &mut self,
-        in_out: &mut IdxSet<D::Idx>,
+        in_out: &mut BitSet<D::Idx>,
         (bb, bb_data): (mir::BasicBlock, &mir::BasicBlockData),
         dirty_list: &mut WorkQueue<mir::BasicBlock>)
     {
@@ -787,7 +786,7 @@ fn propagate_bits_into_graph_successors_of(
                 target, value: _, location: _, unwind: Some(unwind)
             } => {
                 self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
-                if !self.dead_unwinds.contains(&bb) {
+                if !self.dead_unwinds.contains(bb) {
                     self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
                 }
             }
@@ -798,7 +797,7 @@ fn propagate_bits_into_graph_successors_of(
             }
             mir::TerminatorKind::Call { cleanup, ref destination, func: _, args: _ } => {
                 if let Some(unwind) = cleanup {
-                    if !self.dead_unwinds.contains(&bb) {
+                    if !self.dead_unwinds.contains(bb) {
                         self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
                     }
                 }
@@ -819,7 +818,7 @@ fn propagate_bits_into_graph_successors_of(
             mir::TerminatorKind::FalseUnwind { real_target, unwind } => {
                 self.propagate_bits_into_entry_set_for(in_out, real_target, dirty_list);
                 if let Some(unwind) = unwind {
-                    if !self.dead_unwinds.contains(&bb) {
+                    if !self.dead_unwinds.contains(bb) {
                         self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
                     }
                 }
@@ -828,13 +827,11 @@ fn propagate_bits_into_graph_successors_of(
     }
 
     fn propagate_bits_into_entry_set_for(&mut self,
-                                         in_out: &IdxSet<D::Idx>,
+                                         in_out: &BitSet<D::Idx>,
                                          bb: mir::BasicBlock,
                                          dirty_queue: &mut WorkQueue<mir::BasicBlock>) {
-        let entry_set = self.flow_state.sets.for_block(bb.index()).on_entry;
-        let set_changed = bitwise(entry_set.words_mut(),
-                                  in_out.words(),
-                                  &self.flow_state.operator);
+        let entry_set = &mut self.flow_state.sets.for_block(bb.index()).on_entry;
+        let set_changed = self.flow_state.operator.join(entry_set, &in_out);
         if set_changed {
             dirty_queue.insert(bb);
         }
index 7d7da6c96e8699fe3976836d544b743d783d6f77..58a2b9361032e579ac3767cf5ecab10ab11762ee 100644 (file)
@@ -97,6 +97,20 @@ pub struct MovePath<'tcx> {
     pub place: Place<'tcx>,
 }
 
+impl<'tcx> MovePath<'tcx> {
+    pub fn parents(&self, move_paths: &IndexVec<MovePathIndex, MovePath>) -> Vec<MovePathIndex> {
+        let mut parents = Vec::new();
+
+        let mut curr_parent = self.parent;
+        while let Some(parent_mpi) = curr_parent {
+            parents.push(parent_mpi);
+            curr_parent = move_paths[parent_mpi].parent;
+        }
+
+        parents
+    }
+}
+
 impl<'tcx> fmt::Debug for MovePath<'tcx> {
     fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
         write!(w, "MovePath {{")?;
index 85a9734a601011234096a268834990f9b37ee5bc..2ab0a57a855419f23dae98a2d220ebaed70c32ba 100644 (file)
@@ -11,7 +11,7 @@
 use hair::*;
 use hair::cx::Cx;
 use hair::cx::to_ref::ToRef;
-use rustc::middle::region::{self, BlockRemainder};
+use rustc::middle::region;
 use rustc::hir;
 
 use rustc_data_structures::indexed_vec::Idx;
@@ -27,7 +27,10 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> {
             cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id);
         Block {
             targeted_by_break: self.targeted_by_break,
-            region_scope: region::Scope::Node(self.hir_id.local_id),
+            region_scope: region::Scope {
+                id: self.hir_id.local_id,
+                data: region::ScopeData::Node
+            },
             opt_destruction_scope,
             span: self.span,
             stmts,
@@ -59,7 +62,10 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             hir::StmtKind::Semi(ref expr, _) => {
                 result.push(StmtRef::Mirror(Box::new(Stmt {
                     kind: StmtKind::Expr {
-                        scope: region::Scope::Node(hir_id.local_id),
+                        scope: region::Scope {
+                            id: hir_id.local_id,
+                            data: region::ScopeData::Node
+                        },
                         expr: expr.to_ref(),
                     },
                     opt_destruction_scope: opt_dxn_ext,
@@ -71,10 +77,11 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         // ignore for purposes of the MIR
                     }
                     hir::DeclKind::Local(ref local) => {
-                        let remainder_scope = region::Scope::Remainder(BlockRemainder {
-                            block: block_id,
-                            first_statement_index: region::FirstStatementIndex::new(index),
-                        });
+                        let remainder_scope = region::Scope {
+                            id: block_id,
+                            data: region::ScopeData::Remainder(
+                                region::FirstStatementIndex::new(index)),
+                        };
 
                         let mut pattern = cx.pattern_from_hir(&local.pat);
 
@@ -94,7 +101,10 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         result.push(StmtRef::Mirror(Box::new(Stmt {
                             kind: StmtKind::Let {
                                 remainder_scope: remainder_scope,
-                                init_scope: region::Scope::Node(hir_id.local_id),
+                                init_scope: region::Scope {
+                                    id: hir_id.local_id,
+                                    data: region::ScopeData::Node
+                                },
                                 pattern,
                                 initializer: local.init.to_ref(),
                                 lint_level: cx.lint_level_of(local.id),
index 055f238e5db4ea12f2c03d6a079d7ff2fe70b5ea..3183f0f47eace5f51ce1f235b1db86c2c3dec8f2 100644 (file)
@@ -27,7 +27,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
 
     fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
         let temp_lifetime = cx.region_scope_tree.temporary_scope(self.hir_id.local_id);
-        let expr_scope = region::Scope::Node(self.hir_id.local_id);
+        let expr_scope = region::Scope {
+            id: self.hir_id.local_id,
+            data: region::ScopeData::Node
+        };
 
         debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span);
 
@@ -148,7 +151,10 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             // Convert this to a suitable `&foo` and
             // then an unsafe coercion. Limit the region to be just this
             // expression.
-            let region = ty::ReScope(region::Scope::Node(hir_expr.hir_id.local_id));
+            let region = ty::ReScope(region::Scope {
+                id: hir_expr.hir_id.local_id,
+                data: region::ScopeData::Node
+            });
             let region = cx.tcx.mk_region(region);
             expr = Expr {
                 temp_lifetime,
@@ -273,7 +279,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                             Def::VariantCtor(variant_id, CtorKind::Fn) => {
                                 Some((adt_def, adt_def.variant_index_with_id(variant_id)))
                             }
-                            Def::StructCtor(_, CtorKind::Fn) => Some((adt_def, 0)),
+                            Def::StructCtor(_, CtorKind::Fn) |
+                            Def::SelfCtor(..) => Some((adt_def, 0)),
                             _ => None,
                         }
                     })
@@ -580,7 +587,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         hir::ExprKind::Break(dest, ref value) => {
             match dest.target_id {
                 Ok(target_id) => ExprKind::Break {
-                    label: region::Scope::Node(cx.tcx.hir.node_to_hir_id(target_id).local_id),
+                    label: region::Scope {
+                        id: cx.tcx.hir.node_to_hir_id(target_id).local_id,
+                        data: region::ScopeData::Node
+                    },
                     value: value.to_ref(),
                 },
                 Err(err) => bug!("invalid loop id for break: {}", err)
@@ -589,7 +599,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         hir::ExprKind::Continue(dest) => {
             match dest.target_id {
                 Ok(loop_id) => ExprKind::Continue {
-                    label: region::Scope::Node(cx.tcx.hir.node_to_hir_id(loop_id).local_id),
+                    label: region::Scope {
+                        id: cx.tcx.hir.node_to_hir_id(loop_id).local_id,
+                        data: region::ScopeData::Node
+                    },
                 },
                 Err(err) => bug!("invalid loop id for continue: {}", err)
             }
@@ -759,6 +772,25 @@ fn user_annotated_ty_for_def(
                 sty => bug!("unexpected sty: {:?}", sty),
             },
 
+        // `Self` is used in expression as a tuple struct constructor or an unit struct constructor
+        Def::SelfCtor(_) => {
+            let sty = &cx.tables().node_id_to_type(hir_id).sty;
+            match sty {
+                ty::FnDef(ref def_id, _) => {
+                    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_id, user_substs)
+                    }))
+                }
+                ty::Adt(ref adt_def, _) => {
+                    user_annotated_ty_for_adt(cx, hir_id, adt_def)
+                }
+                _ => {
+                    bug!("unexpected sty: {:?}", sty)
+                }
+            }
+        }
         _ =>
             bug!("user_annotated_ty_for_def: unexpected def {:?} at {:?}", def, hir_id)
     }
@@ -857,7 +889,8 @@ 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) => {
+        Def::VariantCtor(_, CtorKind::Fn) |
+        Def::SelfCtor(..) => {
             let user_ty = user_annotated_ty_for_def(cx, expr.hir_id, &def);
             ExprKind::Literal {
                 literal: ty::Const::zero_sized(
index b4257a40e38af0dd0ea3ff3de467b5d4cd080ca6..4d4a89fca8b83b77023d08daad411e14c32ff178 100644 (file)
@@ -118,7 +118,7 @@ pub fn bool_ty(&mut self) -> Ty<'tcx> {
     }
 
     pub fn unit_ty(&mut self) -> Ty<'tcx> {
-        self.tcx.mk_nil()
+        self.tcx.mk_unit()
     }
 
     pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
index bf878145e1fb972ba906caa194f7928044db9e65..23667d1b331a3b1e8386e9d7a8ec00b7116ceb08 100644 (file)
@@ -537,11 +537,15 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
                              "cannot bind by-move with sub-bindings")
                 .span_label(p.span, "binds an already bound by-move value by moving it")
                 .emit();
-        } else if has_guard {
-            struct_span_err!(cx.tcx.sess, p.span, E0008,
-                      "cannot bind by-move into a pattern guard")
-                .span_label(p.span, "moves value into pattern guard")
-                .emit();
+        } else if has_guard && !cx.tcx.allow_bind_by_move_patterns_with_guards() {
+            let mut err = struct_span_err!(cx.tcx.sess, p.span, E0008,
+                                       "cannot bind by-move into a pattern guard");
+            err.span_label(p.span, "moves value into pattern guard");
+            if cx.tcx.sess.opts.unstable_features.is_nightly_build() && cx.tcx.use_mir_borrowck() {
+                err.help("add #![feature(bind_by_move_pattern_guards)] to the \
+                          crate attributes to enable");
+            }
+            err.emit();
         } else if let Some(by_ref_span) = by_ref_span {
             struct_span_err!(
                 cx.tcx.sess,
@@ -613,10 +617,16 @@ fn borrow(&mut self,
               _: LoanCause) {
         match kind {
             ty::MutBorrow => {
-                struct_span_err!(self.cx.tcx.sess, span, E0301,
-                          "cannot mutably borrow in a pattern guard")
-                    .span_label(span, "borrowed mutably in pattern guard")
-                    .emit();
+                let mut err = struct_span_err!(self.cx.tcx.sess, span, E0301,
+                          "cannot mutably borrow in a pattern guard");
+                err.span_label(span, "borrowed mutably in pattern guard");
+                if self.cx.tcx.sess.opts.unstable_features.is_nightly_build() &&
+                    self.cx.tcx.use_mir_borrowck()
+                {
+                    err.help("add #![feature(bind_by_move_pattern_guards)] to the \
+                              crate attributes to enable");
+                }
+                err.emit();
             }
             ty::ImmBorrow | ty::UniqueImmBorrow => {}
         }
index ee50322fbb355b2700760d7b04c09f7caf47bb30..57519d6ad7d70908524d3a404be7aa5662a28202 100644 (file)
@@ -667,7 +667,7 @@ fn lower_variant_or_leaf(
             }
 
             Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
-            Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => {
+            Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => {
                 PatternKind::Leaf { subpatterns: subpatterns }
             }
 
index 3a8723ec2fd9b5ea57dd45fbc5e8731a755ff5b0..fcb310f7045674abce83c78ff297bc62be398419 100644 (file)
@@ -51,6 +51,11 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
     /// a static creates a copy here, in the machine.
     alloc_map: FxHashMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation)>,
 
+    /// To be able to compare pointers with NULL, and to check alignment for accesses
+    /// to ZSTs (where pointers may dangle), we keep track of the size even for allocations
+    /// that do not exist any more.
+    dead_alloc_map: FxHashMap<AllocId, (Size, Align)>,
+
     pub tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
 }
 
@@ -74,6 +79,7 @@ pub fn new(tcx: TyCtxtAt<'a, 'tcx, 'tcx>, data: M::MemoryData) -> Self {
         Memory {
             data,
             alloc_map: FxHashMap::default(),
+            dead_alloc_map: FxHashMap::default(),
             tcx,
         }
     }
@@ -150,6 +156,8 @@ pub fn deallocate(
         size_and_align: Option<(Size, Align)>,
         kind: MemoryKind<M::MemoryKinds>,
     ) -> EvalResult<'tcx> {
+        debug!("deallocating: {}", ptr.alloc_id);
+
         if ptr.offset.bytes() != 0 {
             return err!(DeallocateNonBasePtr);
         }
@@ -189,23 +197,41 @@ pub fn deallocate(
             }
         }
 
-        debug!("deallocated : {}", ptr.alloc_id);
+        // Don't forget to remember size and align of this now-dead allocation
+        let old = self.dead_alloc_map.insert(
+            ptr.alloc_id,
+            (Size::from_bytes(alloc.bytes.len() as u64), alloc.align)
+        );
+        if old.is_some() {
+            bug!("Nothing can be deallocated twice");
+        }
 
         Ok(())
     }
 
-    /// 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.
+    /// Check that the pointer is aligned AND non-NULL. This supports ZSTs in two ways:
+    /// You can pass a scalar, and a `Pointer` does not have to actually still be allocated.
     pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx> {
         // Check non-NULL/Undef, extract offset
         let (offset, alloc_align) = match ptr {
             Scalar::Ptr(ptr) => {
-                let alloc = self.get(ptr.alloc_id)?;
-                (ptr.offset.bytes(), alloc.align)
+                let (size, align) = self.get_size_and_align(ptr.alloc_id)?;
+                // check this is not NULL -- which we can ensure only if this is in-bounds
+                // of some (potentially dead) allocation.
+                if ptr.offset > size {
+                    return err!(PointerOutOfBounds {
+                        ptr,
+                        access: true,
+                        allocation_size: size,
+                    });
+                };
+                // keep data for alignment check
+                (ptr.offset.bytes(), align)
             }
             Scalar::Bits { bits, size } => {
                 assert_eq!(size as u64, self.pointer_size().bytes());
                 assert!(bits < (1u128 << self.pointer_size().bits()));
+                // check this is not NULL
                 if bits == 0 {
                     return err!(InvalidNullPointerUsage);
                 }
@@ -306,6 +332,21 @@ pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> {
         }
     }
 
+    pub fn get_size_and_align(&self, id: AllocId) -> EvalResult<'tcx, (Size, Align)> {
+        Ok(match self.get(id) {
+            Ok(alloc) => (Size::from_bytes(alloc.bytes.len() as u64), alloc.align),
+            Err(err) => match err.kind {
+                EvalErrorKind::DanglingPointerDeref =>
+                    // This should be in the dead allocation map
+                    *self.dead_alloc_map.get(&id).expect(
+                        "allocation missing in dead_alloc_map"
+                    ),
+                // E.g. a function ptr allocation
+                _ => return Err(err)
+            }
+        })
+    }
+
     pub fn get_mut(
         &mut self,
         id: AllocId,
index 461285ff9bc106422dda4d97f10be82a74f61cf4..c7f84f768395351c35405e9fa0c7a39ea4e334fc 100644 (file)
@@ -219,7 +219,7 @@ pub(super) fn try_read_value_from_mplace(
         }
         let (ptr, ptr_align) = mplace.to_scalar_ptr_align();
 
-        if mplace.layout.size.bytes() == 0 {
+        if mplace.layout.is_zst() {
             // Not all ZSTs have a layout we would handle below, so just short-circuit them
             // all here.
             self.memory.check_align(ptr, ptr_align)?;
@@ -340,7 +340,7 @@ pub fn operand_field(
 
         let field = field.try_into().unwrap();
         let field_layout = op.layout.field(self, field)?;
-        if field_layout.size.bytes() == 0 {
+        if field_layout.is_zst() {
             let val = Value::Scalar(Scalar::zst().into());
             return Ok(OpTy { op: Operand::Immediate(val), layout: field_layout });
         }
@@ -376,14 +376,14 @@ pub fn operand_downcast(
         })
     }
 
-    // Take an operand, representing a pointer, and dereference it -- that
+    // Take an operand, representing a pointer, and dereference it to a place -- 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);
+        trace!("deref to {} on {:?}", val.layout.ty, *val);
         Ok(self.ref_to_mplace(val)?)
     }
 
@@ -397,9 +397,15 @@ pub fn operand_projection(
             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(_) => {
+            Subslice { .. } | ConstantIndex { .. } | Index(_) => if base.layout.is_zst() {
+                OpTy {
+                    op: Operand::Immediate(Value::Scalar(Scalar::zst().into())),
+                    // the actual index doesn't matter, so we just pick a convenient one like 0
+                    layout: base.layout.field(self, 0)?,
+                }
+            } else {
+                // The rest should only occur as mplace, we do not use Immediates for types
+                // allowing such operations.  This matches place_projection forcing an allocation.
                 let mplace = base.to_mem_place();
                 self.mplace_projection(mplace, proj_elem)?.into()
             }
index 64e0aeaaab7f042249f2717a6794a3ae91e0364f..e3f7f26f53efda786f55b8045ed9015dca092228 100644 (file)
@@ -612,7 +612,7 @@ fn write_value_to_mplace(
         // wrong type.
 
         // Nothing to do for ZSTs, other than checking alignment
-        if dest.layout.size.bytes() == 0 {
+        if dest.layout.is_zst() {
             self.memory.check_align(ptr, ptr_align)?;
             return Ok(());
         }
index de8681062740938f62df21db9c279c3b17cfd5d3..7ce96b1f62626340d9957b7c75221098efbf09c3 100644 (file)
@@ -436,7 +436,7 @@ fn drop_in_place(
             layout: self.layout_of(self.tcx.mk_mut_ptr(place.layout.ty))?,
         };
 
-        let ty = self.tcx.mk_nil(); // return type is ()
+        let ty = self.tcx.mk_unit(); // return type is ()
         let dest = PlaceTy::null(&self, self.layout_of(ty)?);
 
         self.eval_fn_call(
index e71de0001fbe342d14a829e7b4addc68ce090da3..1594755b4ab87191b6bc13362f2f335ccca75ad6 100644 (file)
@@ -29,6 +29,8 @@
 #![feature(exhaustive_patterns)]
 #![feature(range_contains)]
 #![feature(rustc_diagnostic_macros)]
+#![feature(rustc_attrs)]
+#![cfg_attr(stage0, feature(attr_literals))]
 #![feature(never_type)]
 #![feature(specialization)]
 #![feature(try_trait)]
index 52bbffa7519df069a687358e9f75b1aee345a58b..d50ef2242faeeada6492a3c11f8e11d161e10e39 100644 (file)
 
 use monomorphize::item::{MonoItemExt, DefPathBasedNames, InstantiationMode};
 
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bit_set::GrowableBitSet;
 use rustc_data_structures::sync::{MTRef, MTLock, ParallelIterator, par_iter};
 
 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
@@ -231,7 +231,7 @@ pub struct InliningMap<'tcx> {
 
     // Contains one bit per mono item in the `targets` field. That bit
     // is true if that mono item needs to be inlined into every CGU.
-    inlines: BitVector<usize>,
+    inlines: GrowableBitSet<usize>,
 }
 
 impl<'tcx> InliningMap<'tcx> {
@@ -240,7 +240,7 @@ fn new() -> InliningMap<'tcx> {
         InliningMap {
             index: FxHashMap(),
             targets: Vec::new(),
-            inlines: BitVector::with_capacity(1024),
+            inlines: GrowableBitSet::with_capacity(1024),
         }
     }
 
index dc437ee8510d7c46a7f1929dbe388878669a66e1..3f5a05f9d0ed8381d0540cb1d84ca157e1344ac7 100644 (file)
@@ -368,7 +368,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
 
                 output.push(')');
 
-                if !sig.output().is_nil() {
+                if !sig.output().is_unit() {
                     output.push_str(" -> ");
                     self.push_type_name(sig.output(), output);
                 }
index bf538112e41ed26ec434092858648a6df1081fb1..92b6af8b51f7f0e32e0d8c98d5fdefdb90c5a4e7 100644 (file)
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
 use rustc::util::nodemap::FxHashMap;
-use rustc_data_structures::indexed_set::IdxSet;
+use rustc_data_structures::bit_set::BitSet;
+use std::fmt;
+use syntax::ast;
+use syntax_pos::Span;
 use transform::{MirPass, MirSource};
 use util::patch::MirPatch;
 use util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop};
 use util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode};
-use syntax::ast;
-use syntax_pos::Span;
-
-use std::fmt;
 
 pub struct ElaborateDrops;
 
@@ -92,12 +91,12 @@ fn find_dead_unwinds<'a, 'tcx>(
     mir: &Mir<'tcx>,
     id: ast::NodeId,
     env: &MoveDataParamEnv<'tcx, 'tcx>)
-    -> IdxSet<BasicBlock>
+    -> BitSet<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 = IdxSet::new_empty(mir.basic_blocks().len());
+    let mut dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
     let flow_inits =
         do_dataflow(tcx, mir, id, &[], &dead_unwinds,
                     MaybeInitializedPlaces::new(tcx, mir, &env),
@@ -111,7 +110,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: IdxSet::new_empty(env.move_data.move_paths.len()),
+            dead: BitSet::new_empty(env.move_data.move_paths.len()),
         };
         debug!("find_dead_unwinds @ {:?}: {:?}; init_data={:?}",
                bb, bb_data, init_data.live);
@@ -138,7 +137,7 @@ fn find_dead_unwinds<'a, 'tcx>(
 
         debug!("find_dead_unwinds @ {:?}: maybe_live={}", bb, maybe_live);
         if !maybe_live {
-            dead_unwinds.add(&bb);
+            dead_unwinds.insert(bb);
         }
     }
 
@@ -146,8 +145,8 @@ fn find_dead_unwinds<'a, 'tcx>(
 }
 
 struct InitializationData {
-    live: IdxSet<MovePathIndex>,
-    dead: IdxSet<MovePathIndex>
+    live: BitSet<MovePathIndex>,
+    dead: BitSet<MovePathIndex>
 }
 
 impl InitializationData {
@@ -162,19 +161,19 @@ fn apply_location<'a,'tcx>(&mut self,
                    loc, path, df);
             match df {
                 DropFlagState::Present => {
-                    self.live.add(&path);
-                    self.dead.remove(&path);
+                    self.live.insert(path);
+                    self.dead.remove(path);
                 }
                 DropFlagState::Absent => {
-                    self.dead.add(&path);
-                    self.live.remove(&path);
+                    self.dead.insert(path);
+                    self.live.remove(path);
                 }
             }
         });
     }
 
     fn state(&self, path: MovePathIndex) -> (bool, bool) {
-        (self.live.contains(&path), self.dead.contains(&path))
+        (self.live.contains(path), self.dead.contains(path))
     }
 }
 
index f1f42768ce3248d2ef1483fd1d10a367b3574173..96111519550f6ff18f6f387e5d2cc35f115190a7 100644 (file)
@@ -69,7 +69,7 @@
 use util::liveness::{self, IdentityMap};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
-use rustc_data_structures::indexed_set::IdxSet;
+use rustc_data_structures::bit_set::BitSet;
 use std::borrow::Cow;
 use std::iter::once;
 use std::mem;
@@ -331,7 +331,7 @@ fn visit_statement(&mut self,
                        _location: Location) {
         match statement.kind {
             StatementKind::StorageLive(l) |
-            StatementKind::StorageDead(l) => { self.0.remove(&l); }
+            StatementKind::StorageDead(l) => { self.0.remove(l); }
             _ => (),
         }
     }
@@ -341,7 +341,7 @@ fn visit_statement(&mut self,
 
 fn mark_as_borrowed<'tcx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) {
     match *place {
-        Place::Local(l) => { locals.0.add(&l); },
+        Place::Local(l) => { locals.0.insert(l); },
         Place::Promoted(_) |
         Place::Static(..) => (),
         Place::Projection(ref proj) => {
@@ -376,7 +376,7 @@ fn locals_live_across_suspend_points(
     liveness::LiveVarSet<Local>,
     FxHashMap<BasicBlock, liveness::LiveVarSet<Local>>,
 ) {
-    let dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len());
+    let dead_unwinds = BitSet::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
@@ -388,7 +388,7 @@ fn locals_live_across_suspend_points(
 
     // Find the MIR locals which do not use StorageLive/StorageDead statements.
     // The storage of these locals are always live.
-    let mut ignored = StorageIgnored(IdxSet::new_filled(mir.local_decls.len()));
+    let mut ignored = StorageIgnored(BitSet::new_filled(mir.local_decls.len()));
     ignored.visit_mir(mir);
 
     // Calculate the MIR locals which have been previously
@@ -472,7 +472,7 @@ fn locals_live_across_suspend_points(
     }
 
     // The generator argument is ignored
-    set.remove(&self_arg());
+    set.remove(self_arg());
 
     (set, storage_liveness_map)
 }
@@ -502,7 +502,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     for (local, decl) in mir.local_decls.iter_enumerated() {
         // Ignore locals which are internal or not live
-        if !live_locals.contains(&local) || decl.internal {
+        if !live_locals.contains(local) || decl.internal {
             continue;
         }
 
@@ -518,7 +518,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     let upvar_len = mir.upvar_decls.len();
-    let dummy_local = LocalDecl::new_internal(tcx.mk_nil(), mir.span);
+    let dummy_local = LocalDecl::new_internal(tcx.mk_unit(), mir.span);
 
     // Gather live locals and their indices replacing values in mir.local_decls with a dummy
     // to avoid changing local indices
@@ -656,7 +656,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
     // Replace the return variable
     mir.local_decls[RETURN_PLACE] = LocalDecl {
         mutability: Mutability::Mut,
-        ty: tcx.mk_nil(),
+        ty: tcx.mk_unit(),
         user_ty: None,
         name: None,
         source_info,
@@ -823,7 +823,7 @@ fn create_cases<'a, 'tcx, F>(mir: &mut Mir<'tcx>,
             // Create StorageLive instructions for locals with live storage
             for i in 0..(mir.local_decls.len()) {
                 let l = Local::new(i);
-                if point.storage_liveness.contains(&l) && !transform.remap.contains_key(&l) {
+                if point.storage_liveness.contains(l) && !transform.remap.contains_key(&l) {
                     statements.push(Statement {
                         source_info,
                         kind: StatementKind::StorageLive(l),
index 31e437ce2281acb9b1dc6556f8b336cca8374091..8689fde3ee640b81bbe894e2e02fe028aa83aa3e 100644 (file)
@@ -14,7 +14,7 @@
 use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::def_id::DefId;
 
-use rustc_data_structures::bitvec::BitArray;
+use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 
 use rustc::mir::*;
@@ -271,7 +271,7 @@ fn should_inline(&self,
         // Traverse the MIR manually so we can account for the effects of
         // inlining on the CFG.
         let mut work_list = vec![START_BLOCK];
-        let mut visited = BitArray::new(callee_mir.basic_blocks().len());
+        let mut visited = BitSet::new_empty(callee_mir.basic_blocks().len());
         while let Some(bb) = work_list.pop() {
             if !visited.insert(bb.index()) { continue; }
             let blk = &callee_mir.basic_blocks()[bb];
index a2175dce33a833aa9df8e63062fe523393715d80..bc9cc7274d5e78797581750ce89230f5475e5ba0 100644 (file)
@@ -14,8 +14,7 @@
 //! The Qualif flags below can be used to also provide better
 //! diagnostics as to why a constant rvalue wasn't promoted.
 
-use rustc_data_structures::bitvec::BitArray;
-use rustc_data_structures::indexed_set::IdxSet;
+use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::FxHashSet;
 use rustc::hir;
@@ -116,7 +115,7 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     param_env: ty::ParamEnv<'tcx>,
     local_qualif: IndexVec<Local, Option<Qualif>>,
     qualif: Qualif,
-    const_fn_arg_vars: BitArray<Local>,
+    const_fn_arg_vars: BitSet<Local>,
     temp_promotion_state: IndexVec<Local, TempState>,
     promotion_candidates: Vec<Candidate>
 }
@@ -151,7 +150,7 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             param_env,
             local_qualif,
             qualif: Qualif::empty(),
-            const_fn_arg_vars: BitArray::new(mir.local_decls.len()),
+            const_fn_arg_vars: BitSet::new_empty(mir.local_decls.len()),
             temp_promotion_state: temps,
             promotion_candidates: vec![]
         }
@@ -280,12 +279,12 @@ 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<IdxSet<Local>>) {
+    fn qualify_const(&mut self) -> (Qualif, Lrc<BitSet<Local>>) {
         debug!("qualifying {} {:?}", self.mode, self.def_id);
 
         let mir = self.mir;
 
-        let mut seen_blocks = BitArray::new(mir.basic_blocks().len());
+        let mut seen_blocks = BitSet::new_empty(mir.basic_blocks().len());
         let mut bb = START_BLOCK;
         loop {
             seen_blocks.insert(bb.index());
@@ -383,14 +382,14 @@ fn qualify_const(&mut self) -> (Qualif, Lrc<IdxSet<Local>>) {
 
 
         // Collect all the temps we need to promote.
-        let mut promoted_temps = IdxSet::new_empty(self.temp_promotion_state.len());
+        let mut promoted_temps = BitSet::new_empty(self.temp_promotion_state.len());
 
         for candidate in &self.promotion_candidates {
             match *candidate {
                 Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => {
                     match self.mir[bb].statements[stmt_idx].kind {
                         StatementKind::Assign(_, Rvalue::Ref(_, _, Place::Local(index))) => {
-                            promoted_temps.add(&index);
+                            promoted_temps.insert(index);
                         }
                         _ => {}
                     }
@@ -1121,7 +1120,7 @@ pub fn provide(providers: &mut Providers) {
 
 fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               def_id: DefId)
-                              -> (u8, Lrc<IdxSet<Local>>) {
+                              -> (u8, Lrc<BitSet<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
@@ -1130,7 +1129,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(IdxSet::new_empty(0)));
+        return (Qualif::NOT_CONST.bits(), Lrc::new(BitSet::new_empty(0)));
     }
 
     let mut qualifier = Qualifier::new(tcx, def_id, mir, Mode::Const);
@@ -1220,7 +1219,7 @@ fn run_pass<'a, 'tcx>(&self,
                 block.statements.retain(|statement| {
                     match statement.kind {
                         StatementKind::StorageDead(index) => {
-                            !promoted_temps.contains(&index)
+                            !promoted_temps.contains(index)
                         }
                         _ => true
                     }
@@ -1228,7 +1227,7 @@ fn run_pass<'a, 'tcx>(&self,
                 let terminator = block.terminator_mut();
                 match terminator.kind {
                     TerminatorKind::Drop { location: Place::Local(index), target, .. } => {
-                        if promoted_temps.contains(&index) {
+                        if promoted_temps.contains(index) {
                             terminator.kind = TerminatorKind::Goto {
                                 target,
                             };
index a2561d3d79381d3f91be2496b8e45721df653979..9cdd94a7be7f168e1a7552f81d46b5c06ee812b5 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
-use rustc_data_structures::bitvec::BitArray;
+use rustc_data_structures::bit_set::BitSet;
 use transform::{MirPass, MirSource};
 use util::patch::MirPatch;
 
@@ -45,7 +45,7 @@ fn is_nop_landing_pad(
         &self,
         bb: BasicBlock,
         mir: &Mir,
-        nop_landing_pads: &BitArray<BasicBlock>,
+        nop_landing_pads: &BitSet<BasicBlock>,
     ) -> bool {
         for stmt in &mir[bb].statements {
             match stmt.kind {
@@ -111,7 +111,7 @@ fn remove_nop_landing_pads(&self, mir: &mut Mir) {
 
         let mut jumps_folded = 0;
         let mut landing_pads_removed = 0;
-        let mut nop_landing_pads = BitArray::new(mir.basic_blocks().len());
+        let mut nop_landing_pads = BitSet::new_empty(mir.basic_blocks().len());
 
         // This is a post-order traversal, so that if A post-dominates B
         // then A will be visited before B.
index f3e0f5573632ad476f1695e233b29aa3438e7b34..3c898eedebcc49582b980eda60be6d01e9a4df6f 100644 (file)
@@ -14,7 +14,7 @@
 
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::{self, Mir, Location};
-use rustc_data_structures::indexed_set::IdxSet;
+use rustc_data_structures::bit_set::BitSet;
 use transform::{MirPass, MirSource};
 
 use dataflow::{do_dataflow, DebugFormatted};
@@ -46,7 +46,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 = IdxSet::new_empty(mir.basic_blocks().len());
+        let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
         let flow_inits =
             do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
                         MaybeInitializedPlaces::new(tcx, mir, &mdpe),
@@ -175,7 +175,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 // Okay, our search is over.
                 match move_data.rev_lookup.find(peeking_at_place) {
                     LookupResult::Exact(peek_mpi) => {
-                        let bit_state = sets.on_entry.contains(&peek_mpi);
+                        let bit_state = sets.on_entry.contains(peek_mpi);
                         debug!("rustc_peek({:?} = &{:?}) bit_state: {}",
                                place, peeking_at_place, bit_state);
                         if !bit_state {
index 164790db4b5ec81b0f0ab62420b4481f8afc6419..a6e0932bf0acec6860272ad15ba50c5c7ab71e8c 100644 (file)
@@ -37,7 +37,7 @@
 //! naively generate still contains the `_a = ()` write in the unreachable block "after" the
 //! return.
 
-use rustc_data_structures::bitvec::BitArray;
+use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
@@ -249,7 +249,7 @@ fn strip_nops(&mut self) {
 }
 
 pub fn remove_dead_blocks(mir: &mut Mir) {
-    let mut seen = BitArray::new(mir.basic_blocks().len());
+    let mut seen = BitSet::new_empty(mir.basic_blocks().len());
     for (bb, _) in traversal::preorder(mir) {
         seen.insert(bb.index());
     }
@@ -285,7 +285,7 @@ fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _: MirSource,
                           mir: &mut Mir<'tcx>) {
-        let mut marker = DeclMarker { locals: BitArray::new(mir.local_decls.len()) };
+        let mut marker = DeclMarker { locals: BitSet::new_empty(mir.local_decls.len()) };
         marker.visit_mir(mir);
         // Return pointer and arguments are always live
         marker.locals.insert(RETURN_PLACE);
@@ -310,7 +310,7 @@ fn run_pass<'a, 'tcx>(&self,
 /// Construct the mapping while swapping out unused stuff out from the `vec`.
 fn make_local_map<'tcx, V>(
     vec: &mut IndexVec<Local, V>,
-    mask: BitArray<Local>,
+    mask: BitSet<Local>,
 ) -> IndexVec<Local, Option<Local>> {
     let mut map: IndexVec<Local, Option<Local>> = IndexVec::from_elem(None, &*vec);
     let mut used = Local::new(0);
@@ -326,7 +326,7 @@ fn make_local_map<'tcx, V>(
 }
 
 struct DeclMarker {
-    pub locals: BitArray<Local>,
+    pub locals: BitSet<Local>,
 }
 
 impl<'tcx> Visitor<'tcx> for DeclMarker {
index 1c0c98d621c83325a97b53ded27c6d31d9cb5afa..50bdc14d5099556e725c6054bf28a774bf6591b1 100644 (file)
@@ -529,7 +529,7 @@ fn destructor_call_block<'a>(&mut self, (succ, unwind): (BasicBlock, Unwind))
             mutbl: hir::Mutability::MutMutable
         });
         let ref_place = self.new_temp(ref_ty);
-        let unit_temp = Place::Local(self.new_temp(tcx.mk_nil()));
+        let unit_temp = Place::Local(self.new_temp(tcx.mk_unit()));
 
         let result = BasicBlockData {
             statements: vec![self.assign(
@@ -891,7 +891,7 @@ fn unelaborated_free_block<'a>(
         unwind: Unwind
     ) -> BasicBlock {
         let tcx = self.tcx();
-        let unit_temp = Place::Local(self.new_temp(tcx.mk_nil()));
+        let unit_temp = Place::Local(self.new_temp(tcx.mk_unit()));
         let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
         let args = adt.variants[0].fields.iter().enumerate().map(|(i, f)| {
             let field = Field::new(i);
index 3ae470e1d4bbd113f00d04297b60629c352804aa..420ca4efde37d8d6c72e48650c1a021e8e3d68ae 100644 (file)
@@ -37,7 +37,7 @@
 use rustc::mir::Local;
 use rustc::mir::*;
 use rustc::ty::{item_path, TyCtxt};
-use rustc_data_structures::indexed_set::IdxSet;
+use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::work_queue::WorkQueue;
 use std::fs;
@@ -46,7 +46,7 @@
 use transform::MirSource;
 use util::pretty::{dump_enabled, write_basic_block, write_mir_intro};
 
-pub type LiveVarSet<V> = IdxSet<V>;
+pub type LiveVarSet<V> = BitSet<V>;
 
 /// This gives the result of the liveness analysis at the boundary of
 /// basic blocks.
@@ -243,8 +243,8 @@ fn add_def(&mut self, index: V) {
         //     X = 5
         //     // Defs = {}, Uses = {X}
         //     use(X)
-        self.uses.remove(&index);
-        self.defs.add(&index);
+        self.uses.remove(index);
+        self.defs.insert(index);
     }
 
     fn add_use(&mut self, index: V) {
@@ -258,8 +258,8 @@ fn add_use(&mut self, index: V) {
         //     X = 5
         //     // Defs = {}, Uses = {X}
         //     use(X)
-        self.defs.remove(&index);
-        self.uses.add(&index);
+        self.defs.remove(index);
+        self.uses.insert(index);
     }
 }
 
index 2ee5415018f934ece32799bb45f132a1139caac5..f6ace57f5e0fb52b36a93ac795cdc23426f2a53a 100644 (file)
@@ -182,8 +182,9 @@ fn while_if_let_ambiguity(&self, expr: &P<Expr>) {
             );
 
             if let Ok(snippet) = self.session.source_map().span_to_snippet(span) {
-                err.span_suggestion(
+                err.span_suggestion_with_applicability(
                     span, "consider adding parentheses", format!("({})", snippet),
+                    Applicability::MachineApplicable,
                 );
             }
 
index 61c2ac161bb08096d35fa7d930246940f0436d34..a87e86aee0cf0d395c8b87503d1903096c7f0d84 100644 (file)
@@ -16,6 +16,7 @@
 use rustc::hir::{self, Node, Destination};
 use syntax::ast;
 use syntax_pos::Span;
+use errors::Applicability;
 
 #[derive(Clone, Copy, Debug, PartialEq)]
 enum LoopKind {
@@ -140,11 +141,16 @@ fn visit_expr(&mut self, e: &'hir hir::Expr) {
                                 .span_label(e.span,
                                             "can only break with a value inside \
                                             `loop` or breakable block")
-                                .span_suggestion(e.span,
-                                                 &format!("instead, use `break` on its own \
-                                                           without a value inside this `{}` loop",
-                                                          kind.name()),
-                                                 "break".to_string())
+                                .span_suggestion_with_applicability(
+                                    e.span,
+                                    &format!(
+                                        "instead, use `break` on its own \
+                                        without a value inside this `{}` loop",
+                                        kind.name()
+                                    ),
+                                    "break".to_string(),
+                                    Applicability::MaybeIncorrect,
+                                )
                                 .emit();
                         }
                     }
index 74b010f57b01d7c1279b7375ef0ddb1c30210cd4..828800465209e857447a768f767c03459cd2f4ad 100644 (file)
@@ -376,7 +376,7 @@ fn check_expr_kind<'a, 'tcx>(
             let def = v.tables.qpath_def(qpath, e.hir_id);
             match def {
                 Def::VariantCtor(..) | Def::StructCtor(..) |
-                Def::Fn(..) | Def::Method(..) => Promotable,
+                Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => Promotable,
 
                 // References to a static that are themselves within a static
                 // are inherently promotable with the exception
@@ -441,7 +441,8 @@ fn check_expr_kind<'a, 'tcx>(
             };
             let def_result = match def {
                 Def::StructCtor(_, CtorKind::Fn) |
-                Def::VariantCtor(_, CtorKind::Fn) => Promotable,
+                Def::VariantCtor(_, CtorKind::Fn) |
+                Def::SelfCtor(..) => Promotable,
                 Def::Fn(did) => {
                     v.handle_const_fn_call(did, node_ty, e.span)
                 }
index 7d9139df415013434d21d331213d450dde6ae096..25a7ff9cd3f566ed9a0c50cc188216f99da9eadb 100644 (file)
@@ -22,7 +22,7 @@
 use {resolve_error, resolve_struct_error, ResolutionError};
 
 use rustc::hir::def::*;
-use rustc::hir::def_id::{BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
+use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
 use rustc::ty;
 use rustc::middle::cstore::CrateStore;
 use rustc_metadata::cstore::LoadedMacro;
@@ -769,7 +769,7 @@ pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
         let def_id = self.macro_defs[&expansion];
         if let Some(id) = self.definitions.as_local_node_id(def_id) {
             self.local_macro_def_scopes[&id]
-        } else if def_id.krate == BUILTIN_MACROS_CRATE {
+        } else if def_id.krate == CrateNum::BuiltinMacros {
             self.injected_crate.unwrap_or(self.graph_root)
         } else {
             let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
index 93f1c20661ba620170b69d1025e05be7fd62014f..343ef067a6ce86aac59e251bb1e3dd7d58dd8ec8 100644 (file)
@@ -558,17 +558,21 @@ fn is_expected(self, def: Def) -> bool {
                 Def::StructCtor(_, CtorKind::Const) | Def::StructCtor(_, CtorKind::Fn) |
                 Def::VariantCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Fn) |
                 Def::Const(..) | Def::Static(..) | Def::Local(..) | Def::Upvar(..) |
-                Def::Fn(..) | Def::Method(..) | Def::AssociatedConst(..) => true,
+                Def::Fn(..) | Def::Method(..) | Def::AssociatedConst(..) |
+                Def::SelfCtor(..) => true,
                 _ => false,
             },
             PathSource::Pat => match def {
                 Def::StructCtor(_, CtorKind::Const) |
                 Def::VariantCtor(_, CtorKind::Const) |
-                Def::Const(..) | Def::AssociatedConst(..) => true,
+                Def::Const(..) | Def::AssociatedConst(..) |
+                Def::SelfCtor(..) => true,
                 _ => false,
             },
             PathSource::TupleStruct => match def {
-                Def::StructCtor(_, CtorKind::Fn) | Def::VariantCtor(_, CtorKind::Fn) => true,
+                Def::StructCtor(_, CtorKind::Fn) |
+                Def::VariantCtor(_, CtorKind::Fn) |
+                Def::SelfCtor(..) => true,
                 _ => false,
             },
             PathSource::Struct => match def {
@@ -1425,8 +1429,6 @@ pub struct Resolver<'a, 'b: 'a> {
     ambiguity_errors: Vec<AmbiguityError<'a>>,
     /// `use` injections are delayed for better placement and deduplication
     use_injections: Vec<UseError<'a>>,
-    /// `use` injections for proc macros wrongly imported with #[macro_use]
-    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)>,
 
@@ -1454,9 +1456,6 @@ pub struct Resolver<'a, 'b: 'a> {
     /// Avoid duplicated errors for "name already defined".
     name_already_seen: FxHashMap<Name, Span>,
 
-    /// A set of procedural macros imported by `#[macro_use]` that have already been warned about
-    warned_proc_macros: FxHashSet<Name>,
-
     potentially_unused_imports: Vec<&'a ImportDirective<'a>>,
 
     /// This table maps struct IDs into struct constructor IDs,
@@ -1670,13 +1669,14 @@ pub fn new(session: &'a Session,
 
         let mut extern_prelude: FxHashSet<Name> =
             session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect();
-        if !attr::contains_name(&krate.attrs, "no_core") {
-            if !attr::contains_name(&krate.attrs, "no_std") {
-                extern_prelude.insert(Symbol::intern("std"));
-            } else {
-                extern_prelude.insert(Symbol::intern("core"));
-            }
-        }
+
+        // HACK(eddyb) this ignore the `no_{core,std}` attributes.
+        // FIXME(eddyb) warn (elsewhere) if core/std is used with `no_{core,std}`.
+        // if !attr::contains_name(&krate.attrs, "no_core") {
+        // if !attr::contains_name(&krate.attrs, "no_std") {
+        extern_prelude.insert(Symbol::intern("core"));
+        extern_prelude.insert(Symbol::intern("std"));
+        extern_prelude.insert(Symbol::intern("meta"));
 
         let mut invocations = FxHashMap();
         invocations.insert(Mark::root(),
@@ -1739,7 +1739,6 @@ pub fn new(session: &'a Session,
             privacy_errors: Vec::new(),
             ambiguity_errors: Vec::new(),
             use_injections: Vec::new(),
-            proc_mac_errors: Vec::new(),
             macro_expanded_macro_export_errors: BTreeSet::new(),
 
             arenas,
@@ -1761,7 +1760,6 @@ pub fn new(session: &'a Session,
             local_macro_def_scopes: FxHashMap(),
             name_already_seen: FxHashMap(),
             whitelisted_legacy_custom_derives: Vec::new(),
-            warned_proc_macros: FxHashSet(),
             potentially_unused_imports: Vec::new(),
             struct_constructors: DefIdMap(),
             found_unresolved_macro: false,
@@ -1978,7 +1976,9 @@ fn resolve_ident_in_lexical_scope(&mut self,
                                 "access to extern crates through prelude is experimental").emit();
                 }
 
-                let crate_root = self.load_extern_prelude_crate_if_needed(ident);
+                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 binding = (crate_root, ty::Visibility::Public,
                                ident.span, Mark::root()).to_name_binding(self.arenas);
@@ -2006,13 +2006,6 @@ 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()) {
@@ -2204,6 +2197,19 @@ fn search_label<P, R>(&self, mut ident: Ident, pred: P) -> Option<R>
         None
     }
 
+    fn resolve_adt(&mut self, item: &Item, generics: &Generics) {
+        self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
+            let item_def_id = this.definitions.local_def_id(item.id);
+            if this.session.features_untracked().self_in_typedefs {
+                this.with_self_rib(Def::SelfTy(None, Some(item_def_id)), |this| {
+                    visit::walk_item(this, item);
+                });
+            } else {
+                visit::walk_item(this, item);
+            }
+        });
+    }
+
     fn resolve_item(&mut self, item: &Item) {
         let name = item.ident.name;
         debug!("(resolving item) resolving {}", name);
@@ -2219,16 +2225,7 @@ fn resolve_item(&mut self, item: &Item) {
             ItemKind::Enum(_, ref generics) |
             ItemKind::Struct(_, ref generics) |
             ItemKind::Union(_, ref generics) => {
-                self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
-                    let item_def_id = this.definitions.local_def_id(item.id);
-                    if this.session.features_untracked().self_in_typedefs {
-                        this.with_self_rib(Def::SelfTy(None, Some(item_def_id)), |this| {
-                            visit::walk_item(this, item);
-                        });
-                    } else {
-                        visit::walk_item(this, item);
-                    }
-                });
+                self.resolve_adt(item, generics);
             }
 
             ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
@@ -2503,6 +2500,17 @@ fn with_self_rib<F>(&mut self, self_def: Def, f: F)
         self.ribs[TypeNS].pop();
     }
 
+    fn with_self_struct_ctor_rib<F>(&mut self, impl_id: DefId, f: F)
+        where F: FnOnce(&mut Resolver)
+    {
+        let self_def = Def::SelfCtor(impl_id);
+        let mut self_type_rib = Rib::new(NormalRibKind);
+        self_type_rib.bindings.insert(keywords::SelfType.ident(), self_def);
+        self.ribs[ValueNS].push(self_type_rib);
+        f(self);
+        self.ribs[ValueNS].pop();
+    }
+
     fn resolve_implementation(&mut self,
                               generics: &Generics,
                               opt_trait_reference: &Option<TraitRef>,
@@ -2527,63 +2535,65 @@ fn resolve_implementation(&mut self,
                         this.visit_generics(generics);
                         // Resolve the items within the impl.
                         this.with_current_self_type(self_type, |this| {
-                            for impl_item in impl_items {
-                                this.resolve_visibility(&impl_item.vis);
-
-                                // We also need a new scope for the impl item type parameters.
-                                let type_parameters = HasTypeParameters(&impl_item.generics,
-                                                                        TraitOrImplItemRibKind);
-                                this.with_type_parameter_rib(type_parameters, |this| {
-                                    use self::ResolutionError::*;
-                                    match impl_item.node {
-                                        ImplItemKind::Const(..) => {
-                                            // If this is a trait impl, ensure the const
-                                            // exists in trait
-                                            this.check_trait_item(impl_item.ident,
-                                                                  ValueNS,
-                                                                  impl_item.span,
-                                                |n, s| ConstNotMemberOfTrait(n, s));
-                                            this.with_constant_rib(|this|
-                                                visit::walk_impl_item(this, impl_item)
-                                            );
-                                        }
-                                        ImplItemKind::Method(..) => {
-                                            // If this is a trait impl, ensure the method
-                                            // exists in trait
-                                            this.check_trait_item(impl_item.ident,
-                                                                  ValueNS,
-                                                                  impl_item.span,
-                                                |n, s| MethodNotMemberOfTrait(n, s));
-
-                                            visit::walk_impl_item(this, impl_item);
-                                        }
-                                        ImplItemKind::Type(ref ty) => {
-                                            // If this is a trait impl, ensure the type
-                                            // exists in trait
-                                            this.check_trait_item(impl_item.ident,
-                                                                  TypeNS,
-                                                                  impl_item.span,
-                                                |n, s| TypeNotMemberOfTrait(n, s));
-
-                                            this.visit_ty(ty);
-                                        }
-                                        ImplItemKind::Existential(ref bounds) => {
-                                            // If this is a trait impl, ensure the type
-                                            // exists in trait
-                                            this.check_trait_item(impl_item.ident,
-                                                                  TypeNS,
-                                                                  impl_item.span,
-                                                |n, s| TypeNotMemberOfTrait(n, s));
-
-                                            for bound in bounds {
-                                                this.visit_param_bound(bound);
+                            this.with_self_struct_ctor_rib(item_def_id, |this| {
+                                for impl_item in impl_items {
+                                    this.resolve_visibility(&impl_item.vis);
+
+                                    // We also need a new scope for the impl item type parameters.
+                                    let type_parameters = HasTypeParameters(&impl_item.generics,
+                                                                            TraitOrImplItemRibKind);
+                                    this.with_type_parameter_rib(type_parameters, |this| {
+                                        use self::ResolutionError::*;
+                                        match impl_item.node {
+                                            ImplItemKind::Const(..) => {
+                                                // If this is a trait impl, ensure the const
+                                                // exists in trait
+                                                this.check_trait_item(impl_item.ident,
+                                                                      ValueNS,
+                                                                      impl_item.span,
+                                                    |n, s| ConstNotMemberOfTrait(n, s));
+                                                this.with_constant_rib(|this|
+                                                    visit::walk_impl_item(this, impl_item)
+                                                );
                                             }
+                                            ImplItemKind::Method(..) => {
+                                                // If this is a trait impl, ensure the method
+                                                // exists in trait
+                                                this.check_trait_item(impl_item.ident,
+                                                                      ValueNS,
+                                                                      impl_item.span,
+                                                    |n, s| MethodNotMemberOfTrait(n, s));
+
+                                                visit::walk_impl_item(this, impl_item);
+                                            }
+                                            ImplItemKind::Type(ref ty) => {
+                                                // If this is a trait impl, ensure the type
+                                                // exists in trait
+                                                this.check_trait_item(impl_item.ident,
+                                                                      TypeNS,
+                                                                      impl_item.span,
+                                                    |n, s| TypeNotMemberOfTrait(n, s));
+
+                                                this.visit_ty(ty);
+                                            }
+                                            ImplItemKind::Existential(ref bounds) => {
+                                                // If this is a trait impl, ensure the type
+                                                // exists in trait
+                                                this.check_trait_item(impl_item.ident,
+                                                                      TypeNS,
+                                                                      impl_item.span,
+                                                    |n, s| TypeNotMemberOfTrait(n, s));
+
+                                                for bound in bounds {
+                                                    this.visit_param_bound(bound);
+                                                }
+                                            }
+                                            ImplItemKind::Macro(_) =>
+                                                panic!("unexpanded macro in resolve!"),
                                         }
-                                        ImplItemKind::Macro(_) =>
-                                            panic!("unexpanded macro in resolve!"),
-                                    }
-                                });
-                            }
+                                    });
+                                }
+                            });
                         });
                     });
                 });
@@ -3282,9 +3292,12 @@ fn type_ascription_suggestion(&self,
                         err.span_label(base_span,
                                        "expecting a type here because of type ascription");
                         if line_sp != line_base_sp {
-                            err.span_suggestion_short(sp,
-                                                      "did you mean to use `;` here instead?",
-                                                      ";".to_string());
+                            err.span_suggestion_short_with_applicability(
+                                sp,
+                                "did you mean to use `;` here instead?",
+                                ";".to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
                         }
                         break;
                     } else if snippet.trim().len() != 0  {
@@ -4406,15 +4419,24 @@ fn lookup_import_candidates<FilterFn>(&mut self,
 
         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);
+            for &name in extern_prelude_names.iter() {
+                let ident = Ident::with_empty_ctxt(name);
+                match self.crate_loader.maybe_process_path_extern(name, ident.span) {
+                    Some(crate_id) => {
+                        let crate_root = self.get_module(DefId {
+                            krate: crate_id,
+                            index: CRATE_DEF_INDEX,
+                        });
+                        self.populate_module_if_necessary(&crate_root);
 
-                suggestions.extend(
-                    self.lookup_import_candidates_from_module(
-                        lookup_name, namespace, external_prelude_module, krate_ident, &filter_fn
-                    )
-                );
+                        suggestions.extend(
+                            self.lookup_import_candidates_from_module(
+                                lookup_name, namespace, crate_root, ident, &filter_fn
+                            )
+                        );
+                    }
+                    None => {}
+                }
             }
         }
 
@@ -4576,7 +4598,6 @@ fn report_ambiguity_error(&self, ident: Ident, b1: &NameBinding, b2: &NameBindin
 
     fn report_errors(&mut self, krate: &Crate) {
         self.report_with_use_injections(krate);
-        self.report_proc_macro_import(krate);
         let mut reported_spans = FxHashSet();
 
         for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
@@ -4800,7 +4821,12 @@ fn show_candidates(err: &mut DiagnosticBuilder,
             *candidate = format!("use {};\n{}", candidate, additional_newline);
         }
 
-        err.span_suggestions(span, &msg, path_strings);
+        err.span_suggestions_with_applicability(
+            span,
+            &msg,
+            path_strings,
+            Applicability::Unspecified,
+        );
     } else {
         let mut msg = msg;
         msg.push(':');
index f687e022a412cf646215307bf1c0dda60705c971..cb561b2597b397920e0ac9464bf584e382e04ad5 100644 (file)
 use Namespace::{self, TypeNS, MacroNS};
 use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
 use resolve_imports::ImportResolver;
-use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex,
-                         DefIndexAddressSpace};
+use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex,
+                         CrateNum, DefIndexAddressSpace};
 use rustc::hir::def::{Def, NonMacroAttrKind};
 use rustc::hir::map::{self, DefCollector};
 use rustc::{ty, lint};
-use rustc::middle::cstore::CrateStore;
 use syntax::ast::{self, Name, Ident};
 use syntax::attr;
 use syntax::errors::DiagnosticBuilder;
 use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
 use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
-use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
+use syntax::ext::expand::{AstFragment, Invocation, InvocationKind, TogetherWith};
 use syntax::ext::hygiene::{self, Mark};
 use syntax::ext::tt::macro_rules;
 use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue};
@@ -110,19 +109,21 @@ pub struct ParentScope<'a> {
     crate derives: Vec<ast::Path>,
 }
 
-pub struct ProcMacError {
-    crate_name: Symbol,
-    name: Symbol,
-    module: ast::NodeId,
-    use_span: Span,
-    warn_msg: &'static str,
-}
-
-// For compatibility bang macros are skipped when resolving potentially built-in attributes.
-fn macro_kind_mismatch(name: Name, requirement: Option<MacroKind>, candidate: Option<MacroKind>)
-                       -> bool {
-    requirement == Some(MacroKind::Attr) && candidate == Some(MacroKind::Bang) &&
-    (name == "test" || name == "bench" || is_builtin_attr_name(name))
+// Macro namespace is separated into two sub-namespaces, one for bang macros and
+// one for attribute-like macros (attributes, derives).
+// We ignore resolutions from one sub-namespace when searching names in scope for another.
+fn sub_namespace_mismatch(requirement: Option<MacroKind>, candidate: Option<MacroKind>) -> bool {
+    #[derive(PartialEq)]
+    enum SubNS { Bang, AttrLike }
+    let sub_ns = |kind| match kind {
+        MacroKind::Bang => Some(SubNS::Bang),
+        MacroKind::Attr | MacroKind::Derive => Some(SubNS::AttrLike),
+        MacroKind::ProcMacroStub => None,
+    };
+    let requirement = requirement.and_then(|kind| sub_ns(kind));
+    let candidate = candidate.and_then(|kind| sub_ns(kind));
+    // "No specific sub-namespace" means "matches anything" for both requirements and candidates.
+    candidate.is_some() && requirement.is_some() && candidate != requirement
 }
 
 impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
@@ -218,7 +219,7 @@ fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFra
 
     fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) {
         let def_id = DefId {
-            krate: BUILTIN_MACROS_CRATE,
+            krate: CrateNum::BuiltinMacros,
             index: DefIndex::from_array_index(self.macro_map.len(),
                                               DefIndexAddressSpace::Low),
         };
@@ -331,28 +332,37 @@ fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>, allow_deri
 
     fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool)
                                 -> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
-        let (path, kind, derives_in_scope) = match invoc.kind {
+        let (path, kind, derives_in_scope, together_with) = match invoc.kind {
             InvocationKind::Attr { attr: None, .. } =>
                 return Ok(None),
-            InvocationKind::Attr { attr: Some(ref attr), ref traits, .. } =>
-                (&attr.path, MacroKind::Attr, traits.clone()),
+            InvocationKind::Attr { attr: Some(ref attr), ref traits, together_with, .. } =>
+                (&attr.path, MacroKind::Attr, traits.clone(), together_with),
             InvocationKind::Bang { ref mac, .. } =>
-                (&mac.node.path, MacroKind::Bang, Vec::new()),
+                (&mac.node.path, MacroKind::Bang, Vec::new(), TogetherWith::None),
             InvocationKind::Derive { ref path, .. } =>
-                (path, MacroKind::Derive, Vec::new()),
+                (path, MacroKind::Derive, Vec::new(), TogetherWith::None),
         };
 
         let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
         let (def, ext) = self.resolve_macro_to_def(path, kind, &parent_scope, force)?;
 
         if let Def::Macro(def_id, _) = def {
+            match together_with {
+                TogetherWith::Derive =>
+                    self.session.span_err(invoc.span(),
+                        "macro attributes must be placed before `#[derive]`"),
+                TogetherWith::TestBench if !self.session.features_untracked().plugin =>
+                    self.session.span_err(invoc.span(),
+                        "macro attributes cannot be used together with `#[test]` or `#[bench]`"),
+                _ => {}
+            }
             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);
+            invoc.expansion_data.mark.set_is_builtin(def_id.krate == CrateNum::BuiltinMacros);
         }
 
         Ok(Some(ext))
@@ -641,10 +651,7 @@ enum WhereToResolve<'a> {
                     }
                 }
                 WhereToResolve::BuiltinAttrs => {
-                    // FIXME: Only built-in attributes are not considered as candidates for
-                    // non-attributes to fight off regressions on stable channel (#53205).
-                    // We need to come up with some more principled approach instead.
-                    if kind == Some(MacroKind::Attr) && is_builtin_attr_name(ident.name) {
+                    if is_builtin_attr_name(ident.name) {
                         let binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin),
                                        ty::Visibility::Public, ident.span, Mark::root())
                                        .to_name_binding(self.arenas);
@@ -765,7 +772,7 @@ macro_rules! continue_search { () => {
 
             match result {
                 Ok(result) => {
-                    if macro_kind_mismatch(ident.name, kind, result.0.macro_kind()) {
+                    if sub_namespace_mismatch(kind, result.0.macro_kind()) {
                         continue_search!();
                     }
 
@@ -829,7 +836,7 @@ fn resolve_legacy_scope(
         parent_scope: &ParentScope<'a>,
         record_used: bool,
     ) -> Option<&'a NameBinding<'a>> {
-        if macro_kind_mismatch(ident.name, kind, Some(MacroKind::Bang)) {
+        if sub_namespace_mismatch(kind, Some(MacroKind::Bang)) {
             return None;
         }
 
@@ -973,7 +980,6 @@ pub fn finalize_current_module_macro_resolutions(&mut self) {
                     check_consistency(self, binding.def_ignoring_ambiguity());
                     if from_prelude {
                         self.record_use(ident, MacroNS, binding);
-                        self.err_if_macro_use_proc_macro(ident.name, span, binding);
                     }
                 }
             };
@@ -1125,69 +1131,6 @@ 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 = 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; }
-
-        let ext = binding.get_macro(self);
-
-        match *ext {
-            // If `ext` is a procedural macro, check if we've already warned about it
-            SyntaxExtension::AttrProcMacro(..) | SyntaxExtension::ProcMacro { .. } =>
-                if !self.warned_proc_macros.insert(name) { return; },
-            _ => return,
-        }
-
-        let warn_msg = match *ext {
-            SyntaxExtension::AttrProcMacro(..) =>
-                "attribute procedural macros cannot be imported with `#[macro_use]`",
-            SyntaxExtension::ProcMacro { .. } =>
-                "procedural macros cannot be imported with `#[macro_use]`",
-            _ => return,
-        };
-
-        let def_id = self.current_module.normal_ancestor_id;
-        let node_id = self.definitions.as_local_node_id(def_id).unwrap();
-
-        self.proc_mac_errors.push(ProcMacError {
-            crate_name: self.cstore.crate_name_untracked(krate),
-            name,
-            module: node_id,
-            use_span,
-            warn_msg,
-        });
-    }
-
-    pub fn report_proc_macro_import(&mut self, krate: &ast::Crate) {
-        for err in self.proc_mac_errors.drain(..) {
-            let (span, found_use) = ::UsePlacementFinder::check(krate, err.module);
-
-            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_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)
-                    .help(&format!("instead, import the procedural macro like any other item: \
-                                    `use {}::{};`", err.crate_name, err.name))
-                    .emit();
-            }
-        }
-    }
-
     fn gate_legacy_custom_derive(&mut self, name: Symbol, span: Span) {
         if !self.session.features_untracked().custom_derive {
             let sess = &self.session.parse_sess;
index dfbea0ffe2288e370e1589f4aca0a641b72ad110..dc4a76db6926654ad3af964ed30f5eec4befeba5 100644 (file)
@@ -196,7 +196,11 @@ pub fn resolve_ident_in_module_unadjusted(&mut self,
                     }
 
                     // Fall back to resolving to an external crate.
-                    if !(ns == TypeNS && self.extern_prelude.contains(&ident.name)) {
+                    if !(
+                        ns == TypeNS &&
+                        !ident.is_path_segment_keyword() &&
+                        self.extern_prelude.contains(&ident.name)
+                    ) {
                         // ... unless the crate name is not in the `extern_prelude`.
                         return binding;
                     }
@@ -211,7 +215,11 @@ pub fn resolve_ident_in_module_unadjusted(&mut self,
                     )
                 {
                     self.resolve_crate_root(ident)
-                } else if ns == TypeNS && !ident.is_path_segment_keyword() {
+                } else if
+                    ns == TypeNS &&
+                    !ident.is_path_segment_keyword() &&
+                    self.extern_prelude.contains(&ident.name)
+                {
                     let crate_id =
                         self.crate_loader.process_path_extern(ident.name, ident.span);
                     self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
@@ -630,15 +638,16 @@ pub fn finalize_imports(&mut self) {
             self.finalize_resolutions_in(module);
         }
 
-        #[derive(Default)]
-        struct UniformPathsCanaryResult<'a> {
+        struct UniformPathsCanaryResults<'a> {
+            name: Name,
             module_scope: Option<&'a NameBinding<'a>>,
             block_scopes: Vec<&'a NameBinding<'a>>,
         }
+
         // Collect all tripped `uniform_paths` canaries separately.
         let mut uniform_paths_canaries: BTreeMap<
-            (Span, NodeId),
-            (Name, PerNS<UniformPathsCanaryResult>),
+            (Span, NodeId, Namespace),
+            UniformPathsCanaryResults,
         > = BTreeMap::new();
 
         let mut errors = false;
@@ -665,21 +674,25 @@ struct UniformPathsCanaryResult<'a> {
                     import.module_path.len() > 0 &&
                     import.module_path[0].name == keywords::SelfValue.name();
 
-                let (prev_name, canary_results) =
-                    uniform_paths_canaries.entry((import.span, import.id))
-                        .or_insert((name, PerNS::default()));
-
-                // All the canaries with the same `id` should have the same `name`.
-                assert_eq!(*prev_name, name);
-
                 self.per_ns(|_, ns| {
                     if let Some(result) = result[ns].get().ok() {
+                        let canary_results =
+                            uniform_paths_canaries.entry((import.span, import.id, ns))
+                                .or_insert(UniformPathsCanaryResults {
+                                    name,
+                                    module_scope: None,
+                                    block_scopes: vec![],
+                                });
+
+                        // All the canaries with the same `id` should have the same `name`.
+                        assert_eq!(canary_results.name, name);
+
                         if has_explicit_self {
                             // There should only be one `self::x` (module-scoped) canary.
-                            assert!(canary_results[ns].module_scope.is_none());
-                            canary_results[ns].module_scope = Some(result);
+                            assert!(canary_results.module_scope.is_none());
+                            canary_results.module_scope = Some(result);
                         } else {
-                            canary_results[ns].block_scopes.push(result);
+                            canary_results.block_scopes.push(result);
                         }
                     }
                 });
@@ -720,77 +733,72 @@ struct UniformPathsCanaryResult<'a> {
         }
 
         let uniform_paths_feature = self.session.features_untracked().uniform_paths;
-        for ((span, _), (name, results)) in uniform_paths_canaries {
-            self.per_ns(|this, ns| {
-                let external_crate = if ns == TypeNS && this.extern_prelude.contains(&name) {
-                    let crate_id =
-                        this.crate_loader.process_path_extern(name, span);
-                    Some(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
-                } else {
-                    None
-                };
-                let result_filter = |result: &&NameBinding| {
-                    // Ignore canaries that resolve to an import of the same crate.
-                    // That is, we allow `use crate_name; use crate_name::foo;`.
-                    if let Some(def_id) = external_crate {
-                        if let Some(module) = result.module() {
-                            if module.normal_ancestor_id == def_id {
-                                return false;
-                            }
-                        }
-                    }
+        for ((span, _, ns), results) in uniform_paths_canaries {
+            let name = results.name;
+            let external_crate = if ns == TypeNS && self.extern_prelude.contains(&name) {
+                let crate_id =
+                    self.crate_loader.process_path_extern(name, span);
+                Some(Def::Mod(DefId { krate: crate_id, index: CRATE_DEF_INDEX }))
+            } else {
+                None
+            };
 
-                    true
-                };
-                let module_scope = results[ns].module_scope.filter(result_filter);
-                let block_scopes = || {
-                    results[ns].block_scopes.iter().cloned().filter(result_filter)
-                };
+            // Currently imports can't resolve in non-module scopes,
+            // we only have canaries in them for future-proofing.
+            if external_crate.is_none() && results.module_scope.is_none() {
+                continue;
+            }
+
+            {
+                let mut all_results = external_crate.into_iter().chain(
+                    results.module_scope.iter()
+                        .chain(&results.block_scopes)
+                        .map(|binding| binding.def())
+                );
+                let first = all_results.next().unwrap();
 
-                // An ambiguity requires more than one possible resolution.
+                // An ambiguity requires more than one *distinct* possible resolution.
                 let possible_resultions =
-                    (external_crate.is_some() as usize) +
-                    (module_scope.is_some() as usize) +
-                    (block_scopes().next().is_some() as usize);
+                    1 + all_results.filter(|&def| def != first).count();
                 if possible_resultions <= 1 {
-                    return;
+                    continue;
                 }
+            }
 
-                errors = true;
+            errors = true;
 
-                let msg = format!("`{}` import is ambiguous", name);
-                let mut err = this.session.struct_span_err(span, &msg);
-                let mut suggestion_choices = String::new();
-                if external_crate.is_some() {
-                    write!(suggestion_choices, "`::{}`", name);
-                    err.span_label(span,
-                        format!("can refer to external crate `::{}`", name));
-                }
-                if let Some(result) = module_scope {
-                    if !suggestion_choices.is_empty() {
-                        suggestion_choices.push_str(" or ");
-                    }
-                    write!(suggestion_choices, "`self::{}`", name);
-                    if uniform_paths_feature {
-                        err.span_label(result.span,
-                            format!("can refer to `self::{}`", name));
-                    } else {
-                        err.span_label(result.span,
-                            format!("may refer to `self::{}` in the future", name));
-                    }
-                }
-                for result in block_scopes() {
-                    err.span_label(result.span,
-                        format!("shadowed by block-scoped `{}`", name));
+            let msg = format!("`{}` import is ambiguous", name);
+            let mut err = self.session.struct_span_err(span, &msg);
+            let mut suggestion_choices = String::new();
+            if external_crate.is_some() {
+                write!(suggestion_choices, "`::{}`", name);
+                err.span_label(span,
+                    format!("can refer to external crate `::{}`", name));
+            }
+            if let Some(result) = results.module_scope {
+                if !suggestion_choices.is_empty() {
+                    suggestion_choices.push_str(" or ");
                 }
-                err.help(&format!("write {} explicitly instead", suggestion_choices));
+                write!(suggestion_choices, "`self::{}`", name);
                 if uniform_paths_feature {
-                    err.note("relative `use` paths enabled by `#![feature(uniform_paths)]`");
+                    err.span_label(result.span,
+                        format!("can refer to `self::{}`", name));
                 } else {
-                    err.note("in the future, `#![feature(uniform_paths)]` may become the default");
+                    err.span_label(result.span,
+                        format!("may refer to `self::{}` in the future", name));
                 }
-                err.emit();
-            });
+            }
+            for result in results.block_scopes {
+                err.span_label(result.span,
+                    format!("shadowed by block-scoped `{}`", name));
+            }
+            err.help(&format!("write {} explicitly instead", suggestion_choices));
+            if uniform_paths_feature {
+                err.note("relative `use` paths enabled by `#![feature(uniform_paths)]`");
+            } else {
+                err.note("in the future, `#![feature(uniform_paths)]` may become the default");
+            }
+            err.emit();
         }
 
         if !error_vec.is_empty() {
index 8d6a75ecc59257eb83b66c5d4090327824ee7b41..c9bae297031fffe6a976551e62acb5b17d74e46a 100644 (file)
@@ -813,6 +813,7 @@ fn fn_type(path: &ast::Path) -> bool {
             HirDef::Macro(..) |
             HirDef::ToolMod |
             HirDef::NonMacroAttr(..) |
+            HirDef::SelfCtor(..) |
             HirDef::Err => None,
         }
     }
index eaf1d03de7d0f301af3da953d4d516f97bd99d5e..72502cda6e02d95491aa1d31abe5dd5eb54e19a2 100644 (file)
@@ -1575,7 +1575,7 @@ pub fn ty_of_fn(&self,
 
         let output_ty = match decl.output {
             hir::Return(ref output) => self.ast_ty_to_ty(output),
-            hir::DefaultReturn(..) => tcx.mk_nil(),
+            hir::DefaultReturn(..) => tcx.mk_unit(),
         };
 
         debug!("ty_of_fn: output_ty={:?}", output_ty);
index 7f65a5f0b5a6303205aa6c86cc1aad9a6d50250a..0d2bc575401ef1733334a3cb4085083ffb4e7586 100644 (file)
@@ -666,7 +666,7 @@ pub fn check_match(&self,
                 // us to give better error messages (pointing to a usually better
                 // arm for inconsistent arms or to the whole match when a `()` type
                 // is required).
-                Expectation::ExpectHasType(ety) if ety != self.tcx.mk_nil() => ety,
+                Expectation::ExpectHasType(ety) if ety != self.tcx.mk_unit() => ety,
                 _ => self.next_ty_var(TypeVariableOrigin::MiscVariable(expr.span)),
             };
             CoerceMany::with_coercion_sites(coerce_first, arms)
@@ -687,14 +687,14 @@ pub fn check_match(&self,
             // Handle the fallback arm of a desugared if-let like a missing else.
             let is_if_let_fallback = match match_src {
                 hir::MatchSource::IfLetDesugar { contains_else_clause: false } => {
-                    i == arms.len() - 1 && arm_ty.is_nil()
+                    i == arms.len() - 1 && arm_ty.is_unit()
                 }
                 _ => false
             };
 
             if is_if_let_fallback {
                 let cause = self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse);
-                assert!(arm_ty.is_nil());
+                assert!(arm_ty.is_unit());
                 coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
             } else {
                 let cause = self.cause(expr.span, ObligationCauseCode::MatchExpressionArm {
@@ -766,12 +766,13 @@ fn check_pat_path(&self,
             }
             Def::VariantCtor(_, CtorKind::Const) |
             Def::StructCtor(_, CtorKind::Const) |
+            Def::SelfCtor(..) |
             Def::Const(..) | Def::AssociatedConst(..) => {} // OK
             _ => bug!("unexpected pattern definition: {:?}", def)
         }
 
         // Type check the path.
-        let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
+        let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id).0;
         self.demand_suptype(pat.span, expected, pat_ty);
         pat_ty
     }
@@ -801,6 +802,24 @@ fn check_pat_tuple_struct(&self,
 
         // Resolve the path and check the definition for errors.
         let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
+        if def == Def::Err {
+            self.set_tainted_by_errors();
+            on_error();
+            return self.tcx.types.err;
+        }
+
+        // Type check the path.
+        let (pat_ty, def) = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
+        if !pat_ty.is_fn() {
+            report_unexpected_def(def);
+            return self.tcx.types.err;
+        }
+        // Replace constructor type with constructed type for tuple struct patterns.
+        let pat_ty = pat_ty.fn_sig(tcx).output();
+        let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type");
+
+        self.demand_eqtype(pat.span, expected, pat_ty);
+
         let variant = match def {
             Def::Err => {
                 self.set_tainted_by_errors();
@@ -817,15 +836,6 @@ fn check_pat_tuple_struct(&self,
             }
             _ => bug!("unexpected pattern definition: {:?}", def)
         };
-
-        // Type check the path.
-        let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
-        // Replace constructor type with constructed type for tuple struct patterns.
-        let pat_ty = pat_ty.fn_sig(tcx).output();
-        let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type");
-
-        self.demand_eqtype(pat.span, expected, pat_ty);
-
         // Type check subpatterns.
         if subpats.len() == variant.fields.len() ||
                 subpats.len() < variant.fields.len() && ddpos.is_some() {
index ebe0c279aafab51304754c3b7b21b9499169d52e..85641854e6e2d1d7275f9f12aa110c9b9791692c 100644 (file)
@@ -40,7 +40,7 @@
 
 use super::FnCtxt;
 
-use errors::DiagnosticBuilder;
+use errors::{DiagnosticBuilder,Applicability};
 use hir::def_id::DefId;
 use lint;
 use rustc::hir;
@@ -299,9 +299,12 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
                 err.note("The type information given here is insufficient to check whether \
                           the pointer cast is valid");
                 if unknown_cast_to {
-                    err.span_suggestion_short(self.cast_span,
-                                              "consider giving more type information",
-                                              String::new());
+                    err.span_suggestion_short_with_applicability(
+                        self.cast_span,
+                        "consider giving more type information",
+                        String::new(),
+                        Applicability::Unspecified,
+                    );
                 }
                 err.emit();
             }
@@ -327,9 +330,12 @@ fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
                 if self.cast_ty.is_trait() {
                     match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) {
                         Ok(s) => {
-                            err.span_suggestion(self.cast_span,
-                                                "try casting to a reference instead",
-                                                format!("&{}{}", mtstr, s));
+                            err.span_suggestion_with_applicability(
+                                self.cast_span,
+                                "try casting to a reference instead",
+                                format!("&{}{}", mtstr, s),
+                                Applicability::MachineApplicable,
+                            );
                         }
                         Err(_) => {
                             span_help!(err, self.cast_span, "did you mean `&{}{}`?", mtstr, tstr)
@@ -346,9 +352,12 @@ fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
             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,
-                                            "try casting to a `Box` instead",
-                                            format!("Box<{}>", s));
+                        err.span_suggestion_with_applicability(
+                            self.cast_span,
+                            "try casting to a `Box` instead",
+                            format!("Box<{}>", s),
+                            Applicability::MachineApplicable,
+                        );
                     }
                     Err(_) => span_help!(err, self.cast_span, "did you mean `Box<{}>`?", tstr),
                 }
index 763adb007c3a4d791e8fbea3a4ad5bc702f26e60..9604eb3420fb3cc779a1f91735e8e1fd95933402 100644 (file)
@@ -1077,7 +1077,7 @@ pub fn coerce_forced_unit<'a>(&mut self,
         self.coerce_inner(fcx,
                           cause,
                           None,
-                          fcx.tcx.mk_nil(),
+                          fcx.tcx.mk_unit(),
                           Some(augment_error),
                           label_unit_as_expected)
     }
@@ -1146,8 +1146,8 @@ fn coerce_inner<'a>(&mut self,
             // `expression_ty` will be unit).
             //
             // Another example is `break` with no argument expression.
-            assert!(expression_ty.is_nil());
-            assert!(expression_ty.is_nil(), "if let hack without unit type");
+            assert!(expression_ty.is_unit());
+            assert!(expression_ty.is_unit(), "if let hack without unit type");
             fcx.at(cause, fcx.param_env)
                .eq_exp(label_expression_as_expected, expression_ty, self.merged_ty())
                .map(|infer_ok| {
index 9aa2ba363ed7ab41870188de93b2d8bf101ab303..a192068d28f202c5fa4f321d83f0e455cfdc9836 100644 (file)
@@ -16,6 +16,7 @@
 use rustc::ty::error::{ExpectedFound, TypeError};
 use rustc::ty::subst::{Subst, Substs};
 use rustc::util::common::ErrorReported;
+use errors::Applicability;
 
 use syntax_pos::Span;
 
@@ -321,10 +322,11 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 if let Some(trait_err_span) = trait_err_span {
                     if let Ok(trait_err_str) = tcx.sess.source_map().
                                                span_to_snippet(trait_err_span) {
-                        diag.span_suggestion(
+                        diag.span_suggestion_with_applicability(
                             impl_err_span,
                             "consider change the type to match the mutability in trait",
                             format!("{}", trait_err_str),
+                            Applicability::MachineApplicable,
                         );
                     }
                 }
@@ -799,7 +801,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             .span_to_snippet(trait_m.generics.span)
                             .ok()?;
 
-                        err.multipart_suggestion(
+                        err.multipart_suggestion_with_applicability(
                             "try changing the `impl Trait` argument to a generic parameter",
                             vec![
                                 // replace `impl Trait` with `T`
@@ -809,6 +811,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 // of the generics, but it works for the common case
                                 (generics_span, new_generics),
                             ],
+                            Applicability::MaybeIncorrect,
                         );
                         Some(())
                     })();
@@ -870,7 +873,7 @@ fn nested_visit_map<'this>(
                             .span_to_snippet(bounds)
                             .ok()?;
 
-                        err.multipart_suggestion(
+                        err.multipart_suggestion_with_applicability(
                             "try removing the generic parameter and using `impl Trait` instead",
                             vec![
                                 // delete generic parameters
@@ -878,6 +881,7 @@ fn nested_visit_map<'this>(
                                 // replace param usage with `impl Trait`
                                 (span, format!("impl {}", bounds)),
                             ],
+                            Applicability::MaybeIncorrect,
                         );
                         Some(())
                     })();
index 4e22ead8db987a0514b885a992a43eac35332084..ee19574dc4e95b2a9308291b9b625dd37a7c491b 100644 (file)
@@ -132,9 +132,12 @@ pub fn demand_coerce_diag(&self,
                 let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr));
                 let suggestions = compatible_variants.iter()
                     .map(|v| format!("{}({})", v, expr_text)).collect::<Vec<_>>();
-                err.span_suggestions(expr.span,
-                                     "try using a variant of the expected type",
-                                     suggestions);
+                err.span_suggestions_with_applicability(
+                     expr.span,
+                     "try using a variant of the expected type",
+                     suggestions,
+                     Applicability::MaybeIncorrect,
+                );
             }
         }
 
@@ -415,10 +418,55 @@ pub fn check_for_cast(&self,
                                           src,
                                           if needs_paren { ")" } else { "" },
                                           expected_ty);
-            let into_suggestion = format!("{}{}{}.into()",
-                                          if needs_paren { "(" } else { "" },
-                                          src,
-                                          if needs_paren { ")" } else { "" });
+            let into_suggestion = format!(
+                "{}{}{}.into()",
+                if needs_paren { "(" } else { "" },
+                src,
+                if needs_paren { ")" } else { "" },
+            );
+            let literal_is_ty_suffixed = |expr: &hir::Expr| {
+                if let hir::ExprKind::Lit(lit) = &expr.node {
+                    lit.node.is_suffixed()
+                } else {
+                    false
+                }
+            };
+
+            let into_sugg = into_suggestion.clone();
+            let suggest_to_change_suffix_or_into = |err: &mut DiagnosticBuilder,
+                                                    note: Option<&str>| {
+                let suggest_msg = if literal_is_ty_suffixed(expr) {
+                    format!(
+                        "change the type of the numeric literal from `{}` to `{}`",
+                        checked_ty,
+                        expected_ty,
+                    )
+                } else {
+                    match note {
+                        Some(note) => format!("{}, which {}", msg, note),
+                        _ => format!("{} in a lossless way", msg),
+                    }
+                };
+
+                let suffix_suggestion = format!(
+                    "{}{}{}{}",
+                    if needs_paren { "(" } else { "" },
+                    src.trim_right_matches(&checked_ty.to_string()),
+                    expected_ty,
+                    if needs_paren { ")" } else { "" },
+                );
+
+                err.span_suggestion_with_applicability(
+                    expr.span,
+                    &suggest_msg,
+                    if literal_is_ty_suffixed(expr) {
+                        suffix_suggestion
+                    } else {
+                        into_sugg
+                    },
+                    Applicability::MachineApplicable,
+                );
+            };
 
             match (&expected_ty.sty, &checked_ty.sty) {
                 (&ty::Int(ref exp), &ty::Int(ref found)) => {
@@ -444,11 +492,9 @@ pub fn check_for_cast(&self,
                             }
                         }
                         _ => {
-                            err.span_suggestion_with_applicability(
-                                expr.span,
-                                &format!("{}, which {}", msg, will_sign_extend),
-                                into_suggestion,
-                                Applicability::MachineApplicable
+                            suggest_to_change_suffix_or_into(
+                                err,
+                                Some(will_sign_extend),
                             );
                         }
                     }
@@ -477,12 +523,10 @@ pub fn check_for_cast(&self,
                             }
                         }
                         _ => {
-                            err.span_suggestion_with_applicability(
-                                expr.span,
-                                &format!("{}, which {}", msg, will_zero_extend),
-                                into_suggestion,
-                                Applicability::MachineApplicable
-                            );
+                           suggest_to_change_suffix_or_into(
+                               err,
+                               Some(will_zero_extend),
+                           );
                         }
                     }
                     true
@@ -583,12 +627,10 @@ pub fn check_for_cast(&self,
                 }
                 (&ty::Float(ref exp), &ty::Float(ref found)) => {
                     if found.bit_width() < exp.bit_width() {
-                        err.span_suggestion_with_applicability(
-                            expr.span,
-                            &format!("{} in a lossless way", msg),
-                            into_suggestion,
-                            Applicability::MachineApplicable
-                        );
+                       suggest_to_change_suffix_or_into(
+                           err,
+                           None,
+                       );
                     } else if can_cast {
                         err.span_suggestion_with_applicability(
                             expr.span,
index c7db3debf5a0d6dfacd6b276249715e1202d0a95..8215ae211c0b9285d940ccc9dcda665cd217bab0 100644 (file)
@@ -94,7 +94,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             "load" => (1, vec![tcx.mk_imm_ptr(param(0))],
                        param(0)),
             "store" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)],
-                        tcx.mk_nil()),
+                        tcx.mk_unit()),
 
             "xchg" | "xadd" | "xsub" | "and"  | "nand" | "or" | "xor" | "max" |
             "min"  | "umax" | "umin" => {
@@ -102,7 +102,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                  param(0))
             }
             "fence" | "singlethreadfence" => {
-                (0, Vec::new(), tcx.mk_nil())
+                (0, Vec::new(), tcx.mk_unit())
             }
             op => {
                 struct_span_err!(tcx.sess, it.span, E0092,
@@ -121,7 +121,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             _ => hir::Unsafety::Unsafe,
         };
         let (n_tps, inputs, output) = match &name[..] {
-            "breakpoint" => (0, Vec::new(), tcx.mk_nil()),
+            "breakpoint" => (0, Vec::new(), tcx.mk_unit()),
             "size_of" |
             "pref_align_of" | "min_align_of" => (1, Vec::new(), tcx.types.usize),
             "size_of_val" |  "min_align_of_val" => {
@@ -141,7 +141,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     tcx.mk_mut_ptr(param(0)),
                     param(0)
                   ],
-               tcx.mk_nil())
+               tcx.mk_unit())
             }
             "prefetch_read_data" | "prefetch_write_data" |
             "prefetch_read_instruction" | "prefetch_write_instruction" => {
@@ -149,10 +149,10 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           ty: param(0),
                           mutbl: hir::MutImmutable
                          }), tcx.types.i32],
-                    tcx.mk_nil())
+                    tcx.mk_unit())
             }
             "drop_in_place" => {
-                (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_nil())
+                (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit())
             }
             "needs_drop" => (1, Vec::new(), tcx.types.bool),
 
@@ -185,7 +185,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   }),
                   tcx.types.usize,
                ],
-               tcx.mk_nil())
+               tcx.mk_unit())
             }
             "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
               (1,
@@ -200,7 +200,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   }),
                   tcx.types.usize,
                ],
-               tcx.mk_nil())
+               tcx.mk_unit())
             }
             "write_bytes" | "volatile_set_memory" => {
               (1,
@@ -212,7 +212,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   tcx.types.u8,
                   tcx.types.usize,
                ],
-               tcx.mk_nil())
+               tcx.mk_unit())
             }
             "sqrtf32" => (0, vec![ tcx.types.f32 ], tcx.types.f32),
             "sqrtf64" => (0, vec![ tcx.types.f64 ], tcx.types.f64),
@@ -280,7 +280,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             "volatile_load" | "unaligned_volatile_load" =>
                 (1, vec![ tcx.mk_imm_ptr(param(0)) ], param(0)),
             "volatile_store" | "unaligned_volatile_store" =>
-                (1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_nil()),
+                (1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_unit()),
 
             "ctpop" | "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" |
             "bswap" | "bitreverse" =>
@@ -300,7 +300,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" =>
                 (1, vec![param(0), param(0)], param(0)),
 
-            "assume" => (0, vec![tcx.types.bool], tcx.mk_nil()),
+            "assume" => (0, vec![tcx.types.bool], tcx.mk_unit()),
             "likely" => (0, vec![tcx.types.bool], tcx.types.bool),
             "unlikely" => (0, vec![tcx.types.bool], tcx.types.bool),
 
@@ -313,7 +313,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
                 let fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
                     iter::once(mut_u8),
-                    tcx.mk_nil(),
+                    tcx.mk_unit(),
                     false,
                     hir::Unsafety::Normal,
                     Abi::Rust,
@@ -322,7 +322,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
 
             "nontemporal_store" => {
-                (1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_nil())
+                (1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_unit())
             }
 
             ref other => {
@@ -376,7 +376,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             (3, vec![param(0), param(1), param(2)], param(0))
         }
         "simd_scatter" => {
-            (3, vec![param(0), param(1), param(2)], tcx.mk_nil())
+            (3, vec![param(0), param(1), param(2)], tcx.mk_unit())
         }
         "simd_insert" => (2, vec![param(0), tcx.types.u32, param(1)], param(0)),
         "simd_extract" => (2, vec![param(0), tcx.types.u32], param(1)),
index 85a437283fa681e66c18de97c7cb2d5f959f958d..499daccf5e80f101e20e294c60979ed028502219 100644 (file)
@@ -1064,7 +1064,8 @@ fn emit_unstable_name_collision_hint(
             "a method with this name may be added to the standard library in the future",
         );
 
-        // FIXME: This should be a `span_suggestion` instead of `help`. However `self.span` only
+        // FIXME: This should be a `span_suggestion_with_applicability` instead of `help`
+        // However `self.span` only
         // highlights the method name, so we can't use it. Also consider reusing the code from
         // `report_method_error()`.
         diag.help(&format!(
index abc32ed2ea0433d2576dac7fd5e86d0f2f0f029e..fe5128a695845fb65555dc0260858de620667729 100644 (file)
@@ -251,13 +251,16 @@ pub fn report_method_error(&self,
                                 let snippet = tcx.sess.source_map().span_to_snippet(lit.span)
                                     .unwrap_or("<numeric literal>".to_string());
 
-                                err.span_suggestion(lit.span,
+                                err.span_suggestion_with_applicability(
+                                                    lit.span,
                                                     &format!("you must specify a concrete type for \
                                                               this numeric value, like `{}`",
                                                              concrete_type),
                                                     format!("{}_{}",
                                                             snippet,
-                                                            concrete_type));
+                                                            concrete_type),
+                                                    Applicability::MaybeIncorrect,
+                                );
                             }
                             hir::ExprKind::Path(ref qpath) => {  // local binding
                                 if let &hir::QPath::Resolved(_, ref path) = &qpath {
@@ -281,13 +284,14 @@ pub fn report_method_error(&self,
                                                 ty,
                                                 ..
                                             })) => {
-                                                err.span_suggestion(
+                                                err.span_suggestion_with_applicability(
                                                     // account for `let x: _ = 42;`
                                                     //                  ^^^^
                                                     span.to(ty.as_ref().map(|ty| ty.span)
                                                         .unwrap_or(span)),
                                                     &msg,
                                                     format!("{}: {}", snippet, concrete_type),
+                                                    Applicability::MaybeIncorrect,
                                                 );
                                             }
                                             _ => {
@@ -516,7 +520,12 @@ fn suggest_use_candidates(&self,
                 format!("use {};\n{}", self.tcx.item_path_str(*did), additional_newline)
             }).collect();
 
-            err.span_suggestions(span, &msg, path_strings);
+            err.span_suggestions_with_applicability(
+                                                    span,
+                                                    &msg,
+                                                    path_strings,
+                                                    Applicability::MaybeIncorrect,
+            );
         } else {
             let limit = if candidates.len() == 5 { 5 } else { 4 };
             for (i, trait_did) in candidates.iter().take(limit).enumerate() {
index 9ab269702db1c8d99c8fd4a04d2719fbecb82fae..80df7faf39d22cb588db659d4b41d88821b913bb 100644 (file)
@@ -622,7 +622,10 @@ fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> Self {
         let body_id = item_id.and_then(|id| tcx.hir.maybe_body_owned_by(id));
         let implicit_region_bound = body_id.map(|body_id| {
             let body = tcx.hir.body(body_id);
-            tcx.mk_region(ty::ReScope(region::Scope::CallSite(body.value.hir_id.local_id)))
+            tcx.mk_region(ty::ReScope(region::Scope {
+                id: body.value.hir_id.local_id,
+                data: region::ScopeData::CallSite
+            }))
         });
 
         Inherited {
@@ -2808,9 +2811,9 @@ fn check_argument_types(&self,
         } else {
             // is the missing argument of type `()`?
             let sugg_unit = if expected_arg_tys.len() == 1 && supplied_arg_count == 0 {
-                self.resolve_type_vars_if_possible(&expected_arg_tys[0]).is_nil()
+                self.resolve_type_vars_if_possible(&expected_arg_tys[0]).is_unit()
             } else if fn_inputs.len() == 1 && supplied_arg_count == 0 {
-                self.resolve_type_vars_if_possible(&fn_inputs[0]).is_nil()
+                self.resolve_type_vars_if_possible(&fn_inputs[0]).is_unit()
             } else {
                 false
             };
@@ -3348,7 +3351,12 @@ fn check_field(&self,
                         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);
-                        err.span_suggestion(field.span, &msg, suggestion);
+                        err.span_suggestion_with_applicability(
+                            field.span,
+                            &msg,
+                            suggestion,
+                            Applicability::MaybeIncorrect,
+                        );
                     }
                     _ => {}
                 }
@@ -3898,7 +3906,7 @@ fn check_expr_kind(&self,
             hir::ExprKind::Path(ref qpath) => {
                 let (def, opt_ty, segs) = self.resolve_ty_and_def_ufcs(qpath, expr.id, expr.span);
                 let ty = if def != Def::Err {
-                    self.instantiate_value_path(segs, opt_ty, def, expr.span, id)
+                    self.instantiate_value_path(segs, opt_ty, def, expr.span, id).0
                 } else {
                     self.set_tainted_by_errors();
                     tcx.types.err
@@ -3918,7 +3926,7 @@ fn check_expr_kind(&self,
                 for input in inputs {
                     self.check_expr(input);
                 }
-                tcx.mk_nil()
+                tcx.mk_unit()
             }
             hir::ExprKind::Break(destination, ref expr_opt) => {
                 if let Ok(target_id) = destination.target_id {
@@ -3945,7 +3953,7 @@ fn check_expr_kind(&self,
                     } else {
                         // Otherwise, this is a break *without* a value. That's
                         // always legal, and is equivalent to `break ()`.
-                        e_ty = tcx.mk_nil();
+                        e_ty = tcx.mk_unit();
                         cause = self.misc(expr.span);
                     }
 
@@ -3958,7 +3966,7 @@ fn check_expr_kind(&self,
                         if let Some(ref e) = *expr_opt {
                             coerce.coerce(self, &cause, e, e_ty);
                         } else {
-                            assert!(e_ty.is_nil());
+                            assert!(e_ty.is_unit());
                             coerce.coerce_forced_unit(self, &cause, &mut |_| (), true);
                         }
                     } else {
@@ -4052,7 +4060,7 @@ fn check_expr_kind(&self,
                 if lhs_ty.references_error() || rhs_ty.references_error() {
                     tcx.types.err
                 } else {
-                    tcx.mk_nil()
+                    tcx.mk_unit()
                 }
             }
             hir::ExprKind::If(ref cond, ref then_expr, ref opt_else_expr) => {
@@ -4081,7 +4089,7 @@ fn check_expr_kind(&self,
                     self.diverges.set(Diverges::Maybe);
                 }
 
-                self.tcx.mk_nil()
+                self.tcx.mk_unit()
             }
             hir::ExprKind::Loop(ref body, _, source) => {
                 let coerce = match source {
@@ -4121,7 +4129,7 @@ fn check_expr_kind(&self,
                     // [1]
                     self.tcx.sess.delay_span_bug(body.span, "no coercion, but loop may not break");
                 }
-                ctxt.coerce.map(|c| c.complete(self)).unwrap_or(self.tcx.mk_nil())
+                ctxt.coerce.map(|c| c.complete(self)).unwrap_or(self.tcx.mk_unit())
             }
             hir::ExprKind::Match(ref discrim, ref arms, match_src) => {
                 self.check_match(expr, &discrim, arms, expected, match_src)
@@ -4352,7 +4360,7 @@ fn check_expr_kind(&self,
                                         "yield statement outside of generator literal").emit();
                     }
                 }
-                tcx.mk_nil()
+                tcx.mk_unit()
             }
         }
     }
@@ -4516,7 +4524,7 @@ pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) {
             }
             hir::StmtKind::Expr(ref expr, _) => {
                 // Check with expected type of ()
-                self.check_expr_has_type_or_error(&expr, self.tcx.mk_nil());
+                self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit());
             }
             hir::StmtKind::Semi(ref expr, _) => {
                 self.check_expr(&expr);
@@ -4529,7 +4537,7 @@ pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) {
     }
 
     pub fn check_block_no_value(&self, blk: &'gcx hir::Block)  {
-        let unit = self.tcx.mk_nil();
+        let unit = self.tcx.mk_unit();
         let ty = self.check_block_with_expected(blk, ExpectHasType(unit));
 
         // if the block produces a `!` value, that can always be
@@ -4716,7 +4724,12 @@ pub fn suggest_ref_or_into(
         found: Ty<'tcx>,
     ) {
         if let Some((sp, msg, suggestion)) = self.check_ref(expr, found, expected) {
-            err.span_suggestion(sp, msg, suggestion);
+            err.span_suggestion_with_applicability(
+                sp,
+                msg,
+                suggestion,
+                Applicability::MachineApplicable,
+            );
         } else if !self.check_for_cast(err, expr, found, expected) {
             let methods = self.get_conversion_methods(expr.span, expected, found);
             if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) {
@@ -4726,11 +4739,32 @@ pub fn suggest_ref_or_into(
                         if receiver.ends_with(&method_call) {
                             None  // do not suggest code that is already there (#53348)
                         } else {
-                            Some(format!("{}{}", receiver, method_call))
+                            /*
+                            methods defined in `method_call_list` will overwrite
+                            `.clone()` in copy of `receiver`
+                            */
+                            let method_call_list = [".to_vec()", ".to_string()"];
+                            if receiver.ends_with(".clone()")
+                                    && method_call_list.contains(&method_call.as_str()){
+                                // created copy of `receiver` because we don't want other
+                                // suggestion to get affected
+                                let mut new_receiver = receiver.clone();
+                                let max_len = new_receiver.rfind(".").unwrap();
+                                new_receiver.truncate(max_len);
+                                Some(format!("{}{}", new_receiver, method_call))
+                            }
+                            else {
+                                Some(format!("{}{}", receiver, method_call))
+                            }
                         }
                     }) .collect::<Vec<_>>();
                 if !suggestions.is_empty() {
-                    err.span_suggestions(expr.span, "try using a conversion method", suggestions);
+                    err.span_suggestions_with_applicability(
+                        expr.span,
+                        "try using a conversion method",
+                        suggestions,
+                        Applicability::MaybeIncorrect,
+                    );
                 }
             }
         }
@@ -4752,7 +4786,7 @@ fn suggest_missing_semicolon(&self,
                                  expression: &'gcx hir::Expr,
                                  expected: Ty<'tcx>,
                                  cause_span: Span) {
-        if expected.is_nil() {
+        if expected.is_unit() {
             // `BlockTailExpression` only relevant if the tail expr would be
             // useful on its own.
             match expression.node {
@@ -4795,7 +4829,7 @@ fn suggest_missing_return_type(&self,
                                    can_suggest: bool) {
         // Only suggest changing the return type for methods that
         // 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()) {
+        match (&fn_decl.output, found.is_suggestable(), can_suggest, expected.is_unit()) {
             (&hir::FunctionRetTy::DefaultReturn(span), true, true, true) => {
                 err.span_suggestion_with_applicability(
                     span,
@@ -4923,7 +4957,8 @@ fn def_ids_for_path_segments(&self,
         match def {
             // Case 1. Reference to a struct/variant constructor.
             Def::StructCtor(def_id, ..) |
-            Def::VariantCtor(def_id, ..) => {
+            Def::VariantCtor(def_id, ..) |
+            Def::SelfCtor(.., def_id) => {
                 // Everything but the final segment should have no
                 // parameters at all.
                 let generics = self.tcx.generics_of(def_id);
@@ -4969,7 +5004,7 @@ pub fn instantiate_value_path(&self,
                                   def: Def,
                                   span: Span,
                                   node_id: ast::NodeId)
-                                  -> Ty<'tcx> {
+                                  -> (Ty<'tcx>, Def) {
         debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})",
                segments,
                def,
@@ -5019,7 +5054,7 @@ pub fn instantiate_value_path(&self,
                 let ty = self.local_ty(span, nid);
                 let ty = self.normalize_associated_types_in(span, &ty);
                 self.write_ty(self.tcx.hir.node_to_hir_id(node_id), ty);
-                return ty;
+                return (ty, def);
             }
             _ => {}
         }
@@ -5056,7 +5091,28 @@ pub fn instantiate_value_path(&self,
             self.tcx.generics_of(*def_id).has_self
         }).unwrap_or(false);
 
-        let def_id = def.def_id();
+        let mut new_def = def;
+        let (def_id, ty) = if let Def::SelfCtor(impl_def_id) = def {
+            let ty = self.impl_self_ty(span, impl_def_id).ty;
+
+            match ty.ty_adt_def() {
+                Some(adt_def) if adt_def.is_struct() => {
+                    let variant = adt_def.non_enum_variant();
+                    new_def = Def::StructCtor(variant.did, variant.ctor_kind);
+                    (variant.did, self.tcx.type_of(variant.did))
+                }
+                _ => {
+                    (impl_def_id, self.tcx.types.err)
+                }
+            }
+        } else {
+            let def_id = def.def_id();
+
+            // The things we are substituting into the type should not contain
+            // escaping late-bound regions, and nor should the base type scheme.
+            let ty = self.tcx.type_of(def_id);
+            (def_id, ty)
+        };
 
         let substs = AstConv::create_substs_for_generic_args(
             self.tcx,
@@ -5121,10 +5177,6 @@ pub fn instantiate_value_path(&self,
                 }
             },
         );
-
-        // The things we are substituting into the type should not contain
-        // escaping late-bound regions, and nor should the base type scheme.
-        let ty = self.tcx.type_of(def_id);
         assert!(!substs.has_escaping_regions());
         assert!(!ty.has_escaping_regions());
 
@@ -5168,7 +5220,7 @@ pub fn instantiate_value_path(&self,
 
         self.write_user_substs_from_substs(hir_id, substs);
 
-        ty_substituted
+        (ty_substituted, new_def)
     }
 
     fn check_rustc_args_require_const(&self,
index edfa62f10953877f9f7e0ef26a99ef0c07edf949..5969f288d732070ade1260148782dce99c3897fb 100644 (file)
@@ -16,7 +16,7 @@
 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;
+use errors::{self,Applicability};
 use syntax_pos::Span;
 use syntax::ast::Ident;
 use rustc::hir;
@@ -35,7 +35,7 @@ pub fn check_binop_assign(&self,
         let ty = if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var()
                     && is_builtin_binop(lhs_ty, rhs_ty, op) {
             self.enforce_builtin_binop_types(lhs_expr, lhs_ty, rhs_expr, rhs_ty, op);
-            self.tcx.mk_nil()
+            self.tcx.mk_unit()
         } else {
             return_ty
         };
@@ -444,9 +444,12 @@ fn check_str_addition(
                     err.span_label(expr.span,
                                    "`+` can't be used to concatenate two `&str` strings");
                     match source_map.span_to_snippet(lhs_expr.span) {
-                        Ok(lstring) => err.span_suggestion(lhs_expr.span,
-                                                           msg,
-                                                           format!("{}.to_owned()", lstring)),
+                        Ok(lstring) => err.span_suggestion_with_applicability(
+                            lhs_expr.span,
+                            msg,
+                            format!("{}.to_owned()", lstring),
+                            Applicability::MachineApplicable,
+                        ),
                         _ => err.help(msg),
                     };
                 }
@@ -462,10 +465,14 @@ fn check_str_addition(
                     is_assign,
                 ) {
                     (Ok(l), Ok(r), false) => {
-                        err.multipart_suggestion(msg, vec![
-                            (lhs_expr.span, format!("{}.to_owned()", l)),
-                            (rhs_expr.span, format!("&{}", r)),
-                        ]);
+                        err.multipart_suggestion_with_applicability(
+                            msg,
+                            vec![
+                                (lhs_expr.span, format!("{}.to_owned()", l)),
+                                (rhs_expr.span, format!("&{}", r)),
+                            ],
+                            Applicability::MachineApplicable,
+                        );
                     }
                     _ => {
                         err.help(msg);
index 05fe0cb9262cc07d39a2d13233217f65a8470046..fbf8afc3be234b5364a6b479ca21d4ae92e64731 100644 (file)
@@ -307,7 +307,10 @@ fn visit_fn_body(&mut self,
         let body_id = body.id();
         self.body_id = body_id.node_id;
 
-        let call_site = region::Scope::CallSite(body.value.hir_id.local_id);
+        let call_site = region::Scope {
+            id: body.value.hir_id.local_id,
+            data: region::ScopeData::CallSite
+        };
         self.call_site_scope = Some(call_site);
 
         let fn_sig = {
@@ -333,7 +336,12 @@ fn visit_fn_body(&mut self,
             &fn_sig_tys[..],
             body_id.node_id,
             span);
-        self.link_fn_args(region::Scope::Node(body.value.hir_id.local_id), &body.arguments);
+        self.link_fn_args(
+            region::Scope {
+                id: body.value.hir_id.local_id,
+                data: region::ScopeData::Node
+            },
+            &body.arguments);
         self.visit_body(body);
         self.visit_region_obligations(body_id.node_id);
 
@@ -483,7 +491,10 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
         let expr_ty = self.resolve_node_type(expr.hir_id);
         // the region corresponding to this expression
         let expr_region = self.tcx.mk_region(ty::ReScope(
-            region::Scope::Node(expr.hir_id.local_id)));
+            region::Scope {
+                id: expr.hir_id.local_id,
+                data: region::ScopeData::Node
+            }));
         self.type_must_outlive(infer::ExprTypeIsNotInScope(expr_ty, expr.span),
                                expr_ty, expr_region);
 
@@ -766,7 +777,10 @@ fn constrain_call<'b, I: Iterator<Item=&'b hir::Expr>>(&mut self,
         // call occurs.
         //
         // FIXME(#6268) to support nested method calls, should be callee_id
-        let callee_scope = region::Scope::Node(call_expr.hir_id.local_id);
+        let callee_scope = region::Scope {
+            id: call_expr.hir_id.local_id,
+            data: region::ScopeData::Node
+        };
         let callee_region = self.tcx.mk_region(ty::ReScope(callee_scope));
 
         debug!("callee_region={:?}", callee_region);
@@ -819,7 +833,10 @@ fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult<mc::cmt_<'
         self.check_safety_of_rvalue_destructor_if_necessary(&cmt, expr.span);
 
         let expr_region = self.tcx.mk_region(ty::ReScope(
-            region::Scope::Node(expr.hir_id.local_id)));
+            region::Scope {
+                id: expr.hir_id.local_id,
+                data: region::ScopeData::Node
+            }));
         for adjustment in adjustments {
             debug!("constrain_adjustments: adjustment={:?}, cmt={:?}",
                    adjustment, cmt);
@@ -913,7 +930,10 @@ fn constrain_index(&mut self,
         debug!("constrain_index(index_expr=?, indexed_ty={}",
                self.ty_to_string(indexed_ty));
 
-        let r_index_expr = ty::ReScope(region::Scope::Node(index_expr.hir_id.local_id));
+        let r_index_expr = ty::ReScope(region::Scope {
+            id: index_expr.hir_id.local_id,
+            data: region::ScopeData::Node
+        });
         if let ty::Ref(r_ptr, r_ty, _) = indexed_ty.sty {
             match r_ty.sty {
                 ty::Slice(_) | ty::Str => {
@@ -1072,7 +1092,10 @@ fn link_autoref(&self,
             }
 
             adjustment::AutoBorrow::RawPtr(m) => {
-                let r = self.tcx.mk_region(ty::ReScope(region::Scope::Node(expr.hir_id.local_id)));
+                let r = self.tcx.mk_region(ty::ReScope(region::Scope {
+                    id: expr.hir_id.local_id,
+                    data: region::ScopeData::Node
+                }));
                 self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m), expr_cmt);
             }
         }
index aaa42f8d41225a8ec1dd1b06a6aaa9e84e293d16..c9aa0339dd469f8fc00c2b7358218fbe41940861 100644 (file)
@@ -224,7 +224,7 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 actual.output().skip_binder()
             } else {
                 // standard () main return type
-                tcx.mk_nil()
+                tcx.mk_unit()
             };
 
             let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(
index 75d7488d26a75ac67b9ae9c7474293511f1f15bb..507461f2ea175f9a24e1bd4d4537411e524a310d 100644 (file)
@@ -93,7 +93,8 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa
         // Assume that enum variants and struct types are re-exported next to
         // their constructors.
         Def::VariantCtor(..) |
-        Def::StructCtor(..) => return Some(Vec::new()),
+        Def::StructCtor(..) |
+        Def::SelfCtor(..) => return Some(Vec::new()),
         Def::Mod(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Module);
             clean::ModuleItem(build_module(cx, did, visited))
index a312913a69c17bf2ffd23e18acd40a608d6cdee3..2feeecb388f38d0976be7f8d641930ceab98bd6e 100644 (file)
@@ -260,9 +260,10 @@ fn is_doc_reachable(&self, did: DefId) -> bool {
 ///
 /// If the given `error_format` is `ErrorOutputType::Json` and no `SourceMap` is given, a new one
 /// will be created for the handler.
-pub fn new_handler(error_format: ErrorOutputType, source_map: Option<Lrc<source_map::SourceMap>>)
-    -> errors::Handler
-{
+pub fn new_handler(error_format: ErrorOutputType,
+                   source_map: Option<Lrc<source_map::SourceMap>>,
+                   treat_err_as_bug: bool,
+) -> errors::Handler {
     // rustdoc doesn't override (or allow to override) anything from this that is relevant here, so
     // stick to the defaults
     let sessopts = Options::default();
@@ -299,7 +300,7 @@ pub fn new_handler(error_format: ErrorOutputType, source_map: Option<Lrc<source_
         emitter,
         errors::HandlerFlags {
             can_emit_warnings: true,
-            treat_err_as_bug: false,
+            treat_err_as_bug,
             report_delayed_bugs: false,
             external_macro_backtrace: false,
             ..Default::default()
@@ -323,9 +324,9 @@ pub fn run_core(search_paths: SearchPaths,
                 lint_cap: Option<lint::Level>,
                 describe_lints: bool,
                 mut manual_passes: Vec<String>,
-                mut default_passes: passes::DefaultPassOption)
-    -> (clean::Crate, RenderInfo, Vec<String>)
-{
+                mut default_passes: passes::DefaultPassOption,
+                treat_err_as_bug: bool,
+) -> (clean::Crate, RenderInfo, Vec<String>) {
     // Parse, resolve, and typecheck the given crate.
 
     let cpath = match input {
@@ -388,7 +389,9 @@ pub fn run_core(search_paths: SearchPaths,
     };
     driver::spawn_thread_pool(sessopts, move |sessopts| {
         let source_map = Lrc::new(source_map::SourceMap::new(sessopts.file_path_mapping()));
-        let diagnostic_handler = new_handler(error_format, Some(source_map.clone()));
+        let diagnostic_handler = new_handler(error_format,
+                                             Some(source_map.clone()),
+                                             treat_err_as_bug);
 
         let mut sess = session::build_session_(
             sessopts, cpath, diagnostic_handler, source_map,
index 867b2a329057b5f40f4265eff4fdae879e14c752..1879abe659c831345510638b29befed8f3cde964 100644 (file)
@@ -1667,6 +1667,7 @@ pub fn new(root_path: &'a str, suffix: &'a str) -> Settings<'a> {
                 ("item-attributes", "Auto-hide item attributes.", true),
                 ("trait-implementations", "Auto-hide trait implementations documentation",
                  true),
+                ("method-docs", "Auto-hide item methods' documentation", false),
                 ("go-to-only-result", "Directly go to item in search if there is only one result",
                  false),
             ],
@@ -1829,8 +1830,8 @@ fn render_item(&self,
             *slot.borrow_mut() = self.current.clone();
         });
 
-        let mut title = if it.is_primitive() {
-            // No need to include the namespace for primitive types
+        let mut title = if it.is_primitive() || it.is_keyword() {
+            // No need to include the namespace for primitive types and keywords
             String::new()
         } else {
             self.current.join("::")
@@ -2074,7 +2075,7 @@ fn src_href(&self) -> Option<String> {
 fn wrap_into_docblock<F>(w: &mut fmt::Formatter,
                          f: F) -> fmt::Result
 where F: Fn(&mut fmt::Formatter) -> fmt::Result {
-    write!(w, "<div class=\"docblock type-decl\">")?;
+    write!(w, "<div class=\"docblock type-decl hidden-by-usual-hider\">")?;
     f(w)?;
     write!(w, "</div>")
 }
@@ -2300,17 +2301,21 @@ fn document_non_exhaustive(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::R
 }
 
 fn name_key(name: &str) -> (&str, u64, usize) {
+    let end = name.bytes()
+        .rposition(|b| b.is_ascii_digit()).map_or(name.len(), |i| i + 1);
+
     // find number at end
-    let split = name.bytes().rposition(|b| b < b'0' || b'9' < b).map_or(0, |s| s + 1);
+    let split = name[0..end].bytes()
+        .rposition(|b| !b.is_ascii_digit()).map_or(0, |i| i + 1);
 
     // count leading zeroes
     let after_zeroes =
-        name[split..].bytes().position(|b| b != b'0').map_or(name.len(), |extra| split + extra);
+        name[split..end].bytes().position(|b| b != b'0').map_or(name.len(), |extra| split + extra);
 
     // sort leading zeroes last
     let num_zeroes = after_zeroes - split;
 
-    match name[split..].parse() {
+    match name[split..end].parse() {
         Ok(n) => (&name[..split], n, num_zeroes),
         Err(_) => (name, 0, num_zeroes),
     }
@@ -2701,6 +2706,14 @@ fn bounds(t_bounds: &[clean::GenericBound]) -> String {
     bounds
 }
 
+fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl) -> Ordering {
+    let lhs = format!("{}", lhs.inner_impl());
+    let rhs = format!("{}", rhs.inner_impl());
+
+    // lhs and rhs are formatted as HTML, which may be unnecessary
+    name_key(&lhs).cmp(&name_key(&rhs))
+}
+
 fn item_trait(
     w: &mut fmt::Formatter,
     cx: &Context,
@@ -2904,9 +2917,12 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
                                          .map_or(true, |d| cache.paths.contains_key(&d)));
 
 
-        let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) = local.iter()
+        let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) = local.iter()
             .partition(|i| i.inner_impl().synthetic);
 
+        synthetic.sort_by(compare_impl);
+        concrete.sort_by(compare_impl);
+
         if !foreign.is_empty() {
             write!(w, "
                 <h2 id='foreign-impls' class='small-section-header'>
@@ -4715,6 +4731,7 @@ fn test_name_sorting() {
                  "Fruit1", "Fruit01",
                  "Fruit2", "Fruit02",
                  "Fruit20",
+                 "Fruit30x",
                  "Fruit100",
                  "Pear"];
     let mut sorted = names.to_owned();
index a6027a546576f2708b447cb2bc50620a64b7289a..3dbefabace18f978f6c52902ed00ef2a5f05149d 100644 (file)
         if (collapse) {
             toggleAllDocs(pageId, true);
         }
-        if (getCurrentValue('rustdoc-trait-implementations') !== "false") {
-            onEach(document.getElementsByClassName("collapse-toggle"), function(e) {
+        var collapser = function(e) {
                 // inherent impl ids are like 'impl' or impl-<number>'.
                 // they will never be hidden by default.
-                var n = e.parentNode;
+                var n = e.parentElement;
                 if (n.id.match(/^impl(?:-\d+)?$/) === null) {
                     // Automatically minimize all non-inherent impls
                     if (collapse || hasClass(n, 'impl')) {
                         collapseDocs(e, "hide", pageId);
                     }
                 }
-            });
+        };
+        if (getCurrentValue('rustdoc-trait-implementations') !== "false") {
+            onEach(document.getElementById('implementations-list')
+                           .getElementsByClassName("collapse-toggle"), collapser);
+        }
+        if (getCurrentValue('rustdoc-method-docs') !== "false") {
+            var implItems = document.getElementsByClassName('impl-items');
+
+            if (implItems && implItems.length > 0) {
+                onEach(implItems, function(elem) {
+                    onEach(elem.getElementsByClassName("collapse-toggle"), collapser);
+                });
+            }
         }
     }
 
     onEach(document.getElementsByClassName('associatedconstant'), func);
     onEach(document.getElementsByClassName('impl'), func);
 
-    function createToggle(otherMessage, fontSize, extraClass) {
+    function createToggle(otherMessage, fontSize, extraClass, show) {
         var span = document.createElement('span');
         span.className = 'toggle-label';
-        span.style.display = 'none';
+        if (show) {
+            span.style.display = 'none';
+        }
         if (!otherMessage) {
             span.innerHTML = '&nbsp;Expand&nbsp;description';
         } else {
 
         var wrapper = document.createElement('div');
         wrapper.className = 'toggle-wrapper';
+        if (!show) {
+            addClass(wrapper, 'collapsed');
+            var inner = mainToggle.getElementsByClassName('inner');
+            if (inner && inner.length > 0) {
+                inner[0].innerHTML = '+';
+            }
+        }
         if (extraClass) {
-            wrapper.className += ' ' + extraClass;
+            addClass(wrapper, extraClass);
         }
         wrapper.appendChild(mainToggle);
         return wrapper;
             var otherMessage;
             var fontSize;
             var extraClass;
+            var show = true;
 
             if (hasClass(e, "type-decl")) {
                 fontSize = "20px";
                 otherMessage = '&nbsp;Show&nbsp;declaration';
+                show = getCurrentValue('rustdoc-item-declarations') === "false";
+                if (!show) {
+                    extraClass = 'collapsed';
+                }
             } else if (hasClass(e, "non-exhaustive")) {
                 otherMessage = '&nbsp;This&nbsp;';
                 if (hasClass(e, "non-exhaustive-struct")) {
                 extraClass = "marg-left";
             }
 
-            e.parentNode.insertBefore(createToggle(otherMessage, fontSize, extraClass), e);
-            if (otherMessage && getCurrentValue('rustdoc-item-declarations') !== "false") {
+            e.parentNode.insertBefore(createToggle(otherMessage, fontSize, extraClass, show), e);
+            if (otherMessage && show) {
                 collapseDocs(e.previousSibling.childNodes[0], "toggle");
             }
         }
index bc471d427048b5651f4d612724bc4fa658824948..5f373a635dd7a671a53402b4c5e677218a22e176 100644 (file)
@@ -404,8 +404,11 @@ fn main_args(args: &[String]) -> isize {
                                   `short` (instead was `{}`)", arg));
         }
     };
+    let treat_err_as_bug = matches.opt_strs("Z").iter().any(|x| {
+        *x == "treat-err-as-bug"
+    });
 
-    let diag = core::new_handler(error_format, None);
+    let diag = core::new_handler(error_format, None, treat_err_as_bug);
 
     // check for deprecated options
     check_deprecated_options(&matches, &diag);
@@ -560,7 +563,7 @@ fn main_args(args: &[String]) -> isize {
     let res = acquire_input(PathBuf::from(input), externs, edition, cg, &matches, error_format,
                             move |out| {
         let Output { krate, passes, renderinfo } = out;
-        let diag = core::new_handler(error_format, None);
+        let diag = core::new_handler(error_format, None, treat_err_as_bug);
         info!("going to format");
         match output_format.as_ref().map(|s| &**s) {
             Some("html") | None => {
@@ -609,16 +612,19 @@ fn acquire_input<R, F>(input: PathBuf,
 /// Extracts `--extern CRATE=PATH` arguments from `matches` and
 /// returns a map mapping crate names to their paths or else an
 /// error message.
+// FIXME(eddyb) This shouldn't be duplicated with `rustc::session`.
 fn parse_externs(matches: &getopts::Matches) -> Result<Externs, String> {
     let mut externs: BTreeMap<_, BTreeSet<_>> = BTreeMap::new();
     for arg in &matches.opt_strs("extern") {
         let mut parts = arg.splitn(2, '=');
         let name = parts.next().ok_or("--extern value must not be empty".to_string())?;
-        let location = parts.next()
-                                 .ok_or("--extern value must be of the format `foo=bar`"
-                                    .to_string())?;
+        let location = parts.next().map(|s| s.to_string());
+        if location.is_none() && !nightly_options::is_unstable_enabled(matches) {
+            return Err("the `-Z unstable-options` flag must also be passed to \
+                        enable `--extern crate_name` without `=path`".to_string());
+        }
         let name = name.to_string();
-        externs.entry(name).or_default().insert(location.to_string());
+        externs.entry(name).or_default().insert(location);
     }
     Ok(Externs::new(externs))
 }
@@ -691,6 +697,9 @@ fn rust_input<R, F>(cratefile: PathBuf,
     let force_unstable_if_unmarked = matches.opt_strs("Z").iter().any(|x| {
         *x == "force-unstable-if-unmarked"
     });
+    let treat_err_as_bug = matches.opt_strs("Z").iter().any(|x| {
+        *x == "treat-err-as-bug"
+    });
 
     let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
 
@@ -703,7 +712,8 @@ fn rust_input<R, F>(cratefile: PathBuf,
             core::run_core(paths, cfgs, externs, Input::File(cratefile), triple, maybe_sysroot,
                            display_warnings, crate_name.clone(),
                            force_unstable_if_unmarked, edition, cg, error_format,
-                           lint_opts, lint_cap, describe_lints, manual_passes, default_passes);
+                           lint_opts, lint_cap, describe_lints, manual_passes, default_passes,
+                           treat_err_as_bug);
 
         info!("finished with rustc");
 
index 181fe379248ce52422ae06f30639f5c3a01d83fa..2d5512c538f55c005081878aea5c6cc01b82e735 100644 (file)
@@ -525,7 +525,9 @@ fn ambiguity_error(cx: &DocContext, attrs: &Attributes,
 fn value_ns_kind(def: Def, path_str: &str) -> Option<(&'static str, String)> {
     match def {
         // structs, variants, and mods exist in both namespaces. skip them
-        Def::StructCtor(..) | Def::Mod(..) | Def::Variant(..) | Def::VariantCtor(..) => None,
+        Def::StructCtor(..) | Def::Mod(..) | Def::Variant(..) |
+        Def::VariantCtor(..) | Def::SelfCtor(..)
+            => None,
         Def::Fn(..)
             => Some(("function", format!("{}()", path_str))),
         Def::Method(..)
index 451e24d6c0dc938ecf90a79c4bdb6462a388ba23..0aaf2d526f934a1fcc186a29267fdad3443b526a 100644 (file)
@@ -371,7 +371,7 @@ pub fn visit_item(&mut self, item: &hir::Item,
                 // struct and variant constructors always show up alongside their definitions, we've
                 // already processed them so just discard these.
                 match path.def {
-                    Def::StructCtor(..) | Def::VariantCtor(..) => return,
+                    Def::StructCtor(..) | Def::VariantCtor(..) | Def::SelfCtor(..) => return,
                     _ => {}
                 }
 
index 35ef6327de5fd81f73c63b2092cf79fc6da36745..9439dc78d3ca447029f0ce336d689d6d83c4c6a0 100644 (file)
@@ -490,7 +490,7 @@ macro_rules! emit_enquoted_if_mapkey {
 impl<'a> ::Encoder for Encoder<'a> {
     type Error = EncoderError;
 
-    fn emit_nil(&mut self) -> EncodeResult {
+    fn emit_unit(&mut self) -> EncodeResult {
         if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
         write!(self.writer, "null")?;
         Ok(())
@@ -648,7 +648,7 @@ fn emit_option<F>(&mut self, f: F) -> EncodeResult where
     }
     fn emit_option_none(&mut self) -> EncodeResult {
         if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
-        self.emit_nil()
+        self.emit_unit()
     }
     fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
         F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
@@ -740,7 +740,7 @@ pub fn set_indent(&mut self, indent: usize) {
 impl<'a> ::Encoder for PrettyEncoder<'a> {
     type Error = EncoderError;
 
-    fn emit_nil(&mut self) -> EncodeResult {
+    fn emit_unit(&mut self) -> EncodeResult {
         if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
         write!(self.writer, "null")?;
         Ok(())
@@ -923,7 +923,7 @@ fn emit_option<F>(&mut self, f: F) -> EncodeResult where
     }
     fn emit_option_none(&mut self) -> EncodeResult {
         if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
-        self.emit_nil()
+        self.emit_unit()
     }
     fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
         F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
@@ -1016,7 +1016,7 @@ fn encode<E: ::Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
             Json::Boolean(v) => v.encode(e),
             Json::Array(ref v) => v.encode(e),
             Json::Object(ref v) => v.encode(e),
-            Json::Null => e.emit_nil(),
+            Json::Null => e.emit_unit(),
         }
     }
 }
index c71f474891131dede6617e443b15b3efd4da1e17..4ce80bc36a080a44ce6b693d283a8f9fe043077e 100644 (file)
@@ -55,7 +55,7 @@ impl serialize::Encoder for Encoder {
     type Error = !;
 
     #[inline]
-    fn emit_nil(&mut self) -> EncodeResult {
+    fn emit_unit(&mut self) -> EncodeResult {
         Ok(())
     }
 
index 416be50bfe9ea4f52a19ba7e9dbe4cf28721708e..f0b49c3d9bc8faec0db174a40eeafe0f555e8d70 100644 (file)
@@ -25,7 +25,7 @@ pub trait Encoder {
     type Error;
 
     // Primitive types:
-    fn emit_nil(&mut self) -> Result<(), Self::Error>;
+    fn emit_unit(&mut self) -> Result<(), Self::Error>;
     fn emit_usize(&mut self, v: usize) -> Result<(), Self::Error>;
     fn emit_u128(&mut self, v: u128) -> Result<(), Self::Error>;
     fn emit_u64(&mut self, v: u64) -> Result<(), Self::Error>;
@@ -537,7 +537,7 @@ fn decode<D: Decoder>(d: &mut D) -> Result<char, D::Error> {
 
 impl Encodable for () {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_nil()
+        s.emit_unit()
     }
 }
 
index 804d43f4fc683a38bfd3a82168989fe7d4b2618c..ef5dae724b247eef53a77abd52376d286f76c621 100644 (file)
@@ -3532,12 +3532,11 @@ fn check(m: &HashMap<i32, ()>) {
             m.insert(x, ());
         }
 
-        for i in 0..1000 {
+        for _ in 0..1000 {
             let x = rng.gen_range(-10, 10);
             match m.entry(x) {
                 Vacant(_) => {}
                 Occupied(e) => {
-                    println!("{}: remove {}", i, x);
                     e.remove();
                 }
             }
index 768357ec8dc417e7ea1fedfa4e522dbc2a480009..547f97cc8acee1bccb45bae7ef94922087be66a3 100644 (file)
@@ -742,7 +742,9 @@ fn new_internal(
     ) -> Result<RawTable<K, V>, CollectionAllocErr> {
         unsafe {
             let ret = RawTable::new_uninitialized_internal(capacity, fallibility)?;
-            ptr::write_bytes(ret.hashes.ptr(), 0, capacity);
+            if capacity > 0 {
+                ptr::write_bytes(ret.hashes.ptr(), 0, capacity);
+            }
             Ok(ret)
         }
     }
index a37a5e8ae820b90949aa81c3fe5daa3a2ea007c7..a3345df5e0d8563e2e3351e3682e99e809fe44b1 100644 (file)
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::os_str::{OsString, OsStr};
 
+#[stable(feature = "raw_os", since = "1.1.0")]
+pub use core::ffi::c_void;
+
 mod c_str;
 mod os_str;
index 8ae5e20dac5aa669f37649c43e3490b723cc5cb7..e9390630445a106fbf878479492c212778880e5f 100644 (file)
@@ -34,7 +34,9 @@
 ///
 /// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust
 /// and platform-native string values, and in particular allowing a Rust string
-/// to be converted into an "OS" string with no cost if possible.
+/// to be converted into an "OS" string with no cost if possible.  A consequence
+/// of this is that `OsString` instances are *not* `NUL` terminated; in order
+/// to pass to e.g. Unix system call, you should create a [`CStr`].
 ///
 /// `OsString` is to [`&OsStr`] as [`String`] is to [`&str`]: the former
 /// in each pair are owned strings; the latter are borrowed
@@ -65,6 +67,7 @@
 ///
 /// [`OsStr`]: struct.OsStr.html
 /// [`&OsStr`]: struct.OsStr.html
+/// [`CStr`]: struct.CStr.html
 /// [`From`]: ../convert/trait.From.html
 /// [`String`]: ../string/struct.String.html
 /// [`&str`]: ../primitive.str.html
@@ -420,14 +423,14 @@ fn eq(&self, other: &OsString) -> bool {
     }
 }
 
-#[stable(feature = "os_str_str_ref_eq", since = "1.28.0")]
+#[stable(feature = "os_str_str_ref_eq", since = "1.29.0")]
 impl<'a> PartialEq<&'a str> for OsString {
     fn eq(&self, other: &&'a str) -> bool {
         **self == **other
     }
 }
 
-#[stable(feature = "os_str_str_ref_eq", since = "1.28.0")]
+#[stable(feature = "os_str_str_ref_eq", since = "1.29.0")]
 impl<'a> PartialEq<OsString> for &'a str {
     fn eq(&self, other: &OsString) -> bool {
         **other == **self
index d9657f691c79fdc59a4b07445cd3c79876494423..262646738cf06d10fe267ce9530a16137d0b830c 100644 (file)
@@ -12,7 +12,7 @@
 
 use core::cell::Cell;
 use core::marker::Unpin;
-use core::pin::PinMut;
+use core::pin::Pin;
 use core::option::Option;
 use core::ptr::NonNull;
 use core::task::{self, Poll};
@@ -42,8 +42,8 @@ impl<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {}
 #[unstable(feature = "gen_future", issue = "50547")]
 impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
     type Output = T::Return;
-    fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
-        set_task_cx(cx, || match unsafe { PinMut::get_mut_unchecked(self).0.resume() } {
+    fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output> {
+        set_task_cx(cx, || match unsafe { Pin::get_mut_unchecked(self).0.resume() } {
             GeneratorState::Yielded(()) => Poll::Pending,
             GeneratorState::Complete(x) => Poll::Ready(x),
         })
@@ -108,9 +108,9 @@ pub fn get_task_cx<F, R>(f: F) -> R
 
 #[unstable(feature = "gen_future", issue = "50547")]
 /// Polls a future in the current thread-local task context.
-pub fn poll_in_task_cx<F>(f: PinMut<F>) -> Poll<F::Output>
+pub fn poll_in_task_cx<F>(f: Pin<&mut F>) -> Poll<F::Output>
 where
     F: Future
 {
-    get_task_cx(|cx| f.poll(cx))
+    get_task_cx(|cx| F::poll(f, cx))
 }
index 17f6923eae72368b6190bc70fde284aca26b2ae4..1eb76d6c45ec47783b4619a8cb5b667ca85d4461 100644 (file)
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use alloc_crate::format;
 #[unstable(feature = "pin", issue = "49150")]
-pub use alloc_crate::pin;
+pub use core::pin;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use alloc_crate::slice;
 #[stable(feature = "rust1", since = "1.0.0")]
index b649ec2340e93df33e87121b1143dff8c780e840..e60ef46e738b415eb82d63ed7a9c1a387e1b09c5 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::pin::PinMut::new_unchecked(&mut pinned)
+                    $crate::pin::Pin::new_unchecked(&mut pinned)
                 })
             {
                 break x;
index e80c3eeb876ceebd05cab882fce8da1ce7181ad6..ff35325ab4fdaaacded38db1c1cb484410f67926 100644 (file)
@@ -554,6 +554,7 @@ fn from_inner(addr: c::sockaddr_in6) -> SocketAddrV6 {
 
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
 impl From<SocketAddrV4> for SocketAddr {
+    /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].
     fn from(sock4: SocketAddrV4) -> SocketAddr {
         SocketAddr::V4(sock4)
     }
@@ -561,6 +562,7 @@ fn from(sock4: SocketAddrV4) -> SocketAddr {
 
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
 impl From<SocketAddrV6> for SocketAddr {
+    /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`].
     fn from(sock6: SocketAddrV6) -> SocketAddr {
         SocketAddr::V6(sock6)
     }
@@ -568,6 +570,12 @@ fn from(sock6: SocketAddrV6) -> SocketAddr {
 
 #[stable(feature = "addr_from_into_ip", since = "1.17.0")]
 impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr {
+    /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`].
+    ///
+    /// This conversion creates a [`SocketAddr::V4`] for a [`IpAddr::V4`]
+    /// and creates a [`SocketAddr::V6`] for a [`IpAddr::V6`].
+    ///
+    /// `u16` is treated as port of the newly created [`SocketAddr`].
     fn from(pieces: (I, u16)) -> SocketAddr {
         SocketAddr::new(pieces.0.into(), pieces.1)
     }
index dc33747c05b0670da0c514c6f8dd098efa6b591a..95faf3a5dd63d351460c7f70fa2a770e7d711690 100644 (file)
@@ -18,8 +18,6 @@
 
 #![stable(feature = "raw_os", since = "1.1.0")]
 
-use fmt;
-
 #[doc(include = "os/raw/char.md")]
 #[cfg(any(all(target_os = "linux", any(target_arch = "aarch64",
                                        target_arch = "arm",
 #[doc(include = "os/raw/double.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64;
 
-/// Equivalent to C's `void` type when used as a [pointer].
-///
-/// In essence, `*const c_void` is equivalent to C's `const void*`
-/// and `*mut c_void` is equivalent to C's `void*`. That said, this is
-/// *not* the same as C's `void` return type, which is Rust's `()` type.
-///
-/// Ideally, this type would be equivalent to [`!`], but currently it may
-/// be more ideal to use `c_void` for FFI purposes.
-///
-/// [`!`]: ../../primitive.never.html
-/// [pointer]: ../../primitive.pointer.html
-// NB: For LLVM to recognize the void pointer type and by extension
-//     functions like malloc(), we need to have it represented as i8* in
-//     LLVM bitcode. The enum used here ensures this and prevents misuse
-//     of the "raw" type by only having private variants.. We need two
-//     variants, because the compiler complains about the repr attribute
-//     otherwise.
-#[repr(u8)]
 #[stable(feature = "raw_os", since = "1.1.0")]
-pub enum c_void {
-    #[unstable(feature = "c_void_variant", reason = "should not have to exist",
-               issue = "0")]
-    #[doc(hidden)] __variant1,
-    #[unstable(feature = "c_void_variant", reason = "should not have to exist",
-               issue = "0")]
-    #[doc(hidden)] __variant2,
-}
-
-#[stable(feature = "std_debug", since = "1.16.0")]
-impl fmt::Debug for c_void {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("c_void")
-    }
-}
+#[doc(no_inline)]
+pub use core::ffi::c_void;
 
 #[cfg(test)]
 #[allow(unused_imports)]
index 47547aedcbdec8e0269d5a5d716ef7f1f475f911..bd7a92e9b3f0f904584aeeec58c619a21cfd6672 100644 (file)
@@ -16,7 +16,7 @@
 use cell::UnsafeCell;
 use fmt;
 use future::Future;
-use pin::PinMut;
+use pin::Pin;
 use ops::{Deref, DerefMut};
 use panicking;
 use ptr::{Unique, NonNull};
@@ -327,9 +327,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 impl<'a, F: Future> Future for AssertUnwindSafe<F> {
     type Output = F::Output;
 
-    fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
-        let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) };
-        pinned_field.poll(cx)
+    fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output> {
+        let pinned_field = unsafe { Pin::map_unchecked_mut(self, |x| &mut x.0) };
+        F::poll(pinned_field, cx)
     }
 }
 
index 7074928eaf6daac7dd4334b9c32803daf5c4ae46..4c1fdc4f895386a605a7c3fd6e615b727392c1f1 100644 (file)
@@ -250,6 +250,7 @@ mod prim_bool { }
 /// [`Default`]: default/trait.Default.html
 /// [`default()`]: default/trait.Default.html#tymethod.default
 ///
+#[unstable(feature = "never_type", issue = "35121")]
 mod prim_never { }
 
 #[doc(primitive = "char")]
index b841afe1a5141dfd2db749ad09077400c8cc1933..d09a233ed896f296529bbf597613a28285909639 100644 (file)
@@ -622,7 +622,8 @@ fn no_lookup_host_duplicates() {
             Ok(lh) => lh,
             Err(e) => panic!("couldn't resolve `localhost': {}", e)
         };
-        let _na = lh.map(|sa| *addrs.entry(sa).or_insert(0) += 1).count();
-        assert!(addrs.values().filter(|&&v| v > 1).count() == 0);
+        for sa in lh { *addrs.entry(sa).or_insert(0) += 1; };
+        assert_eq!(addrs.iter().filter(|&(_, &v)| v > 1).collect::<Vec<_>>(), vec![],
+                   "There should be no duplicate localhost entries");
     }
 }
index a7c7dbb1b402762b9c59fae8304070a51ce823cb..3987ae83866e5c472fe6cebb13f1730c4e7d3768 100644 (file)
@@ -800,7 +800,14 @@ pub fn park() {
     match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
         Ok(_) => {}
         Err(NOTIFIED) => {
-            thread.inner.state.store(EMPTY, SeqCst);
+            // We must read here, even though we know it will be `NOTIFIED`.
+            // This is because `unpark` may have been called again since we read
+            // `NOTIFIED` in the `compare_exchange` above. We must perform an
+            // acquire operation that synchronizes with that `unpark` to observe
+            // any writes it made before the call to unpark. To do that we must
+            // read from the write it made to `state`.
+            let old = thread.inner.state.swap(EMPTY, SeqCst);
+            assert_eq!(old, NOTIFIED, "park state changed unexpectedly");
             return;
         } // should consume this notification, so prohibit spurious wakeups in next park.
         Err(_) => panic!("inconsistent park state"),
@@ -889,7 +896,9 @@ pub fn park_timeout(dur: Duration) {
     match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
         Ok(_) => {}
         Err(NOTIFIED) => {
-            thread.inner.state.store(EMPTY, SeqCst);
+            // We must read again here, see `park`.
+            let old = thread.inner.state.swap(EMPTY, SeqCst);
+            assert_eq!(old, NOTIFIED, "park state changed unexpectedly");
             return;
         } // should consume this notification, so prohibit spurious wakeups in next park.
         Err(_) => panic!("inconsistent park_timeout state"),
@@ -1058,23 +1067,22 @@ pub(crate) fn new(name: Option<String>) -> Thread {
     /// [park]: fn.park.html
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unpark(&self) {
-        loop {
-            match self.inner.state.compare_exchange(EMPTY, NOTIFIED, SeqCst, SeqCst) {
-                Ok(_) => return, // no one was waiting
-                Err(NOTIFIED) => return, // already unparked
-                Err(PARKED) => {} // gotta go wake someone up
-                _ => panic!("inconsistent state in unpark"),
-            }
-
-            // Coordinate wakeup through the mutex and a condvar notification
-            let _lock = self.inner.lock.lock().unwrap();
-            match self.inner.state.compare_exchange(PARKED, NOTIFIED, SeqCst, SeqCst) {
-                Ok(_) => return self.inner.cvar.notify_one(),
-                Err(NOTIFIED) => return, // a different thread unparked
-                Err(EMPTY) => {} // parked thread went away, try again
-                _ => panic!("inconsistent state in unpark"),
-            }
+        // To ensure the unparked thread will observe any writes we made
+        // before this call, we must perform a release operation that `park`
+        // can synchronize with. To do that we must write `NOTIFIED` even if
+        // `state` is already `NOTIFIED`. That is why this must be a swap
+        // rather than a compare-and-swap that returns if it reads `NOTIFIED`
+        // on failure.
+        match self.inner.state.swap(NOTIFIED, SeqCst) {
+            EMPTY => return, // no one was waiting
+            NOTIFIED => return, // already unparked
+            PARKED => {} // gotta go wake someone up
+            _ => panic!("inconsistent state in unpark"),
         }
+
+        // Coordinate wakeup through the mutex and a condvar notification
+        let _lock = self.inner.lock.lock().unwrap();
+        self.inner.cvar.notify_one()
     }
 
     /// Gets the thread's unique identifier.
index 63b70b1224840a6afb70c42754e0bec111d7feda..5d978b6b9e6623789db80d537d430b5ecda880fd 100644 (file)
@@ -16,6 +16,7 @@
 use edition::Edition;
 use parse::{token, ParseSess};
 use OneVector;
+use errors::Applicability;
 
 use ptr::P;
 
@@ -123,7 +124,12 @@ pub fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool {
             let error = |span, msg, suggestion: &str| {
                 let mut err = self.sess.span_diagnostic.struct_span_err(span, msg);
                 if !suggestion.is_empty() {
-                    err.span_suggestion(span, "expected syntax is", suggestion.into());
+                    err.span_suggestion_with_applicability(
+                        span,
+                        "expected syntax is",
+                        suggestion.into(),
+                        Applicability::MaybeIncorrect,
+                    );
                 }
                 err.emit();
                 true
index 40903e8ad6cb7e06e2c32bba3da006aea4e7b3ac..33d0e76ca481cb2bbf42bcc6b0cdbf4cc63ca73e 100644 (file)
@@ -216,6 +216,14 @@ pub struct Invocation {
     pub expansion_data: ExpansionData,
 }
 
+// Needed for feature-gating attributes used after derives or together with test/bench
+#[derive(Clone, Copy, PartialEq)]
+pub enum TogetherWith {
+    None,
+    Derive,
+    TestBench,
+}
+
 pub enum InvocationKind {
     Bang {
         mac: ast::Mac,
@@ -226,6 +234,7 @@ pub enum InvocationKind {
         attr: Option<ast::Attribute>,
         traits: Vec<Path>,
         item: Annotatable,
+        together_with: TogetherWith,
     },
     Derive {
         path: Path,
@@ -353,7 +362,7 @@ fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
                     let dummy = invoc.fragment_kind.dummy(invoc.span()).unwrap();
                     let fragment = self.expand_invoc(invoc, &*ext).unwrap_or(dummy);
                     self.collect_invocations(fragment, &[])
-                } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
+                } else if let InvocationKind::Attr { attr: None, traits, item, .. } = invoc.kind {
                     if !item.derive_allowed() {
                         let attr = attr::find_by_name(item.attrs(), "derive")
                             .expect("`derive` attribute should exist");
@@ -1069,14 +1078,23 @@ fn collect_attr(&mut self,
                     attr: Option<ast::Attribute>,
                     traits: Vec<Path>,
                     item: Annotatable,
-                    kind: AstFragmentKind)
+                    kind: AstFragmentKind,
+                    together_with: TogetherWith)
                     -> AstFragment {
-        self.collect(kind, InvocationKind::Attr { attr, traits, item })
+        self.collect(kind, InvocationKind::Attr { attr, traits, item, together_with })
     }
 
-    fn find_attr_invoc(&self, attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
+    fn find_attr_invoc(&self, attrs: &mut Vec<ast::Attribute>, together_with: &mut TogetherWith)
+                       -> Option<ast::Attribute> {
         let attr = attrs.iter()
-                        .position(|a| !attr::is_known(a) && !is_builtin_attr(a))
+                        .position(|a| {
+                            if a.path == "derive" {
+                                *together_with = TogetherWith::Derive
+                            } else if a.path == "rustc_test_marker2" {
+                                *together_with = TogetherWith::TestBench
+                            }
+                            !attr::is_known(a) && !is_builtin_attr(a)
+                        })
                         .map(|i| attrs.remove(i));
         if let Some(attr) = &attr {
             if !self.cx.ecfg.enable_custom_inner_attributes() &&
@@ -1086,14 +1104,19 @@ fn find_attr_invoc(&self, attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attrib
                                  "non-builtin inner attributes are unstable");
             }
         }
+        if together_with == &TogetherWith::None &&
+           attrs.iter().any(|a| a.path == "rustc_test_marker2") {
+            *together_with = TogetherWith::TestBench;
+        }
         attr
     }
 
     /// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
-    fn classify_item<T>(&mut self, mut item: T) -> (Option<ast::Attribute>, Vec<Path>, T)
+    fn classify_item<T>(&mut self, mut item: T)
+                        -> (Option<ast::Attribute>, Vec<Path>, T, TogetherWith)
         where T: HasAttrs,
     {
-        let (mut attr, mut traits) = (None, Vec::new());
+        let (mut attr, mut traits, mut together_with) = (None, Vec::new(), TogetherWith::None);
 
         item = item.map_attrs(|mut attrs| {
             if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs,
@@ -1102,19 +1125,20 @@ fn classify_item<T>(&mut self, mut item: T) -> (Option<ast::Attribute>, Vec<Path
                 return attrs;
             }
 
-            attr = self.find_attr_invoc(&mut attrs);
+            attr = self.find_attr_invoc(&mut attrs, &mut together_with);
             traits = collect_derives(&mut self.cx, &mut attrs);
             attrs
         });
 
-        (attr, traits, item)
+        (attr, traits, item, together_with)
     }
 
     /// Alternative of `classify_item()` that ignores `#[derive]` so invocations fallthrough
     /// to the unused-attributes lint (making it an error on statements and expressions
     /// is a breaking change)
-    fn classify_nonitem<T: HasAttrs>(&mut self, mut item: T) -> (Option<ast::Attribute>, T) {
-        let mut attr = None;
+    fn classify_nonitem<T: HasAttrs>(&mut self, mut item: T)
+                                     -> (Option<ast::Attribute>, T, TogetherWith) {
+        let (mut attr, mut together_with) = (None, TogetherWith::None);
 
         item = item.map_attrs(|mut attrs| {
             if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs,
@@ -1123,11 +1147,11 @@ fn classify_nonitem<T: HasAttrs>(&mut self, mut item: T) -> (Option<ast::Attribu
                 return attrs;
             }
 
-            attr = self.find_attr_invoc(&mut attrs);
+            attr = self.find_attr_invoc(&mut attrs, &mut together_with);
             attrs
         });
 
-        (attr, item)
+        (attr, item, together_with)
     }
 
     fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
@@ -1166,7 +1190,7 @@ fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
         expr.node = self.cfg.configure_expr_kind(expr.node);
 
         // ignore derives so they remain unused
-        let (attr, expr) = self.classify_nonitem(expr);
+        let (attr, expr, together_with) = self.classify_nonitem(expr);
 
         if attr.is_some() {
             // collect the invoc regardless of whether or not attributes are permitted here
@@ -1175,7 +1199,7 @@ fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
 
             // AstFragmentKind::Expr requires the macro to emit an expression
             return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
-                                     AstFragmentKind::Expr).make_expr();
+                                     AstFragmentKind::Expr, together_with).make_expr();
         }
 
         if let ast::ExprKind::Mac(mac) = expr.node {
@@ -1191,14 +1215,13 @@ fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
         expr.node = self.cfg.configure_expr_kind(expr.node);
 
         // ignore derives so they remain unused
-        let (attr, expr) = self.classify_nonitem(expr);
+        let (attr, expr, together_with) = self.classify_nonitem(expr);
 
         if attr.is_some() {
             attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
 
             return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
-                                     AstFragmentKind::OptExpr)
-                .make_opt_expr();
+                                     AstFragmentKind::OptExpr, together_with).make_opt_expr();
         }
 
         if let ast::ExprKind::Mac(mac) = expr.node {
@@ -1230,19 +1253,18 @@ fn fold_stmt(&mut self, stmt: ast::Stmt) -> OneVector<ast::Stmt> {
 
         // we'll expand attributes on expressions separately
         if !stmt.is_expr() {
-            let (attr, derives, stmt_) = if stmt.is_item() {
+            let (attr, derives, stmt_, together_with) = if stmt.is_item() {
                 self.classify_item(stmt)
             } else {
                 // ignore derives on non-item statements so it falls through
                 // to the unused-attributes lint
-                let (attr, stmt) = self.classify_nonitem(stmt);
-                (attr, vec![], stmt)
+                let (attr, stmt, together_with) = self.classify_nonitem(stmt);
+                (attr, vec![], stmt, together_with)
             };
 
             if attr.is_some() || !derives.is_empty() {
-                return self.collect_attr(attr, derives,
-                                         Annotatable::Stmt(P(stmt_)), AstFragmentKind::Stmts)
-                    .make_stmts();
+                return self.collect_attr(attr, derives, Annotatable::Stmt(P(stmt_)),
+                                         AstFragmentKind::Stmts, together_with).make_stmts();
             }
 
             stmt = stmt_;
@@ -1284,10 +1306,10 @@ fn fold_block(&mut self, block: P<Block>) -> P<Block> {
     fn fold_item(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
         let item = configure!(self, item);
 
-        let (attr, traits, item) = self.classify_item(item);
+        let (attr, traits, item, together_with) = self.classify_item(item);
         if attr.is_some() || !traits.is_empty() {
-            let item = Annotatable::Item(item);
-            return self.collect_attr(attr, traits, item, AstFragmentKind::Items).make_items();
+            return self.collect_attr(attr, traits, Annotatable::Item(item),
+                                     AstFragmentKind::Items, together_with).make_items();
         }
 
         match item.node {
@@ -1359,11 +1381,10 @@ fn fold_item(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
     fn fold_trait_item(&mut self, item: ast::TraitItem) -> OneVector<ast::TraitItem> {
         let item = configure!(self, item);
 
-        let (attr, traits, item) = self.classify_item(item);
+        let (attr, traits, item, together_with) = self.classify_item(item);
         if attr.is_some() || !traits.is_empty() {
-            let item = Annotatable::TraitItem(P(item));
-            return self.collect_attr(attr, traits, item, AstFragmentKind::TraitItems)
-                .make_trait_items()
+            return self.collect_attr(attr, traits, Annotatable::TraitItem(P(item)),
+                                     AstFragmentKind::TraitItems, together_with).make_trait_items()
         }
 
         match item.node {
@@ -1379,11 +1400,10 @@ fn fold_trait_item(&mut self, item: ast::TraitItem) -> OneVector<ast::TraitItem>
     fn fold_impl_item(&mut self, item: ast::ImplItem) -> OneVector<ast::ImplItem> {
         let item = configure!(self, item);
 
-        let (attr, traits, item) = self.classify_item(item);
+        let (attr, traits, item, together_with) = self.classify_item(item);
         if attr.is_some() || !traits.is_empty() {
-            let item = Annotatable::ImplItem(P(item));
-            return self.collect_attr(attr, traits, item, AstFragmentKind::ImplItems)
-                .make_impl_items();
+            return self.collect_attr(attr, traits, Annotatable::ImplItem(P(item)),
+                                     AstFragmentKind::ImplItems, together_with).make_impl_items();
         }
 
         match item.node {
@@ -1414,12 +1434,12 @@ fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod
 
     fn fold_foreign_item(&mut self,
                          foreign_item: ast::ForeignItem) -> OneVector<ast::ForeignItem> {
-        let (attr, traits, foreign_item) = self.classify_item(foreign_item);
+        let (attr, traits, foreign_item, together_with) = self.classify_item(foreign_item);
 
         if attr.is_some() || !traits.is_empty() {
-            let item = Annotatable::ForeignItem(P(foreign_item));
-            return self.collect_attr(attr, traits, item, AstFragmentKind::ForeignItems)
-                .make_foreign_items();
+            return self.collect_attr(attr, traits, Annotatable::ForeignItem(P(foreign_item)),
+                                     AstFragmentKind::ForeignItems, together_with)
+                                     .make_foreign_items();
         }
 
         if let ast::ForeignItemKind::Macro(mac) = foreign_item.node {
index 86247745c4116b6eedb3d1cdda9f38aadf05fca0..214bc9cffc4836ece1530718ef2c5730aa9a659e 100644 (file)
@@ -32,6 +32,7 @@
 use std::collections::hash_map::Entry;
 
 use rustc_data_structures::sync::Lrc;
+use errors::Applicability;
 
 pub struct ParserAnyMacro<'a> {
     parser: Parser<'a>,
@@ -187,10 +188,11 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt,
                     if comma_span == DUMMY_SP {
                         err.note("you might be missing a comma");
                     } else {
-                        err.span_suggestion_short(
+                        err.span_suggestion_short_with_applicability(
                             comma_span,
                             "missing comma here",
                             ", ".to_string(),
+                            Applicability::MachineApplicable,
                         );
                     }
                 }
index d98e457439927fac53f01e016c15dab5bb1ee4a0..8ddb7473162b0db32780d199bb3812cfe36f64c2 100644 (file)
@@ -512,6 +512,15 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
 
     // Non-builtin attributes in inner attribute position
     (active, custom_inner_attributes, "1.30.0", Some(38356), None),
+
+    // Self struct constructor  (RFC 2302)
+    (active, self_struct_ctor, "1.31.0", Some(51994), None),
+
+    // allow mixing of bind-by-move in patterns and references to
+    // those identifiers in guards, *if* we are using MIR-borrowck
+    // (aka NLL). Essentially this means you need to be on
+    // edition:2018 or later.
+    (active, bind_by_move_pattern_guards, "1.30.0", Some(15287), None),
 );
 
 declare_features! (
@@ -708,7 +717,7 @@ pub enum AttributeGate {
 impl AttributeGate {
     fn is_deprecated(&self) -> bool {
         match *self {
-            Gated(Stability::Deprecated(_), ..) => true,
+            Gated(Stability::Deprecated(_, _), ..) => true,
             _ => false,
         }
     }
@@ -717,8 +726,9 @@ fn is_deprecated(&self) -> bool {
 #[derive(Copy, Clone, Debug)]
 pub enum Stability {
     Unstable,
-    // Argument is tracking issue link.
-    Deprecated(&'static str),
+    // First argument is tracking issue link; second argument is an optional
+    // help message, which defaults to "remove this attribute"
+    Deprecated(&'static str, Option<&'static str>),
 }
 
 // fn() is not Debug
@@ -967,6 +977,10 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                      "the `#[rustc_test_marker]` attribute \
                                       is used internally to track tests",
                                      cfg_fn!(rustc_attrs))),
+    ("rustc_test_marker2", Normal, Gated(Stability::Unstable,
+                                         "rustc_attrs",
+                                         "temporarily used by rustc to report some errors",
+                                         cfg_fn!(rustc_attrs))),
     ("rustc_transparent_macro", Whitelisted, Gated(Stability::Unstable,
                                                    "rustc_attrs",
                                                    "used internally for testing macro hygiene",
@@ -1041,7 +1055,7 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
     ("no_builtins", Whitelisted, Ungated),
     ("no_mangle", Whitelisted, Ungated),
     ("no_debug", Whitelisted, Gated(
-        Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
+        Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721", None),
         "no_debug",
         "the `#[no_debug]` attribute was an experimental feature that has been \
          deprecated due to lack of demand",
@@ -1054,7 +1068,8 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                                        cfg_fn!(omit_gdb_pretty_printer_section))),
     ("unsafe_destructor_blind_to_params",
      Normal,
-     Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
+     Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761",
+                                 Some("replace this attribute with `#[may_dangle]`")),
            "dropck_parametricity",
            "unsafe_destructor_blind_to_params has been replaced by \
             may_dangle and will be removed in the future",
@@ -1133,9 +1148,10 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
     ("panic_implementation",
      Normal,
      Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/44489\
-                                  #issuecomment-415140224"),
+                                  #issuecomment-415140224",
+                                 Some("replace this attribute with `#[panic_handler]`")),
            "panic_implementation",
-           "This attribute was renamed to `panic_handler`",
+           "this attribute was renamed to `panic_handler`",
            cfg_fn!(panic_implementation))),
 
     // RFC 2070
index 2aaab6aaa16d931942844d5f06e73ff3bb076b3d..68b468417182a0bef98e6e699e195b2215f3d10f 100644 (file)
@@ -46,7 +46,7 @@
 extern crate serialize as rustc_serialize; // used by deriving
 
 use rustc_data_structures::sync::Lock;
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bit_set::GrowableBitSet;
 pub use rustc_data_structures::small_vec::OneVector;
 pub use rustc_data_structures::thin_vec::ThinVec;
 use ast::AttrId;
@@ -82,8 +82,8 @@ macro_rules! unwrap_or {
 }
 
 pub struct Globals {
-    used_attrs: Lock<BitVector<AttrId>>,
-    known_attrs: Lock<BitVector<AttrId>>,
+    used_attrs: Lock<GrowableBitSet<AttrId>>,
+    known_attrs: Lock<GrowableBitSet<AttrId>>,
     syntax_pos_globals: syntax_pos::Globals,
 }
 
@@ -92,8 +92,8 @@ fn new() -> Globals {
         Globals {
             // We have no idea how many attributes their will be, so just
             // initiate the vectors with 0 bits. We'll grow them as necessary.
-            used_attrs: Lock::new(BitVector::new()),
-            known_attrs: Lock::new(BitVector::new()),
+            used_attrs: Lock::new(GrowableBitSet::new_empty()),
+            known_attrs: Lock::new(GrowableBitSet::new_empty()),
             syntax_pos_globals: syntax_pos::Globals::new(),
         }
     }
index f57fca2cfcf604683b7c6489f72939548a220616..6ec1ad969ee708de179210966587bbf46c6bc006 100644 (file)
@@ -732,6 +732,22 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
                   format!("expected {} here", expect)))
             };
             let mut err = self.fatal(&msg_exp);
+            if self.token.is_ident_named("and") {
+                err.span_suggestion_short_with_applicability(
+                    self.span,
+                    "use `&&` instead of `and` for the boolean operator",
+                    "&&".to_string(),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+            if self.token.is_ident_named("or") {
+                err.span_suggestion_short_with_applicability(
+                    self.span,
+                    "use `||` instead of `or` for the boolean operator",
+                    "||".to_string(),
+                    Applicability::MaybeIncorrect,
+                );
+            }
             let sp = if self.token == token::Token::Eof {
                 // This is EOF, don't want to point at the following char, but rather the last token
                 self.prev_span
@@ -3866,7 +3882,12 @@ 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", String::new());
+                        err.span_suggestion_short_with_applicability(
+                            sp,
+                            "remove this comma",
+                            String::new(),
+                            Applicability::MachineApplicable,
+                        );
                     }
                     err.emit();
                     break;
@@ -4751,6 +4772,23 @@ pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
                 e.span_label(sp, "expected `{`");
             }
 
+            if self.token.is_ident_named("and") {
+                e.span_suggestion_short_with_applicability(
+                    self.span,
+                    "use `&&` instead of `and` for the boolean operator",
+                    "&&".to_string(),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+            if self.token.is_ident_named("or") {
+                e.span_suggestion_short_with_applicability(
+                    self.span,
+                    "use `||` instead of `or` for the boolean operator",
+                    "||".to_string(),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+
             // Check to see if the user has written something like
             //
             //    if (cond)
index b86d19ba3ce00a63eeea7a56fbdcede145b38dda..bb47d9b535befbc8cac04a0a537fbada869601d9 100644 (file)
@@ -38,7 +38,7 @@
 
 use std::fmt::{self, Display, Debug};
 use std::iter::FromIterator;
-use std::ops::Deref;
+use std::ops::{Deref, DerefMut};
 use std::{mem, ptr, slice, vec};
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
@@ -103,6 +103,12 @@ fn deref(&self) -> &T {
     }
 }
 
+impl<T: ?Sized> DerefMut for P<T> {
+    fn deref_mut(&mut self) -> &mut T {
+        &mut self.ptr
+    }
+}
+
 impl<T: 'static + Clone> Clone for P<T> {
     fn clone(&self) -> P<T> {
         P((**self).clone())
index efe9c2cefdebe93b3e1e4f646e2b2093061ae5b3..31e608de1f840d282eb777af314db5b3acfe097f 100644 (file)
@@ -996,9 +996,10 @@ macro_rules! check_foreign {
                         ));
                     }
                     if suggestions.len() > 0 {
-                        diag.multipart_suggestion(
+                        diag.multipart_suggestion_with_applicability(
                             "format specifiers use curly braces",
                             suggestions,
+                            Applicability::MachineApplicable,
                         );
                     }
                 }};
index be3485cfa7cc23a5e2c8a40e3a22e42ac4822f39..8ddfb1d9cba224c7aa077042a6b14e1ac30e5d47 100644 (file)
@@ -49,7 +49,7 @@ pub fn expand_test_or_bench(
     // If we're not in test configuration, remove the annotated item
     if !cx.ecfg.should_test { return vec![]; }
 
-    let item =
+    let mut item =
         if let Annotatable::Item(i) = item { i }
         else {
             cx.parse_sess.span_diagnostic.span_fatal(item.span(),
@@ -192,6 +192,12 @@ pub fn expand_test_or_bench(
 
     debug!("Synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
 
+    // Temporarily add another marker to the original item for error reporting
+    let marker2 = cx.attribute(
+        attr_sp, cx.meta_word(attr_sp, Symbol::intern("rustc_test_marker2"))
+    );
+    item.attrs.push(marker2);
+
     vec![
         // Access to libtest under a gensymed name
         Annotatable::Item(test_extern),
diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attr_proc_macro.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attr_proc_macro.rs
deleted file mode 100644 (file)
index 679cb77..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.
-
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::TokenStream;
-
-#[proc_macro_attribute]
-pub fn attr_proc_macro(_: TokenStream, input: TokenStream) -> TokenStream {
-    input
-}
diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/bang_proc_macro.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/bang_proc_macro.rs
deleted file mode 100644 (file)
index 6484725..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.
-
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::TokenStream;
-
-#[proc_macro]
-pub fn bang_proc_macro(input: TokenStream) -> TokenStream {
-    input
-}
diff --git a/src/test/compile-fail-fulldeps/proc-macro/macro-use-attr.rs b/src/test/compile-fail-fulldeps/proc-macro/macro-use-attr.rs
deleted file mode 100644 (file)
index 0fcb9ef..0000000
+++ /dev/null
@@ -1,21 +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.
-
-// aux-build:attr_proc_macro.rs
-
-#[macro_use] extern crate attr_proc_macro;
-
-#[attr_proc_macro]
-//~^ ERROR: attribute procedural macros cannot be imported with `#[macro_use]`
-struct Foo;
-
-fn main() {
-    let _ = Foo;
-}
diff --git a/src/test/compile-fail-fulldeps/proc-macro/macro-use-bang.rs b/src/test/compile-fail-fulldeps/proc-macro/macro-use-bang.rs
deleted file mode 100644 (file)
index be5b8c3..0000000
+++ /dev/null
@@ -1,21 +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.
-
-// aux-build:bang_proc_macro.rs
-
-#![feature(proc_macro_non_items)]
-
-#[macro_use]
-extern crate bang_proc_macro;
-
-fn main() {
-    bang_proc_macro!(println!("Hello, world!"));
-    //~^ ERROR: procedural macros cannot be imported with `#[macro_use]`
-}
index 215d51c227084ed19931519fd31b458b8553919f..83bbb7c13c43f8acb74000f15f55b174084f8f25 100644 (file)
 #[macro_use]
 extern crate derive_b;
 
-#[derive(B)]
 #[B] //~ ERROR `B` is a derive mode
 #[C]
 #[B(D)]
 #[B(E = "foo")]
 #[B(arbitrary tokens)]
+#[derive(B)]
 struct B;
 
 fn main() {}
index 2d5c98ff0ed91336fd24a8c153bc5377f23d7b50..882579c571086ab8e48566a942abece6c3dcbdc4 100644 (file)
@@ -64,11 +64,11 @@ fn main() {
 //     bb0: {
 //         Validate(Acquire, [_1: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]);
 //         StorageLive(_3);
-//         Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(25), first_statement_index: 0 }))), [(*_2): i32]);
+//         Validate(Suspend(ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 })), [(*_2): i32]);
 //         _3 = &ReErased (*_2);
-//         Validate(Acquire, [(*_3): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(25), first_statement_index: 0 })) (imm)]);
+//         Validate(Acquire, [(*_3): i32/ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 }) (imm)]);
 //         _0 = (*_3);
-//         EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(25), first_statement_index: 0 })));
+//         EndRegion(ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 }));
 //         StorageDead(_3);
 //         return;
 //     }
index 72ec9ce400ffeccbb8a30c0a13ffc637bef1c1de..07f5b2aa84b7dda57e8dbb2958867272ac44981d 100644 (file)
@@ -48,12 +48,12 @@ fn _unused2(x: *const i32) -> i32 { unsafe { *x }}
 //         StorageLive(_1);
 //         _1 = Test { x: const 0i32 };
 //         StorageLive(_2);
-//         Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 }))), [_1: Test]);
+//         Validate(Suspend(ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 })), [_1: Test]);
 //         _2 = &ReErased _1;
-//         Validate(Acquire, [(*_2): Test/ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 })) (imm)]);
+//         Validate(Acquire, [(*_2): Test/ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 }) (imm)]);
 //         StorageLive(_4);
 //         StorageLive(_5);
-//         Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [((*_2).0: i32): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 })) (imm)]);
+//         Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [((*_2).0: i32): i32/ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 }) (imm)]);
 //         _5 = &ReErased ((*_2).0: i32);
 //         Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(18))) (imm)]);
 //         Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [(*_5): i32/ReScope(Node(ItemLocalId(18))) (imm)]);
@@ -68,7 +68,7 @@ fn _unused2(x: *const i32) -> i32 { unsafe { *x }}
 //         StorageDead(_4);
 //         StorageDead(_5);
 //         _0 = ();
-//         EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 })));
+//         EndRegion(ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 }));
 //         StorageDead(_2);
 //         StorageDead(_1);
 //         return;
index 6a67b5862a815526ed7fb103d30d77333bdfcc0b..2b931d89f1fec5dd0a13fbc99625b1c32d2ea79b 100644 (file)
@@ -1,9 +1,11 @@
 -include ../tools.mk
 
 all: extern_absolute_paths.rs extern_in_paths.rs krate2
-       $(RUSTC) extern_absolute_paths.rs -Zsave-analysis --edition=2018
+       $(RUSTC) extern_absolute_paths.rs -Zsave-analysis --edition=2018 \
+               -Z unstable-options --extern krate2
        cat $(TMPDIR)/save-analysis/extern_absolute_paths.json | "$(PYTHON)" validate_json.py
-       $(RUSTC) extern_in_paths.rs -Zsave-analysis --edition=2018
+       $(RUSTC) extern_in_paths.rs -Zsave-analysis --edition=2018 \
+               -Z unstable-options --extern krate2
        cat $(TMPDIR)/save-analysis/extern_in_paths.json | "$(PYTHON)" validate_json.py
 
 krate2: krate2.rs
diff --git a/src/test/run-pass-fulldeps/newtype_index.rs b/src/test/run-pass-fulldeps/newtype_index.rs
new file mode 100644 (file)
index 0000000..08e2c35
--- /dev/null
@@ -0,0 +1,20 @@
+#![feature(min_const_fn, rustc_attrs, rustc_private, step_trait)]
+
+#[macro_use] extern crate rustc_data_structures;
+extern crate rustc_serialize;
+
+use rustc_data_structures::indexed_vec::Idx;
+
+newtype_index!(struct MyIdx { MAX = 0xFFFF_FFFA });
+
+use std::mem::size_of;
+
+fn main() {
+    assert_eq!(size_of::<MyIdx>(), 4);
+    assert_eq!(size_of::<Option<MyIdx>>(), 4);
+    assert_eq!(size_of::<Option<Option<MyIdx>>>(), 4);
+    assert_eq!(size_of::<Option<Option<Option<MyIdx>>>>(), 4);
+    assert_eq!(size_of::<Option<Option<Option<Option<MyIdx>>>>>(), 4);
+    assert_eq!(size_of::<Option<Option<Option<Option<Option<MyIdx>>>>>>(), 4);
+    assert_eq!(size_of::<Option<Option<Option<Option<Option<Option<MyIdx>>>>>>>(), 8);
+}
index f692f57abb9c3cd80f334410a37e52a40dc157a7..3301e6a4637fef01dcb905ea143dcb6c8487f421 100644 (file)
@@ -12,8 +12,7 @@
 
 #![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)]
 
-use std::pin::PinBox;
-use std::pin::PinMut;
+use std::pin::Pin;
 use std::future::Future;
 use std::sync::{
     Arc,
@@ -49,7 +48,7 @@ fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) }
 
 impl Future for WakeOnceThenComplete {
     type Output = ();
-    fn poll(mut self: PinMut<Self>, cx: &mut Context) -> Poll<()> {
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> {
         if self.0 {
             Poll::Ready(())
         } else {
@@ -148,16 +147,16 @@ fn test_future_yields_once_then_returns<F, Fut>(f: F)
     F: FnOnce(u8) -> Fut,
     Fut: Future<Output = u8>,
 {
-    let mut fut = PinBox::new(f(9));
+    let mut fut = Box::pinned(f(9));
     let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) });
     let waker = local_waker_from_nonlocal(counter.clone());
     let spawner = &mut NoopSpawner;
     let cx = &mut Context::new(&waker, spawner);
 
     assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst));
-    assert_eq!(Poll::Pending, fut.as_pin_mut().poll(cx));
+    assert_eq!(Poll::Pending, fut.as_mut().poll(cx));
     assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst));
-    assert_eq!(Poll::Ready(9), fut.as_pin_mut().poll(cx));
+    assert_eq!(Poll::Ready(9), fut.as_mut().poll(cx));
 }
 
 fn main() {
index 69a04437691dd3f0a7e4c8654c0954b46fcf0529..6e757fb4f9a42f16ce74b5ceab74d996429b008c 100644 (file)
@@ -11,9 +11,8 @@
 #![feature(arbitrary_self_types, futures_api, pin)]
 #![allow(unused)]
 
-use std::pin::PinBox;
 use std::future::Future;
-use std::pin::PinMut;
+use std::pin::Pin;
 use std::rc::Rc;
 use std::sync::{
     Arc,
@@ -54,12 +53,12 @@ fn spawn_obj(&mut self, _: FutureObj<'static, ()>) -> Result<(), SpawnObjError>
 
 impl Future for MyFuture {
     type Output = ();
-    fn poll(self: PinMut<Self>, cx: &mut Context) -> Poll<Self::Output> {
+    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
         // Ensure all the methods work appropriately
         cx.waker().wake();
         cx.waker().wake();
         cx.local_waker().wake();
-        cx.spawner().spawn_obj(PinBox::new(MyFuture).into()).unwrap();
+        cx.spawner().spawn_obj(Box::pinned(MyFuture).into()).unwrap();
         Poll::Ready(())
     }
 }
@@ -72,7 +71,7 @@ fn test_local_waker() {
     let waker = unsafe { local_waker(counter.clone()) };
     let spawner = &mut NoopSpawner;
     let cx = &mut Context::new(&waker, spawner);
-    assert_eq!(Poll::Ready(()), PinMut::new(&mut MyFuture).poll(cx));
+    assert_eq!(Poll::Ready(()), Pin::new(&mut MyFuture).poll(cx));
     assert_eq!(1, counter.local_wakes.load(atomic::Ordering::SeqCst));
     assert_eq!(2, counter.nonlocal_wakes.load(atomic::Ordering::SeqCst));
 }
@@ -85,7 +84,7 @@ fn test_local_as_nonlocal_waker() {
     let waker: LocalWaker = local_waker_from_nonlocal(counter.clone());
     let spawner = &mut NoopSpawner;
     let cx = &mut Context::new(&waker, spawner);
-    assert_eq!(Poll::Ready(()), PinMut::new(&mut MyFuture).poll(cx));
+    assert_eq!(Poll::Ready(()), Pin::new(&mut MyFuture).poll(cx));
     assert_eq!(0, counter.local_wakes.load(atomic::Ordering::SeqCst));
     assert_eq!(3, counter.nonlocal_wakes.load(atomic::Ordering::SeqCst));
 }
diff --git a/src/test/rustdoc-js/pinbox-new.js b/src/test/rustdoc-js/pinbox-new.js
deleted file mode 100644 (file)
index 55842dc..0000000
+++ /dev/null
@@ -1,20 +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.
-
-// exact-check
-
-const QUERY = 'pinbox::new';
-
-const EXPECTED = {
-    'others': [
-        { 'path': 'std::pin::PinBox', 'name': 'new' },
-        { 'path': 'alloc::pin::PinBox', 'name': 'new' },
-    ],
-};
index 4a654ccb1350351e13fb47a3579fe7d5b3301a66..42951724648fddb9fec66af643d9f8c144421e54 100644 (file)
@@ -14,6 +14,5 @@ const EXPECTED = {
     'others': [
         { 'path': 'std::vec::Vec', 'name': 'new' },
         { 'path': 'std::vec::Vec', 'name': 'ne' },
-        { 'path': 'std::pin::PinBox', 'name': 'new' },
     ],
 };
diff --git a/src/test/rustdoc/issue-53812.rs b/src/test/rustdoc/issue-53812.rs
new file mode 100644 (file)
index 0000000..60d19fb
--- /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.
+
+pub trait MyIterator {
+}
+
+pub struct MyStruct<T>(T);
+
+macro_rules! array_impls {
+    ($($N:expr)+) => {
+        $(
+            impl<'a, T> MyIterator for &'a MyStruct<[T; $N]> {
+            }
+        )+
+    }
+}
+
+// @has issue_53812/trait.MyIterator.html '//*[@id="implementors-list"]//h3[1]' 'MyStruct<[T; 0]>'
+// @has - '//*[@id="implementors-list"]//h3[2]' 'MyStruct<[T; 1]>'
+// @has - '//*[@id="implementors-list"]//h3[3]' 'MyStruct<[T; 2]>'
+// @has - '//*[@id="implementors-list"]//h3[4]' 'MyStruct<[T; 3]>'
+// @has - '//*[@id="implementors-list"]//h3[5]' 'MyStruct<[T; 10]>'
+array_impls! { 10 3 2 1 0 }
index b255ffddafac87c6e443a2964ea1ebcd8ab095c4..73a026c581be55563a5e3ae4e01f35f5ef1a191f 100644 (file)
@@ -15,6 +15,7 @@
 // @has foo/index.html '//h2[@id="keywords"]' 'Keywords'
 // @has foo/index.html '//a[@href="keyword.match.html"]' 'match'
 // @has foo/keyword.match.html '//a[@class="keyword"]' 'match'
+// @has foo/keyword.match.html '//span[@class="in-band"]' 'Keyword match'
 // @has foo/keyword.match.html '//section[@id="main"]//div[@class="docblock"]//p' 'this is a test!'
 // @!has foo/index.html '//a/@href' 'foo/index.html'
 // @!has foo/foo/index.html
diff --git a/src/test/ui-fulldeps/attribute-order-restricted.rs b/src/test/ui-fulldeps/attribute-order-restricted.rs
new file mode 100644 (file)
index 0000000..553cd86
--- /dev/null
@@ -0,0 +1,32 @@
+// aux-build:attr_proc_macro.rs
+// compile-flags:--test
+
+#![feature(test)]
+
+extern crate test;
+extern crate attr_proc_macro;
+use attr_proc_macro::*;
+
+#[attr_proc_macro] // OK
+#[derive(Clone)]
+struct Before;
+
+#[derive(Clone)]
+#[attr_proc_macro] //~ ERROR macro attributes must be placed before `#[derive]`
+struct After;
+
+#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
+#[test]
+fn test_before() {}
+
+#[test]
+#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
+fn test_after() {}
+
+#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
+#[bench]
+fn bench_before(b: &mut test::Bencher) {}
+
+#[bench]
+#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
+fn bench_after(b: &mut test::Bencher) {}
diff --git a/src/test/ui-fulldeps/attribute-order-restricted.stderr b/src/test/ui-fulldeps/attribute-order-restricted.stderr
new file mode 100644 (file)
index 0000000..841fc63
--- /dev/null
@@ -0,0 +1,32 @@
+error: macro attributes must be placed before `#[derive]`
+  --> $DIR/attribute-order-restricted.rs:15:1
+   |
+LL | #[attr_proc_macro] //~ ERROR macro attributes must be placed before `#[derive]`
+   | ^^^^^^^^^^^^^^^^^^
+
+error: macro attributes cannot be used together with `#[test]` or `#[bench]`
+  --> $DIR/attribute-order-restricted.rs:18:1
+   |
+LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
+   | ^^^^^^^^^^^^^^^^^^
+
+error: macro attributes cannot be used together with `#[test]` or `#[bench]`
+  --> $DIR/attribute-order-restricted.rs:23:1
+   |
+LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
+   | ^^^^^^^^^^^^^^^^^^
+
+error: macro attributes cannot be used together with `#[test]` or `#[bench]`
+  --> $DIR/attribute-order-restricted.rs:26:1
+   |
+LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
+   | ^^^^^^^^^^^^^^^^^^
+
+error: macro attributes cannot be used together with `#[test]` or `#[bench]`
+  --> $DIR/attribute-order-restricted.rs:31:1
+   |
+LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
+   | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/attr_proc_macro.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/attr_proc_macro.rs
new file mode 100644 (file)
index 0000000..679cb77
--- /dev/null
@@ -0,0 +1,23 @@
+// 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.
+
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn attr_proc_macro(_: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/bang_proc_macro.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/bang_proc_macro.rs
new file mode 100644 (file)
index 0000000..6484725
--- /dev/null
@@ -0,0 +1,23 @@
+// 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.
+
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn bang_proc_macro(input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed-2.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed-2.rs
new file mode 100644 (file)
index 0000000..9912a89
--- /dev/null
@@ -0,0 +1,2 @@
+#[macro_export]
+macro_rules! my_attr { () => () }
diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed.rs
new file mode 100644 (file)
index 0000000..4e70171
--- /dev/null
@@ -0,0 +1,11 @@
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_derive(MyTrait, attributes(my_attr))]
+pub fn foo(_: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/multispan.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/multispan.rs
new file mode 100644 (file)
index 0000000..cecd9ef
--- /dev/null
@@ -0,0 +1,46 @@
+// 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.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_diagnostic, proc_macro_span)]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Span, Diagnostic};
+
+fn parse(input: TokenStream) -> Result<(), Diagnostic> {
+    let mut hi_spans = vec![];
+    for tree in input {
+        if let TokenTree::Ident(ref ident) = tree {
+            if ident.to_string() == "hi" {
+                hi_spans.push(ident.span());
+            }
+        }
+    }
+
+    if !hi_spans.is_empty() {
+        return Err(Span::def_site()
+                       .error("hello to you, too!")
+                       .span_note(hi_spans, "found these 'hi's"));
+    }
+
+    Ok(())
+}
+
+#[proc_macro]
+pub fn hello(input: TokenStream) -> TokenStream {
+    if let Err(diag) = parse(input) {
+        diag.emit();
+    }
+
+    TokenStream::new()
+}
diff --git a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowed.rs b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowed.rs
new file mode 100644 (file)
index 0000000..792b54b
--- /dev/null
@@ -0,0 +1,16 @@
+// compile-pass
+// aux-build:derive-helper-shadowed.rs
+// aux-build:derive-helper-shadowed-2.rs
+
+#[macro_use]
+extern crate derive_helper_shadowed;
+#[macro_use(my_attr)]
+extern crate derive_helper_shadowed_2;
+
+macro_rules! my_attr { () => () }
+
+#[derive(MyTrait)]
+#[my_attr] // OK
+struct S;
+
+fn main() {}
index c2357d501ee447045c53b84776518f67419c6204..aa9eae0ba317afc4159519d71ed7823cb3cf7367 100644 (file)
@@ -3,8 +3,8 @@
 extern crate derive_helper_shadowing;
 use derive_helper_shadowing::*;
 
-#[derive(MyTrait)]
 #[my_attr] //~ ERROR `my_attr` is ambiguous
+#[derive(MyTrait)]
 struct S;
 
 fn main() {}
index d597b577bb790b82b2af5fff0c365cd31608b15e..cdfecb3d1014667d6c0c60eb8fd774b233105993 100644 (file)
@@ -1,5 +1,5 @@
 error[E0659]: `my_attr` is ambiguous
-  --> $DIR/derive-helper-shadowing.rs:7:3
+  --> $DIR/derive-helper-shadowing.rs:6:3
    |
 LL | #[my_attr] //~ ERROR `my_attr` is ambiguous
    |   ^^^^^^^ ambiguous name
@@ -10,7 +10,7 @@ note: `my_attr` could refer to the name imported here
 LL | use derive_helper_shadowing::*;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: `my_attr` could also refer to the name defined here
-  --> $DIR/derive-helper-shadowing.rs:6:10
+  --> $DIR/derive-helper-shadowing.rs:7:10
    |
 LL | #[derive(MyTrait)]
    |          ^^^^^^^
diff --git a/src/test/ui-fulldeps/proc-macro/macro-use-attr.rs b/src/test/ui-fulldeps/proc-macro/macro-use-attr.rs
new file mode 100644 (file)
index 0000000..904562e
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+// aux-build:attr_proc_macro.rs
+
+#[macro_use] extern crate attr_proc_macro;
+
+#[attr_proc_macro]
+struct Foo;
+
+fn main() {
+    let _ = Foo;
+}
diff --git a/src/test/ui-fulldeps/proc-macro/macro-use-bang.rs b/src/test/ui-fulldeps/proc-macro/macro-use-bang.rs
new file mode 100644 (file)
index 0000000..9a54696
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+// aux-build:bang_proc_macro.rs
+
+#![feature(proc_macro_non_items)]
+
+#[macro_use]
+extern crate bang_proc_macro;
+
+fn main() {
+    bang_proc_macro!(println!("Hello, world!"));
+}
diff --git a/src/test/ui-fulldeps/proc-macro/multispan.rs b/src/test/ui-fulldeps/proc-macro/multispan.rs
new file mode 100644 (file)
index 0000000..940ec01
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:multispan.rs
+// ignore-stage1
+
+#![feature(proc_macro_non_items)]
+
+extern crate multispan;
+
+use multispan::hello;
+
+fn main() {
+    // This one emits no error.
+    hello!();
+
+    // Exactly one 'hi'.
+    hello!(hi); //~ ERROR hello to you, too!
+
+    // Now two, back to back.
+    hello!(hi hi); //~ ERROR hello to you, too!
+
+    // Now three, back to back.
+    hello!(hi hi hi); //~ ERROR hello to you, too!
+
+    // Now several, with spacing.
+    hello!(hi hey hi yo hi beep beep hi hi); //~ ERROR hello to you, too!
+    hello!(hi there, hi how are you? hi... hi.); //~ ERROR hello to you, too!
+    hello!(whoah. hi di hi di ho); //~ ERROR hello to you, too!
+    hello!(hi good hi and good bye); //~ ERROR hello to you, too!
+}
diff --git a/src/test/ui-fulldeps/proc-macro/multispan.stderr b/src/test/ui-fulldeps/proc-macro/multispan.stderr
new file mode 100644 (file)
index 0000000..267313e
--- /dev/null
@@ -0,0 +1,86 @@
+error: hello to you, too!
+  --> $DIR/multispan.rs:25:5
+   |
+LL |     hello!(hi); //~ ERROR hello to you, too!
+   |     ^^^^^^^^^^^
+   |
+note: found these 'hi's
+  --> $DIR/multispan.rs:25:12
+   |
+LL |     hello!(hi); //~ ERROR hello to you, too!
+   |            ^^
+
+error: hello to you, too!
+  --> $DIR/multispan.rs:28:5
+   |
+LL |     hello!(hi hi); //~ ERROR hello to you, too!
+   |     ^^^^^^^^^^^^^^
+   |
+note: found these 'hi's
+  --> $DIR/multispan.rs:28:12
+   |
+LL |     hello!(hi hi); //~ ERROR hello to you, too!
+   |            ^^ ^^
+
+error: hello to you, too!
+  --> $DIR/multispan.rs:31:5
+   |
+LL |     hello!(hi hi hi); //~ ERROR hello to you, too!
+   |     ^^^^^^^^^^^^^^^^^
+   |
+note: found these 'hi's
+  --> $DIR/multispan.rs:31:12
+   |
+LL |     hello!(hi hi hi); //~ ERROR hello to you, too!
+   |            ^^ ^^ ^^
+
+error: hello to you, too!
+  --> $DIR/multispan.rs:34:5
+   |
+LL |     hello!(hi hey hi yo hi beep beep hi hi); //~ ERROR hello to you, too!
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: found these 'hi's
+  --> $DIR/multispan.rs:34:12
+   |
+LL |     hello!(hi hey hi yo hi beep beep hi hi); //~ ERROR hello to you, too!
+   |            ^^     ^^    ^^           ^^ ^^
+
+error: hello to you, too!
+  --> $DIR/multispan.rs:35:5
+   |
+LL |     hello!(hi there, hi how are you? hi... hi.); //~ ERROR hello to you, too!
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: found these 'hi's
+  --> $DIR/multispan.rs:35:12
+   |
+LL |     hello!(hi there, hi how are you? hi... hi.); //~ ERROR hello to you, too!
+   |            ^^        ^^              ^^    ^^
+
+error: hello to you, too!
+  --> $DIR/multispan.rs:36:5
+   |
+LL |     hello!(whoah. hi di hi di ho); //~ ERROR hello to you, too!
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: found these 'hi's
+  --> $DIR/multispan.rs:36:19
+   |
+LL |     hello!(whoah. hi di hi di ho); //~ ERROR hello to you, too!
+   |                   ^^    ^^
+
+error: hello to you, too!
+  --> $DIR/multispan.rs:37:5
+   |
+LL |     hello!(hi good hi and good bye); //~ ERROR hello to you, too!
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: found these 'hi's
+  --> $DIR/multispan.rs:37:12
+   |
+LL |     hello!(hi good hi and good bye); //~ ERROR hello to you, too!
+   |            ^^      ^^
+
+error: aborting due to 7 previous errors
+
index d88530b21647e9f775c5feffa704ebc160abbad2..6aec37d4972f351c328252a89c0b82449c044412 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable
   --> $DIR/E0596.rs:16:18
    |
 LL |     let x = 1;
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 LL |     let y = &mut x; //[ast]~ ERROR [E0596]
    |                  ^ cannot borrow mutably
 
index 45b0c84275be46ef203595a015511bd35870a775..7fefb6672c76bce79aad3017232d7173c49f639a 100644 (file)
@@ -2,7 +2,7 @@ error[E0384]: cannot assign twice to immutable variable `x`
   --> $DIR/asm-out-assign-imm.rs:34:9
    |
 LL |     let x: isize;
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 LL |     x = 1;
    |     ----- first assignment to `x`
 ...
index 6d415eb733318108a18aa6d9a9f3ee6af596f3fa..8a50ec8f52c5844a34b1f3669114d0d5b5af5d4a 100644 (file)
@@ -1,9 +1,9 @@
 error[E0384]: cannot assign twice to immutable variable `v`
-  --> $DIR/assign-imm-local-twice.rs:20:5
+  --> $DIR/assign-imm-local-twice.rs:21:5
    |
 LL |     let v: isize;
-   |         - consider changing this to `mut v`
-LL |     //[mir]~^ NOTE consider changing this to `mut v`
+   |         - help: make this binding mutable: `mut v`
+...
 LL |     v = 1; //[ast]~ NOTE first assignment
    |     ----- first assignment to `v`
 ...
index 32752621e149f0971befe8d0953720e5c8c9de20..a34ac54ae3bfad821742195c71c0535c1f812a2f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0384]: cannot assign twice to immutable variable `v`
-  --> $DIR/assign-imm-local-twice.rs:20:5
+  --> $DIR/assign-imm-local-twice.rs:21:5
    |
 LL |     v = 1; //[ast]~ NOTE first assignment
    |     ----- first assignment to `v`
index 6d415eb733318108a18aa6d9a9f3ee6af596f3fa..8a50ec8f52c5844a34b1f3669114d0d5b5af5d4a 100644 (file)
@@ -1,9 +1,9 @@
 error[E0384]: cannot assign twice to immutable variable `v`
-  --> $DIR/assign-imm-local-twice.rs:20:5
+  --> $DIR/assign-imm-local-twice.rs:21:5
    |
 LL |     let v: isize;
-   |         - consider changing this to `mut v`
-LL |     //[mir]~^ NOTE consider changing this to `mut v`
+   |         - help: make this binding mutable: `mut v`
+...
 LL |     v = 1; //[ast]~ NOTE first assignment
    |     ----- first assignment to `v`
 ...
index ee9dafdd49eb86c897d6ed4672ff8dd0d54e5248..137414ccc6de01a87081e80bd5ea373c3eecfe0d 100644 (file)
@@ -13,7 +13,8 @@
 
 fn test() {
     let v: isize;
-    //[mir]~^ NOTE consider changing this to `mut v`
+    //[mir]~^ HELP make this binding mutable
+    //[mir]~| SUGGESTION mut v
     v = 1; //[ast]~ NOTE first assignment
            //[mir]~^ NOTE first assignment
     println!("v={}", v);
index 57a86227f764d104d6dfa82b593dbc80eeee2f81..64ac6883087dd9b00f5cd472bce8ba12439b53da 100644 (file)
@@ -15,11 +15,11 @@ LL | |     x;  //~ value moved here
    |       borrow later used here
 
 error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
-  --> $DIR/augmented-assignments.rs:30:5
+  --> $DIR/augmented-assignments.rs:31:5
    |
 LL |     let y = Int(2);
    |         - help: consider changing this to be mutable: `mut y`
-LL |     //~^ consider changing this to `mut y`
+...
 LL |     y   //~ error: cannot borrow immutable local variable `y` as mutable
    |     ^ cannot borrow as mutable
 
index 82f5c49eeb7ae520d81ccd85cdce3e14e01794df..2857ff2554a0c1f4e0c29ae8d7f37075896300c7 100644 (file)
@@ -26,7 +26,8 @@ fn main() {
     x;  //~ value moved here
 
     let y = Int(2);
-    //~^ consider changing this to `mut y`
+    //~^ HELP make this binding mutable
+    //~| SUGGESTION mut y
     y   //~ error: cannot borrow immutable local variable `y` as mutable
         //~| cannot borrow
     +=
index 953af813c3821d8e8dcd3c22af3deae23c8aa1e6..a7f3328071e26b370c93c6c778cbc64ab2cf7a34 100644 (file)
@@ -1,9 +1,9 @@
 error[E0596]: cannot borrow immutable local variable `y` as mutable
-  --> $DIR/augmented-assignments.rs:30:5
+  --> $DIR/augmented-assignments.rs:31:5
    |
 LL |     let y = Int(2);
-   |         - consider changing this to `mut y`
-LL |     //~^ consider changing this to `mut y`
+   |         - help: make this binding mutable: `mut y`
+...
 LL |     y   //~ error: cannot borrow immutable local variable `y` as mutable
    |     ^ cannot borrow mutably
 
diff --git a/src/test/ui/bind-by-move/bind-by-move-no-guards.nll.stderr b/src/test/ui/bind-by-move/bind-by-move-no-guards.nll.stderr
new file mode 100644 (file)
index 0000000..5f8b700
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0008]: cannot bind by-move into a pattern guard
+  --> $DIR/bind-by-move-no-guards.rs:8:14
+   |
+LL |         Some(z) if z.recv().unwrap() => { panic!() },
+   |              ^ moves value into pattern guard
+   |
+   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0008`.
index bb6060f2543e2a846cead159de024b47647bc76e..bc9b3a8de4ef5d41416773358b04214960f2989d 100644 (file)
@@ -1,13 +1,3 @@
-// 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.
-
 use std::sync::mpsc::channel;
 
 fn main() {
index ed516cd559ebbc77e3140b6f445ede7f930f8107..2af2b0d660efa3cf1882e4ae5d56934406a70c12 100644 (file)
@@ -1,5 +1,5 @@
 error[E0008]: cannot bind by-move into a pattern guard
-  --> $DIR/bind-by-move-no-guards.rs:18:14
+  --> $DIR/bind-by-move-no-guards.rs:8:14
    |
 LL |         Some(z) if z.recv().unwrap() => { panic!() },
    |              ^ moves value into pattern guard
index b17245673e02a646c5ad01929a7fdd4fb42016d6..c2ecdb33ba90715a21d2265d0f466b23037c4664 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable
   --> $DIR/borrowck-access-permissions.rs:22:24
    |
 LL |     let x = 1;
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 ...
 LL |         let _y1 = &mut x; //[ast]~ ERROR [E0596]
    |                        ^ cannot borrow mutably
@@ -17,7 +17,7 @@ error[E0596]: cannot borrow immutable `Box` content `*box_x` as mutable
   --> $DIR/borrowck-access-permissions.rs:37:24
    |
 LL |         let box_x = Box::new(1);
-   |             ----- consider changing this to `mut box_x`
+   |             ----- help: make this binding mutable: `mut box_x`
 ...
 LL |         let _y1 = &mut *box_x; //[ast]~ ERROR [E0596]
    |                        ^^^^^^ cannot borrow as mutable
index 2a7a7b3ffeeae6f9979ef791445fcb1a7dec3cdc..7b8849ec764dd478972cf2d317cbbec190e8130b 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable argument `arg` as mutable
   --> $DIR/borrowck-argument.rs:20:5
    |
 LL | fn func(arg: S) {
-   |         --- consider changing this to `mut arg`
+   |         --- help: make this binding mutable: `mut arg`
 LL |     arg.mutate(); //~ ERROR: cannot borrow immutable argument
    |     ^^^ cannot borrow mutably
 
@@ -10,7 +10,7 @@ error[E0596]: cannot borrow immutable argument `arg` as mutable
   --> $DIR/borrowck-argument.rs:25:9
    |
 LL |     fn method(&self, arg: S) {
-   |                      --- consider changing this to `mut arg`
+   |                      --- help: make this binding mutable: `mut arg`
 LL |         arg.mutate(); //~ ERROR: cannot borrow immutable argument
    |         ^^^ cannot borrow mutably
 
@@ -18,7 +18,7 @@ error[E0596]: cannot borrow immutable argument `arg` as mutable
   --> $DIR/borrowck-argument.rs:31:9
    |
 LL |     fn default(&self, arg: S) {
-   |                       --- consider changing this to `mut arg`
+   |                       --- help: make this binding mutable: `mut arg`
 LL |         arg.mutate(); //~ ERROR: cannot borrow immutable argument
    |         ^^^ cannot borrow mutably
 
@@ -28,7 +28,7 @@ error[E0596]: cannot borrow immutable argument `arg` as mutable
 LL |     (|arg: S| { arg.mutate() })(s); //~ ERROR: cannot borrow immutable argument
    |       ---       ^^^ cannot borrow mutably
    |       |
-   |       consider changing this to `mut arg`
+   |       help: make this binding mutable: `mut arg`
 
 error: aborting due to 4 previous errors
 
index 6936d32a789717407243393bfcf1085d1704f868..b0f0535b9f6c7aefe768775756dc4bffe85f6d19 100644 (file)
@@ -28,7 +28,7 @@ LL |         let x = 3;
    |             -
    |             |
    |             first assignment to `x`
-   |             consider changing this to `mut x`
+   |             help: make this binding mutable: `mut x`
 LL |         unsafe {
 LL |             asm!("nop" : "=r"(x));  //[ast]~ ERROR cannot assign twice
    |             ^^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
@@ -40,7 +40,7 @@ LL |         let x = 3;
    |             -
    |             |
    |             first assignment to `x`
-   |             consider changing this to `mut x`
+   |             help: make this binding mutable: `mut x`
 LL |         unsafe {
 LL |             asm!("nop" : "+r"(x));  //[ast]~ ERROR cannot assign twice
    |             ^^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
index 6936d32a789717407243393bfcf1085d1704f868..b0f0535b9f6c7aefe768775756dc4bffe85f6d19 100644 (file)
@@ -28,7 +28,7 @@ LL |         let x = 3;
    |             -
    |             |
    |             first assignment to `x`
-   |             consider changing this to `mut x`
+   |             help: make this binding mutable: `mut x`
 LL |         unsafe {
 LL |             asm!("nop" : "=r"(x));  //[ast]~ ERROR cannot assign twice
    |             ^^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
@@ -40,7 +40,7 @@ LL |         let x = 3;
    |             -
    |             |
    |             first assignment to `x`
-   |             consider changing this to `mut x`
+   |             help: make this binding mutable: `mut x`
 LL |         unsafe {
 LL |             asm!("nop" : "+r"(x));  //[ast]~ ERROR cannot assign twice
    |             ^^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
index ca6b86e5ca686cafc27a10f9ca470dd2f4614199..a6338a22389a001cd28793b7cdd44d400f0ae154 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable
   --> $DIR/borrowck-auto-mut-ref-to-immut-var.rs:25:5
    |
 LL |     let x = Foo { x: 3 };
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 LL |     x.printme();    //~ ERROR cannot borrow
    |     ^ cannot borrow mutably
 
index 9fc030f604c11a9e5d8d7da76a41e0ee1f7ef494..19a96d568575277b2a8ccaf1500e5ad5dc905442 100644 (file)
@@ -147,7 +147,7 @@ error[E0596]: cannot borrow field `foo.bar1` of immutable binding as mutable
   --> $DIR/borrowck-borrow-from-owned-ptr.rs:132:21
    |
 LL |     let foo = make_foo();
-   |         --- consider changing this to `mut foo`
+   |         --- help: make this binding mutable: `mut foo`
 LL |     let bar1 = &mut foo.bar1; //~ ERROR cannot borrow
    |                     ^^^^^^^^ cannot mutably borrow field of immutable binding
 
index cd0d6aa4ca3799354f8426764743d9af0d44c2b1..75f12c377edd440c481c46682c5d3c6d8561ea8e 100644 (file)
@@ -114,7 +114,7 @@ error[E0596]: cannot borrow field `foo.bar1` of immutable binding as mutable
   --> $DIR/borrowck-borrow-from-stack-variable.rs:130:21
    |
 LL |     let foo = make_foo();
-   |         --- consider changing this to `mut foo`
+   |         --- help: make this binding mutable: `mut foo`
 LL |     let bar1 = &mut foo.bar1; //~ ERROR cannot borrow
    |                     ^^^^^^^^ cannot mutably borrow field of immutable binding
 
index d852125a775d13d16f94b302f6dc89e8f0fc6c64..9f079b8cf98a9077da179b77a2f107f4cb6c7a7a 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable `Box` content `*a` as mutable
   --> $DIR/borrowck-borrow-immut-deref-of-box-as-mut.rs:22:5
    |
 LL |     let a: Box<_> = box A;
-   |         - consider changing this to `mut a`
+   |         - help: make this binding mutable: `mut a`
 LL |     a.foo();
    |     ^ cannot borrow as mutable
 
index 8f42fb45627215a9a55d19b9a12efb2ac0e11cd2..eee3f9bd5c1308d3112720f39d7e305854c2c798 100644 (file)
@@ -8,6 +8,7 @@ LL |     let x = defer(&vec!["Goodbye", "world!"]);
 LL |     x.x[0];
    |     ------ borrow later used here
    |
+   = note: consider using a `let` binding to create a longer lived value
    = 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
index 04f74af41141c701baf0a1983479dd8b03f43df1..ebf229696d8a99bbb563e606913356be6936ec6b 100644 (file)
@@ -8,6 +8,8 @@ LL |     buggy_map.insert(42, &*Box::new(1)); //~ ERROR borrowed value does not
 ...
 LL |     buggy_map.insert(43, &*tmp);
    |     --------- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
 
 error: aborting due to previous error
 
index 0191e0765b382ef9e7a4790fb0bac2887a7a3426..2eeb4e433adf19ebc7428f43ac38ba4b6ee54a88 100644 (file)
@@ -5,7 +5,7 @@ LL |         x => {
    |         -
    |         |
    |         first assignment to `x`
-   |         consider changing this to `mut x`
+   |         help: make this binding mutable: `mut x`
 LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
    |             ^^^^^^ cannot assign twice to immutable variable
 
@@ -16,7 +16,7 @@ LL |         E::Foo(x) => {
    |                -
    |                |
    |                first assignment to `x`
-   |                consider changing this to `mut x`
+   |                help: make this binding mutable: `mut x`
 LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
    |             ^^^^^^ cannot assign twice to immutable variable
 
@@ -27,7 +27,7 @@ LL |         S { bar: x } => {
    |                  -
    |                  |
    |                  first assignment to `x`
-   |                  consider changing this to `mut x`
+   |                  help: make this binding mutable: `mut x`
 LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
    |             ^^^^^^ cannot assign twice to immutable variable
 
@@ -38,7 +38,7 @@ LL |         (x,) => {
    |          -
    |          |
    |          first assignment to `x`
-   |          consider changing this to `mut x`
+   |          help: make this binding mutable: `mut x`
 LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
    |             ^^^^^^ cannot assign twice to immutable variable
 
@@ -49,7 +49,7 @@ LL |         [x,_,_] => {
    |          -
    |          |
    |          first assignment to `x`
-   |          consider changing this to `mut x`
+   |          help: make this binding mutable: `mut x`
 LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
    |             ^^^^^^ cannot assign twice to immutable variable
 
index 0191e0765b382ef9e7a4790fb0bac2887a7a3426..2eeb4e433adf19ebc7428f43ac38ba4b6ee54a88 100644 (file)
@@ -5,7 +5,7 @@ LL |         x => {
    |         -
    |         |
    |         first assignment to `x`
-   |         consider changing this to `mut x`
+   |         help: make this binding mutable: `mut x`
 LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
    |             ^^^^^^ cannot assign twice to immutable variable
 
@@ -16,7 +16,7 @@ LL |         E::Foo(x) => {
    |                -
    |                |
    |                first assignment to `x`
-   |                consider changing this to `mut x`
+   |                help: make this binding mutable: `mut x`
 LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
    |             ^^^^^^ cannot assign twice to immutable variable
 
@@ -27,7 +27,7 @@ LL |         S { bar: x } => {
    |                  -
    |                  |
    |                  first assignment to `x`
-   |                  consider changing this to `mut x`
+   |                  help: make this binding mutable: `mut x`
 LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
    |             ^^^^^^ cannot assign twice to immutable variable
 
@@ -38,7 +38,7 @@ LL |         (x,) => {
    |          -
    |          |
    |          first assignment to `x`
-   |          consider changing this to `mut x`
+   |          help: make this binding mutable: `mut x`
 LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
    |             ^^^^^^ cannot assign twice to immutable variable
 
@@ -49,7 +49,7 @@ LL |         [x,_,_] => {
    |          -
    |          |
    |          first assignment to `x`
-   |          consider changing this to `mut x`
+   |          help: make this binding mutable: `mut x`
 LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
    |             ^^^^^^ cannot assign twice to immutable variable
 
index 0859a4e0f5550e159174622e9045661fa1f1d5a8..c073db2917a80a22bd759c3aefd0fc2a50c0953f 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable
   --> $DIR/borrowck-mut-addr-of-imm-var.rs:13:30
    |
 LL |     let x: isize = 3;
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 LL |     let y: &mut isize = &mut x; //~ ERROR cannot borrow
    |                              ^ cannot borrow mutably
 
index e2fd9d771f1aad3a51f6f5cce17ee700ecf9cd93..51b8ae83c6147e317ec6e97719dddfd9773d09ed 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `v` as mutable
   --> $DIR/borrowck-mut-slice-of-imm-vec.rs:17:16
    |
 LL |     let v = vec![1, 2, 3];
-   |         - consider changing this to `mut v`
+   |         - help: make this binding mutable: `mut v`
 LL |     write(&mut v); //~ ERROR cannot borrow
    |                ^ cannot borrow mutably
 
diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr
new file mode 100644 (file)
index 0000000..b363a78
--- /dev/null
@@ -0,0 +1,24 @@
+error[E0302]: cannot assign in a pattern guard
+  --> $DIR/borrowck-mutate-in-guard.rs:20:25
+   |
+LL |         Enum::A(_) if { x = Enum::B(false); false } => 1,
+   |                         ^^^^^^^^^^^^^^^^^^ assignment in pattern guard
+
+error[E0301]: cannot mutably borrow in a pattern guard
+  --> $DIR/borrowck-mutate-in-guard.rs:22:38
+   |
+LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
+   |                                      ^ borrowed mutably in pattern guard
+   |
+   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+
+error[E0302]: cannot assign in a pattern guard
+  --> $DIR/borrowck-mutate-in-guard.rs:22:41
+   |
+LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
+   |                                         ^^^^^^^^^^^^^^^^^^^ assignment in pattern guard
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0301, E0302.
+For more information about an error, try `rustc --explain E0301`.
index 213d78339e2a4bfcef04efa06fb9a18096823485..fa2473adc2ffd14a5a5617b9b8772953bbae8140 100644 (file)
@@ -12,7 +12,7 @@ error[E0596]: cannot borrow immutable local variable `s` as mutable
   --> $DIR/borrowck-overloaded-call.rs:77:5
    |
 LL |     let s = SFnMut {
-   |         - consider changing this to `mut s`
+   |         - help: make this binding mutable: `mut s`
 ...
 LL |     s(3);   //~ ERROR cannot borrow immutable local variable `s` as mutable
    |     ^ cannot borrow mutably
index 2e2a1224306cb2c81426ee0bfde02063473d1f0c..520992096b5bc50e167a2da5c9fb624318d9d12d 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow field `(x as std::prelude::v1::Some).0` of immutable
   --> $DIR/borrowck-ref-mut-of-imm.rs:14:12
    |
 LL | fn destructure(x: Option<isize>) -> isize {
-   |                - consider changing this to `mut x`
+   |                - help: make this binding mutable: `mut x`
 ...
 LL |       Some(ref mut v) => *v //~ ERROR cannot borrow
    |            ^^^^^^^^^ cannot mutably borrow field of immutable binding
index 03b835d30770b99dfa52ddfbce5d3e4e62be1597..0c067c47004cfbe03b19236b070605bf20b7a75e 100644 (file)
@@ -12,7 +12,7 @@ error[E0596]: cannot borrow immutable argument `f` as mutable
   --> $DIR/borrowck-unboxed-closures.rs:17:5
    |
 LL | fn b<F:FnMut(isize, isize) -> isize>(f: F) {
-   |                                      - consider changing this to `mut f`
+   |                                      - help: make this binding mutable: `mut f`
 LL |     f(1, 2);    //~ ERROR cannot borrow immutable argument
    |     ^ cannot borrow mutably
 
index 1cf68795bf07f5e3dc4101d9162eebdb259068ed..06ae5cdbcc63bac03f2e400fb818206c92d54b85 100644 (file)
@@ -10,7 +10,7 @@ error[E0384]: cannot assign to immutable argument `_x` (Mir)
   --> $DIR/immutable-arg.rs:14:5
    |
 LL | fn foo(_x: u32) {
-   |        -- consider changing this to `mut _x`
+   |        -- help: make this binding mutable: `mut _x`
 LL |     _x = 4;
    |     ^^^^^^ cannot assign to immutable argument
 
index 2a94e05016d4edff759287c8ed80717eb095dfed..9431ef5f13dc8bf095d5fcc1fa1aeb3de97d4cea 100644 (file)
@@ -18,9 +18,6 @@ pub fn main(){
         }
         //~^^ ERROR use of partially moved value: `maybe` (Ast) [E0382]
         //~| ERROR use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast) [E0382]
-        //~| ERROR use of moved value: `maybe` (Mir) [E0382]
-        //~| ERROR use of moved value: `maybe` (Mir) [E0382]
         //~| ERROR use of moved value (Mir) [E0382]
-        //~| ERROR borrow of moved value: `maybe` (Mir) [E0382]
     }
 }
index b6e005a6673ebc53a74a9e3c0cdb1dbd33daf99f..957ccfe45dd012d6511796a52ef21fdd6d28c9b1 100644 (file)
@@ -16,17 +16,6 @@ LL |         if let Some(thing) = maybe {
    |
    = note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `maybe` (Mir)
-  --> $DIR/issue-41962.rs:17:16
-   |
-LL |         if let Some(thing) = maybe {
-   |                ^^^^^-----^
-   |                |    |
-   |                |    value moved here
-   |                value used here after move
-   |
-   = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
-
 error[E0382]: use of moved value (Mir)
   --> $DIR/issue-41962.rs:17:21
    |
@@ -35,26 +24,6 @@ LL |         if let Some(thing) = maybe {
    |
    = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `maybe` (Mir)
-  --> $DIR/issue-41962.rs:17:30
-   |
-LL |         if let Some(thing) = maybe {
-   |                     -----    ^^^^^ value used here after move
-   |                     |
-   |                     value moved here
-   |
-   = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
-
-error[E0382]: borrow of moved value: `maybe` (Mir)
-  --> $DIR/issue-41962.rs:17:30
-   |
-LL |         if let Some(thing) = maybe {
-   |                     -----    ^^^^^ value borrowed here after move
-   |                     |
-   |                     value moved here
-   |
-   = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
-
-error: aborting due to 6 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0382`.
index d77254f31414b8251eb156c44680b3e3437b920d..5013f877e7ecb19ea72d9eb1b329d8e05b613f4d 100644 (file)
@@ -230,7 +230,7 @@ error[E0596]: cannot borrow immutable argument `x` as mutable
   --> $DIR/mutability-errors.rs:64:10
    |
 LL | fn imm_local(x: (i32,)) {
-   |              - consider changing this to `mut x`
+   |              - help: make this binding mutable: `mut x`
 LL |     &mut x; //~ ERROR
    |          ^ cannot borrow mutably
 
@@ -238,7 +238,7 @@ error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
   --> $DIR/mutability-errors.rs:65:10
    |
 LL | fn imm_local(x: (i32,)) {
-   |              - consider changing this to `mut x`
+   |              - help: make this binding mutable: `mut x`
 LL |     &mut x; //~ ERROR
 LL |     &mut x.0; //~ ERROR
    |          ^^^ cannot mutably borrow field of immutable binding
@@ -247,7 +247,7 @@ error[E0595]: closure cannot assign to immutable argument `x`
   --> $DIR/mutability-errors.rs:69:5
    |
 LL | fn imm_capture(x: (i32,)) {
-   |                - consider changing this to `mut x`
+   |                - help: make this binding mutable: `mut x`
 LL |     || { //~ ERROR
    |     ^^ cannot borrow mutably
 
index 54d12f8fae85d8ef419eb44010a0953a9ad8a18f..d16c0a5e37b8f9eba933bbb2e9ee6e2b33d02f52 100644 (file)
@@ -2,7 +2,7 @@ error[E0594]: cannot assign to field `x.0` of immutable binding
   --> $DIR/reassignment_immutable_fields.rs:17:5
    |
 LL |     let x: (u32, u32);
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 LL |     x.0 = 1; //~ ERROR
    |     ^^^^^^^ cannot mutably borrow field of immutable binding
 
@@ -10,7 +10,7 @@ error[E0594]: cannot assign to field `x.1` of immutable binding
   --> $DIR/reassignment_immutable_fields.rs:18:5
    |
 LL |     let x: (u32, u32);
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 LL |     x.0 = 1; //~ ERROR
 LL |     x.1 = 22; //~ ERROR
    |     ^^^^^^^^ cannot mutably borrow field of immutable binding
@@ -31,7 +31,7 @@ error[E0594]: cannot assign to field `x.0` of immutable binding
   --> $DIR/reassignment_immutable_fields.rs:25:5
    |
 LL |     let x: (u32, u32);
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 LL |     x.0 = 1; //~ ERROR
    |     ^^^^^^^ cannot mutably borrow field of immutable binding
 
@@ -39,7 +39,7 @@ error[E0594]: cannot assign to field `x.1` of immutable binding
   --> $DIR/reassignment_immutable_fields.rs:26:5
    |
 LL |     let x: (u32, u32);
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 LL |     x.0 = 1; //~ ERROR
 LL |     x.1 = 22; //~ ERROR
    |     ^^^^^^^^ cannot mutably borrow field of immutable binding
index 70849905f92ab84e1624c19063185e376e0b704f..b0b351889b79abd1b02059e35433d07525e092a7 100644 (file)
@@ -2,7 +2,7 @@ error[E0594]: cannot assign to field `x.a` of immutable binding
   --> $DIR/reassignment_immutable_fields_overlapping.rs:22:5
    |
 LL |     let x: Foo;
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 LL |     x.a = 1;  //~ ERROR
    |     ^^^^^^^ cannot mutably borrow field of immutable binding
 
@@ -10,7 +10,7 @@ error[E0594]: cannot assign to field `x.b` of immutable binding
   --> $DIR/reassignment_immutable_fields_overlapping.rs:23:5
    |
 LL |     let x: Foo;
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 LL |     x.a = 1;  //~ ERROR
 LL |     x.b = 22; //~ ERROR
    |     ^^^^^^^^ cannot mutably borrow field of immutable binding
index b3c013d8b1f493ce3801aae56d9c4bc6874ceb9d..65dff51059cefed5fb1e1ad7cd904b46e3849409 100644 (file)
@@ -2,7 +2,7 @@ error[E0594]: cannot assign to field `x.0` of immutable binding
   --> $DIR/reassignment_immutable_fields_twice.rs:17:5
    |
 LL |     let x: (u32, u32);
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 LL |     x = (22, 44);
 LL |     x.0 = 1; //~ ERROR
    |     ^^^^^^^ cannot mutably borrow field of immutable binding
@@ -11,7 +11,7 @@ error[E0594]: cannot assign to field `x.0` of immutable binding
   --> $DIR/reassignment_immutable_fields_twice.rs:22:5
    |
 LL |     let x: (u32, u32);
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 LL |     x.0 = 1; //~ ERROR
    |     ^^^^^^^ cannot mutably borrow field of immutable binding
 
@@ -19,7 +19,7 @@ error[E0594]: cannot assign to field `x.0` of immutable binding
   --> $DIR/reassignment_immutable_fields_twice.rs:23:5
    |
 LL |     let x: (u32, u32);
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 LL |     x.0 = 1; //~ ERROR
 LL |     x.0 = 22; //~ ERROR
    |     ^^^^^^^^ cannot mutably borrow field of immutable binding
@@ -28,7 +28,7 @@ error[E0594]: cannot assign to field `x.1` of immutable binding
   --> $DIR/reassignment_immutable_fields_twice.rs:24:5
    |
 LL |     let x: (u32, u32);
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 ...
 LL |     x.1 = 44; //~ ERROR
    |     ^^^^^^^^ cannot mutably borrow field of immutable binding
index 68818f50cd27393e50b639cd8356a033d5472d94..42eb1e9cb2193a2f46b4ccc44df4a240753cf07e 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable
   --> $DIR/huge_multispan_highlight.rs:100:18
    |
 LL |     let x = "foo";
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 ...
 LL |     let y = &mut x; //~ ERROR cannot borrow
    |                  ^ cannot borrow mutably
index 46bb7c5af5744f9da42d2156b3800196dfd7ec87..6273ba33e167b3ed7a2405e7587631814cc3da5b 100644 (file)
@@ -5,7 +5,7 @@ LL |     let x = 42;
    |         -
    |         |
    |         first assignment to `x`
-   |         consider changing this to `mut x`
+   |         help: make this binding mutable: `mut x`
 LL |     x = 43;
    |     ^^^^^^ cannot assign twice to immutable variable
 
diff --git a/src/test/ui/consts/const-eval/zst_operand_eval.rs b/src/test/ui/consts/const-eval/zst_operand_eval.rs
new file mode 100644 (file)
index 0000000..d837da1
--- /dev/null
@@ -0,0 +1,5 @@
+// compile-pass
+
+static ASSERT: () = [()][!(std::mem::size_of::<u32>() == 4) as usize];
+
+fn main() {}
index 4a29cd81425c4131a8456332052ac30778a363d6..591c3a0df0366792ccbd075ac7e926697dc99f67 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow field `f.v` of immutable binding as mutable
   --> $DIR/issue-35937.rs:17:5
    |
 LL |     let f = Foo { v: Vec::new() };
-   |         - consider changing this to `mut f`
+   |         - help: make this binding mutable: `mut f`
 LL |     f.v.push("cat".to_string()); //~ ERROR cannot borrow
    |     ^^^ cannot mutably borrow field of immutable binding
 
@@ -10,7 +10,7 @@ error[E0594]: cannot assign to field `s.x` of immutable binding
   --> $DIR/issue-35937.rs:26:5
    |
 LL |     let s = S { x: 42 };
-   |         - consider changing this to `mut s`
+   |         - help: make this binding mutable: `mut s`
 LL |     s.x += 1; //~ ERROR cannot assign
    |     ^^^^^^^^ cannot mutably borrow field of immutable binding
 
@@ -18,7 +18,7 @@ error[E0594]: cannot assign to field `s.x` of immutable binding
   --> $DIR/issue-35937.rs:30:5
    |
 LL | fn bar(s: S) {
-   |        - consider changing this to `mut s`
+   |        - help: make this binding mutable: `mut s`
 LL |     s.x += 1; //~ ERROR cannot assign
    |     ^^^^^^^^ cannot mutably borrow field of immutable binding
 
index dfa9cb880e56880f0351720b53355cdf49c61caa..7cf2ca720ef11bfb15dda7c50ead123b7e5f0d22 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow field `z.x` of immutable binding as mutable
   --> $DIR/issue-39544.rs:21:18
    |
 LL |     let z = Z { x: X::Y };
-   |         - consider changing this to `mut z`
+   |         - help: make this binding mutable: `mut z`
 LL |     let _ = &mut z.x; //~ ERROR cannot borrow
    |                  ^^^ cannot mutably borrow field of immutable binding
 
@@ -77,7 +77,7 @@ error[E0596]: cannot borrow field `z.x` of immutable binding as mutable
   --> $DIR/issue-39544.rs:51:18
    |
 LL | pub fn with_arg(z: Z, w: &Z) {
-   |                 - consider changing this to `mut z`
+   |                 - help: make this binding mutable: `mut z`
 LL |     let _ = &mut z.x; //~ ERROR cannot borrow
    |                  ^^^ cannot mutably borrow field of immutable binding
 
diff --git a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs
new file mode 100644 (file)
index 0000000..d053b11
--- /dev/null
@@ -0,0 +1,66 @@
+// 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 test_and() {
+    let a = true;
+    let b = false;
+    if a and b {
+        //~^ ERROR expected `{`, found `and`
+        println!("both");
+    }
+}
+
+fn test_or() {
+    let a = true;
+    let b = false;
+    if a or b {
+        //~^ ERROR expected `{`, found `or`
+        println!("both");
+    }
+}
+
+fn test_and_par() {
+    let a = true;
+    let b = false;
+    if (a and b) {
+        //~^ ERROR expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `and`
+        println!("both");
+    }
+}
+
+fn test_or_par() {
+    let a = true;
+    let b = false;
+    if (a or b) {
+        //~^ ERROR expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `or`
+        println!("both");
+    }
+}
+
+fn test_while_and() {
+    let a = true;
+    let b = false;
+    while a and b {
+        //~^ ERROR expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `and`
+        println!("both");
+    }
+}
+
+fn test_while_or() {
+    let a = true;
+    let b = false;
+    while a or b {
+        //~^ ERROR expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `or`
+        println!("both");
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr
new file mode 100644 (file)
index 0000000..2284577
--- /dev/null
@@ -0,0 +1,54 @@
+error: expected `{`, found `and`
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:14:10
+   |
+LL |     if a and b {
+   |     --   ^^^ help: use `&&` instead of `and` for the boolean operator
+   |     |
+   |     this `if` statement has a condition, but no block
+
+error: expected `{`, found `or`
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:23:10
+   |
+LL |     if a or b {
+   |     --   ^^ help: use `||` instead of `or` for the boolean operator
+   |     |
+   |     this `if` statement has a condition, but no block
+
+error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `and`
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:32:11
+   |
+LL |     if (a and b) {
+   |           ^^^
+   |           |
+   |           expected one of 8 possible tokens here
+   |           help: use `&&` instead of `and` for the boolean operator
+
+error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `or`
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:41:11
+   |
+LL |     if (a or b) {
+   |           ^^
+   |           |
+   |           expected one of 8 possible tokens here
+   |           help: use `||` instead of `or` for the boolean operator
+
+error: expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `and`
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:50:13
+   |
+LL |     while a and b {
+   |             ^^^
+   |             |
+   |             expected one of `!`, `.`, `::`, `?`, `{`, or an operator here
+   |             help: use `&&` instead of `and` for the boolean operator
+
+error: expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `or`
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:59:13
+   |
+LL |     while a or b {
+   |             ^^
+   |             |
+   |             expected one of `!`, `.`, `::`, `?`, `{`, or an operator here
+   |             help: use `||` instead of `or` for the boolean operator
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/error-codes/E0008.nll.stderr b/src/test/ui/error-codes/E0008.nll.stderr
new file mode 100644 (file)
index 0000000..ce627cb
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0008]: cannot bind by-move into a pattern guard
+  --> $DIR/E0008.rs:13:14
+   |
+LL |         Some(s) if s.len() == 0 => {},
+   |              ^ moves value into pattern guard
+   |
+   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0008`.
diff --git a/src/test/ui/error-codes/E0301.nll.stderr b/src/test/ui/error-codes/E0301.nll.stderr
new file mode 100644 (file)
index 0000000..f060eb9
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0301]: cannot mutably borrow in a pattern guard
+  --> $DIR/E0301.rs:14:19
+   |
+LL |         option if option.take().is_none() => {}, //~ ERROR E0301
+   |                   ^^^^^^ borrowed mutably in pattern guard
+   |
+   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0301`.
index 80d81ea03cb6df4ffdc9bb28dcbe382da4ea3f78..d3d5bd498cfe8084777a7eb9de586d47b503872b 100644 (file)
@@ -2,7 +2,7 @@ error: use of deprecated attribute `dropck_parametricity`: unsafe_destructor_bli
   --> $DIR/feature-gate-dropck-ugeh-2.rs:17:5
    |
 LL |     #[unsafe_destructor_blind_to_params]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this attribute with `#[may_dangle]`
    |
 note: lint level defined here
   --> $DIR/feature-gate-dropck-ugeh-2.rs:11:9
index 84e5f302c1676e027c04c17a6e9862642daa8d76..ca51154884f1227fb047c5df0bc3940fbcb87993 100644 (file)
@@ -15,7 +15,7 @@
 
 use core::panic::PanicInfo;
 
-#[panic_implementation] //~ ERROR This attribute was renamed to `panic_handler` (see issue #44489)
+#[panic_implementation] //~ ERROR this attribute was renamed to `panic_handler` (see issue #44489)
 fn panic(info: &PanicInfo) -> ! {
     loop {}
 }
index 926a49ae83199b4c6e07c386d6f5a3719ecfb685..a54780468c42de97a4c48303f78e7fe4d8435237 100644 (file)
@@ -1,7 +1,7 @@
-error[E0658]: This attribute was renamed to `panic_handler` (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 This attribute was renamed to `panic_handler` (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-self-struct-ctor.rs b/src/test/ui/feature-gates/feature-gate-self-struct-ctor.rs
new file mode 100644 (file)
index 0000000..98eab39
--- /dev/null
@@ -0,0 +1,22 @@
+struct ST1(i32, i32);
+
+impl ST1 {
+    fn ctor() -> Self {
+        Self(1,2)
+        //~^ ERROR: `Self` struct constructors are unstable (see issue #51994) [E0658]
+    }
+}
+
+struct ST2;
+
+impl ST2 {
+    fn ctor() -> Self {
+        Self
+        //~^ ERROR: `Self` struct constructors are unstable (see issue #51994) [E0658]
+    }
+}
+
+fn main() {
+    let _ = ST1::ctor();
+    let _ = ST2::ctor();
+}
diff --git a/src/test/ui/feature-gates/feature-gate-self-struct-ctor.stderr b/src/test/ui/feature-gates/feature-gate-self-struct-ctor.stderr
new file mode 100644 (file)
index 0000000..6061a0d
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0658]: `Self` struct constructors are unstable (see issue #51994)
+  --> $DIR/feature-gate-self-struct-ctor.rs:5:9
+   |
+LL |         Self(1,2)
+   |         ^^^^
+   |
+   = help: add #![feature(self_struct_ctor)] to the crate attributes to enable
+
+error[E0658]: `Self` struct constructors are unstable (see issue #51994)
+  --> $DIR/feature-gate-self-struct-ctor.rs:14:9
+   |
+LL |         Self
+   |         ^^^^
+   |
+   = help: add #![feature(self_struct_ctor)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
index 54125b955cb1fdfad51881c48761e57a69af6db9..7b2061950f3dea16a9212eb3a338c04feb7e5b6b 100644 (file)
@@ -2,7 +2,7 @@ error[E0594]: cannot assign to immutable `Box` content `*y`
   --> $DIR/immut-function-arguments.rs:15:5
    |
 LL | fn f(y: Box<isize>) {
-   |      - consider changing this to `mut y`
+   |      - help: make this binding mutable: `mut y`
 LL |     *y = 5; //[ast]~ ERROR cannot assign
    |     ^^^^^^ cannot borrow as mutable
 
@@ -12,7 +12,7 @@ error[E0594]: cannot assign to immutable `Box` content `*q`
 LL |     let _frob = |q: Box<isize>| { *q = 2; }; //[ast]~ ERROR cannot assign
    |                  -                ^^^^^^ cannot borrow as mutable
    |                  |
-   |                  consider changing this to `mut q`
+   |                  help: make this binding mutable: `mut q`
 
 error: aborting due to 2 previous errors
 
index 1e3e997b111ace1bf9505c1552335042eee99f36..3019e3aa1f7324c64535d2ee08b85f7c5275dbce 100644 (file)
@@ -11,12 +11,18 @@ error: unsatisfied lifetime constraints
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
    |             -- lifetime `'a` defined here  ^ returning this value requires that `'a` must outlive `'static`
+help: to allow this impl Trait to capture borrowed data with lifetime `'a`, add `'a` as a constraint
+   |
+LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
+   |                                ^^^^^^^^^^^^^^
 
 error: unsatisfied lifetime constraints
   --> $DIR/must_outlive_least_region_or_bound.rs:22:69
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    |               -- lifetime `'a` defined here                         ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: unsatisfied lifetime constraints
   --> $DIR/must_outlive_least_region_or_bound.rs:29:5
index d75de81fc1c7fad951aa779bce692990d69a86fe..4bc8876c232e3354d3bf76a39e6d1a52265d77cb 100644 (file)
@@ -5,6 +5,10 @@ LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
    |                         - let's call the lifetime of this reference `'1`
 LL |         self.x.iter().map(|a| a.0)
    |         ^^^^^^ cast requires that `'1` must outlive `'static`
+help: to allow this impl Trait to capture borrowed data with lifetime `'1`, add `'_` as a constraint
+   |
+LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unsatisfied lifetime constraints
   --> $DIR/static-return-lifetime-infered.rs:21:9
@@ -13,6 +17,10 @@ LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
    |                    -- lifetime `'a` defined here
 LL |         self.x.iter().map(|a| a.0)
    |         ^^^^^^ cast requires that `'a` must outlive `'static`
+help: to allow this impl Trait to capture borrowed data with lifetime `'a`, add `'a` as a constraint
+   |
+LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 4b6b6c2fe7677069b35d955529aae7ad2437bb14..e7f4e32dc7c41b17a757858e2e9b1ea6aa51ef7d 100644 (file)
 // regression test for issue 11256
 #![crate_type="foo"]    //~ ERROR invalid `crate_type` value
 
+// Tests for suggestions (#53958)
+
+#![crate_type="statoclib"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION staticlib
+
+#![crate_type="procmacro"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION proc-macro
+
+#![crate_type="static-lib"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION staticlib
+
+#![crate_type="drylib"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION dylib
+
+#![crate_type="dlib"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION rlib
+
+#![crate_type="lob"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION lib
+
+#![crate_type="bon"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION bin
+
+#![crate_type="cdalib"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION cdylib
+
 fn main() {
     return
 }
index 6dc8a0f2bbb04b500cc4a24da0256ffd7b2d41ec..c82da865f33531b135ae8b628638220a0f378175 100644 (file)
@@ -1,10 +1,58 @@
 error: invalid `crate_type` value
-  --> $DIR/invalid-crate-type.rs:12:1
+  --> $DIR/invalid-crate-type.rs:12:15
    |
 LL | #![crate_type="foo"]    //~ ERROR invalid `crate_type` value
-   | ^^^^^^^^^^^^^^^^^^^^
+   |               ^^^^^
    |
    = note: #[deny(unknown_crate_types)] on by default
 
-error: aborting due to previous error
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:16:15
+   |
+LL | #![crate_type="statoclib"]
+   |               ^^^^^^^^^^^ help: did you mean: `"staticlib"`
+
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:21:15
+   |
+LL | #![crate_type="procmacro"]
+   |               ^^^^^^^^^^^ help: did you mean: `"proc-macro"`
+
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:26:15
+   |
+LL | #![crate_type="static-lib"]
+   |               ^^^^^^^^^^^^ help: did you mean: `"staticlib"`
+
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:31:15
+   |
+LL | #![crate_type="drylib"]
+   |               ^^^^^^^^ help: did you mean: `"dylib"`
+
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:36:15
+   |
+LL | #![crate_type="dlib"]
+   |               ^^^^^^ help: did you mean: `"rlib"`
+
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:41:15
+   |
+LL | #![crate_type="lob"]
+   |               ^^^^^ help: did you mean: `"lib"`
+
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:46:15
+   |
+LL | #![crate_type="bon"]
+   |               ^^^^^ help: did you mean: `"bin"`
+
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:51:15
+   |
+LL | #![crate_type="cdalib"]
+   |               ^^^^^^^^ help: did you mean: `"cdylib"`
+
+error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/issue-53692.rs b/src/test/ui/issue-53692.rs
new file mode 100644 (file)
index 0000000..0b6cc36
--- /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.
+fn main() {
+        let items = vec![1, 2, 3];
+        let ref_items: &[i32] = &items;
+        let items_clone: Vec<i32> = ref_items.clone();
+
+        // in that case no suggestion will be triggered
+        let items_clone_2:Vec<i32> = items.clone();
+
+        let s = "hi";
+        let string: String = s.clone();
+
+        // in that case no suggestion will be triggered
+        let s2 = "hi";
+        let string_2: String = s2.to_string();
+}
diff --git a/src/test/ui/issue-53692.stderr b/src/test/ui/issue-53692.stderr
new file mode 100644 (file)
index 0000000..9cd8a53
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-53692.rs:13:37
+   |
+LL |         let items_clone: Vec<i32> = ref_items.clone();
+   |                                     ^^^^^^^^^^^^^^^^^
+   |                                     |
+   |                                     expected struct `std::vec::Vec`, found &[i32]
+   |                                     help: try using a conversion method: `ref_items.to_vec()`
+   |
+   = note: expected type `std::vec::Vec<i32>`
+              found type `&[i32]`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-53692.rs:19:30
+   |
+LL |         let string: String = s.clone();
+   |                              ^^^^^^^^^
+   |                              |
+   |                              expected struct `std::string::String`, found &str
+   |                              help: try using a conversion method: `s.to_string()`
+   |
+   = note: expected type `std::string::String`
+              found type `&str`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 2e94a27838e433bb6b75fe90a5c5bddef6546656..a4b8b48384d7aa59213dd67d81ca73053fb6ed70 100644 (file)
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    concat!(test!()); //~ ERROR `test` can only be used in attributes
+    concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
 }
index 186c59a61493d68a9863569436759baa8bffea62..85f600dbff24e85712d7d16a428242cbe33e4459 100644 (file)
@@ -1,7 +1,7 @@
-error: `test` can only be used in attributes
+error: cannot find macro `test!` in this scope
   --> $DIR/issue-11692-2.rs:12:13
    |
-LL |     concat!(test!()); //~ ERROR `test` can only be used in attributes
+LL |     concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
    |             ^^^^
 
 error: aborting due to previous error
index 85924a75261685fecf5fdb72b129e693a39dffcb..c7b0b57000f5e18b97d22f24b00e6bf4538be8c9 100644 (file)
@@ -1,23 +1,3 @@
-error[E0382]: use of moved value: `foo`
-  --> $DIR/issue-17385.rs:28:11
-   |
-LL |     drop(foo);
-   |          --- value moved here
-LL |     match foo { //~ ERROR use of moved value
-   |           ^^^ value used here after move
-   |
-   = note: move occurs because `foo` has type `X`, which does not implement the `Copy` trait
-
-error[E0382]: borrow of moved value: `foo`
-  --> $DIR/issue-17385.rs:28:11
-   |
-LL |     drop(foo);
-   |          --- value moved here
-LL |     match foo { //~ ERROR use of moved value
-   |           ^^^ value borrowed here after move
-   |
-   = note: move occurs because `foo` has type `X`, which does not implement the `Copy` trait
-
 error[E0382]: use of moved value: `foo.0`
   --> $DIR/issue-17385.rs:29:11
    |
@@ -39,27 +19,6 @@ LL |     match e { //~ ERROR use of moved value
    |
    = note: move occurs because `e` has type `Enum`, which does not implement the `Copy` trait
 
-error[E0382]: borrow of moved value: `e`
-  --> $DIR/issue-17385.rs:35:11
-   |
-LL |     drop(e);
-   |          - value moved here
-LL |     match e { //~ ERROR use of moved value
-   |           ^ value borrowed here after move
-   |
-   = note: move occurs because `e` has type `Enum`, which does not implement the `Copy` trait
-
-error[E0382]: use of moved value: `e`
-  --> $DIR/issue-17385.rs:36:9
-   |
-LL |     drop(e);
-   |          - value moved here
-LL |     match e { //~ ERROR use of moved value
-LL |         Enum::Variant1 => unreachable!(),
-   |         ^^^^^^^^^^^^^^ value used here after move
-   |
-   = note: move occurs because `e` has type `Enum`, which does not implement the `Copy` trait
-
-error: aborting due to 6 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0382`.
index cf280bd80b27fbb1a2005aca89afb5bc615b13dd..e02f21f6e1247a1384d6baff47e71cc9421f1b29 100644 (file)
@@ -8,6 +8,8 @@ LL |     let val: &_ = x.borrow().0;
 ...
 LL |     println!("{}", val);
    |                    --- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
 
 error: aborting due to previous error
 
index cf280bd80b27fbb1a2005aca89afb5bc615b13dd..e02f21f6e1247a1384d6baff47e71cc9421f1b29 100644 (file)
@@ -8,6 +8,8 @@ LL |     let val: &_ = x.borrow().0;
 ...
 LL |     println!("{}", val);
    |                    --- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
 
 error: aborting due to previous error
 
index ed6a2f85fbe23a8bb963bf61732b64239649e2d9..579ec4d923be1318f212965c03a337bcca3ab1d8 100644 (file)
@@ -28,6 +28,7 @@ fn main() {
     //[mir]~^^^^^ ERROR borrowed value does not live long enough [E0597]
     //[mir]~| NOTE temporary value does not live long enough
     //[mir]~| NOTE temporary value only lives until here
+    //[mir]~| NOTE consider using a `let` binding to create a longer lived value
     println!("{}", val);
     //[mir]~^ borrow later used here
 }
index dbd6999b4f29fbb300c49f7f6c12db21f44e34d1..b0aadf3a51467c5bbd03dcc5a07e81741afcb16b 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable `Box` content `*x` as mutable
   --> $DIR/issue-36400.rs:15:12
    |
 LL |     let x = Box::new(3);
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 LL |     f(&mut *x); //~ ERROR cannot borrow immutable
    |            ^^ cannot borrow as mutable
 
index ce39776252b6ae25871f750044a33cc415fc3d71..3c7e92e2bc9ca6acbb7448a07debdef3d8a62043 100644 (file)
@@ -1,9 +1,9 @@
 error[E0384]: cannot assign twice to immutable variable `b`
-  --> $DIR/issue-45199.rs:19:5
+  --> $DIR/issue-45199.rs:20:5
    |
 LL |     let b: Box<isize>;
-   |         - consider changing this to `mut b`
-LL |     //[mir]~^ NOTE consider changing this to `mut b`
+   |         - help: make this binding mutable: `mut b`
+...
 LL |     b = Box::new(1);    //[ast]~ NOTE first assignment
    |     - first assignment to `b`
 LL |                         //[mir]~^ NOTE first assignment
@@ -11,23 +11,23 @@ LL |     b = Box::new(2);    //[ast]~ ERROR cannot assign twice to immutable var
    |     ^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `b`
-  --> $DIR/issue-45199.rs:29:5
+  --> $DIR/issue-45199.rs:31:5
    |
 LL |     let b = Box::new(1);    //[ast]~ NOTE first assignment
    |         -
    |         |
    |         first assignment to `b`
-   |         consider changing this to `mut b`
+   |         help: make this binding mutable: `mut b`
 ...
 LL |     b = Box::new(2);        //[ast]~ ERROR cannot assign twice to immutable variable
    |     ^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign to immutable argument `b`
-  --> $DIR/issue-45199.rs:37:5
+  --> $DIR/issue-45199.rs:40:5
    |
 LL | fn test_args(b: Box<i32>) {  //[ast]~ NOTE first assignment
-   |              - consider changing this to `mut b`
-LL |                                 //[mir]~^ NOTE consider changing this to `mut b`
+   |              - help: make this binding mutable: `mut b`
+...
 LL |     b = Box::new(2);            //[ast]~ ERROR cannot assign twice to immutable variable
    |     ^ cannot assign to immutable argument
 
index ff8f78b5116351cb11bd075f518d0a87d65873f4..cf8ceacca57ae54febb587f9a9a02194621fc26a 100644 (file)
@@ -1,5 +1,5 @@
 error[E0384]: cannot assign twice to immutable variable `b`
-  --> $DIR/issue-45199.rs:19:5
+  --> $DIR/issue-45199.rs:20:5
    |
 LL |     b = Box::new(1);    //[ast]~ NOTE first assignment
    |     --------------- first assignment to `b`
@@ -8,7 +8,7 @@ LL |     b = Box::new(2);    //[ast]~ ERROR cannot assign twice to immutable var
    |     ^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `b`
-  --> $DIR/issue-45199.rs:29:5
+  --> $DIR/issue-45199.rs:31:5
    |
 LL |     let b = Box::new(1);    //[ast]~ NOTE first assignment
    |         - first assignment to `b`
@@ -17,11 +17,11 @@ LL |     b = Box::new(2);        //[ast]~ ERROR cannot assign twice to immutable
    |     ^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `b`
-  --> $DIR/issue-45199.rs:37:5
+  --> $DIR/issue-45199.rs:40:5
    |
 LL | fn test_args(b: Box<i32>) {  //[ast]~ NOTE first assignment
    |              - first assignment to `b`
-LL |                                 //[mir]~^ NOTE consider changing this to `mut b`
+...
 LL |     b = Box::new(2);            //[ast]~ ERROR cannot assign twice to immutable variable
    |     ^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
 
index ce39776252b6ae25871f750044a33cc415fc3d71..3c7e92e2bc9ca6acbb7448a07debdef3d8a62043 100644 (file)
@@ -1,9 +1,9 @@
 error[E0384]: cannot assign twice to immutable variable `b`
-  --> $DIR/issue-45199.rs:19:5
+  --> $DIR/issue-45199.rs:20:5
    |
 LL |     let b: Box<isize>;
-   |         - consider changing this to `mut b`
-LL |     //[mir]~^ NOTE consider changing this to `mut b`
+   |         - help: make this binding mutable: `mut b`
+...
 LL |     b = Box::new(1);    //[ast]~ NOTE first assignment
    |     - first assignment to `b`
 LL |                         //[mir]~^ NOTE first assignment
@@ -11,23 +11,23 @@ LL |     b = Box::new(2);    //[ast]~ ERROR cannot assign twice to immutable var
    |     ^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `b`
-  --> $DIR/issue-45199.rs:29:5
+  --> $DIR/issue-45199.rs:31:5
    |
 LL |     let b = Box::new(1);    //[ast]~ NOTE first assignment
    |         -
    |         |
    |         first assignment to `b`
-   |         consider changing this to `mut b`
+   |         help: make this binding mutable: `mut b`
 ...
 LL |     b = Box::new(2);        //[ast]~ ERROR cannot assign twice to immutable variable
    |     ^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign to immutable argument `b`
-  --> $DIR/issue-45199.rs:37:5
+  --> $DIR/issue-45199.rs:40:5
    |
 LL | fn test_args(b: Box<i32>) {  //[ast]~ NOTE first assignment
-   |              - consider changing this to `mut b`
-LL |                                 //[mir]~^ NOTE consider changing this to `mut b`
+   |              - help: make this binding mutable: `mut b`
+...
 LL |     b = Box::new(2);            //[ast]~ ERROR cannot assign twice to immutable variable
    |     ^ cannot assign to immutable argument
 
index 61e19ffc0d293b7db19a27131db79728eddaecb5..90a4960cb63f71635334a26ceaac877f4b55cbc2 100644 (file)
@@ -13,7 +13,8 @@
 
 fn test_drop_replace() {
     let b: Box<isize>;
-    //[mir]~^ NOTE consider changing this to `mut b`
+    //[mir]~^ HELP make this binding mutable
+    //[mir]~| SUGGESTION mut b
     b = Box::new(1);    //[ast]~ NOTE first assignment
                         //[mir]~^ NOTE first assignment
     b = Box::new(2);    //[ast]~ ERROR cannot assign twice to immutable variable
@@ -25,7 +26,8 @@ fn test_drop_replace() {
 fn test_call() {
     let b = Box::new(1);    //[ast]~ NOTE first assignment
                             //[mir]~^ NOTE first assignment
-                            //[mir]~| NOTE consider changing this to `mut b`
+                            //[mir]~| HELP make this binding mutable
+                            //[mir]~| SUGGESTION mut b
     b = Box::new(2);        //[ast]~ ERROR cannot assign twice to immutable variable
                             //[mir]~^ ERROR cannot assign twice to immutable variable `b`
                             //[ast]~| NOTE cannot assign twice to immutable
@@ -33,7 +35,8 @@ fn test_call() {
 }
 
 fn test_args(b: Box<i32>) {  //[ast]~ NOTE first assignment
-                                //[mir]~^ NOTE consider changing this to `mut b`
+                                //[mir]~^ HELP make this binding mutable
+                                //[mir]~| SUGGESTION mut b
     b = Box::new(2);            //[ast]~ ERROR cannot assign twice to immutable variable
                                 //[mir]~^ ERROR cannot assign to immutable argument `b`
                                 //[ast]~| NOTE cannot assign twice to immutable
index c43cc12ca0229d187c51a91061a8189e8b9c6d54..f26392e82acbd59094a90c8bae12443848c91f67 100644 (file)
@@ -10,6 +10,7 @@
 
 // edition:2018
 // aux-build:issue-52489.rs
+// compile-flags:--extern issue_52489
 
 use issue_52489;
 //~^ ERROR use of unstable library feature 'issue_52489_unstable'
index 5b38a0789ad7fd78a1ba4e547f350fdeaeb622e7..b8c41d82643e838927cba76e8480796184b2ce6f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: use of unstable library feature 'issue_52489_unstable'
-  --> $DIR/issue-52489.rs:14:5
+  --> $DIR/issue-52489.rs:15:5
    |
 LL | use issue_52489;
    |     ^^^^^^^^^^^
diff --git a/src/test/ui/issues/issue-53675-a-test-called-panic.rs b/src/test/ui/issues/issue-53675-a-test-called-panic.rs
new file mode 100644 (file)
index 0000000..8a35b36
--- /dev/null
@@ -0,0 +1,36 @@
+// rust-lang/rust#53675: At one point the compiler errored when a test
+// named `panic` used the `assert!` macro in expression position.
+
+// compile-pass
+// compile-flags: --test
+
+mod in_expression_position {
+    #[test]
+    fn panic() {
+        assert!(true)
+    }
+}
+
+mod in_statement_position {
+    #[test]
+    fn panic() {
+        assert!(true);
+    }
+}
+
+mod what_if_we_use_panic_directly_in_expr {
+    #[test]
+    #[should_panic]
+    fn panic() {
+        panic!("in expr")
+    }
+}
+
+
+mod what_if_we_use_panic_directly_in_stmt {
+    #[test]
+    #[should_panic]
+    fn panic() {
+        panic!("in stmt");
+    }
+}
index 611eea533b29692be2a21a946767ea2409e6da45..5ea18af7c68001cb39c15ff7874b4ce8eb02c510 100644 (file)
@@ -2,7 +2,7 @@ error[E0594]: cannot assign to field `_iter.node` of immutable binding
   --> $DIR/issue-5500-1.rs:22:5
    |
 LL |       let _iter = TrieMapIterator{node: &a};
-   |           ----- consider changing this to `mut _iter`
+   |           ----- help: make this binding mutable: `mut _iter`
 LL | /     _iter.node = & //[ast]~ ERROR cannot assign to field `_iter.node` of immutable binding
 LL | |                    //[mir]~^ ERROR cannot assign to field `_iter.node` of immutable binding (Ast)
 LL | |                    // MIR doesn't generate an error because the code isn't reachable. This is OK
index 465485e5e290c58afdfab0c5781a2b35371b78b0..5cb72794961d1ae24e6b28cde055eb2bdc8b9a70 100644 (file)
@@ -2,7 +2,7 @@ error[E0594]: cannot assign to field `_iter.node` of immutable binding (Ast)
   --> $DIR/issue-5500-1.rs:22:5
    |
 LL |       let _iter = TrieMapIterator{node: &a};
-   |           ----- consider changing this to `mut _iter`
+   |           ----- help: make this binding mutable: `mut _iter`
 LL | /     _iter.node = & //[ast]~ ERROR cannot assign to field `_iter.node` of immutable binding
 LL | |                    //[mir]~^ ERROR cannot assign to field `_iter.node` of immutable binding (Ast)
 LL | |                    // MIR doesn't generate an error because the code isn't reachable. This is OK
index b50fc68bed6be587c24f1d525165931dfd543fb6..ad5b8fb64342d0aa469250f99c62101a2f24531f 100644 (file)
@@ -10,4 +10,5 @@
 
 fn main() {
     let Self = 22; //~ ERROR cannot find unit struct/variant or constant `Self` in this scope
+        //~^ ERROR `Self` struct constructors are unstable (see issue #51994)
 }
index c47f4aeabefd81f2cdcf53cceaef157cc3fdbefe..296269819f8364507501645c8b26ca448ea72c42 100644 (file)
@@ -4,6 +4,15 @@ error[E0531]: cannot find unit struct/variant or constant `Self` in this scope
 LL |     let Self = 22; //~ ERROR cannot find unit struct/variant or constant `Self` in this scope
    |         ^^^^ not found in this scope
 
-error: aborting due to previous error
+error[E0658]: `Self` struct constructors are unstable (see issue #51994)
+  --> $DIR/keyword-self-as-identifier.rs:12:9
+   |
+LL |     let Self = 22; //~ ERROR cannot find unit struct/variant or constant `Self` in this scope
+   |         ^^^^
+   |
+   = help: add #![feature(self_struct_ctor)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0531`.
+Some errors occurred: E0531, E0658.
+For more information about an error, try `rustc --explain E0531`.
index a485c80f3b0d81e0913d2fa36d4f5d13da57555f..a8a1b33c925bcf7fdef038de7661bd1780df260c 100644 (file)
@@ -9,6 +9,7 @@ LL |     //~^ ERROR borrowed value does not live long enough
 LL |     x.use_mut();
    |     - borrow later used here
    |
+   = note: consider using a `let` binding to create a longer lived value
    = 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
index 749b576092967e9553dd99172c1fe7a1a7b1fa60..1a5f788e1436816a5113c878771e50d5a0373eeb 100644 (file)
@@ -12,7 +12,7 @@ error[E0384]: cannot assign to immutable argument `y`
   --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:5
    |
 LL | fn foo(mut x: Ref, y: &u32) {
-   |                    - consider changing this to `mut y`
+   |                    - help: make this binding mutable: `mut y`
 LL |     y = x.b; //~ ERROR lifetime mismatch
    |     ^^^^^^^ cannot assign to immutable argument
 
index 0620235371a3928126d3037102188b5002ed61b6..fd3ae53d6eda5a9fd28296827ffcdf2b2e8732a2 100644 (file)
@@ -33,7 +33,7 @@ error[E0384]: cannot assign twice to immutable variable `x` (Mir)
   --> $DIR/liveness-assign-imm-local-notes.rs:23:9
    |
 LL |     let x;
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 ...
 LL |         x = 2;
    |         ----- first assignment to `x`
@@ -44,7 +44,7 @@ error[E0384]: cannot assign twice to immutable variable `x` (Mir)
   --> $DIR/liveness-assign-imm-local-notes.rs:35:13
    |
 LL |         let x;
-   |             - consider changing this to `mut x`
+   |             - help: make this binding mutable: `mut x`
 ...
 LL |             x = 2;
    |             ----- first assignment to `x`
@@ -55,7 +55,7 @@ error[E0384]: cannot assign twice to immutable variable `x` (Mir)
   --> $DIR/liveness-assign-imm-local-notes.rs:45:13
    |
 LL |     let x;
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 ...
 LL |             x = 1;      //~ ERROR (Ast) [E0384]
    |             ^^^^^ cannot assign twice to immutable variable
@@ -64,7 +64,7 @@ error[E0384]: cannot assign twice to immutable variable `x` (Mir)
   --> $DIR/liveness-assign-imm-local-notes.rs:48:13
    |
 LL |     let x;
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 ...
 LL |             x = 1;      //~ ERROR (Ast) [E0384]
    |             ----- first assignment to `x`
diff --git a/src/test/ui/lint/issue-54099-camel-case-underscore-types.rs b/src/test/ui/lint/issue-54099-camel-case-underscore-types.rs
new file mode 100644 (file)
index 0000000..e4be1ed
--- /dev/null
@@ -0,0 +1,14 @@
+// compile-pass
+
+#![forbid(non_camel_case_types)]
+#![allow(dead_code)]
+
+// None of the following types should generate a warning
+struct _X {}
+struct __X {}
+struct __ {}
+struct X_ {}
+struct X__ {}
+struct X___ {}
+
+fn main() { }
index 5dcdf3a863f879accf87179314344c0a3e415394..2f0b6c57d55d088b007b5fa7664a9d78a6e5d434 100644 (file)
@@ -43,8 +43,6 @@ struct foo7 {
     bar: isize,
 }
 
-type __ = isize; //~ ERROR type `__` should have a camel case name such as `CamelCase`
-
 struct X86_64;
 
 struct X86__64; //~ ERROR type `X86__64` should have a camel case name such as `X86_64`
index 85610dc7fa3799ac7c508a0c8f7c44c2c00af766..05834a66cd051114b07f2af0df429932342dfda3 100644 (file)
@@ -60,29 +60,23 @@ error: type parameter `ty` should have a camel case name such as `Ty`
 LL | fn f<ty>(_: ty) {} //~ ERROR type parameter `ty` should have a camel case name such as `Ty`
    |      ^^
 
-error: type `__` should have a camel case name such as `CamelCase`
-  --> $DIR/lint-non-camel-case-types.rs:46:1
-   |
-LL | type __ = isize; //~ ERROR type `__` should have a camel case name such as `CamelCase`
-   | ^^^^^^^^^^^^^^^^
-
 error: type `X86__64` should have a camel case name such as `X86_64`
-  --> $DIR/lint-non-camel-case-types.rs:50:1
+  --> $DIR/lint-non-camel-case-types.rs:48:1
    |
 LL | struct X86__64; //~ ERROR type `X86__64` should have a camel case name such as `X86_64`
    | ^^^^^^^^^^^^^^^
 
 error: type `Abc_123` should have a camel case name such as `Abc123`
-  --> $DIR/lint-non-camel-case-types.rs:52:1
+  --> $DIR/lint-non-camel-case-types.rs:50:1
    |
 LL | struct Abc_123; //~ ERROR type `Abc_123` should have a camel case name such as `Abc123`
    | ^^^^^^^^^^^^^^^
 
 error: type `A1_b2_c3` should have a camel case name such as `A1B2C3`
-  --> $DIR/lint-non-camel-case-types.rs:54:1
+  --> $DIR/lint-non-camel-case-types.rs:52:1
    |
 LL | struct A1_b2_c3; //~ ERROR type `A1_b2_c3` should have a camel case name such as `A1B2C3`
    | ^^^^^^^^^^^^^^^^
 
-error: aborting due to 12 previous errors
+error: aborting due to 11 previous errors
 
index 58a76bd2cf385e463d2924a438acf5000f30db5d..b23225adbb4a0de61882189d14cdf2efcb80f19b 100644 (file)
@@ -1,8 +1,8 @@
 error[E0384]: cannot assign twice to immutable variable `v`
-  --> $DIR/liveness-assign-imm-local-in-loop.rs:18:9
+  --> $DIR/liveness-assign-imm-local-in-loop.rs:19:9
    |
 LL |     let v: isize;
-   |         - consider changing this to `mut v`
+   |         - help: make this binding mutable: `mut v`
 ...
 LL |         v = 1; //[ast]~ ERROR cannot assign twice to immutable variable
    |         ^^^^^ cannot assign twice to immutable variable
index 54419fd5b256cbbabd4f3fc8d6a6d9da11f3db31..54135ca78eaa8b3f4f52f7d09a4b71225bdf901e 100644 (file)
@@ -1,5 +1,5 @@
 error[E0384]: cannot assign twice to immutable variable `v`
-  --> $DIR/liveness-assign-imm-local-in-loop.rs:18:9
+  --> $DIR/liveness-assign-imm-local-in-loop.rs:19:9
    |
 LL |         v = 1; //[ast]~ ERROR cannot assign twice to immutable variable
    |         ^^^^^ cannot assign twice to immutable variable
index 58a76bd2cf385e463d2924a438acf5000f30db5d..b23225adbb4a0de61882189d14cdf2efcb80f19b 100644 (file)
@@ -1,8 +1,8 @@
 error[E0384]: cannot assign twice to immutable variable `v`
-  --> $DIR/liveness-assign-imm-local-in-loop.rs:18:9
+  --> $DIR/liveness-assign-imm-local-in-loop.rs:19:9
    |
 LL |     let v: isize;
-   |         - consider changing this to `mut v`
+   |         - help: make this binding mutable: `mut v`
 ...
 LL |         v = 1; //[ast]~ ERROR cannot assign twice to immutable variable
    |         ^^^^^ cannot assign twice to immutable variable
index 7bc3680ca772343b51bafa75f343847445487c0d..6f44d67e823dde94587447b0a802b31af7c8a238 100644 (file)
@@ -13,7 +13,8 @@
 
 fn test() {
     let v: isize;
-    //[mir]~^ NOTE consider changing this to `mut v`
+    //[mir]~^ HELP make this binding mutable
+    //[mir]~| SUGGESTION mut v
     loop {
         v = 1; //[ast]~ ERROR cannot assign twice to immutable variable
                //[mir]~^ ERROR cannot assign twice to immutable variable `v`
index 091547ed1228a85fbb709a5de7fbd04ebc163f68..3dabbcb816b01408d59101a494198aedf6ef7db3 100644 (file)
@@ -1,9 +1,9 @@
 error[E0384]: cannot assign twice to immutable variable `v`
-  --> $DIR/liveness-assign-imm-local-in-op-eq.rs:19:5
+  --> $DIR/liveness-assign-imm-local-in-op-eq.rs:20:5
    |
 LL |     let v: isize;
-   |         - consider changing this to `mut v`
-LL |     //[mir]~^ NOTE consider changing this to `mut v`
+   |         - help: make this binding mutable: `mut v`
+...
 LL |     v = 2;  //[ast]~ NOTE first assignment
    |     ----- first assignment to `v`
 LL |             //[mir]~^ NOTE first assignment
index a98c3c29bd2e83cff9daaa5c6927b1277239c883..266fb63c7c775741e85dc008fe79693f103284db 100644 (file)
@@ -1,5 +1,5 @@
 error[E0384]: cannot assign twice to immutable variable `v`
-  --> $DIR/liveness-assign-imm-local-in-op-eq.rs:19:5
+  --> $DIR/liveness-assign-imm-local-in-op-eq.rs:20:5
    |
 LL |     v = 2;  //[ast]~ NOTE first assignment
    |     ----- first assignment to `v`
index 091547ed1228a85fbb709a5de7fbd04ebc163f68..3dabbcb816b01408d59101a494198aedf6ef7db3 100644 (file)
@@ -1,9 +1,9 @@
 error[E0384]: cannot assign twice to immutable variable `v`
-  --> $DIR/liveness-assign-imm-local-in-op-eq.rs:19:5
+  --> $DIR/liveness-assign-imm-local-in-op-eq.rs:20:5
    |
 LL |     let v: isize;
-   |         - consider changing this to `mut v`
-LL |     //[mir]~^ NOTE consider changing this to `mut v`
+   |         - help: make this binding mutable: `mut v`
+...
 LL |     v = 2;  //[ast]~ NOTE first assignment
    |     ----- first assignment to `v`
 LL |             //[mir]~^ NOTE first assignment
index 7812cdd8684f6c773599909581afcb7db2c2498e..f585da8a3a5eaa54dd6530d7ac658b04b8c9580d 100644 (file)
@@ -13,7 +13,8 @@
 
 fn test() {
     let v: isize;
-    //[mir]~^ NOTE consider changing this to `mut v`
+    //[mir]~^ HELP make this binding mutable
+    //[mir]~| SUGGESTION mut v
     v = 2;  //[ast]~ NOTE first assignment
             //[mir]~^ NOTE first assignment
     v += 1; //[ast]~ ERROR cannot assign twice to immutable variable
index e954b1f5e0f8b9b3ee9592fe8ffd62a41017bc17..4a2b3b5d5fe47a350d1be72a8445528d73040637 100644 (file)
@@ -1,11 +1,11 @@
 error[E0384]: cannot assign twice to immutable variable `b`
-  --> $DIR/liveness-assign-imm-local-with-drop.rs:19:5
+  --> $DIR/liveness-assign-imm-local-with-drop.rs:20:5
    |
 LL |     let b = Box::new(1); //[ast]~ NOTE first assignment
    |         -
    |         |
    |         first assignment to `b`
-   |         consider changing this to `mut b`
+   |         help: make this binding mutable: `mut b`
 ...
 LL |     b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable
    |     ^ cannot assign twice to immutable variable
index 6abcf175f488a671abe77a517046a8080b0c3a3e..94799d919ae8c67e06d893f423de69ce52e9b6eb 100644 (file)
@@ -1,5 +1,5 @@
 error[E0384]: cannot assign twice to immutable variable `b`
-  --> $DIR/liveness-assign-imm-local-with-drop.rs:19:5
+  --> $DIR/liveness-assign-imm-local-with-drop.rs:20:5
    |
 LL |     let b = Box::new(1); //[ast]~ NOTE first assignment
    |         - first assignment to `b`
index e954b1f5e0f8b9b3ee9592fe8ffd62a41017bc17..4a2b3b5d5fe47a350d1be72a8445528d73040637 100644 (file)
@@ -1,11 +1,11 @@
 error[E0384]: cannot assign twice to immutable variable `b`
-  --> $DIR/liveness-assign-imm-local-with-drop.rs:19:5
+  --> $DIR/liveness-assign-imm-local-with-drop.rs:20:5
    |
 LL |     let b = Box::new(1); //[ast]~ NOTE first assignment
    |         -
    |         |
    |         first assignment to `b`
-   |         consider changing this to `mut b`
+   |         help: make this binding mutable: `mut b`
 ...
 LL |     b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable
    |     ^ cannot assign twice to immutable variable
index bb61a9037d906c9b80939e26350de5ca426c5b64..c32d2c4bb0f757084beb41c4442b1fe3b3d0a129 100644 (file)
@@ -14,7 +14,8 @@
 fn test() {
     let b = Box::new(1); //[ast]~ NOTE first assignment
                          //[mir]~^ NOTE first assignment
-                         //[mir]~| NOTE consider changing this to `mut b`
+                         //[mir]~| HELP make this binding mutable
+                         //[mir]~| SUGGESTION mut b
     drop(b);
     b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable
                      //[mir]~^ ERROR cannot assign twice to immutable variable `b`
index 70a6ab3edf80318f925113fc30d9679f7ac40fe6..6137c9f5882d5b5fc2b962935fcdd465cae5bfdb 100644 (file)
@@ -1,11 +1,11 @@
 error[E0384]: cannot assign twice to immutable variable `v`
-  --> $DIR/liveness-assign-imm-local-with-init.rs:19:5
+  --> $DIR/liveness-assign-imm-local-with-init.rs:20:5
    |
 LL |     let v: isize = 1; //[ast]~ NOTE first assignment
    |         -
    |         |
    |         first assignment to `v`
-   |         consider changing this to `mut v`
+   |         help: make this binding mutable: `mut v`
 ...
 LL |     v = 2; //[ast]~ ERROR cannot assign twice to immutable variable
    |     ^^^^^ cannot assign twice to immutable variable
index 47c780e83e8c208e4f9c0dcb1396249462d66ab8..d48608684a25be1b9ff73f135100f0ab936c9e2e 100644 (file)
@@ -1,5 +1,5 @@
 error[E0384]: cannot assign twice to immutable variable `v`
-  --> $DIR/liveness-assign-imm-local-with-init.rs:19:5
+  --> $DIR/liveness-assign-imm-local-with-init.rs:20:5
    |
 LL |     let v: isize = 1; //[ast]~ NOTE first assignment
    |         - first assignment to `v`
index 70a6ab3edf80318f925113fc30d9679f7ac40fe6..6137c9f5882d5b5fc2b962935fcdd465cae5bfdb 100644 (file)
@@ -1,11 +1,11 @@
 error[E0384]: cannot assign twice to immutable variable `v`
-  --> $DIR/liveness-assign-imm-local-with-init.rs:19:5
+  --> $DIR/liveness-assign-imm-local-with-init.rs:20:5
    |
 LL |     let v: isize = 1; //[ast]~ NOTE first assignment
    |         -
    |         |
    |         first assignment to `v`
-   |         consider changing this to `mut v`
+   |         help: make this binding mutable: `mut v`
 ...
 LL |     v = 2; //[ast]~ ERROR cannot assign twice to immutable variable
    |     ^^^^^ cannot assign twice to immutable variable
index 672e9fab83743b8bf7b668fa17029850878ace20..158eb7d428cbc8b9ad4d13b801f1532311f2f9fb 100644 (file)
@@ -14,7 +14,8 @@
 fn test() {
     let v: isize = 1; //[ast]~ NOTE first assignment
                       //[mir]~^ NOTE first assignment
-                      //[mir]~| NOTE consider changing this to `mut v`
+                      //[mir]~| HELP make this binding mutable
+                      //[mir]~| SUGGESTION mut v
     v.clone();
     v = 2; //[ast]~ ERROR cannot assign twice to immutable variable
            //[mir]~^ ERROR cannot assign twice to immutable variable `v`
index 5ca5dc647090d91d183d1f2d587cfae013795f80..9f1ffd91518b314c75afda5c1018e042b823f8bf 100644 (file)
@@ -8,14 +8,6 @@ LL |         while true { while true { while true { x = y; x.clone(); } } }
    |
    = note: move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `y`
-  --> $DIR/liveness-move-in-while.rs:18:52
-   |
-LL |         while true { while true { while true { x = y; x.clone(); } } }
-   |                                                    ^ value moved here in previous iteration of loop
-   |
-   = note: move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0382`.
index c706b8f613dd7a78e4c63539b07de81aaead4c2c..597053d625134d831fa6f6c73a2a97ba1d670a51 100644 (file)
@@ -1,16 +1,3 @@
-// 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.
-
-#[derive(inline)] //~ ERROR cannot find derive macro `inline` in this scope
-struct S;
-
 fn main() {
     inline!(); //~ ERROR cannot find macro `inline!` in this scope
 }
index a8edf54d2204851045c74700ca826144a2e3cd96..1772325118174e88fd2c4051f33d1976b0302659 100644 (file)
@@ -1,14 +1,8 @@
-error: cannot find derive macro `inline` in this scope
-  --> $DIR/macro-path-prelude-fail-3.rs:11:10
-   |
-LL | #[derive(inline)] //~ ERROR cannot find derive macro `inline` in this scope
-   |          ^^^^^^
-
 error: cannot find macro `inline!` in this scope
-  --> $DIR/macro-path-prelude-fail-3.rs:15:5
+  --> $DIR/macro-path-prelude-fail-3.rs:2:5
    |
 LL |     inline!(); //~ ERROR cannot find macro `inline!` in this scope
    |     ^^^^^^ help: you could try the macro: `line`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/macros/macro-path-prelude-fail-4.rs b/src/test/ui/macros/macro-path-prelude-fail-4.rs
new file mode 100644 (file)
index 0000000..283427b
--- /dev/null
@@ -0,0 +1,4 @@
+#[derive(inline)] //~ ERROR expected a macro, found built-in attribute
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-path-prelude-fail-4.stderr b/src/test/ui/macros/macro-path-prelude-fail-4.stderr
new file mode 100644 (file)
index 0000000..e354f34
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected a macro, found built-in attribute
+  --> $DIR/macro-path-prelude-fail-4.rs:1:10
+   |
+LL | #[derive(inline)] //~ ERROR expected a macro, found built-in attribute
+   |          ^^^^^^
+
+error: aborting due to previous error
+
index c67095d9ee7596ed332b61b3773b1aa7de4659de..d3ba6fc005ecc38ef331db7700510c3e501fbf71 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `foo` as mutable
   --> $DIR/span-covering-argument-1.rs:15:19
    |
 LL |             let $s = 0;
-   |                 -- consider changing this to `mut $s`
+   |                 -- help: make this binding mutable: `mut $s`
 LL |             *&mut $s = 0;
    |                   ^^ cannot borrow mutably
 ...
diff --git a/src/test/ui/mismatched_types/numeric-literal-cast.rs b/src/test/ui/mismatched_types/numeric-literal-cast.rs
new file mode 100644 (file)
index 0000000..516b2e8
--- /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 foo(_: u16) {}
+fn foo1(_: f64) {}
+fn foo2(_: i32) {}
+
+fn main() {
+    foo(1u8);
+    foo1(2f32);
+    foo2(3i16);
+}
+
diff --git a/src/test/ui/mismatched_types/numeric-literal-cast.stderr b/src/test/ui/mismatched_types/numeric-literal-cast.stderr
new file mode 100644 (file)
index 0000000..e2fe1a0
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-literal-cast.rs:16:9
+   |
+LL |     foo(1u8);
+   |         ^^^ expected u16, found u8
+help: change the type of the numeric literal from `u8` to `u16`
+   |
+LL |     foo(1u16);
+   |         ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-literal-cast.rs:17:10
+   |
+LL |     foo1(2f32);
+   |          ^^^^ expected f64, found f32
+help: change the type of the numeric literal from `f32` to `f64`
+   |
+LL |     foo1(2f64);
+   |          ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-literal-cast.rs:18:10
+   |
+LL |     foo2(3i16);
+   |          ^^^^ expected i32, found i16
+help: change the type of the numeric literal from `i16` to `i32`
+   |
+LL |     foo2(3i32);
+   |          ^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 0df303eed779ad4af22819202008578cfd2cdfb4..8b8414b8f1b740617ef03d85f41aad9ae2084277 100644 (file)
@@ -5,7 +5,7 @@ LL |     let &mut x = foo;
    |              -
    |              |
    |              first assignment to `x`
-   |              consider changing this to `mut x`
+   |              help: make this binding mutable: `mut x`
 LL |     x += 1; //[ast]~ ERROR cannot assign twice to immutable variable
    |     ^^^^^^ cannot assign twice to immutable variable
 
index 0df303eed779ad4af22819202008578cfd2cdfb4..8b8414b8f1b740617ef03d85f41aad9ae2084277 100644 (file)
@@ -5,7 +5,7 @@ LL |     let &mut x = foo;
    |              -
    |              |
    |              first assignment to `x`
-   |              consider changing this to `mut x`
+   |              help: make this binding mutable: `mut x`
 LL |     x += 1; //[ast]~ ERROR cannot assign twice to immutable variable
    |     ^^^^^^ cannot assign twice to immutable variable
 
index 39a1e93d61975545a3bb4766c8c2092c6ecdb79e..9501294a5ab0defe8a06bf92131e320925863f09 100644 (file)
@@ -1,18 +1,18 @@
 error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable
-  --> $DIR/mut-suggestion.rs:21:5
+  --> $DIR/mut-suggestion.rs:22:5
    |
 LL | fn func(arg: S) {
    |         --- help: consider changing this to be mutable: `mut arg`
-LL |     //~^ consider changing this to `mut arg`
+...
 LL |     arg.mutate();
    |     ^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow `local` as mutable, as it is not declared as mutable
-  --> $DIR/mut-suggestion.rs:29:5
+  --> $DIR/mut-suggestion.rs:31:5
    |
 LL |     let local = S;
    |         ----- help: consider changing this to be mutable: `mut local`
-LL |     //~^ consider changing this to `mut local`
+...
 LL |     local.mutate();
    |     ^^^^^ cannot borrow as mutable
 
index 0015c8e5c00a1212731754a71b73af892d25d0e2..af04927c713e9b974fb52d0fc97eaa43caa73f5c 100644 (file)
@@ -17,7 +17,8 @@ fn mutate(&mut self) {
 }
 
 fn func(arg: S) {
-    //~^ consider changing this to `mut arg`
+    //~^ HELP make this binding mutable
+    //~| SUGGESTION mut arg
     arg.mutate();
     //~^ ERROR cannot borrow immutable argument
     //~| cannot borrow mutably
@@ -25,7 +26,8 @@ fn func(arg: S) {
 
 fn main() {
     let local = S;
-    //~^ consider changing this to `mut local`
+    //~^ HELP make this binding mutable
+    //~| SUGGESTION mut local
     local.mutate();
     //~^ ERROR cannot borrow immutable local variable
     //~| cannot borrow mutably
index 4aa964903f59d641553aa87f0b9f44c447ee5751..b4917887630e6f5d7b66a6b9d762ce0b01ffa4e4 100644 (file)
@@ -1,18 +1,18 @@
 error[E0596]: cannot borrow immutable argument `arg` as mutable
-  --> $DIR/mut-suggestion.rs:21:5
+  --> $DIR/mut-suggestion.rs:22:5
    |
 LL | fn func(arg: S) {
-   |         --- consider changing this to `mut arg`
-LL |     //~^ consider changing this to `mut arg`
+   |         --- help: make this binding mutable: `mut arg`
+...
 LL |     arg.mutate();
    |     ^^^ cannot borrow mutably
 
 error[E0596]: cannot borrow immutable local variable `local` as mutable
-  --> $DIR/mut-suggestion.rs:29:5
+  --> $DIR/mut-suggestion.rs:31:5
    |
 LL |     let local = S;
-   |         ----- consider changing this to `mut local`
-LL |     //~^ consider changing this to `mut local`
+   |         ----- help: make this binding mutable: `mut local`
+...
 LL |     local.mutate();
    |     ^^^^^ cannot borrow mutably
 
index 0a4d3a0e96881b73ff0860ced9fb0ef854ab5060..fc12e22815eff449a0a603f1abcd40f1428b3a3d 100644 (file)
@@ -2,7 +2,7 @@ error[E0594]: cannot assign to field `nyan.how_hungry` of immutable binding
   --> $DIR/mutable-class-fields.rs:28:3
    |
 LL |   let nyan : cat = cat(52, 99);
-   |       ---- consider changing this to `mut nyan`
+   |       ---- help: make this binding mutable: `mut nyan`
 LL |   nyan.how_hungry = 0; //[ast]~ ERROR cannot assign
    |   ^^^^^^^^^^^^^^^^^^^ cannot mutably borrow field of immutable binding
 
index 37746a173eb7aa62eba0387bf3180b92aa43c921..8b69c57d3765db1062d7a84d547644a9bca396cb 100644 (file)
@@ -8,6 +8,8 @@ LL |     });
    |       - temporary value only lives until here
 LL |     println!("{:?}", x);
    |                      - borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/issue-52669.rs b/src/test/ui/nll/issue-52669.rs
new file mode 100644 (file)
index 0000000..17a5999
--- /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.
+
+#![feature(nll)]
+
+struct A {
+    b: B,
+}
+
+#[derive(Clone)]
+struct B;
+
+fn foo(_: A) {}
+
+fn bar(mut a: A) -> B {
+    a.b = B;
+    foo(a);
+    a.b.clone()
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-52669.stderr b/src/test/ui/nll/issue-52669.stderr
new file mode 100644 (file)
index 0000000..ca1576f
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0382]: borrow of moved value: `a.b`
+  --> $DIR/issue-52669.rs:25:5
+   |
+LL |     foo(a);
+   |         - value moved here
+LL |     a.b.clone()
+   |     ^^^ value borrowed here after move
+   |
+   = note: move occurs because `a` has type `A`, 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/nll/issue-53807.nll.stderr b/src/test/ui/nll/issue-53807.nll.stderr
new file mode 100644 (file)
index 0000000..0c019a4
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0382]: use of moved value
+  --> $DIR/issue-53807.rs:14:21
+   |
+LL |         if let Some(thing) = maybe {
+   |                     ^^^^^ value moved here in previous iteration of loop
+   |
+   = note: move occurs because value has type `std::vec::Vec<bool>`, 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/nll/issue-53807.rs b/src/test/ui/nll/issue-53807.rs
new file mode 100644 (file)
index 0000000..791dee2
--- /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.
+
+pub fn main(){
+    let maybe = Some(vec![true, true]);
+     loop {
+        if let Some(thing) = maybe {
+        }
+    }
+}
diff --git a/src/test/ui/nll/issue-53807.stderr b/src/test/ui/nll/issue-53807.stderr
new file mode 100644 (file)
index 0000000..7056899
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0382]: use of partially moved value: `maybe`
+  --> $DIR/issue-53807.rs:14:30
+   |
+LL |         if let Some(thing) = maybe {
+   |                     -----    ^^^^^ value used here after move
+   |                     |
+   |                     value moved here
+   |
+   = note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `(maybe as std::prelude::v1::Some).0`
+  --> $DIR/issue-53807.rs:14:21
+   |
+LL |         if let Some(thing) = maybe {
+   |                     ^^^^^ value moved here in previous iteration of loop
+   |
+   = note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/nll/move-subpaths-moves-root.rs b/src/test/ui/nll/move-subpaths-moves-root.rs
new file mode 100644 (file)
index 0000000..7a4e518
--- /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(nll)]
+
+fn main() {
+    let x = (vec![1, 2, 3], );
+    drop(x.0);
+    drop(x);
+}
diff --git a/src/test/ui/nll/move-subpaths-moves-root.stderr b/src/test/ui/nll/move-subpaths-moves-root.stderr
new file mode 100644 (file)
index 0000000..76a1279
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/move-subpaths-moves-root.rs:16:10
+   |
+LL |     drop(x.0);
+   |          --- value moved here
+LL |     drop(x);
+   |          ^ value used here after move
+   |
+   = note: move occurs because `x.0` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
index a58d5ad6fa72317ca2a30a19dbc44daf05bf75d0..31dba18338ab72846451952b881ae8a9dc253ce5 100644 (file)
@@ -11,19 +11,6 @@ LL |     assert_eq!((*arc_v)[2], 3);
    |
    = note: move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
 
-error[E0382]: borrow of moved value: `arc_v`
-  --> $DIR/no-capture-arc.rs:26:23
-   |
-LL |     thread::spawn(move|| {
-   |                   ------ value moved into closure here
-LL |         assert_eq!((*arc_v)[3], 4);
-   |                      ----- variable moved due to use in closure
-...
-LL |     println!("{:?}", *arc_v);
-   |                       ^^^^^ value borrowed here after move
-   |
-   = note: move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0382`.
index 902affc80462c85002dd8bbd3ab43547fc1f73dd..bffcae6e2f50a472ab12532ceaa337d77b5a2549 100644 (file)
@@ -11,19 +11,6 @@ LL |     assert_eq!((*arc_v)[2], 3); //~ ERROR use of moved value: `arc_v`
    |
    = note: move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
 
-error[E0382]: borrow of moved value: `arc_v`
-  --> $DIR/no-reuse-move-arc.rs:24:23
-   |
-LL |     thread::spawn(move|| {
-   |                   ------ value moved into closure here
-LL |         assert_eq!((*arc_v)[3], 4);
-   |                      ----- variable moved due to use in closure
-...
-LL |     println!("{:?}", *arc_v); //~ ERROR use of moved value: `arc_v`
-   |                       ^^^^^ value borrowed here after move
-   |
-   = note: move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0382`.
index 43f51447ac46e05647cf73b39558053088ef9998..fabfba94878f520548230e5db2c5b80fd808f10c 100644 (file)
@@ -1,8 +1,8 @@
-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
+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
+   | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this attribute with `#[panic_handler]`
    |
 note: lint level defined here
   --> $DIR/panic-implementation-deprecated.rs:13:9
index 54b1a6fa970b70c37d8ac97baa0727b58a610a8e..aa744a3ae8a7482e18a1c757dafaac5e7fc1f225 100644 (file)
@@ -8,6 +8,7 @@ LL |         x = &id(3); //~ ERROR borrowed value does not live long enough
 LL |         assert_eq!(*x, 3);
    |         ------------------ borrow later used here
    |
+   = note: consider using a `let` binding to create a longer lived value
    = 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
index 0dbca07b771d747837a20eb94bcd67a51ce09a58..1f3588dd3ca4ece95b999e942258fdedd44368e6 100644 (file)
 struct S(u8, u16);
 type A = S;
 
-impl S {
-    fn f() {
-        let s = Self(0, 1); //~ ERROR expected function
-        match s {
-            Self(..) => {} //~ ERROR expected tuple struct/variant
-        }
-    }
-}
-
 fn main() {
     let s = A(0, 1); //~ ERROR expected function
     match s {
index cdac6277bcfa3b4d57f8d4b92e12e2673c248d84..ad2ae4acb8b0e387cf4bab04f5cef24a79ddaf8f 100644 (file)
@@ -1,21 +1,5 @@
-error[E0423]: expected function, found self type `Self`
-  --> $DIR/tuple-struct-alias.rs:16:17
-   |
-LL |         let s = Self(0, 1); //~ ERROR expected function
-   |                 ^^^^ not a function
-   |
-   = note: can't use `Self` as a constructor, you must use the implemented struct
-
-error[E0532]: expected tuple struct/variant, found self type `Self`
-  --> $DIR/tuple-struct-alias.rs:18:13
-   |
-LL |             Self(..) => {} //~ ERROR expected tuple struct/variant
-   |             ^^^^ not a tuple struct/variant
-   |
-   = note: can't use `Self` as a constructor, you must use the implemented struct
-
 error[E0423]: expected function, found type alias `A`
-  --> $DIR/tuple-struct-alias.rs:24:13
+  --> $DIR/tuple-struct-alias.rs:15:13
    |
 LL |     let s = A(0, 1); //~ ERROR expected function
    |             ^ did you mean `S`?
@@ -23,14 +7,14 @@ LL |     let s = A(0, 1); //~ ERROR expected function
    = note: can't use a type alias as a constructor
 
 error[E0532]: expected tuple struct/variant, found type alias `A`
-  --> $DIR/tuple-struct-alias.rs:26:9
+  --> $DIR/tuple-struct-alias.rs:17:9
    |
 LL |         A(..) => {} //~ ERROR expected tuple struct/variant
    |         ^ did you mean `S`?
    |
    = note: can't use a type alias as a constructor
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 Some errors occurred: E0423, E0532.
 For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs
new file mode 100644 (file)
index 0000000..2f3c094
--- /dev/null
@@ -0,0 +1,21 @@
+// Adaptation of existing ui test (from way back in
+// rust-lang/rust#2329), that starts passing with this feature in
+// place.
+
+// compile-pass
+
+#![feature(nll)]
+#![feature(bind_by_move_pattern_guards)]
+
+use std::sync::mpsc::channel;
+
+fn main() {
+    let (tx, rx) = channel();
+    let x = Some(rx);
+    tx.send(false);
+    match x {
+        Some(z) if z.recv().unwrap() => { panic!() },
+        Some(z) => { assert!(!z.recv().unwrap()); },
+        None => panic!()
+    }
+}
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr
new file mode 100644 (file)
index 0000000..4c17ce2
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0008]: cannot bind by-move into a pattern guard
+  --> $DIR/feature-gate.rs:33:16
+   |
+LL |         A { a: v } if *v == 42 => v,
+   |                ^ moves value into pattern guard
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0008`.
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr
new file mode 100644 (file)
index 0000000..4bde9b0
--- /dev/null
@@ -0,0 +1,10 @@
+error: compilation successful
+  --> $DIR/feature-gate.rs:42:1
+   |
+LL | / fn main() {
+LL | |     foo(107)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr
new file mode 100644 (file)
index 0000000..4bde9b0
--- /dev/null
@@ -0,0 +1,10 @@
+error: compilation successful
+  --> $DIR/feature-gate.rs:42:1
+   |
+LL | / fn main() {
+LL | |     foo(107)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr
new file mode 100644 (file)
index 0000000..4bde9b0
--- /dev/null
@@ -0,0 +1,10 @@
+error: compilation successful
+  --> $DIR/feature-gate.rs:42:1
+   |
+LL | / fn main() {
+LL | |     foo(107)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr
new file mode 100644 (file)
index 0000000..4c17ce2
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0008]: cannot bind by-move into a pattern guard
+  --> $DIR/feature-gate.rs:33:16
+   |
+LL |         A { a: v } if *v == 42 => v,
+   |                ^ moves value into pattern guard
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0008`.
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs
new file mode 100644 (file)
index 0000000..f6df4d0
--- /dev/null
@@ -0,0 +1,47 @@
+// Check that pattern-guards with move-bound variables is only allowed
+// with the appropriate set of feature gates. (Note that we require
+// the code to opt into MIR-borrowck in *some* way before the feature
+// will work; we use the revision system here to enumerate a number of
+// ways that opt-in could occur.)
+
+// gate-test-bind_by_move_pattern_guards
+
+// revisions: no_gate gate_and_2015 gate_and_2018 gate_and_znll gate_and_feature_nll
+
+// (We're already testing NLL behavior quite explicitly, no need for compare-mode=nll.)
+// ignore-compare-mode-nll
+
+#![feature(rustc_attrs)]
+
+#![cfg_attr(gate_and_2015, feature(bind_by_move_pattern_guards))]
+#![cfg_attr(gate_and_2018, feature(bind_by_move_pattern_guards))]
+#![cfg_attr(gate_and_znll, feature(bind_by_move_pattern_guards))]
+#![cfg_attr(gate_and_feature_nll, feature(bind_by_move_pattern_guards))]
+
+#![cfg_attr(gate_and_feature_nll, feature(nll))]
+
+//[gate_and_2015] edition:2015
+//[gate_and_2018] edition:2018
+//[gate_and_znll] compile-flags: -Z borrowck=mir
+
+struct A { a: Box<i32> }
+
+fn foo(n: i32) {
+    let x = A { a: Box::new(n) };
+    let _y = match x {
+
+        A { a: v } if *v == 42 => v,
+        //[no_gate]~^ ERROR cannot bind by-move into a pattern guard
+        //[gate_and_2015]~^^ ERROR cannot bind by-move into a pattern guard
+
+        _ => Box::new(0)
+    };
+}
+
+#[rustc_error]
+fn main() {
+    foo(107)
+}
+//[gate_and_2018]~^^^ ERROR compilation successful
+//[gate_and_znll]~^^^^ ERROR compilation successful
+//[gate_and_feature_nll]~^^^^^ ERROR compilation successful
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs
new file mode 100644 (file)
index 0000000..9a9d11c
--- /dev/null
@@ -0,0 +1,40 @@
+#![feature(nll)]
+#![feature(bind_by_move_pattern_guards)]
+
+// compile-pass
+
+struct A { a: Box<i32> }
+
+impl A {
+    fn get(&self) -> i32 { *self.a }
+}
+
+fn foo(n: i32) {
+    let x = A { a: Box::new(n) };
+    let y = match x {
+        A { a: v } if *v == 42 => v,
+        _ => Box::new(0),
+    };
+}
+
+fn bar(n: i32) {
+    let x = A { a: Box::new(n) };
+    let y = match x {
+        A { a: v } if x.get() == 42 => v,
+        _ => Box::new(0),
+    };
+}
+
+fn baz(n: i32) {
+    let x = A { a: Box::new(n) };
+    let y = match x {
+        A { a: v } if *v.clone() == 42 => v,
+        _ => Box::new(0),
+    };
+}
+
+fn main() {
+    foo(107);
+    bar(107);
+    baz(107);
+}
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs
new file mode 100644 (file)
index 0000000..0fec6b2
--- /dev/null
@@ -0,0 +1,16 @@
+#![feature(nll)]
+#![feature(bind_by_move_pattern_guards)]
+
+enum VecWrapper { A(Vec<i32>) }
+
+fn foo(x: VecWrapper) -> usize {
+    match x {
+        VecWrapper::A(v) if { drop(v); false } => 1,
+        //~^ ERROR cannot move out of borrowed content
+        VecWrapper::A(v) => v.len()
+    }
+}
+
+fn main() {
+    foo(VecWrapper::A(vec![107]));
+}
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
new file mode 100644 (file)
index 0000000..502006e
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/rfc-reject-double-move-across-arms.rs:8:36
+   |
+LL |         VecWrapper::A(v) if { drop(v); false } => 1,
+   |                                    ^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs
new file mode 100644 (file)
index 0000000..396bfc1
--- /dev/null
@@ -0,0 +1,17 @@
+#![feature(nll)]
+#![feature(bind_by_move_pattern_guards)]
+
+struct A { a: Box<i32> }
+
+fn foo(n: i32) {
+    let x = A { a: Box::new(n) };
+    let _y = match x {
+        A { a: v } if { drop(v); true } => v,
+        //~^ ERROR cannot move out of borrowed content
+        _ => Box::new(0),
+    };
+}
+
+fn main() {
+    foo(107);
+}
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
new file mode 100644 (file)
index 0000000..dd8f42f
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/rfc-reject-double-move-in-first-arm.rs:9:30
+   |
+LL |         A { a: v } if { drop(v); true } => v,
+   |                              ^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs b/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs
new file mode 100644 (file)
index 0000000..499a322
--- /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.
+
+// edition:2018
+
+// Tests that `meta` is whitelisted, even if the crate doesn't exist
+// yet (i.e. it causes a different error than `not-whitelisted.rs`).
+use meta; //~ ERROR can't find crate for `meta`
+
+fn main() {}
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr
new file mode 100644 (file)
index 0000000..b8a9b54
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0463]: can't find crate for `meta`
+  --> $DIR/meta.rs:15:5
+   |
+LL | use meta; //~ ERROR can't find crate for `meta`
+   |     ^^^^ can't find crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0463`.
index 826bf675bd699899da0638a33c1b7b8edd8ba420..a259266420a1de9e6fa89e50a40f0cd03de4401b 100644 (file)
@@ -10,6 +10,6 @@
 
 // edition:2018
 
-use xcrate::S; //~ ERROR can't find crate for `xcrate`
+use xcrate::S; //~ ERROR unresolved import `xcrate`
 
 fn main() {}
index 27a69ec1b1fafaa2d445fc5c500a65de13ae25f6..1a8ceec5dac068ddd8a4bffbc2f7e16686910ce4 100644 (file)
@@ -1,9 +1,9 @@
-error[E0463]: can't find crate for `xcrate`
+error[E0432]: unresolved import `xcrate`
   --> $DIR/non-existent-1.rs:13:5
    |
-LL | use xcrate::S; //~ ERROR can't find crate for `xcrate`
-   |     ^^^^^^ can't find crate
+LL | use xcrate::S; //~ ERROR unresolved import `xcrate`
+   |     ^^^^^^ Could not find `xcrate` in `{{root}}`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0463`.
+For more information about this error, try `rustc --explain E0432`.
index 053bf92f4d196a2aa0108d5062a397a4ff995ea5..41adb974f21760a685fdc23069cbbb7c09fccfd0 100644 (file)
@@ -11,5 +11,6 @@
 // edition:2018
 
 fn main() {
-    let s = ::xcrate::S; //~ ERROR can't find crate for `xcrate`
+    let s = ::xcrate::S;
+    //~^ ERROR failed to resolve. Could not find `xcrate` in `{{root}}`
 }
index eb96d5f05d7a6eb47e11964fa2bba62def0e557a..b46576b01436784650a47092c6e8762f338dedcb 100644 (file)
@@ -1,9 +1,9 @@
-error[E0463]: can't find crate for `xcrate`
+error[E0433]: failed to resolve. Could not find `xcrate` in `{{root}}`
   --> $DIR/non-existent-2.rs:14:15
    |
-LL |     let s = ::xcrate::S; //~ ERROR can't find crate for `xcrate`
-   |               ^^^^^^ can't find crate
+LL |     let s = ::xcrate::S;
+   |               ^^^^^^ Could not find `xcrate` in `{{root}}`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0463`.
+For more information about this error, try `rustc --explain E0433`.
index 1b9e5a75e83071f82bc8f0bccc067d6f85bf030d..0cbeb8cf50fe3db7704a73d4dea113d0797e518b 100644 (file)
@@ -10,6 +10,6 @@
 
 // edition:2018
 
-use ycrate; //~ ERROR can't find crate for `ycrate`
+use ycrate; //~ ERROR unresolved import `ycrate`
 
 fn main() {}
index 434bde79a8322659654267d0ddf75b0b6af1b392..31486e14bd2a88da47b8d794b1323ff3cd4f68ac 100644 (file)
@@ -1,9 +1,9 @@
-error[E0463]: can't find crate for `ycrate`
+error[E0432]: unresolved import `ycrate`
   --> $DIR/non-existent-3.rs:13:5
    |
-LL | use ycrate; //~ ERROR can't find crate for `ycrate`
-   |     ^^^^^^ can't find crate
+LL | use ycrate; //~ ERROR unresolved import `ycrate`
+   |     ^^^^^^ no `ycrate` external crate
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0463`.
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs
new file mode 100644 (file)
index 0000000..f95961d
--- /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.
+
+// edition:2018
+
+// Tests that arbitrary crates (other than `core`, `std` and `meta`)
+// aren't allowed without `--extern`, even if they're in the sysroot.
+use alloc; //~ ERROR unresolved import `alloc`
+use test; //~ ERROR unresolved import `test`
+use proc_macro; //~ ERROR unresolved import `proc_macro`
+
+fn main() {}
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr
new file mode 100644 (file)
index 0000000..0865bd6
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0432]: unresolved import `alloc`
+  --> $DIR/not-whitelisted.rs:15:5
+   |
+LL | use alloc; //~ ERROR unresolved import `alloc`
+   |     ^^^^^ no `alloc` external crate
+
+error[E0432]: unresolved import `test`
+  --> $DIR/not-whitelisted.rs:16:5
+   |
+LL | use test; //~ ERROR unresolved import `test`
+   |     ^^^^ no `test` external crate
+
+error[E0432]: unresolved import `proc_macro`
+  --> $DIR/not-whitelisted.rs:17:5
+   |
+LL | use proc_macro; //~ ERROR unresolved import `proc_macro`
+   |     ^^^^^^^^^^ no `proc_macro` external crate
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
index 69fc4b4f7f8fcb1dc41e82caf0132b888ac8421a..b5b1485f662c58393f1d9ce73fb3f6a3491b9081 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:xcrate.rs
+// compile-flags:--extern xcrate
 // edition:2018
 
 use crate; //~ ERROR crate root imports need to be explicitly named: `use crate as name;`
index cfb1a0ac39ac27de3bccaf19e9657625f9b5e720..b49291b9c0c61a0195299e097335c3abba2456f9 100644 (file)
@@ -1,17 +1,17 @@
 error: crate root imports need to be explicitly named: `use crate as name;`
-  --> $DIR/single-segment.rs:14:5
+  --> $DIR/single-segment.rs:15:5
    |
 LL | use crate; //~ ERROR crate root imports need to be explicitly named: `use crate as name;`
    |     ^^^^^
 
 error: cannot glob-import all possible crates
-  --> $DIR/single-segment.rs:15:5
+  --> $DIR/single-segment.rs:16:5
    |
 LL | use *; //~ ERROR cannot glob-import all possible crates
    |     ^
 
 error[E0423]: expected value, found module `xcrate`
-  --> $DIR/single-segment.rs:18:13
+  --> $DIR/single-segment.rs:19:13
    |
 LL |     let s = ::xcrate; //~ ERROR expected value, found module `xcrate`
    |             ^^^^^^^^ not a value
index 7eba02ed444bb89417aaad0c4c58da9605e32b81..c17e74c547c1840c0bfefb04b339d88d72693266 100644 (file)
@@ -10,6 +10,6 @@
 
 #![feature(extern_in_paths)]
 
-use extern::xcrate::S; //~ ERROR can't find crate for `xcrate`
+use extern::xcrate::S; //~ ERROR unresolved import `extern::xcrate`
 
 fn main() {}
index c25698c395e1c00dbb9ea4b794c02010082ba8f5..55b8b6255073ea6506c7fb90d2893879c8e38467 100644 (file)
@@ -1,9 +1,9 @@
-error[E0463]: can't find crate for `xcrate`
+error[E0432]: unresolved import `extern::xcrate`
   --> $DIR/non-existent-1.rs:13:13
    |
-LL | use extern::xcrate::S; //~ ERROR can't find crate for `xcrate`
-   |             ^^^^^^ can't find crate
+LL | use extern::xcrate::S; //~ ERROR unresolved import `extern::xcrate`
+   |             ^^^^^^ Could not find `xcrate` in `extern`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0463`.
+For more information about this error, try `rustc --explain E0432`.
index 4d09a05253ec2c338abbdd9381c86d68a3a0e699..128ecf41a303df83d2cd3fe1f315629a3cd9259a 100644 (file)
@@ -11,5 +11,6 @@
 #![feature(extern_in_paths)]
 
 fn main() {
-    let s = extern::xcrate::S; //~ ERROR can't find crate for `xcrate`
+    let s = extern::xcrate::S;
+    //~^ ERROR failed to resolve. Could not find `xcrate` in `extern`
 }
index b7ca8890c19420f63d6a0641e601ff9f1cf437ad..7fbe50a92022b23661d1203295fddb2d56e00588 100644 (file)
@@ -1,9 +1,9 @@
-error[E0463]: can't find crate for `xcrate`
+error[E0433]: failed to resolve. Could not find `xcrate` in `extern`
   --> $DIR/non-existent-2.rs:14:21
    |
-LL |     let s = extern::xcrate::S; //~ ERROR can't find crate for `xcrate`
-   |                     ^^^^^^ can't find crate
+LL |     let s = extern::xcrate::S;
+   |                     ^^^^^^ Could not find `xcrate` in `extern`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0463`.
+For more information about this error, try `rustc --explain E0433`.
index 402d294b2e324d98dea61b313dc39b72409cc941..350cca70487f3bc1332ef609e1fa2939f57fda9b 100644 (file)
@@ -10,6 +10,6 @@
 
 #![feature(extern_in_paths)]
 
-use extern::ycrate; //~ ERROR can't find crate for `ycrate`
+use extern::ycrate; //~ ERROR unresolved import `extern::ycrate`
 
 fn main() {}
index fbea89ae93a97b8d4b8b451bb4c2a47c38d9d38b..0a49d1721695bd364bf059810f8857916c09b58c 100644 (file)
@@ -1,9 +1,9 @@
-error[E0463]: can't find crate for `ycrate`
-  --> $DIR/non-existent-3.rs:13:13
+error[E0432]: unresolved import `extern::ycrate`
+  --> $DIR/non-existent-3.rs:13:5
    |
-LL | use extern::ycrate; //~ ERROR can't find crate for `ycrate`
-   |             ^^^^^^ can't find crate
+LL | use extern::ycrate; //~ ERROR unresolved import `extern::ycrate`
+   |     ^^^^^^^^^^^^^^ no `ycrate` external crate
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0463`.
+For more information about this error, try `rustc --explain E0432`.
index 017844a0252e274218fd12275d665839b59d5993..ea4488637031e316bf1135998992928107922fb2 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:xcrate.rs
+// compile-flags:--extern xcrate
 
 #![feature(extern_in_paths)]
 
index 8b1dd89fe3ca71e4c958aaad22c93a7415425dda..033bedb3b938b20ee746c9b54a0ff4e65dc3e81c 100644 (file)
@@ -1,17 +1,17 @@
 error: cannot glob-import all possible crates
-  --> $DIR/single-segment.rs:17:5
+  --> $DIR/single-segment.rs:18:5
    |
 LL | use extern::*; //~ ERROR cannot glob-import all possible crates
    |     ^^^^^^^^^
 
 error[E0432]: unresolved import `extern`
-  --> $DIR/single-segment.rs:15:5
+  --> $DIR/single-segment.rs:16:5
    |
 LL | use extern; //~ ERROR unresolved import `extern`
    |     ^^^^^^ no `extern` in the root
 
 error[E0423]: expected value, found module `extern::xcrate`
-  --> $DIR/single-segment.rs:20:13
+  --> $DIR/single-segment.rs:21:13
    |
 LL |     let s = extern::xcrate; //~ ERROR expected value, found module `extern::xcrate`
    |             ^^^^^^^^^^^^^^ not a value
index c17a4796555c736492915bd80d4758c299176f7b..3d727e2ad1b56139fb8792246a902e817ae422c9 100644 (file)
@@ -10,6 +10,7 @@
 
 // run-pass
 // aux-build:some_crate.rs
+// compile-flags:--extern some_crate
 // edition:2018
 
 mod foo {
index d1003bb2908af4d20888195c1e4e6fef66f5268b..20705dc38e1aec1413a285769e51980abc4b7016 100644 (file)
@@ -10,6 +10,7 @@
 
 // run-pass
 // aux-build:some_crate.rs
+// compile-flags:--extern some_crate
 // edition:2018
 
 use some_crate as some_name;
index 3d828ba60d3cdd6b4a890b89bba35a2ac564f671..00cb5ac103a9130709ffe15916ae8085cf9b2de0 100644 (file)
@@ -10,6 +10,7 @@
 
 // run-pass
 // aux-build:png2.rs
+// compile-flags:--extern png2
 // edition:2018
 
 mod png {
index 9186974f0a37853a50070cbc276be36c12a52021..f674123aac7a2684c73d3f183c46cf9b01a40d41 100644 (file)
@@ -62,30 +62,30 @@ fn assert_ne() {
 
 #[test]
 fn cfg() {
-    cfg!(pants);
-    cfg!(pants,);
-    cfg!(pants = "pants");
-    cfg!(pants = "pants",);
-    cfg!(all(pants));
-    cfg!(all(pants),);
-    cfg!(all(pants,));
-    cfg!(all(pants,),);
+    let _ = cfg!(pants);
+    let _ = cfg!(pants,);
+    let _ = cfg!(pants = "pants");
+    let _ = cfg!(pants = "pants",);
+    let _ = cfg!(all(pants));
+    let _ = cfg!(all(pants),);
+    let _ = cfg!(all(pants,));
+    let _ = cfg!(all(pants,),);
 }
 
 #[test]
 fn column() {
-    column!();
+    let _ = column!();
 }
 
 // compile_error! is in a companion to this test in compile-fail
 
 #[test]
 fn concat() {
-    concat!();
-    concat!("hello");
-    concat!("hello",);
-    concat!("hello", " world");
-    concat!("hello", " world",);
+    let _ = concat!();
+    let _ = concat!("hello");
+    let _ = concat!("hello",);
+    let _ = concat!("hello", " world");
+    let _ = concat!("hello", " world",);
 }
 
 #[test]
@@ -131,10 +131,10 @@ fn debug_assert_ne() {
 
 #[test]
 fn env() {
-    env!("PATH");
-    env!("PATH",);
-    env!("PATH", "not found");
-    env!("PATH", "not found",);
+    let _ = env!("PATH");
+    let _ = env!("PATH",);
+    let _ = env!("PATH", "not found");
+    let _ = env!("PATH", "not found",);
 }
 
 #[cfg(std)]
@@ -158,58 +158,58 @@ fn eprintln() {
 
 #[test]
 fn file() {
-    file!();
+    let _ = file!();
 }
 
 #[cfg(std)]
 #[test]
 fn format() {
-    format!("hello");
-    format!("hello",);
-    format!("hello {}", "world");
-    format!("hello {}", "world",);
+    let _ = format!("hello");
+    let _ = format!("hello",);
+    let _ = format!("hello {}", "world");
+    let _ = format!("hello {}", "world",);
 }
 
 #[test]
 fn format_args() {
-    format_args!("hello");
-    format_args!("hello",);
-    format_args!("hello {}", "world");
-    format_args!("hello {}", "world",);
+    let _ = format_args!("hello");
+    let _ = format_args!("hello",);
+    let _ = format_args!("hello {}", "world");
+    let _ = format_args!("hello {}", "world",);
 }
 
 #[test]
 fn include() {
-    include!("auxiliary/macro-comma-support.rs");
-    include!("auxiliary/macro-comma-support.rs",);
+    let _ = include!("auxiliary/macro-comma-support.rs");
+    let _ = include!("auxiliary/macro-comma-support.rs",);
 }
 
 #[test]
 fn include_bytes() {
-    include_bytes!("auxiliary/macro-comma-support.rs");
-    include_bytes!("auxiliary/macro-comma-support.rs",);
+    let _ = include_bytes!("auxiliary/macro-comma-support.rs");
+    let _ = include_bytes!("auxiliary/macro-comma-support.rs",);
 }
 
 #[test]
 fn include_str() {
-    include_str!("auxiliary/macro-comma-support.rs");
-    include_str!("auxiliary/macro-comma-support.rs",);
+    let _ = include_str!("auxiliary/macro-comma-support.rs");
+    let _ = include_str!("auxiliary/macro-comma-support.rs",);
 }
 
 #[test]
 fn line() {
-    line!();
+    let _ = line!();
 }
 
 #[test]
 fn module_path() {
-    module_path!();
+    let _ = module_path!();
 }
 
 #[test]
 fn option_env() {
-    option_env!("PATH");
-    option_env!("PATH",);
+    let _ = option_env!("PATH");
+    let _ = option_env!("PATH",);
 }
 
 #[test]
@@ -309,10 +309,10 @@ fn unreachable() {
 #[test]
 fn vec() {
     let _: Vec<()> = vec![];
-    vec![0];
-    vec![0,];
-    vec![0, 1];
-    vec![0, 1,];
+    let _ = vec![0];
+    let _ = vec![0,];
+    let _ = vec![0, 1];
+    let _ = vec![0, 1,];
 }
 
 // give a test body access to a fmt::Formatter, which seems
@@ -340,21 +340,21 @@ fn fmt(&self, $f: &mut fmt::Formatter) -> fmt::Result {
 test_with_formatter! {
     #[test]
     fn write(f: &mut fmt::Formatter) {
-        write!(f, "hello");
-        write!(f, "hello",);
-        write!(f, "hello {}", "world");
-        write!(f, "hello {}", "world",);
+        let _ = write!(f, "hello");
+        let _ = write!(f, "hello",);
+        let _ = write!(f, "hello {}", "world");
+        let _ = write!(f, "hello {}", "world",);
     }
 }
 
 test_with_formatter! {
     #[test]
     fn writeln(f: &mut fmt::Formatter) {
-        writeln!(f);
-        writeln!(f,);
-        writeln!(f, "hello");
-        writeln!(f, "hello",);
-        writeln!(f, "hello {}", "world");
-        writeln!(f, "hello {}", "world",);
+        let _ = writeln!(f);
+        let _ = writeln!(f,);
+        let _ = writeln!(f, "hello");
+        let _ = writeln!(f, "hello",);
+        let _ = writeln!(f, "hello {}", "world");
+        let _ = writeln!(f, "hello {}", "world",);
     }
 }
index c5a356d979d314072ba1dd2e551971c3ce08e3e4..b13602297a4af35a3934c24b7cb5e8447f0f1b2c 100644 (file)
@@ -10,6 +10,7 @@
 
 // run-pass
 // aux-build:xcrate.rs
+// compile-flags:--extern xcrate
 // edition:2018
 
 use xcrate::Z;
index 3d31c2d3a4dd105f753d799c97b1d9c0e4297384..0d84ccc3d322155f352a679da655a317fd808ace 100644 (file)
@@ -10,6 +10,7 @@
 
 // run-pass
 // aux-build:xcrate.rs
+// compile-flags:--extern xcrate
 
 #![feature(extern_in_paths)]
 
diff --git a/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/whitelisted.rs b/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/whitelisted.rs
new file mode 100644 (file)
index 0000000..dfd9fbd
--- /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.
+
+// run-pass
+// edition:2018
+
+// Tests that `core` and `std` are always available.
+use core::iter;
+use std::io;
+// FIXME(eddyb) Add a `meta` crate to the distribution.
+// use meta;
+
+fn main() {
+    for _ in iter::once(()) {
+        io::stdout();
+    }
+}
diff --git a/src/test/ui/run-pass/rfcs/rfc-2302-self-struct-ctor.rs b/src/test/ui/run-pass/rfcs/rfc-2302-self-struct-ctor.rs
new file mode 100644 (file)
index 0000000..156e240
--- /dev/null
@@ -0,0 +1,129 @@
+// run-pass
+
+#![feature(self_struct_ctor)]
+
+#![allow(dead_code)]
+
+use std::fmt::Display;
+
+struct ST1(i32, i32);
+
+impl ST1 {
+    fn new() -> Self {
+        ST1(0, 1)
+    }
+
+    fn ctor() -> Self {
+        Self(1,2)         // Self as a constructor
+    }
+
+    fn pattern(self) {
+        match self {
+            Self(x, y) => println!("{} {}", x, y), // Self as a pattern
+        }
+    }
+}
+
+struct ST2<T>(T); // With type parameter
+
+impl<T> ST2<T> where T: Display {
+
+    fn ctor(v: T) -> Self {
+        Self(v)
+    }
+
+    fn pattern(&self) {
+        match self {
+            Self(ref v) => println!("{}", v),
+        }
+    }
+}
+
+struct ST3<'a>(&'a i32); // With lifetime parameter
+
+impl<'a> ST3<'a> {
+
+    fn ctor(v: &'a i32) -> Self {
+        Self(v)
+    }
+
+    fn pattern(self) {
+        let Self(ref v) = self;
+        println!("{}", v);
+    }
+}
+
+struct ST4(usize);
+
+impl ST4 {
+    fn map(opt: Option<usize>) -> Option<Self> {
+        opt.map(Self)     // use `Self` as a function passed somewhere
+    }
+}
+
+struct ST5;               // unit struct
+
+impl ST5 {
+    fn ctor() -> Self {
+        Self               // `Self` as a unit struct value
+    }
+
+    fn pattern(self) -> Self {
+        match self {
+            Self => Self,   // `Self` as a unit struct value for matching
+        }
+    }
+}
+
+struct ST6(i32);
+type T = ST6;
+impl T {
+    fn ctor() -> Self {
+        ST6(1)
+    }
+
+    fn type_alias(self) {
+        let Self(_x) = match self { Self(x) => Self(x) };
+        let _opt: Option<Self> = Some(0).map(Self);
+    }
+}
+
+struct ST7<T1, T2>(T1, T2);
+
+impl ST7<i32, usize> {
+
+    fn ctor() -> Self {
+        Self(1, 2)
+    }
+
+    fn pattern(self) -> Self {
+        match self {
+            Self(x, y) => Self(x, y),
+        }
+    }
+}
+
+fn main() {
+    let v1 = ST1::ctor();
+    v1.pattern();
+
+    let v2 = ST2::ctor(10);
+    v2.pattern();
+
+    let local = 42;
+    let v3 = ST3::ctor(&local);
+    v3.pattern();
+
+    let v4 = Some(1usize);
+    let _ = ST4::map(v4);
+
+    let v5 = ST5::ctor();
+    v5.pattern();
+
+    let v6 = ST6::ctor();
+    v6.type_alias();
+
+    let v7 = ST7::<i32, usize>::ctor();
+    let r = v7.pattern();
+    println!("{} {}", r.0, r.1)
+}
index 1fe5d8abbe2e78966f25b2921dbdc6fe3b6392c4..1aaa1e70726c88295a352c3959f50b23bbd4fe37 100644 (file)
@@ -59,4 +59,12 @@ fn main() {
     bar::io::stdout();
     bar::std();
     bar::std!();
+
+    {
+        // Test that having `io` in a module scope and a non-module
+        // scope is allowed, when both resolve to the same definition.
+        use std::io;
+        use io::stdout;
+        stdout();
+    }
 }
index d8e68e9be972341305b611455a30e5d39f6d68a4..7d997fe493a7bc01b53ccf4c4f2d48e0d6e9a974 100644 (file)
@@ -33,4 +33,12 @@ fn main() {
     Foo(());
     std_io::stdout();
     local_io(());
+
+    {
+        // Test that having `std_io` in a module scope and a non-module
+        // scope is allowed, when both resolve to the same definition.
+        use ::std::io as std_io;
+        use std_io::stdout;
+        stdout();
+    }
 }
index fc81ab08f624d480ee5491354e3cfb911653f98a..36a837509c50cb3ea79ef3e3d98407b5d1ca0823 100644 (file)
@@ -10,6 +10,7 @@
 
 // aux-build:edition-lint-paths.rs
 // run-rustfix
+// compile-flags:--extern edition_lint_paths
 // edition:2018
 
 // The "normal case". Ideally we would remove the `extern crate` here,
index 72751f2080cc9b2d28f31ab179189438679dc9a1..9daa4145630b7b1d89f8f73444a90d266ab11243 100644 (file)
@@ -10,6 +10,7 @@
 
 // aux-build:edition-lint-paths.rs
 // run-rustfix
+// compile-flags:--extern edition_lint_paths
 // edition:2018
 
 // The "normal case". Ideally we would remove the `extern crate` here,
index 0ecfd4e4a2ca3076523bffe3ebf6a840dd5fcda9..b3afa2bd1d59289bb9c7ffd23a23829793436a7b 100644 (file)
@@ -1,18 +1,18 @@
 error: unused extern crate
-  --> $DIR/extern-crate-idiomatic-in-2018.rs:21:1
+  --> $DIR/extern-crate-idiomatic-in-2018.rs:22:1
    |
 LL | extern crate edition_lint_paths;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
    |
 note: lint level defined here
-  --> $DIR/extern-crate-idiomatic-in-2018.rs:18:9
+  --> $DIR/extern-crate-idiomatic-in-2018.rs:19:9
    |
 LL | #![deny(rust_2018_idioms)]
    |         ^^^^^^^^^^^^^^^^
    = note: #[deny(unused_extern_crates)] implied by #[deny(rust_2018_idioms)]
 
 error: `extern crate` is not idiomatic in the new edition
-  --> $DIR/extern-crate-idiomatic-in-2018.rs:24:1
+  --> $DIR/extern-crate-idiomatic-in-2018.rs:25:1
    |
 LL | extern crate edition_lint_paths as bar;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
index a874a62220298c7f81c4c051f09aa2daffcd714d..0be1f2cc72bb0eb9b1c4f22c43cc87e07e16db0d 100644 (file)
@@ -10,6 +10,7 @@
 
 // run-pass
 // aux-build:edition-lint-paths.rs
+// compile-flags:--extern edition_lint_paths
 // run-rustfix
 
 // The "normal case". Ideally we would remove the `extern crate` here,
index a874a62220298c7f81c4c051f09aa2daffcd714d..0be1f2cc72bb0eb9b1c4f22c43cc87e07e16db0d 100644 (file)
@@ -10,6 +10,7 @@
 
 // run-pass
 // aux-build:edition-lint-paths.rs
+// compile-flags:--extern edition_lint_paths
 // run-rustfix
 
 // The "normal case". Ideally we would remove the `extern crate` here,
diff --git a/src/test/ui/rust-2018/issue-54006.rs b/src/test/ui/rust-2018/issue-54006.rs
new file mode 100644 (file)
index 0000000..ee58d24
--- /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.
+
+// edition:2018
+
+#![no_std]
+#![crate_type = "lib"]
+
+use alloc::vec;
+//~^ ERROR unresolved import `alloc`
+
+pub fn foo() {
+    let mut xs = vec![];
+    //~^ ERROR cannot determine resolution for the macro `vec`
+    xs.push(0);
+}
diff --git a/src/test/ui/rust-2018/issue-54006.stderr b/src/test/ui/rust-2018/issue-54006.stderr
new file mode 100644 (file)
index 0000000..1183dc9
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0432]: unresolved import `alloc`
+  --> $DIR/issue-54006.rs:16:5
+   |
+LL | use alloc::vec;
+   |     ^^^^^ Could not find `alloc` in `{{root}}`
+
+error: cannot determine resolution for the macro `vec`
+  --> $DIR/issue-54006.rs:20:18
+   |
+LL |     let mut xs = vec![];
+   |                  ^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
index 995be4290b887cae86e11acdea047b44b76caa50..cdae815b200d5d19ea266391697aa446f0a2a7c5 100644 (file)
@@ -12,6 +12,7 @@
 // edition:2018
 // compile-pass
 // aux-build:remove-extern-crate.rs
+// compile-flags:--extern remove_extern_crate
 
 #![warn(rust_2018_idioms)]
 
index 3ab97a7428704d2304de0b72cad8154ceafd83e4..4984da802c05bc98dd047a7e5b5a4aa5ae89b573 100644 (file)
@@ -12,6 +12,7 @@
 // edition:2018
 // compile-pass
 // aux-build:remove-extern-crate.rs
+// compile-flags:--extern remove_extern_crate
 
 #![warn(rust_2018_idioms)]
 
index 752a7b180de138b6c31d7107ee165a5806649a72..064a853625f743e7a95d5d9e3fca049fc05e7b23 100644 (file)
@@ -1,24 +1,24 @@
 warning: unused extern crate
-  --> $DIR/remove-extern-crate.rs:18:1
+  --> $DIR/remove-extern-crate.rs:19:1
    |
 LL | extern crate core;
    | ^^^^^^^^^^^^^^^^^^ help: remove it
    |
 note: lint level defined here
-  --> $DIR/remove-extern-crate.rs:16:9
+  --> $DIR/remove-extern-crate.rs:17: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
+  --> $DIR/remove-extern-crate.rs:20: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
+  --> $DIR/remove-extern-crate.rs:33:5
    |
 LL |     extern crate core;
    |     ^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs
new file mode 100644 (file)
index 0000000..1f19a05
--- /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.
+
+// edition:2018
+
+// Dummy import to introduce `uniform_paths` canaries.
+use std;
+
+// fn version() -> &'static str {""}
+
+mod foo {
+    // Error wasn't reported, despite `version` being commented out above.
+    use crate::version; //~ ERROR unresolved import `crate::version`
+
+    fn bar() {
+        version();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr
new file mode 100644 (file)
index 0000000..6dcc451
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `crate::version`
+  --> $DIR/issue-54253.rs:20:9
+   |
+LL |     use crate::version; //~ ERROR unresolved import `crate::version`
+   |         ^^^^^^^^^^^^^^ no `version` in the root
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rust-2018/uniform-paths/issue-54253.rs b/src/test/ui/rust-2018/uniform-paths/issue-54253.rs
new file mode 100644 (file)
index 0000000..7ca5c9e
--- /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.
+
+// edition:2018
+
+#![feature(uniform_paths)]
+
+// Dummy import to introduce `uniform_paths` canaries.
+use std;
+
+// fn version() -> &'static str {""}
+
+mod foo {
+    // Error wasn't reported, despite `version` being commented out above.
+    use crate::version; //~ ERROR unresolved import `crate::version`
+
+    fn bar() {
+        version();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/issue-54253.stderr b/src/test/ui/rust-2018/uniform-paths/issue-54253.stderr
new file mode 100644 (file)
index 0000000..0016e21
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `crate::version`
+  --> $DIR/issue-54253.rs:22:9
+   |
+LL |     use crate::version; //~ ERROR unresolved import `crate::version`
+   |         ^^^^^^^^^^^^^^ no `version` in the root
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
index 8331ae0b307d95ebd222685fdf2147be7be246c8..bbaf060ca87e3b226afb54ba50076c9458f6c3a2 100644 (file)
 pub fn main() {
     let Self = 5;
     //~^ ERROR cannot find unit struct/variant or constant `Self` in this scope
+    //~^^ ERROR `Self` struct constructors are unstable (see issue #51994)
 
     match 15 {
         Self => (),
         //~^ ERROR cannot find unit struct/variant or constant `Self` in this scope
+        //~^^ ERROR `Self` struct constructors are unstable (see issue #51994)
         Foo { x: Self } => (),
         //~^ ERROR cannot find unit struct/variant or constant `Self` in this scope
+        //~^^ ERROR `Self` struct constructors are unstable (see issue #51994)
     }
 }
index 972e5bdddc6733493e530b2b1015c11bbac8336b..82529974d0e37a4f74b01b4bd5c78c514e480a0b 100644 (file)
@@ -11,18 +11,42 @@ LL |     let Self = 5;
    |         ^^^^ not found in this scope
 
 error[E0531]: cannot find unit struct/variant or constant `Self` in this scope
-  --> $DIR/self_type_keyword-2.rs:18:9
+  --> $DIR/self_type_keyword-2.rs:19:9
    |
 LL |         Self => (),
    |         ^^^^ not found in this scope
 
 error[E0531]: cannot find unit struct/variant or constant `Self` in this scope
-  --> $DIR/self_type_keyword-2.rs:20:18
+  --> $DIR/self_type_keyword-2.rs:22:18
    |
 LL |         Foo { x: Self } => (),
    |                  ^^^^ not found in this scope
 
-error: aborting due to 4 previous errors
+error[E0658]: `Self` struct constructors are unstable (see issue #51994)
+  --> $DIR/self_type_keyword-2.rs:14:9
+   |
+LL |     let Self = 5;
+   |         ^^^^
+   |
+   = help: add #![feature(self_struct_ctor)] to the crate attributes to enable
+
+error[E0658]: `Self` struct constructors are unstable (see issue #51994)
+  --> $DIR/self_type_keyword-2.rs:19:9
+   |
+LL |         Self => (),
+   |         ^^^^
+   |
+   = help: add #![feature(self_struct_ctor)] to the crate attributes to enable
+
+error[E0658]: `Self` struct constructors are unstable (see issue #51994)
+  --> $DIR/self_type_keyword-2.rs:22:18
+   |
+LL |         Foo { x: Self } => (),
+   |                  ^^^^
+   |
+   = help: add #![feature(self_struct_ctor)] to the crate attributes to enable
+
+error: aborting due to 7 previous errors
 
-Some errors occurred: E0432, E0531.
+Some errors occurred: E0432, E0531, E0658.
 For more information about an error, try `rustc --explain E0432`.
index 01c0603256c15123c86d19c92c0edf72a3ff88c1..d91ff6964237b2c65e5c116ec9b02b5463707b12 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable argument `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:63:24
    |
 LL | fn deref_mut_field1(x: Own<Point>) {
-   |                     - consider changing this to `mut x`
+   |                     - help: make this binding mutable: `mut x`
 LL |     let __isize = &mut x.y; //~ ERROR cannot borrow
    |                        ^ cannot borrow mutably
 
@@ -28,7 +28,7 @@ error[E0596]: cannot borrow immutable argument `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:98:5
    |
 LL | fn assign_field1<'a>(x: Own<Point>) {
-   |                      - consider changing this to `mut x`
+   |                      - help: make this binding mutable: `mut x`
 LL |     x.y = 3; //~ ERROR cannot borrow
    |     ^ cannot borrow mutably
 
@@ -54,7 +54,7 @@ error[E0596]: cannot borrow immutable argument `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:119:5
    |
 LL | fn deref_mut_method1(x: Own<Point>) {
-   |                      - consider changing this to `mut x`
+   |                      - help: make this binding mutable: `mut x`
 LL |     x.set(0, 0); //~ ERROR cannot borrow
    |     ^ cannot borrow mutably
 
@@ -70,7 +70,7 @@ error[E0596]: cannot borrow immutable argument `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:139:6
    |
 LL | fn assign_method1<'a>(x: Own<Point>) {
-   |                       - consider changing this to `mut x`
+   |                       - help: make this binding mutable: `mut x`
 LL |     *x.y_mut() = 3; //~ ERROR cannot borrow
    |      ^ cannot borrow mutably
 
index 3a28ef36d05937ecd98420e8d1ca4e9f872d77e7..62be8e0f73e30a842d5a86ba9b967614708ccd72 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable argument `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:39:25
    |
 LL | fn deref_mut1(x: Own<isize>) {
-   |               - consider changing this to `mut x`
+   |               - help: make this binding mutable: `mut x`
 LL |     let __isize = &mut *x; //~ ERROR cannot borrow
    |                         ^ cannot borrow mutably
 
@@ -18,7 +18,7 @@ error[E0596]: cannot borrow immutable argument `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:59:6
    |
 LL | fn assign1<'a>(x: Own<isize>) {
-   |                - consider changing this to `mut x`
+   |                - help: make this binding mutable: `mut x`
 LL |     *x = 3; //~ ERROR cannot borrow
    |      ^ cannot borrow mutably
 
index 79cfee2d01fd565b541b6eff7949b00cd53f0380..001eba4b039b1e39486624d277127ea553dd96d3 100644 (file)
@@ -8,6 +8,8 @@ LL |     v3.push(&id('x'));           // statement 6
 ...
 LL |     (v1, v2, v3, /* v4 is above. */ v5).use_ref();
    |              -- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
 
 error[E0597]: borrowed value does not live long enough
   --> $DIR/borrowck-let-suggestion-suffixes.rs:38:18
@@ -19,6 +21,8 @@ LL |         v4.push(&id('y'));
 ...
 LL |         v4.use_ref();
    |         -- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
 
 error[E0597]: borrowed value does not live long enough
   --> $DIR/borrowck-let-suggestion-suffixes.rs:49:14
@@ -30,6 +34,8 @@ LL |     v5.push(&id('z'));
 ...
 LL |     (v1, v2, v3, /* v4 is above. */ v5).use_ref();
    |                                     -- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
 
 error: aborting due to 3 previous errors
 
index 5bc07949a951ca3798baa467ab257a8d74b5f9f2..67ee911b381781a959777f2642ebc961a0a6b98f 100644 (file)
@@ -11,7 +11,7 @@ error[E0596]: cannot borrow immutable `Box` content `*x` as mutable
   --> $DIR/borrowck-object-mutability.rs:29:5
    |
 LL | fn owned_receiver(x: Box<Foo>) {
-   |                   - consider changing this to `mut x`
+   |                   - help: make this binding mutable: `mut x`
 LL |     x.borrowed();
 LL |     x.borrowed_mut(); //~ ERROR cannot borrow
    |     ^ cannot borrow as mutable
index 171bb3dda66646302a787f33c4faf626e060f796..c565842c2c0020e5ad0ecd9b50b09e1289d53000 100644 (file)
@@ -8,6 +8,8 @@ LL |     }
    |     - temporary value only lives until here
 LL |     println!("{}", *msg);
    |                    ---- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
 
 error: aborting due to previous error
 
index 2f3f6c5efa2ddf2102375745f173f19a3ea81b4e..8dcf486f8301142310ee1a6fa9de04c3a64b3767 100644 (file)
@@ -8,6 +8,8 @@ LL |     ];
 ...
 LL |     for &&x in &v {
    |                -- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
 
 error: aborting due to previous error
 
index 651296dbeaf6a701e7b4f785b702d8f716006a01..3788b5a32849528d07d36def77ca1ef3fd323117 100644 (file)
@@ -8,6 +8,8 @@ LL |     }
    |     - temporary value only lives until here
 LL | }
    | - borrow later used here, when `blah` is dropped
+   |
+   = note: consider using a `let` binding to create a longer lived value
 
 error: aborting due to previous error
 
index aefba8324cf9cf1c28c893428dd8eeb196a5ac16..4a15d8ff455372cbd746da01d526242a1a266818 100644 (file)
@@ -9,6 +9,7 @@ LL |     }
 LL |     y.use_ref();
    |     - borrow later used here
    |
+   = note: consider using a `let` binding to create a longer lived value
    = 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
index 02fbb5f17eeedab695f76bb062446fc1cc5a4842..0ba48545c600be108de0cb626b10bfbfa0f63e0b 100644 (file)
@@ -2,7 +2,7 @@ error[E0595]: closure cannot assign to immutable local variable `x`
   --> $DIR/unboxed-closure-immutable-capture.rs:23:5
    |
 LL |     let x = 0;
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 ...
 LL |     || x = 1; //~ ERROR cannot assign
    |     ^^ cannot borrow mutably
@@ -11,7 +11,7 @@ error[E0595]: closure cannot assign to immutable local variable `x`
   --> $DIR/unboxed-closure-immutable-capture.rs:25:5
    |
 LL |     let x = 0;
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 ...
 LL |     || set(&mut x); //~ ERROR cannot assign
    |     ^^ cannot borrow mutably
@@ -20,7 +20,7 @@ error[E0595]: closure cannot assign to immutable local variable `x`
   --> $DIR/unboxed-closure-immutable-capture.rs:26:5
    |
 LL |     let x = 0;
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 ...
 LL |     || x = 1; //~ ERROR cannot assign
    |     ^^ cannot borrow mutably
@@ -29,7 +29,7 @@ error[E0595]: closure cannot assign to immutable local variable `x`
   --> $DIR/unboxed-closure-immutable-capture.rs:28:5
    |
 LL |     let x = 0;
-   |         - consider changing this to `mut x`
+   |         - help: make this binding mutable: `mut x`
 ...
 LL |     || set(&mut x); //~ ERROR cannot assign
    |     ^^ cannot borrow mutably
index bb2ffcd21b0969ed542c62a4bcb4bc3c25e52aaa..4303b4c2f21b729cd7bfa5434d0d99ef61adcae7 100644 (file)
@@ -2,7 +2,7 @@ error[E0595]: closure cannot assign to immutable local variable `tick1`
   --> $DIR/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs:26:17
    |
 LL |     let tick1 = || {
-   |         ----- consider changing this to `mut tick1`
+   |         ----- help: make this binding mutable: `mut tick1`
 ...
 LL |     let tick2 = || { //~ ERROR closure cannot assign to immutable local variable `tick1`
    |                 ^^ cannot borrow mutably
@@ -11,7 +11,7 @@ error[E0596]: cannot borrow immutable local variable `tick2` as mutable
   --> $DIR/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs:30:5
    |
 LL |     let tick2 = || { //~ ERROR closure cannot assign to immutable local variable `tick1`
-   |         ----- consider changing this to `mut tick2`
+   |         ----- help: make this binding mutable: `mut tick2`
 ...
 LL |     tick2(); //~ ERROR cannot borrow
    |     ^^^^^ cannot borrow mutably
index 22e11b6977c03a22fd21b9065a701c38308021c9..1930a929da1a0c3818d75c97f1d473d0663be6ff 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `tick` as mutable
   --> $DIR/unboxed-closures-infer-fnmut-missing-mut.rs:17:5
    |
 LL |     let tick = || counter += 1;
-   |         ---- consider changing this to `mut tick`
+   |         ---- help: make this binding mutable: `mut tick`
 LL |     tick(); //~ ERROR cannot borrow immutable local variable `tick` as mutable
    |     ^^^^ cannot borrow mutably
 
index f9fd6c21b706c284cc75a773997865d658ff5a94..9515fe502417a15eaf4f68621b8b067c9b69e333 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `tick` as mutable
   --> $DIR/unboxed-closures-infer-fnmut-move-missing-mut.rs:17:5
    |
 LL |     let tick = move || counter += 1;
-   |         ---- consider changing this to `mut tick`
+   |         ---- help: make this binding mutable: `mut tick`
 LL |     tick(); //~ ERROR cannot borrow immutable local variable `tick` as mutable
    |     ^^^^ cannot borrow mutably
 
index 1164a864b6b46d6706e103268fd24e278049ae5c..c0a7f3f0709bd37c2ceebcd0eae1caadd9ec6d32 100644 (file)
@@ -2,7 +2,7 @@ error[E0595]: closure cannot assign to immutable local variable `n`
   --> $DIR/unboxed-closures-mutate-upvar.rs:24:27
    |
 LL |     let n = 0;
-   |         - consider changing this to `mut n`
+   |         - help: make this binding mutable: `mut n`
 LL |     let mut f = to_fn_mut(|| { //~ ERROR closure cannot assign
    |                           ^^ cannot borrow mutably
 
index 07e1779713909dfac2be07c5417034e4f289d9a2..d1e09521dd8ac21cb465ec70d206b2ef469a46fc 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `v` as mutable
   --> $DIR/writing-to-immutable-vec.rs:14:5
    |
 LL |     let v: Vec<isize> = vec![1, 2, 3];
-   |         - consider changing this to `mut v`
+   |         - help: make this binding mutable: `mut v`
 LL |     v[1] = 4; //~ ERROR cannot borrow immutable local variable `v` as mutable
    |     ^ cannot borrow mutably
 
index fdd830f52c082b83db0dac3e0066c0cf114050d2..125907ad08853b92d35e86aecebcf0f784f348d5 160000 (submodule)
@@ -1 +1 @@
-Subproject commit fdd830f52c082b83db0dac3e0066c0cf114050d2
+Subproject commit 125907ad08853b92d35e86aecebcf0f784f348d5
index e6f1e15676c26fdc7c4713647fe007b26f361a8e..130d803b3243a92f5c2d9230935cba7fa88e263e 160000 (submodule)
@@ -1 +1 @@
-Subproject commit e6f1e15676c26fdc7c4713647fe007b26f361a8e
+Subproject commit 130d803b3243a92f5c2d9230935cba7fa88e263e
index fa922de1e5e1f02b576b7a5aa6ded16935693ec5..2b21611d38a16a775f55ea102d8f442dfc51cf6d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit fa922de1e5e1f02b576b7a5aa6ded16935693ec5
+Subproject commit 2b21611d38a16a775f55ea102d8f442dfc51cf6d