]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #54265 - arielb1:civilize-proc-macros, r=alexcrichton
authorbors <bors@rust-lang.org>
Sat, 22 Sep 2018 11:56:08 +0000 (11:56 +0000)
committerbors <bors@rust-lang.org>
Sat, 22 Sep 2018 11:56:08 +0000 (11:56 +0000)
avoid leaking host details in proc macro metadata decoding

proc macro crates are essentially implemented as dynamic libraries using
a dlopen-based ABI. They are also Rust crates, so they have 2 worlds -
the "host" world in which they are defined, and the "target" world in
which they are used.

For all the "target" world knows, the proc macro crate might not even
be implemented in Rust, so leaks of details from the host to the target
must be avoided for correctness.

Because the "host" DefId space is different from the "target" DefId
space, any leak involving a DefId will have a nonsensical or
out-of-bounds DefKey, and will cause all sorts of crashes.

This PR fixes all leaks I have found in `decoder`. In particular, #54059
was caused by host native libraries leaking into the target, which feels
like it might even be a correctness issue if it doesn't cause an ICE.

Fixes #54059

638 files changed:
.travis.yml
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/test.rs
src/bootstrap/tool.rs
src/doc/README.md [deleted file]
src/doc/book
src/doc/index.md
src/doc/unstable-book/src/language-features/crate-in-paths.md [deleted file]
src/doc/unstable-book/src/language-features/extern-absolute-paths.md [deleted file]
src/liballoc/boxed.rs
src/liballoc/lib.rs
src/liballoc/pin.rs [deleted file]
src/liballoc/rc.rs
src/liballoc/slice.rs
src/liballoc/str.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/option.rs
src/libcore/pin.rs
src/libcore/slice/mod.rs
src/libcore/tests/lib.rs
src/libcore/time.rs
src/librustc/cfg/construct.rs
src/librustc/hir/map/mod.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/middle/expr_use_visitor.rs
src/librustc/middle/liveness.rs
src/librustc/middle/region.rs
src/librustc/mir/traversal.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/auto_trait.rs
src/librustc/traits/codegen/mod.rs
src/librustc/traits/coherence.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/fulfill.rs
src/librustc/traits/mod.rs
src/librustc/traits/object_safety.rs
src/librustc/traits/on_unimplemented.rs
src/librustc/traits/project.rs
src/librustc/traits/query/dropck_outlives.rs
src/librustc/traits/query/normalize.rs
src/librustc/traits/select.rs
src/librustc/traits/specialize/mod.rs
src/librustc/traits/specialize/specialization_graph.rs
src/librustc/traits/structural_impls.rs
src/librustc/traits/util.rs
src/librustc/ty/context.rs
src/librustc/ty/mod.rs
src/librustc/ty/query/mod.rs
src/librustc/ty/query/plumbing.rs
src/librustc/ty/trait_def.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/back/linker.rs
src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
src/librustc_codegen_llvm/debuginfo/metadata.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/librustc_codegen_llvm/mir/analyze.rs
src/librustc_codegen_llvm/mir/mod.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/bitvec.rs [deleted file]
src/librustc_data_structures/graph/implementation/mod.rs
src/librustc_data_structures/indexed_set.rs [deleted file]
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/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_lint/builtin.rs
src/librustc_lint/nonstandard_style.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore_impl.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/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/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/pattern/check_match.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/monomorphize/collector.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/liveness.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/loops.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_target/spec/aarch64_pc_windows_msvc.rs
src/librustc_traits/lib.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/demand.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/librustdoc/Cargo.toml
src/librustdoc/clean/blanket_impl.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/librustdoc/fold.rs
src/librustdoc/html/render.rs
src/librustdoc/lib.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/collect_trait_impls.rs [new file with mode: 0644]
src/librustdoc/passes/mod.rs
src/librustdoc/passes/strip_hidden.rs
src/librustdoc/passes/strip_private.rs
src/librustdoc/test.rs
src/librustdoc/visit_ast.rs
src/librustdoc/visit_lib.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/sys/wasm/cmath.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/llvm
src/rustllvm/llvm-rebuild-trigger
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/run-make-fulldeps/extern-prelude/Makefile
src/test/run-make-fulldeps/extern-prelude/feature-gate.rs [deleted file]
src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile
src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs
src/test/run-pass-fulldeps/custom-derive-partial-eq.stderr [new file with mode: 0644]
src/test/run-pass-fulldeps/derive-no-std-not-supported.rs
src/test/run-pass-fulldeps/deriving-encodable-decodable-box.rs
src/test/run-pass-fulldeps/deriving-encodable-decodable-cell-refcell.rs
src/test/run-pass-fulldeps/deriving-global.rs
src/test/run-pass-fulldeps/deriving-hygiene.rs
src/test/run-pass-fulldeps/dropck_tarena_sound_drop.rs
src/test/run-pass-fulldeps/issue-11881.rs
src/test/run-pass-fulldeps/issue-14021.rs
src/test/run-pass-fulldeps/issue-15149.rs
src/test/run-pass-fulldeps/issue-15924.rs
src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs
src/test/run-pass-fulldeps/issue-24972.rs
src/test/run-pass-fulldeps/issue-2804.rs
src/test/run-pass-fulldeps/issue-4016.rs
src/test/run-pass-fulldeps/issue-40663.rs
src/test/run-pass-fulldeps/macro-crate-multi-decorator-literals.rs
src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs
src/test/run-pass-fulldeps/macro-crate.rs
src/test/run-pass-fulldeps/macro-quote-cond.rs
src/test/run-pass-fulldeps/proc-macro/call-site.rs
src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs
src/test/run-pass-fulldeps/proc-macro/derive-same-struct.rs
src/test/run-pass-fulldeps/proc-macro/derive-same-struct.stdout [new file with mode: 0644]
src/test/run-pass-fulldeps/proc-macro/derive-two-attrs.rs
src/test/run-pass-fulldeps/proc-macro/derive-union.rs
src/test/run-pass-fulldeps/proc-macro/empty-crate.rs
src/test/run-pass-fulldeps/proc-macro/hygiene_example.rs
src/test/run-pass-fulldeps/proc-macro/issue-39889.rs
src/test/run-pass-fulldeps/proc-macro/issue-50061.rs
src/test/run-pass-fulldeps/proc-macro/lifetimes.rs
src/test/run-pass-fulldeps/proc-macro/load-two.rs
src/test/run-pass-fulldeps/proc-macro/smoke.rs
src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs
src/test/run-pass-fulldeps/qquote.rs
src/test/run-pass-fulldeps/quote-tokens.rs
src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs
src/test/run-pass-fulldeps/regions-mock-tcx.rs
src/test/run-pass-fulldeps/rename-directory.rs
src/test/run-pass/abort-on-c-abi.rs
src/test/run-pass/alias-uninit-value.rs
src/test/run-pass/align-with-extern-c-fn.rs
src/test/run-pass/alignment-gep-tup-like-1.rs
src/test/run-pass/alloca-from-derived-tydesc.rs
src/test/run-pass/allocator-alloc-one.rs
src/test/run-pass/asm-in-moved.rs
src/test/run-pass/async-await.rs
src/test/run-pass/atomic-access-bool.rs
src/test/run-pass/atomic-compare_exchange.rs
src/test/run-pass/atomic-print.rs
src/test/run-pass/attr-before-view-item.rs
src/test/run-pass/attr-before-view-item2.rs
src/test/run-pass/attr-mix-new.rs
src/test/run-pass/attr-on-generic-formals.rs
src/test/run-pass/augmented-assignments.rs
src/test/run-pass/auto-instantiate.rs
src/test/run-pass/auto-is-contextual.rs
src/test/run-pass/binops.rs
src/test/run-pass/blind-item-local-shadow.rs
src/test/run-pass/block-arg-call-as.rs
src/test/run-pass/block-expr-precedence.rs
src/test/run-pass/builtin-clone-unwind.rs
src/test/run-pass/builtin-superkinds-in-metadata.rs
src/test/run-pass/builtin-superkinds-phantom-typaram.rs
src/test/run-pass/cast.rs
src/test/run-pass/cell-does-not-clone.rs
src/test/run-pass/check-static-recursion-foreign.rs
src/test/run-pass/cleanup-arm-conditional.rs
src/test/run-pass/cleanup-rvalue-for-scope.rs
src/test/run-pass/cleanup-rvalue-scopes.rs
src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs
src/test/run-pass/clone-with-exterior.rs
src/test/run-pass/close-over-big-then-small-data.rs
src/test/run-pass/collections-const-new.rs
src/test/run-pass/command-before-exec.rs
src/test/run-pass/command-exec.rs
src/test/run-pass/complex.rs
src/test/run-pass/core-run-destroy.rs
src/test/run-pass/crt-static-off-works.rs
src/test/run-pass/crt-static-on-works.rs
src/test/run-pass/default-method-simple.rs
src/test/run-pass/defaults-well-formedness.rs
src/test/run-pass/discriminant_value.rs
src/test/run-pass/diverging-fallback-control-flow.rs
src/test/run-pass/diverging-fallback-method-chain.rs
src/test/run-pass/double-ref.rs
src/test/run-pass/early-ret-binop-add.rs
src/test/run-pass/early-vtbl-resolution.rs
src/test/run-pass/edition-keywords-2015-2015.rs
src/test/run-pass/edition-keywords-2015-2018.rs
src/test/run-pass/edition-keywords-2018-2015.rs
src/test/run-pass/edition-keywords-2018-2018.rs
src/test/run-pass/empty-allocation-rvalue-non-null.rs
src/test/run-pass/env-home-dir.rs
src/test/run-pass/env-null-vars.rs
src/test/run-pass/epoch-gate-feature.rs
src/test/run-pass/estr-uniq.rs
src/test/run-pass/existential_type.rs
src/test/run-pass/explicit-i-suffix.rs
src/test/run-pass/export-glob-imports-target.rs
src/test/run-pass/expr-block.rs
src/test/run-pass/expr-empty-ret.rs
src/test/run-pass/exterior.rs
src/test/run-pass/fixup-deref-mut.rs
src/test/run-pass/format-hygiene.rs
src/test/run-pass/fsu-moves-and-copies.rs
src/test/run-pass/futures-api.rs
src/test/run-pass/guards-not-exhaustive.rs
src/test/run-pass/guards.rs
src/test/run-pass/hashmap-memory.rs
src/test/run-pass/html-literals.rs
src/test/run-pass/if-ret.rs
src/test/run-pass/ignore-all-the-things.rs
src/test/run-pass/infer-fn-tail-expr.rs
src/test/run-pass/init-large-type.rs
src/test/run-pass/init-res-into-things.rs
src/test/run-pass/instantiable.rs
src/test/run-pass/invalid_const_promotion.rs
src/test/run-pass/issue-53728.rs
src/test/run-pass/item-attributes.rs
src/test/run-pass/item-name-overload.rs
src/test/run-pass/keyword-changes-2012-07-31.rs
src/test/run-pass/kindck-implicit-close-over-mut-var.rs
src/test/run-pass/lambda-infer-unresolved.rs
src/test/run-pass/large-records.rs
src/test/run-pass/last-use-in-block.rs
src/test/run-pass/last-use-in-cap-clause.rs
src/test/run-pass/last-use-is-capture.rs
src/test/run-pass/lazy-init.rs
src/test/run-pass/lib-defaults.rs
src/test/run-pass/link-section.rs
src/test/run-pass/lint-non-camel-case-types-non-uppercase-statics-unicode.rs
src/test/run-pass/lint-non-camel-case-with-trailing-underscores.rs
src/test/run-pass/list.rs
src/test/run-pass/liveness-assign-imm-local-after-ret.rs
src/test/run-pass/log-knows-the-names-of-variants-in-std.rs
src/test/run-pass/log-knows-the-names-of-variants.rs
src/test/run-pass/max-min-classes.rs
src/test/run-pass/mid-path-type-params.rs
src/test/run-pass/monad.rs
src/test/run-pass/monomorphize-abi-alignment.rs
src/test/run-pass/multiple-reprs.rs
src/test/run-pass/mutual-recursion-group.rs
src/test/run-pass/nested-class.rs
src/test/run-pass/never-result.rs
src/test/run-pass/newlambdas-ret-infer.rs
src/test/run-pass/newlambdas-ret-infer2.rs
src/test/run-pass/newtype-polymorphic.rs
src/test/run-pass/newtype.rs
src/test/run-pass/nil-decl-in-foreign.rs
src/test/run-pass/no-core-1.rs
src/test/run-pass/nullable-pointer-size.rs
src/test/run-pass/operator-overloading.rs
src/test/run-pass/optimization-fuel-0.stdout [new file with mode: 0644]
src/test/run-pass/optimization-fuel-1.stdout [new file with mode: 0644]
src/test/run-pass/option-unwrap.rs
src/test/run-pass/out-of-stack.rs
src/test/run-pass/output-slot-variants.rs
src/test/run-pass/over-constrained-vregs.rs
src/test/run-pass/parse-panic.rs
src/test/run-pass/paths-containing-nul.rs
src/test/run-pass/project-cache-issue-37154.rs
src/test/run-pass/project-defer-unification.rs
src/test/run-pass/ptr-coercion.rs
src/test/run-pass/pure-sum.rs
src/test/run-pass/range-type-infer.rs
src/test/run-pass/range.rs
src/test/run-pass/range_inclusive_gate.rs
src/test/run-pass/rcvr-borrowed-to-region.rs
src/test/run-pass/readalias.rs
src/test/run-pass/resolve-issue-2428.rs
src/test/run-pass/resource-assign-is-not-copy.rs
src/test/run-pass/resource-destruct.rs
src/test/run-pass/ret-none.rs
src/test/run-pass/rustc-rust-log.rs
src/test/run-pass/segfault-no-out-of-stack.rs
src/test/run-pass/semistatement-in-lambda.rs
src/test/run-pass/shadow.rs
src/test/run-pass/shadowed-use-visibility.rs
src/test/run-pass/sigpipe-should-be-ignored.rs
src/test/run-pass/simple-infer.rs
src/test/run-pass/simple_global_asm.rs
src/test/run-pass/size-and-align.rs
src/test/run-pass/sized-borrowed-pointer.rs
src/test/run-pass/sized-owned-pointer.rs
src/test/run-pass/snake-case-no-lowercase-equivalent.rs
src/test/run-pass/sse2.rs
src/test/run-pass/structured-compare.rs
src/test/run-pass/super-fast-paren-parsing.rs
src/test/run-pass/super.rs
src/test/run-pass/swap-overlapping.rs
src/test/run-pass/trivial-message.rs
src/test/run-pass/try-block.rs
src/test/run-pass/try-is-identifier-edition2015.rs
src/test/run-pass/try-operator-hygiene.rs
src/test/run-pass/try-operator.rs
src/test/run-pass/try-wait.rs
src/test/run-pass/tup.rs
src/test/run-pass/tydesc-name.rs
src/test/run-pass/type-ascription.rs
src/test/run-pass/type-in-nested-module.rs
src/test/run-pass/type-infer-generalize-ty-var.rs
src/test/run-pass/type-param-constraints.rs
src/test/run-pass/type-param.rs
src/test/run-pass/type-params-in-for-each.rs
src/test/run-pass/type-ptr.rs
src/test/run-pass/type-sizes.rs
src/test/run-pass/typeck_type_placeholder_1.rs
src/test/run-pass/typeclasses-eq-example-static.rs
src/test/run-pass/typeclasses-eq-example.rs
src/test/run-pass/typeid-intrinsic.rs
src/test/run-pass/typestate-cfg-nesting.rs
src/test/run-pass/underscore-lifetimes.rs
src/test/run-pass/unit.rs
src/test/run-pass/unreachable-code-1.rs
src/test/run-pass/unreachable-code.rs
src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs
src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs
src/test/run-pass/unsized.rs
src/test/run-pass/unsized2.rs
src/test/run-pass/unwind-resource.rs
src/test/run-pass/use-keyword-2.rs
src/test/run-pass/use-mod.rs
src/test/run-pass/use.rs
src/test/run-pass/utf8_idents.rs
src/test/run-pass/variant-attributes.rs
src/test/run-pass/volatile-fat-ptr.rs
src/test/run-pass/warn-ctypes-inhibit.rs
src/test/run-pass/weird-exprs.rs
src/test/run-pass/wf-bound-region-in-object-type.rs
src/test/run-pass/writealias.rs
src/test/run-pass/wrong-hashset-issue-42918.rs
src/test/run-pass/x86stdcall2.rs
src/test/run-pass/yield.rs
src/test/run-pass/yield1.rs
src/test/rustdoc-js/pinbox-new.js [deleted file]
src/test/rustdoc-js/vec-new.js
src/test/rustdoc/doc-proc-macro.rs
src/test/rustdoc/inline_cross/auxiliary/trait-vis.rs [new file with mode: 0644]
src/test/rustdoc/inline_cross/trait-vis.rs [new file with mode: 0644]
src/test/rustdoc/inline_local/trait-vis.rs [new file with mode: 0644]
src/test/rustdoc/intra-link-in-bodies.rs [new file with mode: 0644]
src/test/rustdoc/issue-53812.rs [new file with mode: 0644]
src/test/rustdoc/keyword.rs
src/test/rustdoc/primitive-generic-impl.rs
src/test/rustdoc/traits-in-bodies-private.rs [new file with mode: 0644]
src/test/rustdoc/traits-in-bodies.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/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/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-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/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-crate_in_paths.rs [deleted file]
src/test/ui/feature-gates/feature-gate-crate_in_paths.stderr [deleted file]
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/hygiene/dollar-crate-modern.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/issues/issue-17385.nll.stderr
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-53712.rs [new file with mode: 0644]
src/test/ui/issues/issue-53712.stderr [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/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-pass.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/borrowck-thread-local-static-mut-borrow-outlives-fn.rs [new file with mode: 0644]
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/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/extern/extern-prelude-core.stderr [new file with mode: 0644]
src/test/ui/run-pass/extern/extern-prelude-std.stderr [new file with mode: 0644]
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-crate-paths/crate-path-absolute.stderr [new file with mode: 0644]
src/test/ui/run-pass/rfcs/rfc-2126-crate-paths/crate-path-visibility-ambiguity.stderr [new file with mode: 0644]
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/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/span/borrowck-borrow-overloaded-auto-deref-mut.stderr
src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr
src/test/ui/span/borrowck-object-mutability.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/cargo
src/tools/clippy
src/tools/compiletest/src/common.rs
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/runtest.rs
src/tools/miri
src/tools/rls
src/tools/tidy/src/deps.rs

index b1701e4a65451aa82205f0c1af1211ef3e007ae2..0646f4d4687a6c87f8b53f8c686ec22642cd4816 100644 (file)
@@ -301,7 +301,7 @@ after_failure:
       EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!checkout!\(.*\)|\1|;y|!|/|');
       if [ -f "$EXE" ]; then
         printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE";
-        gdb -q -c "$CORE" "$EXE"
+        gdb --batch -q -c "$CORE" "$EXE"
           -iex 'set auto-load off'
           -iex 'dir src/'
           -iex 'set sysroot .'
index 989655ffb4f5c5b608b5541244d2d61d5feeacb7..c2c3f37db3726e1c750fc15729e192c75accd1ee 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)",
@@ -170,18 +170,24 @@ name = "byteorder"
 version = "1.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "bytesize"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "cargo"
-version = "0.31.0"
+version = "0.32.0"
 dependencies = [
  "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "crates-io 0.19.0",
+ "crates-io 0.20.0",
  "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -198,7 +204,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.9 (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 +246,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 +362,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 +393,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 +439,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]]
@@ -452,9 +458,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "crates-io"
-version = "0.19.0"
+version = "0.20.0"
 dependencies = [
- "curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -475,7 +481,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)",
 ]
 
@@ -546,10 +552,10 @@ dependencies = [
 
 [[package]]
 name = "curl"
-version = "0.4.14"
+version = "0.4.17"
 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 +567,13 @@ 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)",
+ "libnghttp2-sys 0.1.0 (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 +815,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 +832,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.9 (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)",
@@ -827,7 +844,7 @@ name = "git2-curl"
 version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1063,27 +1080,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libgit2-sys"
-version = "0.7.7"
+version = "0.7.9"
 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 = "libnghttp2-sys"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.25 (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 +1115,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 +1166,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 +1270,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 +1292,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 +1379,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 +1387,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 +1467,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 +1594,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 +1667,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)",
@@ -1753,7 +1776,7 @@ dependencies = [
 name = "rls"
 version = "0.130.5"
 dependencies = [
- "cargo 0.31.0",
+ "cargo 0.32.0",
  "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "clippy_lints 0.0.212",
  "crossbeam-channel 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1767,6 +1790,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 +2108,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 +2197,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 +2216,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 +2242,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]]
@@ -2433,6 +2458,7 @@ name = "rustdoc"
 version = "0.0.0"
 dependencies = [
  "minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2620,14 +2646,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 +2820,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 +3040,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"
@@ -3122,8 +3159,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
 "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
 "checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9"
+"checksum bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "716960a18f978640f25101b5cbf1c6f6b0d3192fab36a2d98ca96f0ecbe41010"
 "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"
@@ -3146,8 +3184,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum crossbeam-utils 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ea52fab26a99d96cdff39d0ca75c9716125937f5dba2ab83923aaaf5928f684a"
 "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
 "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4"
-"checksum curl 0.4.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 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c8172e96ecfb1a2bfe3843d9d7154099a15130cf4a2f658259c7aa9cc2b5d4ff"
+"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 +3214,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 +3240,10 @@ 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.9 (registry+https://github.com/rust-lang/crates.io-index)" = "93f2b22fce91fb820363cf88a849a8f8fdfd8be37774b6a9dd6cbda05cf940e6"
+"checksum libnghttp2-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ffbfb81475cc9f625e44f3a8f8b9cf7173815ae1c7cc2fa91853ec009e38198"
+"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 +3302,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 +3388,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 92665c09f72aa7bef15f0984ad7dd3b2fb32f4f5..0c4816dc90458e291d28a9abd4cd82ef2a861ee8 100644 (file)
@@ -755,10 +755,11 @@ fn run(self, builder: &Builder) {
     compare_mode: "nll"
 });
 
-default_test!(RunPass {
+default_test_with_compare_mode!(RunPass {
     path: "src/test/run-pass",
     mode: "run-pass",
-    suite: "run-pass"
+    suite: "run-pass",
+    compare_mode: "nll"
 });
 
 default_test!(CompileFail {
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 cff0930664b688f1dd22aefb3d16944eb4cdbfd5..fa91738b66367b6f70b078251868a071f1991ace 160000 (submodule)
@@ -1 +1 @@
-Subproject commit cff0930664b688f1dd22aefb3d16944eb4cdbfd5
+Subproject commit fa91738b66367b6f70b078251868a071f1991ace
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/crate-in-paths.md b/src/doc/unstable-book/src/language-features/crate-in-paths.md
deleted file mode 100644 (file)
index 9901dc1..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-# `crate_in_paths`
-
-The tracking issue for this feature is: [#44660]
-
-[#44660]: https://github.com/rust-lang/rust/issues/44660
-
-------------------------
-
-The `crate_in_paths` feature allows to explicitly refer to the crate root in absolute paths
-using keyword `crate`.
-
-This feature is required in `feature(extern_absolute_paths)` mode to refer to any absolute path
-in the local crate (absolute paths refer to extern crates by default in that mode), but can be
-used without `feature(extern_absolute_paths)` as well.
-
-```rust
-#![feature(crate_in_paths)]
-
-// Imports, `::` is added implicitly
-use crate::m::f;
-use crate as root;
-
-mod m {
-    pub fn f() -> u8 { 1 }
-    pub fn g() -> u8 { 2 }
-    pub fn h() -> u8 { 3 }
-
-    // OK, visibilities implicitly add starting `::` as well, like imports
-    pub(in crate::m) struct S;
-}
-
-mod n
-{
-    use crate::m::f;
-    use crate as root;
-    pub fn check() {
-        assert_eq!(f(), 1);
-        assert_eq!(crate::m::g(), 2);
-        assert_eq!(root::m::h(), 3);
-    }
-}
-
-fn main() {
-    assert_eq!(f(), 1);
-    assert_eq!(crate::m::g(), 2);
-    assert_eq!(root::m::h(), 3);
-    n::check();
-}
-```
diff --git a/src/doc/unstable-book/src/language-features/extern-absolute-paths.md b/src/doc/unstable-book/src/language-features/extern-absolute-paths.md
deleted file mode 100644 (file)
index 6a22e7e..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-# `extern_absolute_paths`
-
-The tracking issue for this feature is: [#44660]
-
-[#44660]: https://github.com/rust-lang/rust/issues/44660
-
-------------------------
-
-The `extern_absolute_paths` feature enables mode allowing to refer to names from other crates
-"inline", without introducing `extern crate` items, using absolute paths like `::my_crate::a::b`.
-
-`::my_crate::a::b` will resolve to path `a::b` in crate `my_crate`.
-
-`feature(crate_in_paths)` can be used in `feature(extern_absolute_paths)` mode for referring
-to absolute paths in the local crate (`crate::a::b`).
-
-`feature(extern_in_paths)` provides the same effect by using keyword `extern` to refer to
-paths from other crates (`extern::my_crate::a::b`).
-
-```rust,ignore
-#![feature(extern_absolute_paths)]
-
-// Suppose we have a dependency crate `xcrate` available through `Cargo.toml`, or `--extern`
-// options, or standard Rust distribution, or some other means.
-
-use xcrate::Z;
-
-fn f() {
-    use xcrate;
-    use xcrate as ycrate;
-    let s = xcrate::S;
-    assert_eq!(format!("{:?}", s), "S");
-    let z = ycrate::Z;
-    assert_eq!(format!("{:?}", z), "Z");
-}
-
-fn main() {
-    let s = ::xcrate::S;
-    assert_eq!(format!("{:?}", s), "S");
-    let z = Z;
-    assert_eq!(format!("{:?}", z), "Z");
-}
-```
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 9d442b3e00ca074ea7b6d1584272923bc8b922ef..6c0b1c33a1f7673ee3c4a2ed40a789214a20be4d 100644 (file)
@@ -392,6 +392,10 @@ pub fn into_vec(self: Box<Self>) -> Vec<T> {
 
     /// Creates a vector by repeating a slice `n` times.
     ///
+    /// # Panics
+    ///
+    /// This function will panic if the capacity would overflow.
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -403,6 +407,16 @@ pub fn into_vec(self: Box<Self>) -> Vec<T> {
     ///     assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]);
     /// }
     /// ```
+    ///
+    /// A panic upon overflow:
+    ///
+    /// ```should_panic
+    /// #![feature(repeat_generic_slice)]
+    /// fn main() {
+    ///     // this will panic at runtime
+    ///     b"0123456789abcdef".repeat(usize::max_value());
+    /// }
+    /// ```
     #[unstable(feature = "repeat_generic_slice",
                reason = "it's on str, why not on slice?",
                issue = "48784")]
@@ -417,7 +431,7 @@ pub fn repeat(&self, n: usize) -> Vec<T> where T: Copy {
         // and `rem` is the remaining part of `n`.
 
         // Using `Vec` to access `set_len()`.
-        let mut buf = Vec::with_capacity(self.len() * n);
+        let mut buf = Vec::with_capacity(self.len().checked_mul(n).expect("capacity overflow"));
 
         // `2^expn` repetition is done by doubling `buf` `expn`-times.
         buf.extend(self);
index c451a051c74dcbfc2a7c92b209d05238ef92d3b6..2af89562d69fe1d0a6f37c07350c212117c8b131 100644 (file)
@@ -515,6 +515,10 @@ pub fn into_string(self: Box<str>) -> String {
 
     /// Creates a new [`String`] by repeating a string `n` times.
     ///
+    /// # Panics
+    ///
+    /// This function will panic if the capacity would overflow.
+    ///
     /// [`String`]: string/struct.String.html
     ///
     /// # Examples
@@ -524,6 +528,15 @@ pub fn into_string(self: Box<str>) -> String {
     /// ```
     /// assert_eq!("abc".repeat(4), String::from("abcabcabcabc"));
     /// ```
+    ///
+    /// A panic upon overflow:
+    ///
+    /// ```should_panic
+    /// fn main() {
+    ///     // this will panic at runtime
+    ///     "0123456789abcdef".repeat(usize::max_value());
+    /// }
+    /// ```
     #[stable(feature = "repeat_str", since = "1.16.0")]
     pub fn repeat(&self, n: usize) -> String {
         unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) }
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 dfdc375765d5faa52bd4bfa291f43ae581d90301..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))
         }
     }
 
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 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 31fba3ad97493158d9d3a879f514d81e0cea7dbf..6e35755d9a4ec228d93024ef5f4c56fe123309d5 100644 (file)
@@ -709,17 +709,22 @@ pub fn get_parent(&self, id: NodeId) -> NodeId {
         }
     }
 
-    /// Returns the NodeId of `id`'s nearest module parent, or `id` itself if no
+    /// Returns the DefId of `id`'s nearest module parent, or `id` itself if no
     /// module parent is in this map.
     pub fn get_module_parent(&self, id: NodeId) -> DefId {
-        let id = match self.walk_parent_nodes(id, |node| match *node {
+        self.local_def_id(self.get_module_parent_node(id))
+    }
+
+    /// Returns the NodeId of `id`'s nearest module parent, or `id` itself if no
+    /// module parent is in this map.
+    pub fn get_module_parent_node(&self, id: NodeId) -> NodeId {
+        match self.walk_parent_nodes(id, |node| match *node {
             Node::Item(&Item { node: ItemKind::Mod(_), .. }) => true,
             _ => false,
         }, |_| false) {
             Ok(id) => id,
             Err(id) => id,
-        };
-        self.local_def_id(id)
+        }
     }
 
     /// Returns the nearest enclosing scope. A scope is an item or block.
index a0c96554c91f1d4046d0ac1206eaaca6f6852ad8..cf76c3b7e02dfbb94185bdd6ff561e07c0b400ee 100644 (file)
@@ -118,7 +118,7 @@ pub fn note_and_explain_region(
                         return;
                     }
                 };
-                let scope_decorated_tag = match scope.data() {
+                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",
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 c017c90b8955043ad0ab52fc285e09c98a57b0b7..2eaf1eebb394ca5bc09ec9e754825e258de3b29d 100644 (file)
@@ -73,7 +73,7 @@
 #![cfg_attr(not(stage0), feature(impl_header_lifetime_elision))]
 #![feature(in_band_lifetimes)]
 #![feature(macro_at_most_once_rep)]
-#![feature(crate_in_paths)]
+#![cfg_attr(stage0, feature(crate_in_paths))]
 #![feature(crate_visibility_modifier)]
 
 #![recursion_limit="512"]
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 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 2f99743cfbdca0346b1334d749a30cf319a23a27..788fbcef17163581c6e5709b10cdb90ed2da018b 100644 (file)
 /// generated via deriving here.
 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, RustcEncodable, RustcDecodable)]
 pub struct Scope {
-    pub(crate) id: hir::ItemLocalId,
-    pub(crate) data: ScopeData,
+    pub id: hir::ItemLocalId,
+    pub data: ScopeData,
 }
 
 impl fmt::Debug for Scope {
@@ -172,48 +172,6 @@ pub struct FirstStatementIndex { .. }
 #[cfg(not(stage0))]
 static ASSERT: () = [()][!(mem::size_of::<ScopeData>() == 4) as usize];
 
-#[allow(non_snake_case)]
-impl Scope {
-    #[inline]
-    pub fn data(self) -> ScopeData {
-        self.data
-    }
-
-    #[inline]
-    pub fn new(id: hir::ItemLocalId, data: ScopeData) -> Self {
-        Scope { id, data }
-    }
-
-    #[inline]
-    pub fn Node(id: hir::ItemLocalId) -> Self {
-        Self::new(id, ScopeData::Node)
-    }
-
-    #[inline]
-    pub fn CallSite(id: hir::ItemLocalId) -> Self {
-        Self::new(id, ScopeData::CallSite)
-    }
-
-    #[inline]
-    pub fn Arguments(id: hir::ItemLocalId) -> Self {
-        Self::new(id, ScopeData::Arguments)
-    }
-
-    #[inline]
-    pub fn Destruction(id: hir::ItemLocalId) -> Self {
-        Self::new(id, ScopeData::Destruction)
-    }
-
-    #[inline]
-    pub fn Remainder(
-        id: hir::ItemLocalId,
-        first: FirstStatementIndex,
-    ) -> Self {
-        Self::new(id, ScopeData::Remainder(first))
-    }
-}
-
-
 impl Scope {
     /// Returns a item-local id associated with this scope.
     ///
@@ -244,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(first_statement_index) = 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
@@ -498,7 +456,7 @@ 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 = child.data() {
+        if let ScopeData::Destruction = child.data {
             self.destruction_scopes.insert(child.item_local_id(), child);
         }
     }
@@ -578,10 +536,10 @@ 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() {
+            match p.data {
                 ScopeData::Destruction => {
                     debug!("temporary_scope({:?}) = {:?} [enclosing]",
                            expr_id, id);
@@ -637,7 +595,7 @@ 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 = scope.data() {
+            if let ScopeData::CallSite = scope.data {
                 return Some(scope.item_local_id());
             }
 
@@ -730,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`,
@@ -750,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,
@@ -854,7 +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(blk.hir_id.local_id, FirstStatementIndex::new(i))
+                    Scope {
+                        id: blk.hir_id.local_id,
+                        data: ScopeData::Remainder(FirstStatementIndex::new(i))
+                    }
                 );
                 visitor.cx.var_parent = visitor.cx.parent;
             }
@@ -879,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 {
@@ -1008,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));
@@ -1016,7 +977,7 @@ 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() {
+                Some(&(superscope, _)) => match superscope.data {
                     ScopeData::CallSite => break,
                     _ => scope = superscope
                 },
@@ -1280,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 });
     }
 }
 
@@ -1315,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 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 ed95aa73078a92f5282e1137fd8a0b24d21fa969..4bed3c5935cd7829ec7111c6a5516cc9e608d018 100644 (file)
@@ -112,6 +112,7 @@ pub fn find_auto_trait_generics<A>(
                 orig_params,
                 trait_pred.to_poly_trait_predicate(),
             ));
+
             match result {
                 Ok(Some(Vtable::VtableImpl(_))) => {
                     debug!(
@@ -119,10 +120,10 @@ pub fn find_auto_trait_generics<A>(
                          manual impl found, bailing out",
                         did, trait_did, generics
                     );
-                    return true;
+                    true
                 }
-                _ => return false,
-            };
+                _ => false
+            }
         });
 
         // If an explicit impl exists, it always takes priority over an auto impl
@@ -426,6 +427,7 @@ fn add_user_pred<'c>(&self, user_computed_preds: &mut FxHashSet<ty::Predicate<'c
                     if new_trait.def_id() == old_trait.def_id() {
                         let new_substs = new_trait.skip_binder().trait_ref.substs;
                         let old_substs = old_trait.skip_binder().trait_ref.substs;
+
                         if !new_substs.types().eq(old_substs.types()) {
                             // We can't compare lifetimes if the types are different,
                             // so skip checking old_pred
@@ -489,12 +491,12 @@ pub fn region_name(&self, region: Region) -> Option<String> {
 
     pub fn get_lifetime(&self, region: Region, names_map: &FxHashMap<String, String>) -> String {
         self.region_name(region)
-            .map(|name| {
-                names_map.get(&name).unwrap_or_else(|| {
+            .map(|name|
+                names_map.get(&name).unwrap_or_else(||
                     panic!("Missing lifetime with name {:?} for {:?}", name, region)
-                })
-            })
-            .unwrap_or(&"'static".to_string())
+                )
+            )
+            .unwrap_or(&"'static".to_owned())
             .clone()
     }
 
index cf404202ac120830ff9da5309a4b4280136a3700..4e88150a18acc65b60325eefdf85238450b5cbb7 100644 (file)
@@ -39,7 +39,7 @@ pub fn codegen_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>,
     let trait_ref = ty.erase_regions(&trait_ref);
 
     debug!("codegen_fulfill_obligation(trait_ref={:?}, def_id={:?})",
-            (param_env, trait_ref), trait_ref.def_id());
+        (param_env, trait_ref), trait_ref.def_id());
 
     // Do the initial selection for the obligation. This yields the
     // shallow result we are looking for -- that is, what specific impl.
@@ -48,8 +48,8 @@ pub fn codegen_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>,
 
         let obligation_cause = ObligationCause::dummy();
         let obligation = Obligation::new(obligation_cause,
-                                            param_env,
-                                            trait_ref.to_poly_trait_predicate());
+                                         param_env,
+                                         trait_ref.to_poly_trait_predicate());
 
         let selection = match selcx.select(&obligation) {
             Ok(Some(selection)) => selection,
@@ -61,12 +61,11 @@ pub fn codegen_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>,
                 // overflow bug, since I believe this is the only case
                 // where ambiguity can result.
                 bug!("Encountered ambiguity selecting `{:?}` during codegen, \
-                        presuming due to overflow",
-                        trait_ref)
+                      presuming due to overflow",
+                      trait_ref)
             }
             Err(e) => {
-                bug!("Encountered error `{:?}` selecting `{:?}` during codegen",
-                            e, trait_ref)
+                bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
             }
         };
 
@@ -163,22 +162,16 @@ fn drain_fulfillment_cx_or_panic<T>(&self,
         // In principle, we only need to do this so long as `result`
         // contains unbound type parameters. It could be a slight
         // optimization to stop iterating early.
-        match fulfill_cx.select_all_or_error(self) {
-            Ok(()) => { }
-            Err(errors) => {
-                span_bug!(span, "Encountered errors `{:?}` resolving bounds after type-checking",
-                          errors);
-            }
+        if let Err(errors) = fulfill_cx.select_all_or_error(self) {
+            span_bug!(span, "Encountered errors `{:?}` resolving bounds after type-checking",
+                      errors);
         }
 
         let result = self.resolve_type_vars_if_possible(result);
         let result = self.tcx.erase_regions(&result);
 
-        match self.tcx.lift_to_global(&result) {
-            Some(result) => result,
-            None => {
-                span_bug!(span, "Uninferred types/regions in `{:?}`", result);
-            }
-        }
+        self.tcx.lift_to_global(&result).unwrap_or_else(||
+            span_bug!(span, "Uninferred types/regions in `{:?}`", result)
+        )
     }
 }
index b8dd2a12fb58d3129d2437bbb7091e98792c3e21..251743b0d3bb41a2477cad2f5d8bbbd9e9bee5b7 100644 (file)
@@ -115,9 +115,7 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
                             b_def_id: DefId)
                             -> Option<OverlapResult<'tcx>>
 {
-    debug!("overlap(a_def_id={:?}, b_def_id={:?})",
-           a_def_id,
-           b_def_id);
+    debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id);
 
     // For the purposes of this check, we don't bring any skolemized
     // types into scope; instead, we replace the generic types with
@@ -133,10 +131,9 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
 
     // Do `a` and `b` unify? If not, no overlap.
     let obligations = match selcx.infcx().at(&ObligationCause::dummy(), param_env)
-                                         .eq_impl_headers(&a_impl_header, &b_impl_header) {
-        Ok(InferOk { obligations, value: () }) => {
-            obligations
-        }
+                                         .eq_impl_headers(&a_impl_header, &b_impl_header)
+    {
+        Ok(InferOk { obligations, value: () }) => obligations,
         Err(_) => return None
     };
 
@@ -164,7 +161,7 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
         return None
     }
 
-    let impl_header =  selcx.infcx().resolve_type_vars_if_possible(&a_impl_header);
+    let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header);
     let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes();
     debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes);
     Some(OverlapResult { impl_header, intercrate_ambiguity_causes })
@@ -471,14 +468,12 @@ fn ty_is_local_constructor(ty: Ty, in_crate: InCrate) -> bool {
         ty::Foreign(did) => def_id_is_local(did, in_crate),
 
         ty::Dynamic(ref tt, ..) => {
-            tt.principal().map_or(false, |p| {
+            tt.principal().map_or(false, |p|
                 def_id_is_local(p.def_id(), in_crate)
-            })
+            )
         }
 
-        ty::Error => {
-            true
-        }
+        ty::Error => true,
 
         ty::Closure(..) |
         ty::Generator(..) |
index 466d472cca338a92734ff8ee93dcc121a4a23c02..6fb5acde72c49735d7280e8e9f39c8782c9a16f7 100644 (file)
@@ -34,6 +34,7 @@
 use infer::{self, InferCtxt};
 use infer::type_variable::TypeVariableOrigin;
 use std::fmt;
+use std::iter;
 use syntax::ast;
 use session::DiagnosticMessageId;
 use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
@@ -58,7 +59,7 @@ struct ErrorDescriptor<'tcx> {
             index: Option<usize>, // None if this is an old error
         }
 
-        let mut error_map : FxHashMap<_, Vec<_>> =
+        let mut error_map: FxHashMap<_, Vec<_>> =
             self.reported_trait_errors.borrow().iter().map(|(&span, predicates)| {
                 (span, predicates.iter().map(|predicate| ErrorDescriptor {
                     predicate: predicate.clone(),
@@ -80,7 +81,7 @@ struct ErrorDescriptor<'tcx> {
 
         // We do this in 2 passes because we want to display errors in order, tho
         // maybe it *is* better to sort errors by span or something.
-        let mut is_suppressed: Vec<bool> = errors.iter().map(|_| false).collect();
+        let mut is_suppressed = vec![false; errors.len()];
         for (_, error_set) in error_map.iter() {
             // We want to suppress "duplicate" errors with the same span.
             for error in error_set {
@@ -349,7 +350,7 @@ fn on_unimplemented_note(
             _ => {
                 // this is a "direct", user-specified, rather than derived,
                 // obligation.
-                flags.push(("direct".to_string(), None));
+                flags.push(("direct".to_owned(), None));
             }
         }
 
@@ -361,24 +362,24 @@ fn on_unimplemented_note(
             // Currently I'm leaving it for what I need for `try`.
             if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
                 let method = self.tcx.item_name(item);
-                flags.push(("from_method".to_string(), None));
-                flags.push(("from_method".to_string(), Some(method.to_string())));
+                flags.push(("from_method".to_owned(), None));
+                flags.push(("from_method".to_owned(), Some(method.to_string())));
             }
         }
 
         if let Some(k) = obligation.cause.span.compiler_desugaring_kind() {
-            flags.push(("from_desugaring".to_string(), None));
-            flags.push(("from_desugaring".to_string(), Some(k.name().to_string())));
+            flags.push(("from_desugaring".to_owned(), None));
+            flags.push(("from_desugaring".to_owned(), Some(k.name().to_string())));
         }
         let generics = self.tcx.generics_of(def_id);
         let self_ty = trait_ref.self_ty();
         // This is also included through the generics list as `Self`,
         // but the parser won't allow you to use it
-        flags.push(("_Self".to_string(), Some(self_ty.to_string())));
+        flags.push(("_Self".to_owned(), Some(self_ty.to_string())));
         if let Some(def) = self_ty.ty_adt_def() {
             // We also want to be able to select self's original
             // signature with no type arguments resolved
-            flags.push(("_Self".to_string(), Some(self.tcx.type_of(def.did).to_string())));
+            flags.push(("_Self".to_owned(), Some(self.tcx.type_of(def.did).to_string())));
         }
 
         for param in generics.params.iter() {
@@ -393,7 +394,7 @@ fn on_unimplemented_note(
         }
 
         if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) {
-            flags.push(("crate_local".to_string(), None));
+            flags.push(("crate_local".to_owned(), None));
         }
 
         if let Ok(Some(command)) = OnUnimplementedDirective::of_item(
@@ -412,27 +413,26 @@ fn find_similar_impl_candidates(&self,
         let simp = fast_reject::simplify_type(self.tcx,
                                               trait_ref.skip_binder().self_ty(),
                                               true);
-        let mut impl_candidates = Vec::new();
+        let all_impls = self.tcx.all_impls(trait_ref.def_id());
 
         match simp {
-            Some(simp) => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| {
+            Some(simp) => all_impls.iter().filter_map(|&def_id| {
                 let imp = self.tcx.impl_trait_ref(def_id).unwrap();
                 let imp_simp = fast_reject::simplify_type(self.tcx,
                                                           imp.self_ty(),
                                                           true);
                 if let Some(imp_simp) = imp_simp {
                     if simp != imp_simp {
-                        return;
+                        return None
                     }
                 }
-                impl_candidates.push(imp);
-            }),
-            None => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| {
-                impl_candidates.push(
-                    self.tcx.impl_trait_ref(def_id).unwrap());
-            })
-        };
-        impl_candidates
+
+                Some(imp)
+            }).collect(),
+            None => all_impls.iter().map(|&def_id|
+                self.tcx.impl_trait_ref(def_id).unwrap()
+            ).collect()
+        }
     }
 
     fn report_similar_impl_candidates(&self,
@@ -603,10 +603,10 @@ pub fn report_selection_error(&self,
                             span,
                             E0277,
                             "{}",
-                            message.unwrap_or_else(|| {
+                            message.unwrap_or_else(||
                                 format!("the trait bound `{}` is not satisfied{}",
                                          trait_ref.to_predicate(), post_message)
-                            }));
+                            ));
 
                         let explanation =
                             if obligation.cause.code == ObligationCauseCode::MainFunctionType {
@@ -645,7 +645,7 @@ pub fn report_selection_error(&self,
                             //     "the type `T` can't be frobnicated"
                             // which is somewhat confusing.
                             err.help(&format!("consider adding a `where {}` bound",
-                                                trait_ref.to_predicate()));
+                                              trait_ref.to_predicate()));
                         } else if !have_alt_message {
                             // Can't show anything else useful, try to find similar impls.
                             let impl_candidates = self.find_similar_impl_candidates(trait_ref);
@@ -693,7 +693,7 @@ pub fn report_selection_error(&self,
                     ty::Predicate::RegionOutlives(ref predicate) => {
                         let predicate = self.resolve_type_vars_if_possible(predicate);
                         let err = self.region_outlives_predicate(&obligation.cause,
-                                                                    &predicate).err().unwrap();
+                                                                 &predicate).err().unwrap();
                         struct_span_err!(self.tcx.sess, span, E0279,
                             "the requirement `{}` is not satisfied (`{}`)",
                             predicate, err)
@@ -722,7 +722,7 @@ pub fn report_selection_error(&self,
                         let mut err = struct_span_err!(
                             self.tcx.sess, closure_span, E0525,
                             "expected a closure that implements the `{}` trait, \
-                                but this closure only implements `{}`",
+                             but this closure only implements `{}`",
                             kind,
                             found_kind);
 
@@ -779,40 +779,34 @@ pub fn report_selection_error(&self,
             OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
                 let found_trait_ref = self.resolve_type_vars_if_possible(&*found_trait_ref);
                 let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref);
+
                 if expected_trait_ref.self_ty().references_error() {
                     return;
                 }
+
                 let found_trait_ty = found_trait_ref.self_ty();
 
                 let found_did = match found_trait_ty.sty {
-                    ty::Closure(did, _) |
-                    ty::Foreign(did) |
-                    ty::FnDef(did, _) => Some(did),
+                    ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
                     ty::Adt(def, _) => Some(def.did),
                     _ => None,
                 };
-                let found_span = found_did.and_then(|did| {
+
+                let found_span = found_did.and_then(|did|
                     self.tcx.hir.span_if_local(did)
-                }).map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
+                ).map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
 
                 let found = match found_trait_ref.skip_binder().substs.type_at(1).sty {
-                    ty::Tuple(ref tys) => tys.iter()
-                        .map(|_| ArgKind::empty()).collect::<Vec<_>>(),
+                    ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
                     _ => vec![ArgKind::empty()],
                 };
+
                 let expected = match expected_trait_ref.skip_binder().substs.type_at(1).sty {
                     ty::Tuple(ref tys) => tys.iter()
-                        .map(|t| match t.sty {
-                            ty::Tuple(ref tys) => ArgKind::Tuple(
-                                Some(span),
-                                tys.iter()
-                                    .map(|ty| ("_".to_owned(), ty.sty.to_string()))
-                                    .collect::<Vec<_>>()
-                            ),
-                            _ => ArgKind::Arg("_".to_owned(), t.sty.to_string()),
-                        }).collect(),
+                        .map(|t| ArgKind::from_expected_ty(t, Some(span))).collect(),
                     ref sty => vec![ArgKind::Arg("_".to_owned(), sty.to_string())],
                 };
+
                 if found.len() == expected.len() {
                     self.report_closure_arg_mismatch(span,
                                                      found_span,
@@ -836,8 +830,7 @@ pub fn report_selection_error(&self,
 
             TraitNotObjectSafe(did) => {
                 let violations = self.tcx.object_safety_violations(did);
-                self.tcx.report_object_safety_error(span, did,
-                                                    violations)
+                self.tcx.report_object_safety_error(span, did, violations)
             }
 
             ConstEvalFailure(ref err) => {
@@ -846,7 +839,11 @@ pub fn report_selection_error(&self,
                     "could not evaluate constant expression",
                 ) {
                     Some(err) => err,
-                    None => return,
+                    None => {
+                        self.tcx.sess.delay_span_bug(span,
+                            &format!("constant in type had an ignored error: {:?}", err));
+                        return;
+                    }
                 }
             }
 
@@ -981,11 +978,9 @@ pub fn get_fn_like_arguments(&self, node: Node) -> (Span, Vec<ArgKind>) {
                         .map(|arg| match arg.clone().node {
                     hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
                         Some(arg.span),
-                        tys.iter()
-                            .map(|_| ("_".to_owned(), "_".to_owned()))
-                            .collect::<Vec<_>>(),
+                        vec![("_".to_owned(), "_".to_owned()); tys.len()]
                     ),
-                    _ => ArgKind::Arg("_".to_owned(), "_".to_owned())
+                    _ => ArgKind::empty()
                 }).collect::<Vec<ArgKind>>())
             }
             Node::Variant(&hir::Variant {
@@ -997,15 +992,13 @@ pub fn get_fn_like_arguments(&self, node: Node) -> (Span, Vec<ArgKind>) {
                 ..
             }) => {
                 (self.tcx.sess.source_map().def_span(span),
-                 fields.iter().map(|field| {
+                 fields.iter().map(|field|
                      ArgKind::Arg(field.ident.to_string(), "_".to_string())
-                 }).collect::<Vec<_>>())
+                 ).collect::<Vec<_>>())
             }
             Node::StructCtor(ref variant_data) => {
                 (self.tcx.sess.source_map().def_span(self.tcx.hir.span(variant_data.id())),
-                 variant_data.fields()
-                    .iter().map(|_| ArgKind::Arg("_".to_owned(), "_".to_owned()))
-                    .collect())
+                 vec![ArgKind::empty(); variant_data.fields().len()])
             }
             _ => panic!("non-FnLike node found: {:?}", node),
         }
@@ -1054,7 +1047,7 @@ pub fn report_arg_count_mismatch(
             found_str,
         );
 
-        err.span_label(span, format!( "expected {} that takes {}", kind, expected_str));
+        err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
 
         if let Some(found_span) = found_span {
             err.span_label(found_span, format!("takes {}", found_str));
@@ -1063,9 +1056,8 @@ pub fn report_arg_count_mismatch(
             // found arguments is empty (assume the user just wants to ignore args in this case).
             // For example, if `expected_args_length` is 2, suggest `|_, _|`.
             if found_args.is_empty() && is_closure {
-                let underscores = "_".repeat(expected_args.len())
-                                      .split("")
-                                      .filter(|s| !s.is_empty())
+                let underscores = iter::repeat("_")
+                                      .take(expected_args.len())
                                       .collect::<Vec<_>>()
                                       .join(", ");
                 err.span_suggestion_with_applicability(
@@ -1087,7 +1079,8 @@ pub fn report_arg_count_mismatch(
                 if fields.len() == expected_args.len() {
                     let sugg = fields.iter()
                         .map(|(name, _)| name.to_owned())
-                        .collect::<Vec<String>>().join(", ");
+                        .collect::<Vec<String>>()
+                        .join(", ");
                     err.span_suggestion_with_applicability(found_span,
                                                            "change the closure to take multiple \
                                                             arguments instead of a single tuple",
@@ -1146,7 +1139,7 @@ fn build_fn_sig_string<'a, 'gcx, 'tcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>,
             let inputs = trait_ref.substs.type_at(1);
             let sig = if let ty::Tuple(inputs) = inputs.sty {
                 tcx.mk_fn_sig(
-                    inputs.iter().map(|&x| x),
+                    inputs.iter().cloned(),
                     tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
                     false,
                     hir::Unsafety::Normal,
@@ -1220,10 +1213,9 @@ pub fn report_object_safety_error(self,
 
         let mut reported_violations = FxHashSet();
         for violation in violations {
-            if !reported_violations.insert(violation.clone()) {
-                continue;
+            if reported_violations.insert(violation.clone()) {
+                err.note(&violation.error_msg());
             }
-            err.note(&violation.error_msg());
         }
         err
     }
@@ -1289,10 +1281,10 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>,
                         self.need_type_info_err(body_id, span, self_ty).emit();
                     } else {
                         let mut err = struct_span_err!(self.tcx.sess,
-                                                        span, E0283,
-                                                        "type annotations required: \
+                                                       span, E0283,
+                                                       "type annotations required: \
                                                         cannot resolve `{}`",
-                                                        predicate);
+                                                       predicate);
                         self.note_obligation_cause(&mut err, obligation);
                         err.emit();
                     }
@@ -1438,6 +1430,7 @@ fn note_obligation_cause_code<T>(&self,
             ObligationCauseCode::ItemObligation(item_def_id) => {
                 let item_name = tcx.item_path_str(item_def_id);
                 let msg = format!("required by `{}`", item_name);
+
                 if let Some(sp) = tcx.hir.span_if_local(item_def_id) {
                     let sp = tcx.sess.source_map().def_span(sp);
                     err.span_note(sp, &msg);
@@ -1529,9 +1522,9 @@ fn note_obligation_cause_code<T>(&self,
                              parent_trait_ref.skip_binder().self_ty()));
                 let parent_predicate = parent_trait_ref.to_predicate();
                 self.note_obligation_cause_code(err,
-                                            &parent_predicate,
-                                            &data.parent_code,
-                                            obligated_types);
+                                                &parent_predicate,
+                                                &data.parent_code,
+                                                obligated_types);
             }
             ObligationCauseCode::CompareImplMethodObligation { .. } => {
                 err.note(
@@ -1560,21 +1553,21 @@ fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder) {
     }
 
     fn is_recursive_obligation(&self,
-                                   obligated_types: &mut Vec<&ty::TyS<'tcx>>,
-                                   cause_code: &ObligationCauseCode<'tcx>) -> bool {
+                               obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+                               cause_code: &ObligationCauseCode<'tcx>) -> bool {
         if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
             let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref);
-            for obligated_type in obligated_types {
-                if obligated_type == &parent_trait_ref.skip_binder().self_ty() {
-                    return true;
-                }
+
+            if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
+                return true;
             }
         }
-        return false;
+        false
     }
 }
 
 /// Summarizes information
+#[derive(Clone)]
 pub enum ArgKind {
     /// An argument of non-tuple type. Parameters are (name, ty)
     Arg(String, String),
@@ -1592,11 +1585,11 @@ fn empty() -> ArgKind {
     }
 
     /// Creates an `ArgKind` from the expected type of an
-    /// argument. This has no name (`_`) and no source spans..
-    pub fn from_expected_ty(t: Ty<'_>) -> ArgKind {
+    /// argument. It has no name (`_`) and an optional source span.
+    pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
         match t.sty {
             ty::Tuple(ref tys) => ArgKind::Tuple(
-                None,
+                span,
                 tys.iter()
                    .map(|ty| ("_".to_owned(), ty.sty.to_string()))
                    .collect::<Vec<_>>()
index 9998db4ad1d48569f8ce45bd488d949a5f3b2467..707af02acbf4757f4253ee5d34e662ec3b2fd33f 100644 (file)
@@ -526,7 +526,7 @@ fn process_backedge<'c, I>(&mut self, cycle: I,
         if self.selcx.coinductive_match(cycle.clone().map(|s| s.obligation.predicate)) {
             debug!("process_child_obligations: coinductive match");
         } else {
-            let cycle : Vec<_> = cycle.map(|c| c.obligation.clone()).collect();
+            let cycle: Vec<_> = cycle.map(|c| c.obligation.clone()).collect();
             self.selcx.infcx().report_overflow_error_cycle(&cycle);
         }
     }
index e2dbe88354060b2221957de9398ed8696e392ecd..edf7772f2f78ef76f907275f62fd7700fce9da06 100644 (file)
@@ -661,7 +661,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     let predicates: Vec<_> =
         util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec())
-        .collect();
+            .collect();
 
     debug!("normalize_param_env_or_error: elaborated-predicates={:?}",
            predicates);
@@ -707,7 +707,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         };
 
         debug!("normalize_param_env_or_error: normalized predicates={:?}",
-            predicates);
+               predicates);
 
         let region_scope_tree = region::ScopeTree::default();
 
@@ -851,16 +851,16 @@ fn vtable_methods<'a, 'tcx>(
 
                 // the method may have some early-bound lifetimes, add
                 // regions for those
-                let substs = trait_ref.map_bound(|trait_ref| {
-                    Substs::for_item(tcx, def_id, |param, _| {
+                let substs = trait_ref.map_bound(|trait_ref|
+                    Substs::for_item(tcx, def_id, |param, _|
                         match param.kind {
                             GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
                             GenericParamDefKind::Type {..} => {
                                 trait_ref.substs[param.index as usize]
                             }
                         }
-                    })
-                });
+                    )
+                );
 
                 // the trait type may have higher-ranked lifetimes in it;
                 // so erase them if they appear, so that we get the type
index 17d55b77625b2c5cc347cbec2229b5c4d9a9978d..0046a23a085e70cf308b1db304f7f6f1997cbba6 100644 (file)
@@ -124,20 +124,21 @@ fn object_safety_violations_for_trait(self, trait_def_id: DefId)
         // Check methods for violations.
         let mut violations: Vec<_> = self.associated_items(trait_def_id)
             .filter(|item| item.kind == ty::AssociatedKind::Method)
-            .filter_map(|item| {
+            .filter_map(|item|
                 self.object_safety_violation_for_method(trait_def_id, &item)
                     .map(|code| ObjectSafetyViolation::Method(item.ident.name, code))
-            }).filter(|violation| {
+            ).filter(|violation| {
                 if let ObjectSafetyViolation::Method(_,
-                                MethodViolationCode::WhereClauseReferencesSelf(span)) = violation {
-                    // Using`CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
+                    MethodViolationCode::WhereClauseReferencesSelf(span)) = violation
+                {
+                    // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
                     // It's also hard to get a use site span, so we use the method definition span.
                     self.lint_node_note(
                         lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY,
                         ast::CRATE_NODE_ID,
                         *span,
                         &format!("the trait `{}` cannot be made into an object",
-                                self.item_path_str(trait_def_id)),
+                                 self.item_path_str(trait_def_id)),
                         &violation.error_msg());
                     false
                 } else {
@@ -213,24 +214,23 @@ fn generics_require_sized_self(self, def_id: DefId) -> bool {
         let predicates = self.predicates_of(def_id);
         let predicates = predicates.instantiate_identity(self).predicates;
         elaborate_predicates(self, predicates)
-            .any(|predicate| {
-                match predicate {
-                    ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
-                        trait_pred.skip_binder().self_ty().is_self()
-                    }
-                    ty::Predicate::Projection(..) |
-                    ty::Predicate::Trait(..) |
-                    ty::Predicate::Subtype(..) |
-                    ty::Predicate::RegionOutlives(..) |
-                    ty::Predicate::WellFormed(..) |
-                    ty::Predicate::ObjectSafe(..) |
-                    ty::Predicate::ClosureKind(..) |
-                    ty::Predicate::TypeOutlives(..) |
-                    ty::Predicate::ConstEvaluatable(..) => {
-                        false
-                    }
+            .any(|predicate| match predicate {
+                ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
+                    trait_pred.skip_binder().self_ty().is_self()
                 }
-            })
+                ty::Predicate::Projection(..) |
+                ty::Predicate::Trait(..) |
+                ty::Predicate::Subtype(..) |
+                ty::Predicate::RegionOutlives(..) |
+                ty::Predicate::WellFormed(..) |
+                ty::Predicate::ObjectSafe(..) |
+                ty::Predicate::ClosureKind(..) |
+                ty::Predicate::TypeOutlives(..) |
+                ty::Predicate::ConstEvaluatable(..) => {
+                    false
+                }
+            }
+        )
     }
 
     /// Returns `Some(_)` if this method makes the containing trait not object safe.
index 280ce75720bcfef8d309c0caefbc6197b6648102..f59812c0eea984f4212a3367aa585a35bf9df4c0 100644 (file)
@@ -74,17 +74,17 @@ pub fn parse(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         let condition = if is_root {
             None
         } else {
-            let cond = item_iter.next().ok_or_else(|| {
+            let cond = item_iter.next().ok_or_else(||
                 parse_error(tcx, span,
                             "empty `on`-clause in `#[rustc_on_unimplemented]`",
                             "empty on-clause here",
                             None)
-            })?.meta_item().ok_or_else(|| {
+            )?.meta_item().ok_or_else(||
                 parse_error(tcx, span,
                             "invalid `on`-clause in `#[rustc_on_unimplemented]`",
                             "invalid on-clause here",
                             None)
-            })?;
+            )?;
             attr::eval_condition(cond, &tcx.sess.parse_sess, &mut |_| true);
             Some(cond.clone())
         };
@@ -259,9 +259,9 @@ fn verify(&self,
                     // `{from_desugaring}` is allowed
                     Position::ArgumentNamed(s) if s == "from_desugaring" => (),
                     // So is `{A}` if A is a type parameter
-                    Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
+                    Position::ArgumentNamed(s) => match generics.params.iter().find(|param|
                         param.name == s
-                    }) {
+                    ) {
                         Some(_) => (),
                         None => {
                             span_err!(tcx.sess, span, E0230,
@@ -304,7 +304,7 @@ pub fn format(&self,
         let empty_string = String::new();
 
         let parser = Parser::new(&self.0, None);
-        parser.map(|p| {
+        parser.map(|p|
             match p {
                 Piece::String(s) => s,
                 Piece::NextArgument(a) => match a.position {
@@ -326,11 +326,9 @@ pub fn format(&self,
                             }
                         }
                     },
-                    _ => {
-                        bug!("broken on_unimplemented {:?} - bad format arg", self.0)
-                    }
+                    _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0)
                 }
             }
-        }).collect()
+        ).collect()
     }
 }
index e50f59cbc82c1b03476c9cff3b5e422c58d02f3b..5ea936f750e2e24398963263b4b46a649defc494 100644 (file)
@@ -171,7 +171,7 @@ fn push_candidate(&mut self, candidate: ProjectionTyCandidate<'tcx>) -> bool {
                 match (current, candidate) {
                     (ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (),
                     (ParamEnv(..), _) => return false,
-                    (_, ParamEnv(..)) => { unreachable!(); }
+                    (_, ParamEnv(..)) => unreachable!(),
                     (_, _) => convert_to_ambiguous = (),
                 }
             }
@@ -419,9 +419,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 normalized_ty
             }
 
-            _ => {
-                ty
-            }
+            _ => ty
         }
     }
 
@@ -437,12 +435,9 @@ fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tc
                             instance,
                             promoted: None
                         };
-                        match tcx.const_eval(param_env.and(cid)) {
-                            Ok(evaluated) => {
-                                let evaluated = evaluated.subst(self.tcx(), substs);
-                                return self.fold_const(evaluated);
-                            }
-                            Err(_) => {}
+                        if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
+                            let evaluated = evaluated.subst(self.tcx(), substs);
+                            return self.fold_const(evaluated);
                         }
                     }
                 } else {
@@ -453,9 +448,8 @@ fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tc
                                 instance,
                                 promoted: None
                             };
-                            match tcx.const_eval(param_env.and(cid)) {
-                                Ok(evaluated) => return self.fold_const(evaluated),
-                                Err(_) => {}
+                            if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
+                                return self.fold_const(evaluated)
                             }
                         }
                     }
@@ -993,7 +987,7 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>(
             candidate_set.mark_ambiguous();
             return;
         }
-        _ => { return; }
+        _ => return
     };
 
     // If so, extract what we know from the trait and try to come up with a good answer.
@@ -1023,33 +1017,30 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>(
     for predicate in env_predicates {
         debug!("assemble_candidates_from_predicates: predicate={:?}",
                predicate);
-        match predicate {
-            ty::Predicate::Projection(data) => {
-                let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
-
-                let is_match = same_def_id && infcx.probe(|_| {
-                    let data_poly_trait_ref =
-                        data.to_poly_trait_ref(infcx.tcx);
-                    let obligation_poly_trait_ref =
-                        obligation_trait_ref.to_poly_trait_ref();
-                    infcx.at(&obligation.cause, obligation.param_env)
-                         .sup(obligation_poly_trait_ref, data_poly_trait_ref)
-                         .map(|InferOk { obligations: _, value: () }| {
-                             // FIXME(#32730) -- do we need to take obligations
-                             // into account in any way? At the moment, no.
-                         })
-                         .is_ok()
-                });
-
-                debug!("assemble_candidates_from_predicates: candidate={:?} \
-                                                             is_match={} same_def_id={}",
-                       data, is_match, same_def_id);
-
-                if is_match {
-                    candidate_set.push_candidate(ctor(data));
-                }
+        if let ty::Predicate::Projection(data) = predicate {
+            let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
+
+            let is_match = same_def_id && infcx.probe(|_| {
+                let data_poly_trait_ref =
+                    data.to_poly_trait_ref(infcx.tcx);
+                let obligation_poly_trait_ref =
+                    obligation_trait_ref.to_poly_trait_ref();
+                infcx.at(&obligation.cause, obligation.param_env)
+                     .sup(obligation_poly_trait_ref, data_poly_trait_ref)
+                     .map(|InferOk { obligations: _, value: () }| {
+                         // FIXME(#32730) -- do we need to take obligations
+                         // into account in any way? At the moment, no.
+                     })
+                     .is_ok()
+            });
+
+            debug!("assemble_candidates_from_predicates: candidate={:?} \
+                    is_match={} same_def_id={}",
+                   data, is_match, same_def_id);
+
+            if is_match {
+                candidate_set.push_candidate(ctor(data));
             }
-            _ => {}
         }
     }
 }
@@ -1072,8 +1063,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
                 return Err(());
             }
             Err(e) => {
-                debug!("assemble_candidates_from_impls: selection error {:?}",
-                       e);
+                debug!("assemble_candidates_from_impls: selection error {:?}", e);
                 candidate_set.mark_error(e);
                 return Err(());
             }
@@ -1295,11 +1285,11 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
         let mut env_predicates = env_predicates.filter(|data| {
             let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx());
             let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
-            selcx.infcx().probe(|_| {
+            selcx.infcx().probe(|_|
                 selcx.infcx().at(&obligation.cause, obligation.param_env)
                              .sup(obligation_poly_trait_ref, data_poly_trait_ref)
                              .is_ok()
-            })
+            )
         });
 
         // select the first matching one; there really ought to be one or
@@ -1447,7 +1437,7 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>(
                                               obligation.predicate.self_ty(),
                                               fn_sig,
                                               flag)
-        .map_bound(|(trait_ref, ret_type)| {
+        .map_bound(|(trait_ref, ret_type)|
             ty::ProjectionPredicate {
                 projection_ty: ty::ProjectionTy::from_ref_and_name(
                     tcx,
@@ -1456,7 +1446,7 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>(
                 ),
                 ty: ret_type
             }
-        });
+        );
 
     confirm_param_env_candidate(selcx, obligation, predicate)
 }
index fd8898dffd4f2da428494386eead02f528c62179..f5fb183ec1a5d2d36873515861c93b7a9e9ba677 100644 (file)
@@ -57,22 +57,19 @@ pub fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec<Kind<'tcx>>> {
         debug!("c_ty = {:?}", c_ty);
         match &gcx.dropck_outlives(c_ty) {
             Ok(result) if result.is_proven() => {
-                match self.infcx.instantiate_query_result_and_region_obligations(
+                if let Ok(InferOk { value, obligations }) =
+                    self.infcx.instantiate_query_result_and_region_obligations(
                     self.cause,
                     self.param_env,
                     &orig_values,
-                    result,
-                ) {
-                    Ok(InferOk { value, obligations }) => {
-                        let ty = self.infcx.resolve_type_vars_if_possible(&ty);
-                        let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
-                        return InferOk {
-                            value: kinds,
-                            obligations,
-                        };
-                    }
-
-                    Err(_) => { /* fallthrough to error-handling code below */ }
+                    result)
+                {
+                    let ty = self.infcx.resolve_type_vars_if_possible(&ty);
+                    let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
+                    return InferOk {
+                        value: kinds,
+                        obligations,
+                    };
                 }
             }
 
@@ -161,12 +158,7 @@ impl<'tcx> FromIterator<DtorckConstraint<'tcx>> for DtorckConstraint<'tcx> {
     fn from_iter<I: IntoIterator<Item = DtorckConstraint<'tcx>>>(iter: I) -> Self {
         let mut result = Self::empty();
 
-        for DtorckConstraint {
-            outlives,
-            dtorck_types,
-            overflows,
-        } in iter
-        {
+        for DtorckConstraint { outlives, dtorck_types, overflows } in iter {
             result.outlives.extend(outlives);
             result.dtorck_types.extend(dtorck_types);
             result.overflows.extend(overflows);
@@ -254,7 +246,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
             }
         }
 
-        // The following *might* require a destructor: it would deeper inspection to tell.
+        // The following *might* require a destructor: needs deeper inspection.
         ty::Dynamic(..)
         | ty::Projection(..)
         | ty::Param(_)
index ea8bc3b20aae94d4a61203e91bedfd83776d115e..9b9643aab97d596d1d098e5fd25578297fc16ede 100644 (file)
@@ -48,6 +48,13 @@ pub fn normalize<T>(&self, value: &T) -> Result<Normalized<'tcx, T>, NoSolution>
             value,
             self.param_env,
         );
+        if !value.has_projections() {
+            return Ok(Normalized {
+                value: value.clone(),
+                obligations: vec![],
+            });
+        }
+
         let mut normalizer = QueryNormalizer {
             infcx: self.infcx,
             cause: self.cause,
@@ -56,12 +63,6 @@ pub fn normalize<T>(&self, value: &T) -> Result<Normalized<'tcx, T>, NoSolution>
             error: false,
             anon_depth: 0,
         };
-        if !value.has_projections() {
-            return Ok(Normalized {
-                value: value.clone(),
-                obligations: vec![],
-            });
-        }
 
         let value1 = value.fold_with(&mut normalizer);
         if normalizer.error {
@@ -154,8 +155,8 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 let gcx = self.infcx.tcx.global_tcx();
 
                 let mut orig_values = SmallVec::new();
-                let c_data = self.infcx
-                    .canonicalize_query(&self.param_env.and(*data), &mut orig_values);
+                let c_data = self.infcx.canonicalize_query(
+                    &self.param_env.and(*data), &mut orig_values);
                 debug!("QueryNormalizer: c_data = {:#?}", c_data);
                 debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
                 match gcx.normalize_projection_ty(c_data) {
@@ -170,12 +171,9 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                             self.cause,
                             self.param_env,
                             &orig_values,
-                            &result,
-                        ) {
-                            Ok(InferOk {
-                                value: result,
-                                obligations,
-                            }) => {
+                            &result)
+                        {
+                            Ok(InferOk { value: result, obligations }) => {
                                 debug!("QueryNormalizer: result = {:#?}", result);
                                 debug!("QueryNormalizer: obligations = {:#?}", obligations);
                                 self.obligations.extend(obligations);
@@ -212,12 +210,9 @@ fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tc
                             instance,
                             promoted: None,
                         };
-                        match tcx.const_eval(param_env.and(cid)) {
-                            Ok(evaluated) => {
-                                let evaluated = evaluated.subst(self.tcx(), substs);
-                                return self.fold_const(evaluated);
-                            }
-                            Err(_) => {}
+                        if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
+                            let evaluated = evaluated.subst(self.tcx(), substs);
+                            return self.fold_const(evaluated);
                         }
                     }
                 } else {
@@ -228,9 +223,8 @@ fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tc
                                 instance,
                                 promoted: None,
                             };
-                            match tcx.const_eval(param_env.and(cid)) {
-                                Ok(evaluated) => return self.fold_const(evaluated),
-                                Err(_) => {}
+                            if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
+                                return self.fold_const(evaluated)
                             }
                         }
                     }
index 232ef108537fefdb0ed634ad594e0db40bcf6940..c6099e15f8bb587d45dc3eec530d00d978b7e906 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;
@@ -55,7 +55,6 @@
 use hir;
 use util::nodemap::{FxHashMap, FxHashSet};
 
-
 pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
     infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
 
@@ -149,7 +148,7 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> {
 #[derive(Clone)]
 pub struct SelectionCache<'tcx> {
     hashmap: Lock<FxHashMap<ty::TraitRef<'tcx>,
-                               WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>>>,
+                            WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>>>,
 }
 
 /// The selection process begins by considering all impls, where
@@ -623,9 +622,9 @@ pub fn evaluate_obligation_recursively(&mut self,
                                            obligation: &PredicateObligation<'tcx>)
                                            -> Result<EvaluationResult, OverflowError>
     {
-        self.probe(|this, _| {
+        self.probe(|this, _|
             this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation)
-        })
+        )
     }
 
     /// Evaluates the predicates in `predicates` recursively. Note that
@@ -717,13 +716,9 @@ fn evaluate_predicate_recursively<'o>(&mut self,
                             self.infcx.projection_cache.borrow_mut().complete(key);
                         }
                         result
-                    }
-                    Ok(None) => {
-                        Ok(EvaluatedToAmbig)
-                    }
-                    Err(_) => {
-                        Ok(EvaluatedToErr)
-                    }
+                    },
+                    Ok(None) => Ok(EvaluatedToAmbig),
+                    Err(_) => Ok(EvaluatedToErr)
                 }
             }
 
@@ -735,10 +730,8 @@ fn evaluate_predicate_recursively<'o>(&mut self,
                         } else {
                             Ok(EvaluatedToErr)
                         }
-                    }
-                    None => {
-                        Ok(EvaluatedToAmbig)
-                    }
+                    },
+                    None => Ok(EvaluatedToAmbig)
                 }
             }
 
@@ -901,13 +894,13 @@ fn evaluate_stack<'o>(&mut self,
         // same unbound type variable.
         if let Some(rec_index) =
             stack.iter()
-            .skip(1) // skip top-most frame
-            .position(|prev| stack.obligation.param_env == prev.obligation.param_env &&
-                      stack.fresh_trait_ref == prev.fresh_trait_ref)
+                 .skip(1) // skip top-most frame
+                 .position(|prev| stack.obligation.param_env == prev.obligation.param_env &&
+                                  stack.fresh_trait_ref == prev.fresh_trait_ref)
         {
             debug!("evaluate_stack({:?}) --> recursive",
                    stack.fresh_trait_ref);
-            let cycle = stack.iter().skip(1).take(rec_index+1);
+            let cycle = stack.iter().skip(1).take(rec_index + 1);
             let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate));
             if self.coinductive_match(cycle) {
                 debug!("evaluate_stack({:?}) --> recursive, coinductive",
@@ -947,10 +940,8 @@ fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
         let result = match predicate {
             ty::Predicate::Trait(ref data) => {
                 self.tcx().trait_is_auto(data.def_id())
-            }
-            _ => {
-                false
-            }
+            },
+            _ => false
         };
         debug!("coinductive_predicate({:?}) = {:?}", predicate, result);
         result
@@ -1088,9 +1079,9 @@ fn candidate_from_obligation<'o>(&mut self,
         }
 
         // If no match, compute result and insert into cache.
-        let (candidate, dep_node) = self.in_task(|this| {
+        let (candidate, dep_node) = self.in_task(|this|
             this.candidate_from_obligation_no_cache(stack)
-        });
+        );
 
         debug!("CACHE MISS: SELECT({:?})={:?}",
                cache_fresh_trait_pred, candidate);
@@ -1104,9 +1095,9 @@ fn candidate_from_obligation<'o>(&mut self,
     fn in_task<OP, R>(&mut self, op: OP) -> (R, DepNodeIndex)
         where OP: FnOnce(&mut Self) -> R
     {
-        let (result, dep_node) = self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || {
+        let (result, dep_node) = self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, ||
             op(self)
-        });
+        );
         self.tcx().dep_graph.read_index(dep_node);
         (result, dep_node)
     }
@@ -1138,46 +1129,53 @@ fn candidate_from_obligation_no_cache<'o>(&mut self,
             return Ok(None);
         }
 
-        match self.is_knowable(stack) {
-            None => {}
-            Some(conflict) => {
-                debug!("coherence stage: not knowable");
-                if self.intercrate_ambiguity_causes.is_some() {
-                    debug!("evaluate_stack: intercrate_ambiguity_causes is some");
-                    // Heuristics: show the diagnostics when there are no candidates in crate.
-                    if let Ok(candidate_set) = self.assemble_candidates(stack) {
-                        let no_candidates_apply =
-                            candidate_set
-                            .vec
-                            .iter()
-                            .map(|c| self.evaluate_candidate(stack, &c))
-                            .collect::<Result<Vec<_>, OverflowError>>()?
-                            .iter()
-                            .all(|r| !r.may_apply());
-                        if !candidate_set.ambiguous && no_candidates_apply {
-                            let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
-                            let self_ty = trait_ref.self_ty();
-                            let trait_desc = trait_ref.to_string();
-                            let self_desc = if self_ty.has_concrete_skeleton() {
-                                Some(self_ty.to_string())
-                            } else {
-                                None
-                            };
-                            let cause = if let Conflict::Upstream = conflict {
-                                IntercrateAmbiguityCause::UpstreamCrateUpdate {
-                                    trait_desc,
-                                    self_desc,
-                                }
-                            } else {
-                                IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
-                            };
-                            debug!("evaluate_stack: pushing cause = {:?}", cause);
-                            self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+        if let Some(conflict) = self.is_knowable(stack) {
+            debug!("coherence stage: not knowable");
+            if self.intercrate_ambiguity_causes.is_some() {
+                debug!("evaluate_stack: intercrate_ambiguity_causes is some");
+                // Heuristics: show the diagnostics when there are no candidates in crate.
+                if let Ok(candidate_set) = self.assemble_candidates(stack) {
+                    let mut no_candidates_apply = true;
+                    {
+                        let evaluated_candidates = candidate_set.vec.iter().map(|c|
+                            self.evaluate_candidate(stack, &c));
+
+                        for ec in evaluated_candidates {
+                            match ec {
+                                Ok(c) => {
+                                    if c.may_apply() {
+                                        no_candidates_apply = false;
+                                        break
+                                    }
+                                },
+                                Err(e) => return Err(e.into())
+                            }
                         }
                     }
+
+                    if !candidate_set.ambiguous && no_candidates_apply {
+                        let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
+                        let self_ty = trait_ref.self_ty();
+                        let trait_desc = trait_ref.to_string();
+                        let self_desc = if self_ty.has_concrete_skeleton() {
+                            Some(self_ty.to_string())
+                        } else {
+                            None
+                        };
+                        let cause = if let Conflict::Upstream = conflict {
+                            IntercrateAmbiguityCause::UpstreamCrateUpdate {
+                                trait_desc,
+                                self_desc,
+                            }
+                        } else {
+                            IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
+                        };
+                        debug!("evaluate_stack: pushing cause = {:?}", cause);
+                        self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+                    }
                 }
-                return Ok(None);
             }
+            return Ok(None);
         }
 
         let candidate_set = self.assemble_candidates(stack)?;
@@ -1434,9 +1432,9 @@ fn assemble_candidates<'o>(&mut self,
 
         // Other bounds. Consider both in-scope bounds from fn decl
         // and applicable impls. There is a certain set of precedence rules here.
-
         let def_id = obligation.predicate.def_id();
         let lang_items = self.tcx().lang_items();
+
         if lang_items.copy_trait() == Some(def_id) {
             debug!("obligation self ty is {:?}",
                    obligation.predicate.skip_binder().self_ty());
@@ -1495,15 +1493,15 @@ fn assemble_candidates_from_projected_tys(&mut self,
             ty::Projection(_) | ty::Opaque(..) => {}
             ty::Infer(ty::TyVar(_)) => {
                 span_bug!(obligation.cause.span,
-                    "Self=_ should have been handled by assemble_candidates");
+                          "Self=_ should have been handled by assemble_candidates");
             }
             _ => return
         }
 
-        let result = self.probe(|this, snapshot| {
+        let result = self.probe(|this, snapshot|
             this.match_projection_obligation_against_definition_bounds(obligation,
                                                                        snapshot)
-        });
+        );
 
         if result {
             candidates.vec.push(ProjectionCandidate);
@@ -1533,7 +1531,7 @@ fn match_projection_obligation_against_definition_bounds(
                 span_bug!(
                     obligation.cause.span,
                     "match_projection_obligation_against_definition_bounds() called \
-                     but self-ty not a projection: {:?}",
+                     but self-ty is not a projection: {:?}",
                     skol_trait_predicate.trait_ref.self_ty());
             }
         };
@@ -1637,14 +1635,14 @@ fn evaluate_where_clause<'o>(&mut self,
                                  where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
                                  -> Result<EvaluationResult, OverflowError>
     {
-        self.probe(move |this, _| {
+        self.probe(move |this, _|
             match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
                 Ok(obligations) => {
                     this.evaluate_predicates_recursively(stack.list(), obligations.iter())
                 }
                 Err(()) => Ok(EvaluatedToErr)
             }
-        })
+        )
     }
 
     fn assemble_generator_candidates(&mut self,
@@ -1667,15 +1665,15 @@ fn assemble_generator_candidates(&mut self,
                        obligation);
 
                 candidates.vec.push(GeneratorCandidate);
-                Ok(())
             }
             ty::Infer(ty::TyVar(_)) => {
                 debug!("assemble_generator_candidates: ambiguous self-type");
                 candidates.ambiguous = true;
-                return Ok(());
             }
-            _ => { return Ok(()); }
+            _ => {}
         }
+
+        Ok(())
     }
 
     /// Check for the artificial impl that the compiler will create for an obligation like `X :
@@ -1712,16 +1710,16 @@ fn assemble_closure_candidates(&mut self,
                         debug!("assemble_unboxed_candidates: closure_kind not yet known");
                         candidates.vec.push(ClosureCandidate);
                     }
-                };
-                Ok(())
+                }
             }
             ty::Infer(ty::TyVar(_)) => {
                 debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
                 candidates.ambiguous = true;
-                return Ok(());
             }
-            _ => { return Ok(()); }
+            _ => {}
         }
+
+        Ok(())
     }
 
     /// Implement one of the `Fn()` family for a fn pointer.
@@ -1742,7 +1740,6 @@ fn assemble_fn_pointer_candidates(&mut self,
                 debug!("assemble_fn_pointer_candidates: ambiguous self-type");
                 candidates.ambiguous = true; // could wind up being a fn() type
             }
-
             // provide an impl, but only for suitable `fn` pointers
             ty::FnDef(..) | ty::FnPtr(_) => {
                 if let ty::FnSig {
@@ -1754,8 +1751,7 @@ fn assemble_fn_pointer_candidates(&mut self,
                     candidates.vec.push(FnPointerCandidate);
                 }
             }
-
-            _ => { }
+            _ => {}
         }
 
         Ok(())
@@ -1773,18 +1769,15 @@ fn assemble_candidates_from_impls(&mut self,
             obligation.predicate.def_id(),
             obligation.predicate.skip_binder().trait_ref.self_ty(),
             |impl_def_id| {
-                self.probe(|this, snapshot| { /* [1] */
-                    match this.match_impl(impl_def_id, obligation, snapshot) {
-                        Ok(skol_map) => {
-                            candidates.vec.push(ImplCandidate(impl_def_id));
-
-                            // NB: we can safely drop the skol map
-                            // since we are in a probe [1]
-                            mem::drop(skol_map);
-                        }
-                        Err(_) => { }
+                self.probe(|this, snapshot| /* [1] */
+                    if let Ok(skol_map) = this.match_impl(impl_def_id, obligation, snapshot) {
+                        candidates.vec.push(ImplCandidate(impl_def_id));
+
+                        // NB: we can safely drop the skol map
+                        // since we are in a probe [1]
+                        mem::drop(skol_map);
                     }
-                });
+                );
             }
         );
 
@@ -1874,7 +1867,7 @@ fn assemble_candidates_from_object_ty(&mut self,
                 ty::Dynamic(ref data, ..) => {
                     if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
                         debug!("assemble_candidates_from_object_ty: matched builtin bound, \
-                                    pushing candidate");
+                                pushing candidate");
                         candidates.vec.push(BuiltinObjectCandidate);
                         return;
                     }
@@ -1889,9 +1882,7 @@ fn assemble_candidates_from_object_ty(&mut self,
                     candidates.ambiguous = true; // could wind up being an object type
                     return;
                 }
-                _ => {
-                    return;
-                }
+                _ => return
             };
 
             debug!("assemble_candidates_from_object_ty: poly_trait_ref={:?}",
@@ -1904,12 +1895,12 @@ fn assemble_candidates_from_object_ty(&mut self,
             // but `Foo` is declared as `trait Foo : Bar<u32>`.
             let upcast_trait_refs =
                 util::supertraits(this.tcx(), poly_trait_ref)
-                .filter(|upcast_trait_ref| {
+                .filter(|upcast_trait_ref|
                     this.probe(|this, _| {
                         let upcast_trait_ref = upcast_trait_ref.clone();
                         this.match_poly_trait_ref(obligation, upcast_trait_ref).is_ok()
                     })
-                })
+                )
                 .count();
 
             if upcast_trait_refs > 1 {
@@ -2028,6 +2019,10 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
         other: &EvaluatedCandidate<'tcx>)
         -> bool
     {
+        if victim.candidate == other.candidate {
+            return true;
+        }
+
         // Check if a bound would previously have been removed when normalizing
         // the param_env so that it can be given the lowest priority. See
         // #50825 for the motivation for this.
@@ -2035,10 +2030,6 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
             cand.is_global() && !cand.has_late_bound_regions()
         };
 
-        if victim.candidate == other.candidate {
-            return true;
-        }
-
         match other.candidate {
             // Prefer BuiltinCandidate { has_nested: false } to anything else.
             // This is a fix for #53123 and prevents winnowing from accidentally extending the
@@ -2046,9 +2037,8 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
             BuiltinCandidate { has_nested: false } => true,
             ParamCandidate(ref cand) => match victim.candidate {
                 AutoImplCandidate(..) => {
-                    bug!(
-                        "default implementations shouldn't be recorded \
-                         when there are other valid candidates");
+                    bug!("default implementations shouldn't be recorded \
+                          when there are other valid candidates");
                 }
                 // Prefer BuiltinCandidate { has_nested: false } to anything else.
                 // This is a fix for #53123 and prevents winnowing from accidentally extending the
@@ -2077,9 +2067,8 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
             ObjectCandidate |
             ProjectionCandidate => match victim.candidate {
                 AutoImplCandidate(..) => {
-                    bug!(
-                        "default implementations shouldn't be recorded \
-                         when there are other valid candidates");
+                    bug!("default implementations shouldn't be recorded \
+                          when there are other valid candidates");
                 }
                 // Prefer BuiltinCandidate { has_nested: false } to anything else.
                 // This is a fix for #53123 and prevents winnowing from accidentally extending the
@@ -2151,7 +2140,7 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
     fn assemble_builtin_bound_candidates<'o>(&mut self,
                                              conditions: BuiltinImplConditions<'tcx>,
                                              candidates: &mut SelectionCandidateSet<'tcx>)
-                                             -> Result<(),SelectionError<'tcx>>
+                                             -> Result<(), SelectionError<'tcx>>
     {
         match conditions {
             BuiltinImplConditions::Where(nested) => {
@@ -2159,18 +2148,20 @@ fn assemble_builtin_bound_candidates<'o>(&mut self,
                 candidates.vec.push(BuiltinCandidate {
                     has_nested: nested.skip_binder().len() > 0
                 });
-                Ok(())
             }
-            BuiltinImplConditions::None => { Ok(()) }
+            BuiltinImplConditions::None => {}
             BuiltinImplConditions::Ambiguous => {
                 debug!("assemble_builtin_bound_candidates: ambiguous builtin");
-                Ok(candidates.ambiguous = true)
+                candidates.ambiguous = true;
             }
         }
+
+        Ok(())
     }
 
-    fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>)
-                     -> BuiltinImplConditions<'tcx>
+    fn sized_conditions(&mut self,
+                        obligation: &TraitObligation<'tcx>)
+                        -> BuiltinImplConditions<'tcx>
     {
         use self::BuiltinImplConditions::{Ambiguous, None, Where};
 
@@ -2216,8 +2207,9 @@ fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>)
         }
     }
 
-    fn copy_clone_conditions(&mut self, obligation: &TraitObligation<'tcx>)
-                     -> BuiltinImplConditions<'tcx>
+    fn copy_clone_conditions(&mut self,
+                             obligation: &TraitObligation<'tcx>)
+                             -> BuiltinImplConditions<'tcx>
     {
         // NOTE: binder moved to (*)
         let self_ty = self.infcx.shallow_resolve(
@@ -2551,17 +2543,15 @@ fn confirm_builtin_candidate(&mut self,
         let lang_items = self.tcx().lang_items();
         let obligations = if has_nested {
             let trait_def = obligation.predicate.def_id();
-            let conditions = match trait_def {
-                _ if Some(trait_def) == lang_items.sized_trait() => {
+            let conditions =
+                if Some(trait_def) == lang_items.sized_trait() {
                     self.sized_conditions(obligation)
-                }
-                _ if Some(trait_def) == lang_items.copy_trait() => {
+                } else if Some(trait_def) == lang_items.copy_trait() {
                     self.copy_clone_conditions(obligation)
-                }
-                _ if Some(trait_def) == lang_items.clone_trait() => {
+                } else if Some(trait_def) == lang_items.clone_trait() {
                     self.copy_clone_conditions(obligation)
-                }
-                _ => bug!("unexpected builtin trait {:?}", trait_def)
+                } else {
+                    bug!("unexpected builtin trait {:?}", trait_def)
             };
             let nested = match conditions {
                 BuiltinImplConditions::Where(nested) => nested,
@@ -2608,10 +2598,10 @@ fn confirm_auto_impl_candidate(&mut self,
 
     /// See `confirm_auto_impl_candidate`
     fn vtable_auto_impl(&mut self,
-                           obligation: &TraitObligation<'tcx>,
-                           trait_def_id: DefId,
-                           nested: ty::Binder<Vec<Ty<'tcx>>>)
-                           -> VtableAutoImplData<PredicateObligation<'tcx>>
+                        obligation: &TraitObligation<'tcx>,
+                        trait_def_id: DefId,
+                        nested: ty::Binder<Vec<Ty<'tcx>>>)
+                        -> VtableAutoImplData<PredicateObligation<'tcx>>
     {
         debug!("vtable_auto_impl: nested={:?}", nested);
 
@@ -2731,10 +2721,8 @@ fn confirm_object_candidate(&mut self,
             ty::Dynamic(ref data, ..) => {
                 data.principal().unwrap().with_self_ty(self.tcx(), self_ty)
             }
-            _ => {
-                span_bug!(obligation.cause.span,
-                          "object candidate with non-object");
-            }
+            _ => span_bug!(obligation.cause.span,
+                           "object candidate with non-object")
         };
 
         let mut upcast_trait_ref = None;
@@ -2752,10 +2740,9 @@ fn confirm_object_candidate(&mut self,
             // record it for later.)
             let nonmatching =
                 util::supertraits(tcx, poly_trait_ref)
-                .take_while(|&t| {
-                    match
-                        self.commit_if_ok(
-                            |this, _| this.match_poly_trait_ref(obligation, t))
+                .take_while(|&t|
+                    match self.commit_if_ok(|this, _|
+                        this.match_poly_trait_ref(obligation, t))
                     {
                         Ok(obligations) => {
                             upcast_trait_ref = Some(t);
@@ -2764,16 +2751,13 @@ fn confirm_object_candidate(&mut self,
                         }
                         Err(_) => { true }
                     }
-                });
+                );
 
             // Additionally, for each of the nonmatching predicates that
             // we pass over, we sum up the set of number of vtable
             // entries, so that we can compute the offset for the selected
             // trait.
-            vtable_base =
-                nonmatching.map(|t| tcx.count_own_vtable_entries(t))
-                           .sum();
-
+            vtable_base = nonmatching.map(|t| tcx.count_own_vtable_entries(t)).sum();
         }
 
         VtableObjectData {
@@ -2816,7 +2800,7 @@ fn confirm_fn_pointer_candidate(&mut self, obligation: &TraitObligation<'tcx>)
     fn confirm_generator_candidate(&mut self,
                                    obligation: &TraitObligation<'tcx>)
                                    -> Result<VtableGeneratorData<'tcx, PredicateObligation<'tcx>>,
-                                           SelectionError<'tcx>>
+                                             SelectionError<'tcx>>
     {
         // ok to skip binder because the substs on generator types never
         // touch bound regions, they just capture the in-scope
@@ -2869,10 +2853,11 @@ fn confirm_closure_candidate(&mut self,
     {
         debug!("confirm_closure_candidate({:?})", obligation);
 
-        let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()) {
-            Some(k) => k,
-            None => bug!("closure candidate for non-fn trait {:?}", obligation)
-        };
+        let kind = self.tcx()
+                       .lang_items()
+                       .fn_trait_kind(obligation.predicate.def_id())
+                       .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}",
+                                               obligation));
 
         // ok to skip binder because the substs on closure types never
         // touch bound regions, they just capture the in-scope
@@ -2901,9 +2886,9 @@ fn confirm_closure_candidate(&mut self,
 
         obligations.extend(
             self.confirm_poly_trait_refs(obligation.cause.clone(),
-                                        obligation.param_env,
-                                        obligation.predicate.to_poly_trait_ref(),
-                                        trait_ref)?);
+                                         obligation.param_env,
+                                         obligation.predicate.to_poly_trait_ref(),
+                                         trait_ref)?);
 
         obligations.push(Obligation::new(
             obligation.cause.clone(),
@@ -3008,20 +2993,19 @@ fn confirm_builtin_unsize_candidate(&mut self,
             (_, &ty::Dynamic(ref data, r)) => {
                 let mut object_dids =
                     data.auto_traits().chain(data.principal().map(|p| p.def_id()));
-                if let Some(did) = object_dids.find(|did| {
-                    !tcx.is_object_safe(*did)
-                }) {
+                if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
                     return Err(TraitNotObjectSafe(did))
                 }
 
                 let cause = ObligationCause::new(obligation.cause.span,
                                                  obligation.cause.body_id,
                                                  ObjectCastObligation(target));
-                let mut push = |predicate| {
-                    nested.push(Obligation::with_depth(cause.clone(),
-                                                       obligation.recursion_depth + 1,
-                                                       obligation.param_env,
-                                                       predicate));
+
+                let predicate_to_obligation = |predicate| {
+                    Obligation::with_depth(cause.clone(),
+                                           obligation.recursion_depth + 1,
+                                           obligation.param_env,
+                                           predicate)
                 };
 
                 // Create obligations:
@@ -3030,21 +3014,22 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 //  words, if the object type is Foo+Send, this would create an obligation for the
                 //  Send check.)
                 //  - Projection predicates
-                for predicate in data.iter() {
-                    push(predicate.with_self_ty(tcx, source));
-                }
+                nested.extend(data.iter().map(|d|
+                    predicate_to_obligation(d.with_self_ty(tcx, source))
+                ));
 
                 // We can only make objects from sized types.
                 let tr = ty::TraitRef {
                     def_id: tcx.require_lang_item(lang_items::SizedTraitLangItem),
                     substs: tcx.mk_substs_trait(source, &[]),
                 };
-                push(tr.to_predicate());
+                nested.push(predicate_to_obligation(tr.to_predicate()));
 
                 // If the type is `Foo+'a`, ensures that the type
                 // being cast to `Foo+'a` outlives `'a`:
                 let outlives = ty::OutlivesPredicate(source, r);
-                push(ty::Binder::dummy(outlives).to_predicate());
+                nested.push(predicate_to_obligation(
+                    ty::Binder::dummy(outlives).to_predicate()));
             }
 
             // [T; n] -> [T].
@@ -3069,7 +3054,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 {
@@ -3105,13 +3090,13 @@ fn confirm_builtin_unsize_candidate(&mut self,
 
                 // Check that the source struct with the target's
                 // unsized parameters is equal to the target.
-                let params = substs_a.iter().enumerate().map(|(i, &k)| {
+                let params = substs_a.iter().enumerate().map(|(i, &k)|
                     if ty_params.contains(i) {
                         substs_b.type_at(i).into()
                     } else {
                         k
                     }
-                });
+                );
                 let new_struct = tcx.mk_adt(def, tcx.mk_substs(params));
                 let InferOk { obligations, .. } =
                     self.infcx.at(&obligation.cause, obligation.param_env)
@@ -3236,10 +3221,9 @@ fn match_impl(&mut self,
         let InferOk { obligations, .. } =
             self.infcx.at(&obligation.cause, obligation.param_env)
                       .eq(skol_obligation_trait_ref, impl_trait_ref)
-                      .map_err(|e| {
-                          debug!("match_impl: failed eq_trait_refs due to `{}`", e);
-                          ()
-                      })?;
+                      .map_err(|e|
+                          debug!("match_impl: failed eq_trait_refs due to `{}`", e)
+                      )?;
         nested_obligations.extend(obligations);
 
         if let Err(e) = self.infcx.leak_check(false,
@@ -3288,7 +3272,7 @@ fn fast_reject_trait_refs(&mut self,
     fn match_where_clause_trait_ref(&mut self,
                                     obligation: &TraitObligation<'tcx>,
                                     where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
-                                    -> Result<Vec<PredicateObligation<'tcx>>,()>
+                                    -> Result<Vec<PredicateObligation<'tcx>>, ()>
     {
         self.match_poly_trait_ref(obligation, where_clause_trait_ref)
     }
@@ -3298,7 +3282,7 @@ fn match_where_clause_trait_ref(&mut self,
     fn match_poly_trait_ref(&mut self,
                             obligation: &TraitObligation<'tcx>,
                             poly_trait_ref: ty::PolyTraitRef<'tcx>)
-                            -> Result<Vec<PredicateObligation<'tcx>>,()>
+                            -> Result<Vec<PredicateObligation<'tcx>>, ()>
     {
         debug!("match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}",
                obligation,
@@ -3350,20 +3334,20 @@ fn closure_trait_ref_unnormalized(&mut self,
         // in fact unparameterized (or at least does not reference any
         // regions bound in the obligation). Still probably some
         // refactoring could make this nicer.
-
         self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
                                                      obligation.predicate
-                                                         .skip_binder().self_ty(), // (1)
+                                                               .skip_binder()
+                                                               .self_ty(), // (1)
                                                      closure_type,
                                                      util::TupleArgumentsFlag::No)
             .map_bound(|(trait_ref, _)| trait_ref)
     }
 
     fn generator_trait_ref_unnormalized(&mut self,
-                                      obligation: &TraitObligation<'tcx>,
-                                      closure_def_id: DefId,
-                                      substs: ty::GeneratorSubsts<'tcx>)
-                                      -> ty::PolyTraitRef<'tcx>
+                                        obligation: &TraitObligation<'tcx>,
+                                        closure_def_id: DefId,
+                                        substs: ty::GeneratorSubsts<'tcx>)
+                                        -> ty::PolyTraitRef<'tcx>
     {
         let gen_sig = substs.poly_sig(closure_def_id, self.tcx());
 
@@ -3375,7 +3359,8 @@ fn generator_trait_ref_unnormalized(&mut self,
 
         self.tcx().generator_trait_ref_and_outputs(obligation.predicate.def_id(),
                                                    obligation.predicate
-                                                       .skip_binder().self_ty(), // (1)
+                                                             .skip_binder()
+                                                             .self_ty(), // (1)
                                                    gen_sig)
             .map_bound(|(trait_ref, ..)| trait_ref)
     }
@@ -3453,8 +3438,8 @@ fn impl_or_trait_obligations(&mut self,
 impl<'tcx> TraitObligation<'tcx> {
     #[allow(unused_comparisons)]
     pub fn derived_cause(&self,
-                        variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>)
-                        -> ObligationCause<'tcx>
+                         variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>)
+                         -> ObligationCause<'tcx>
     {
         /*!
          * Creates a cause for obligations that are derived from
index 9343eff9e79b4f2f43407ade6b09ea0e74d85a8e..dbd84397b597d37542a038d9ff1675a9f98b2863 100644 (file)
@@ -100,10 +100,10 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
             }
 
             fulfill_implication(infcx, param_env, source_trait_ref, target_impl)
-                .unwrap_or_else(|_| {
+                .unwrap_or_else(|_|
                     bug!("When translating substitutions for specialization, the expected \
                           specialization failed to hold")
-                })
+                )
         }
         specialization_graph::Node::Trait(..) => source_trait_ref.substs,
     };
@@ -137,17 +137,15 @@ pub fn find_associated_item<'a, 'tcx>(
                 let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id,
                                               substs, node_item.node);
                 let substs = infcx.tcx.erase_regions(&substs);
-                tcx.lift(&substs).unwrap_or_else(|| {
+                tcx.lift(&substs).unwrap_or_else(||
                     bug!("find_method: translate_substs \
                           returned {:?} which contains inference types/regions",
-                         substs);
-                })
+                         substs)
+                )
             });
             (node_item.item.def_id, substs)
         }
-        None => {
-            bug!("{:?} not found in {:?}", item, impl_data.impl_def_id)
-        }
+        None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id)
     }
 }
 
@@ -312,8 +310,7 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
                                                       -> Lrc<specialization_graph::Graph> {
     let mut sg = specialization_graph::Graph::new();
 
-    let mut trait_impls = Vec::new();
-    tcx.for_each_impl(trait_id, |impl_did| trait_impls.push(impl_did));
+    let mut trait_impls = tcx.all_impls(trait_id);
 
     // The coherence checking implementation seems to rely on impls being
     // iterated over (roughly) in definition order, so we are sorting by
@@ -367,9 +364,9 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
                                        "first implementation here".to_string());
                         err.span_label(impl_span,
                                        format!("conflicting implementation{}",
-                                                overlap.self_desc
-                                                    .map_or(String::new(),
-                                                            |ty| format!(" for `{}`", ty))));
+                                               overlap.self_desc
+                                                      .map_or(String::new(),
+                                                          |ty| format!(" for `{}`", ty))));
                     }
                     Err(cname) => {
                         let msg = match to_pretty_impl_header(tcx, overlap.with_impl) {
@@ -428,7 +425,9 @@ fn to_pretty_impl_header(tcx: TyCtxt, impl_def_id: DefId) -> Option<String> {
     // The predicates will contain default bounds like `T: Sized`. We need to
     // remove these bounds, and add `T: ?Sized` to any untouched type parameters.
     let predicates = tcx.predicates_of(impl_def_id).predicates;
-    let mut pretty_predicates = Vec::with_capacity(predicates.len());
+    let mut pretty_predicates = Vec::with_capacity(
+        predicates.len() + types_without_default_bounds.len());
+
     for p in predicates {
         if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() {
             if Some(poly_trait_ref.def_id()) == sized_trait {
@@ -438,9 +437,11 @@ fn to_pretty_impl_header(tcx: TyCtxt, impl_def_id: DefId) -> Option<String> {
         }
         pretty_predicates.push(p.to_string());
     }
+
     pretty_predicates.extend(
         types_without_default_bounds.iter().map(|ty| format!("{}: ?Sized", ty))
     );
+
     if !pretty_predicates.is_empty() {
         write!(w, "\n  where {}", pretty_predicates.join(", ")).unwrap();
     }
index a7652574c1a2e9cb855f20234febb849be7c3d00..756f55545bc45a87090a52085df7588197cbf1a8 100644 (file)
@@ -390,11 +390,12 @@ fn next(&mut self) -> Option<Node> {
         let cur = self.current_source.take();
         if let Some(Node::Impl(cur_impl)) = cur {
             let parent = self.specialization_graph.parent(cur_impl);
-            if parent == self.trait_def_id {
-                self.current_source = Some(Node::Trait(parent));
+
+            self.current_source = if parent == self.trait_def_id {
+                Some(Node::Trait(parent))
             } else {
-                self.current_source = Some(Node::Impl(parent));
-            }
+                Some(Node::Impl(parent))
+            };
         }
         cur
     }
index 10e930d1c92d9a58b3f08632f86b97a27db9aa06..a4230707b70cae5b449760c5812d58bdc5195111 100644 (file)
@@ -166,10 +166,10 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
         match *self {
             super::Unimplemented => Some(super::Unimplemented),
             super::OutputTypeParameterMismatch(a, b, ref err) => {
-                tcx.lift(&(a, b)).and_then(|(a, b)| {
+                tcx.lift(&(a, b)).and_then(|(a, b)|
                     tcx.lift(err)
                         .map(|err| super::OutputTypeParameterMismatch(a, b, err))
-                })
+                )
             }
             super::TraitNotObjectSafe(def_id) => Some(super::TraitNotObjectSafe(def_id)),
             super::ConstEvalFailure(ref err) => tcx.lift(&**err).map(|err| super::ConstEvalFailure(
@@ -193,10 +193,10 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
             super::ReferenceOutlivesReferent(ty) => {
                 tcx.lift(&ty).map(super::ReferenceOutlivesReferent)
             }
-            super::ObjectTypeBound(ty, r) => tcx.lift(&ty).and_then(|ty| {
+            super::ObjectTypeBound(ty, r) => tcx.lift(&ty).and_then(|ty|
                 tcx.lift(&r)
-                    .and_then(|r| Some(super::ObjectTypeBound(ty, r)))
-            }),
+                   .and_then(|r| Some(super::ObjectTypeBound(ty, r)))
+            ),
             super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation),
             super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
             super::TupleInitializerSized => Some(super::TupleInitializerSized),
@@ -245,13 +245,13 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
 impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> {
     type Lifted = traits::DerivedObligationCause<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.parent_trait_ref).and_then(|trait_ref| {
+        tcx.lift(&self.parent_trait_ref).and_then(|trait_ref|
             tcx.lift(&*self.parent_code)
-                .map(|code| traits::DerivedObligationCause {
-                    parent_trait_ref: trait_ref,
-                    parent_code: Rc::new(code),
-                })
-        })
+               .map(|code| traits::DerivedObligationCause {
+                   parent_trait_ref: trait_ref,
+                   parent_code: Rc::new(code),
+               })
+        )
     }
 }
 
@@ -275,40 +275,40 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
                 impl_def_id,
                 substs,
                 nested,
-            }) => tcx.lift(&substs).map(|substs| {
+            }) => tcx.lift(&substs).map(|substs|
                 traits::VtableImpl(traits::VtableImplData {
                     impl_def_id,
                     substs,
                     nested,
                 })
-            }),
+            ),
             traits::VtableAutoImpl(t) => Some(traits::VtableAutoImpl(t)),
             traits::VtableGenerator(traits::VtableGeneratorData {
                 generator_def_id,
                 substs,
                 nested,
-            }) => tcx.lift(&substs).map(|substs| {
+            }) => tcx.lift(&substs).map(|substs|
                 traits::VtableGenerator(traits::VtableGeneratorData {
                     generator_def_id: generator_def_id,
                     substs: substs,
                     nested: nested,
                 })
-            }),
+            ),
             traits::VtableClosure(traits::VtableClosureData {
                 closure_def_id,
                 substs,
                 nested,
-            }) => tcx.lift(&substs).map(|substs| {
+            }) => tcx.lift(&substs).map(|substs|
                 traits::VtableClosure(traits::VtableClosureData {
                     closure_def_id,
                     substs,
                     nested,
                 })
-            }),
+            ),
             traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) => {
-                tcx.lift(&fn_ty).map(|fn_ty| {
+                tcx.lift(&fn_ty).map(|fn_ty|
                     traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested })
-                })
+                )
             }
             traits::VtableParam(n) => Some(traits::VtableParam(n)),
             traits::VtableBuiltin(n) => Some(traits::VtableBuiltin(n)),
@@ -316,13 +316,13 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
                 upcast_trait_ref,
                 vtable_base,
                 nested,
-            }) => tcx.lift(&upcast_trait_ref).map(|trait_ref| {
+            }) => tcx.lift(&upcast_trait_ref).map(|trait_ref|
                 traits::VtableObject(traits::VtableObjectData {
                     upcast_trait_ref: trait_ref,
                     vtable_base,
                     nested,
                 })
-            }),
+            ),
         }
     }
 }
index 40f13ac06f56fbed1439d69e2df4f9793004bafc..2ca8214daf768cd829550a99e5184a63f4c46a7f 100644 (file)
@@ -346,8 +346,7 @@ fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
                 Some(ty::Predicate::Trait(data)) => {
                     return Some(data.to_poly_trait_ref());
                 }
-                Some(_) => {
-                }
+                Some(_) => {}
             }
         }
     }
index d1f37250379723e85d380e6e420c268d64962a95..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;
@@ -872,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
@@ -1247,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(),
@@ -1432,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
@@ -1567,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> {
index d9e3bdaf266a9a76a8d19210b18f8a78a321edbe..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};
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 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 6332080a1836c427f8308a5a0843c6cd288de1d2..fd3f7a12376d8440724f85d2e21c0b9fbfe0ca8a 100644 (file)
@@ -138,6 +138,15 @@ pub fn for_each_relevant_impl<F: FnMut(DefId)>(self,
             }
         }
     }
+
+    /// Return a vector containing all impls
+    pub fn all_impls(self, def_id: DefId) -> Vec<DefId> {
+        let impls = self.trait_impls_of(def_id);
+
+        impls.blanket_impls.iter().chain(
+            impls.non_blanket_impls.values().flatten()
+        ).cloned().collect()
+    }
 }
 
 // Query provider for `trait_impls_of`.
index 5ffb77dda688a923c03a22e85a5e084089bf9a5a..9a1add26bb0b4bf24b80816145343ef97aba9e41 100644 (file)
@@ -769,7 +769,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     write!(f, "{}", br)
                 }
                 ty::ReScope(scope) if cx.identify_regions => {
-                    match scope.data() {
+                    match scope.data {
                         region::ScopeData::Node =>
                             write!(f, "'{}s", scope.item_local_id().as_usize()),
                         region::ScopeData::CallSite =>
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 95be2d82123a7c619be090ffabb789dbc4973235..c03180c02fe634f5d1c6b5c62a304cd2eb40fcb4 100644 (file)
@@ -1071,6 +1071,10 @@ fn finalize(&mut self) -> Command {
         // Make the default table accessible
         self.cmd.arg("--export-table");
 
+        // Rust code should never have warnings, and warnings are often
+        // indicative of bugs, let's prevent them.
+        self.cmd.arg("--fatal-warnings");
+
         let mut cmd = Command::new("");
         ::std::mem::swap(&mut cmd, &mut self.cmd);
         cmd
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 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();
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/bitvec.rs b/src/librustc_data_structures/bitvec.rs
deleted file mode 100644 (file)
index 52cc347..0000000
+++ /dev/null
@@ -1,781 +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 rustc_serialize;
-use std::iter;
-use std::marker::PhantomData;
-use std::slice;
-
-pub type Word = u64;
-pub const WORD_BYTES: usize = ::std::mem::size_of::<Word>();
-pub const WORD_BITS: usize = WORD_BYTES * 8;
-
-/// A very simple BitArray type.
-///
-/// It does not support resizing after creation; use `BitVector` for that.
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct BitArray<C: Idx> {
-    data: Vec<Word>,
-    marker: PhantomData<C>,
-}
-
-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 = num_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> {
-        BitArray::new_empty(num_bits)
-    }
-
-    #[inline]
-    pub fn new_empty(num_bits: usize) -> BitArray<C> {
-        let num_words = num_words(num_bits);
-        BitArray {
-            data: vec![0; num_words],
-            marker: PhantomData,
-        }
-    }
-
-    #[inline]
-    pub fn new_filled(num_bits: usize) -> BitArray<C> {
-        let num_words = num_words(num_bits);
-        let mut result = BitArray {
-            data: vec![!0; num_words],
-            marker: PhantomData,
-        };
-        result.clear_above(num_bits);
-        result
-    }
-
-    #[inline]
-    pub fn clear(&mut self) {
-        for p in &mut self.data {
-            *p = 0;
-        }
-    }
-
-    /// Sets all elements up to `num_bits`.
-    pub fn set_up_to(&mut self, num_bits: usize) {
-        for p in &mut self.data {
-            *p = !0;
-        }
-        self.clear_above(num_bits);
-    }
-
-    /// Clear all elements above `num_bits`.
-    fn clear_above(&mut self, num_bits: usize) {
-        let first_clear_block = num_bits / WORD_BITS;
-
-        if first_clear_block < self.data.len() {
-            // Within `first_clear_block`, the `num_bits % WORD_BITS` LSBs
-            // should remain.
-            let mask = (1 << (num_bits % WORD_BITS)) - 1;
-            self.data[first_clear_block] &= mask;
-
-            // All the blocks above `first_clear_block` are fully cleared.
-            for b in &mut self.data[first_clear_block + 1..] {
-                *b = 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 = !0;
-        }
-    }
-
-    /// 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
-    }
-
-    pub fn words(&self) -> &[Word] {
-        &self.data
-    }
-
-    pub fn words_mut(&mut self) -> &mut [Word] {
-        &mut self.data
-    }
-
-    /// Iterates over indexes of set bits in a sorted order
-    #[inline]
-    pub fn iter<'a>(&'a self) -> BitIter<'a, C> {
-        BitIter {
-            cur: None,
-            iter: self.data.iter().enumerate(),
-            marker: PhantomData,
-        }
-    }
-}
-
-impl<T: Idx> rustc_serialize::Encodable for BitArray<T> {
-    fn encode<E: rustc_serialize::Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
-        self.data.encode(encoder)
-    }
-}
-
-impl<T: Idx> rustc_serialize::Decodable for BitArray<T> {
-    fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<BitArray<T>, D::Error> {
-        let words: Vec<Word> = rustc_serialize::Decodable::decode(d)?;
-        Ok(BitArray {
-            data: words,
-            marker: PhantomData,
-        })
-    }
-}
-
-pub struct BitIter<'a, C: Idx> {
-    cur: Option<(Word, usize)>,
-    iter: iter::Enumerate<slice::Iter<'a, Word>>,
-    marker: PhantomData<C>
-}
-
-impl<'a, C: Idx> Iterator for BitIter<'a, C> {
-    type Item = C;
-    fn next(&mut self) -> Option<C> {
-        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(C::new(bit_pos + offset))
-                }
-            }
-
-            let (i, word) = self.iter.next()?;
-            self.cur = Some((*word, WORD_BITS * i));
-        }
-    }
-}
-
-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;
-}
-
-#[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_elem, in_elem) in out_vec.iter_mut().zip(in_vec.iter()) {
-        let old_val = *out_elem;
-        let new_val = op.join(old_val, *in_elem);
-        *out_elem = new_val;
-        changed |= old_val != new_val;
-    }
-    changed
-}
-
-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 }
-}
-
-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..WORD_BYTES { // 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
-}
-
-/// A resizable BitVector type.
-#[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
-        }
-    }
-}
-
-/// 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 = num_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 = 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, 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 {
-            cur: None,
-            iter: self.vector[start..end].iter().enumerate(),
-            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 num_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 test_clear_above() {
-    use std::cmp;
-
-    for i in 0..256 {
-        let mut idx_buf: BitArray<usize> = BitArray::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![BitArray::new_empty(128), BitArray::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 = BitArray::new_filled(i);
-        let elems: Vec<usize> = idx_buf.iter().collect();
-        let expected: Vec<usize> = (0..i).collect();
-        assert_eq!(elems, expected);
-    }
-}
-
-#[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 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 5ba8c15..0000000
+++ /dev/null
@@ -1,358 +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::mem;
-use std::slice;
-use bitvec::{bitwise, BitArray, BitIter, Intersect, Subtract, Union, Word, WORD_BITS};
-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(Clone, Eq, PartialEq)]
-pub struct IdxSet<T: Idx>(BitArray<T>);
-
-impl<T: Idx> rustc_serialize::Encodable for IdxSet<T> {
-    fn encode<E: rustc_serialize::Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
-        self.0.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> {
-        Ok(IdxSet(rustc_serialize::Decodable::decode(d)?))
-    }
-}
-
-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> {
-    /// Creates set holding no elements.
-    pub fn new_empty(domain_size: usize) -> Self {
-        IdxSet(BitArray::new_empty(domain_size))
-    }
-
-    /// Creates set holding every element whose index falls in range 0..domain_size.
-    pub fn new_filled(domain_size: usize) -> Self {
-        IdxSet(BitArray::new_filled(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.words().len() * WORD_BITS;
-
-        // 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) {
-        self.0.clear();
-    }
-
-    /// Sets all elements up to `domain_size`
-    pub fn set_up_to(&mut self, domain_size: usize) {
-        self.0.set_up_to(domain_size);
-    }
-
-    /// Removes `elem` from the set `self`; returns true iff this changed `self`.
-    pub fn remove(&mut self, elem: &T) -> bool {
-        self.0.remove(*elem)
-    }
-
-    /// Adds `elem` to the set `self`; returns true iff this changed `self`.
-    pub fn add(&mut self, elem: &T) -> bool {
-        self.0.insert(*elem)
-    }
-
-    /// Returns true iff set `self` contains `elem`.
-    pub fn contains(&self, elem: &T) -> bool {
-        self.0.contains(*elem)
-    }
-
-    pub fn words(&self) -> &[Word] {
-        self.0.words()
-    }
-
-    pub fn words_mut(&mut self) -> &mut [Word] {
-        self.0.words_mut()
-    }
-
-    /// 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) -> BitIter<T> {
-        self.0.iter()
-    }
-}
-
-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)
-    }
-}
-
-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) -> slice::Iter<T> {
-        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
-    }
-}
-
-/// 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(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(),
-        }
-    }
-}
index 9435cb3184293acb020899727964e16c5d964a13..70b960ac351c0031069b153b00cff8cedfb5402d 100644 (file)
 pub use rustc_serialize::hex::ToHex;
 
 pub mod svh;
-pub mod array_vec;
 pub mod base_n;
-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 ff35371976aa49e3bdb024e1d2e928c5e6530ae0..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),
@@ -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 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 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 4382a3c12c961e15ffc3e91b2d900529535adc7a..23f941f744b3b88fead2bb8cfcc3159d8d0480ae 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 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 977b6a71f5e269f7d8440a22a427db7a28df14e7..9187cb97e69e52f387e37605ae3df7a00b780aa1 100644 (file)
@@ -17,7 +17,7 @@
 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;
@@ -38,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));
@@ -49,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
@@ -57,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),
@@ -80,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(
@@ -167,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();
+            }
         }
     }
 
@@ -564,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);
 
@@ -702,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 a4900ab57f58861d37043996794cd322e66e2b0d..16bb1ef78dc6f85c2000609280aa2f35b8e1e966 100644 (file)
@@ -15,7 +15,7 @@
 
 use rustc::mir::{BasicBlock, Location};
 use rustc::ty::RegionVid;
-use rustc_data_structures::bitvec::BitIter;
+use rustc_data_structures::bit_set::BitIter;
 
 use borrow_check::location::LocationIndex;
 
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 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 d46b0813ca703e840c6fb4331fbd470a78e5bc79..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 1406183955bd430ce962fc556893714165d9d557..cc5b08f2a90474776ee07ef381c9b0f06d8fdb0e 100644 (file)
@@ -565,7 +565,7 @@ 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() {
+        assert!(match self.scopes[1].region_scope.data {
             region::ScopeData::Arguments => true,
             _ => false,
         });
index 39643af77a17845306d25780004dabddb36221f8..d815bfedc3713237ea72d6ae3102a50d940d4b1d 100644 (file)
@@ -12,8 +12,7 @@
 //! locations.
 
 use rustc::mir::{BasicBlock, Location};
-use rustc_data_structures::bitvec::BitIter;
-use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet};
+use rustc_data_structures::bit_set::{BitIter, BitSet, HybridBitSet};
 
 use dataflow::{BitDenotation, BlockSets, DataflowResults};
 use dataflow::move_paths::{HasMoveData, MovePathIndex};
@@ -76,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>
@@ -105,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,
@@ -121,7 +120,7 @@ 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)
     }
 
@@ -224,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();
@@ -236,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 9487147ea9df95e4ee193a763196aaa565e22068..45baab844abc35cdcf1e517e6bbe84223f1ee2b3 100644 (file)
@@ -12,7 +12,6 @@
 
 use syntax::ast::NodeId;
 use rustc::mir::{BasicBlock, Mir};
-use rustc_data_structures::bitvec::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 66f020faa87df8e31ac0f2e3541de4593c533801..010ffafc4bd60db7e057529b301a01cf478ec368 100644 (file)
 use rustc::ty::{RegionKind, RegionVid};
 use rustc::ty::RegionKind::ReScope;
 
-use rustc_data_structures::bitvec::{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 c8f704798529bd5151f13652bf088ec0c2012103..984d1f686d987bfeb645d3ce1e15b8004fe5add2 100644 (file)
@@ -14,8 +14,7 @@
 
 use rustc::ty::TyCtxt;
 use rustc::mir::{self, Mir, Location};
-use rustc_data_structures::bitvec::{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 49d75d31fc7fb95f1896b668ed93d765e4cde690..1e362e6f0dccfeb55b816d62192216370f1d1589 100644 (file)
@@ -10,8 +10,7 @@
 
 use syntax::ast::{self, MetaItem};
 
-use rustc_data_structures::bitvec::{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 b0a60fedfbbc2f64b8bc6fcabeb2a2c873ff04e5..2ab0a57a855419f23dae98a2d220ebaed70c32ba 100644 (file)
@@ -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(
-                            block_id,
-                            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 510e7eb9c63f79e483b6d5b8a898786066560c65..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,
@@ -581,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)
@@ -590,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)
             }
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 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 8bb93d09a2aa2babbb20a14809a839d9f4d29177..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)?;
@@ -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)?)
     }
 
index 64e0aeaaab7f042249f2717a6794a3ae91e0364f..0f03aa097c9dfdb64ff8e0fef412f01e8a566fed 100644 (file)
@@ -316,7 +316,10 @@ pub fn mplace_field(
         };
 
         let ptr = base.ptr.ptr_offset(offset, self)?;
-        let align = base.align.min(field_layout.align); // only use static information
+        let align = base.align
+            // We do not look at `base.layout.align` nor `field_layout.align`, unlike
+            // codegen -- mostly to see if we can get away with that
+            .restrict_for_offset(offset); // must be last thing that happens
 
         Ok(MPlaceTy { mplace: MemPlace { ptr, align, extra }, layout: field_layout })
     }
@@ -612,7 +615,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 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 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 01edfd2bfc9f220a63192f962b350900c9edfbd0..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;
         }
 
@@ -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 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 f0ff8c419fd461975aa3bb9902513d53c554cfb9..327eaacdf163bee302fc7191409b3dae2fdf4c50 100644 (file)
@@ -65,7 +65,6 @@
 use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
 use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path};
 use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
-use syntax::feature_gate::{feature_err, GateIssue};
 use syntax::ptr::P;
 
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
@@ -1429,8 +1428,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)>,
 
@@ -1458,9 +1455,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,
@@ -1471,9 +1465,6 @@ pub struct Resolver<'a, 'b: 'a> {
     current_type_ascription: Vec<Span>,
 
     injected_crate: Option<Module<'a>>,
-
-    /// Only supposed to be used by rustdoc, otherwise should be false.
-    pub ignore_extern_prelude_feature: bool,
 }
 
 /// Nothing really interesting here, it just provides memory for the rest of the crate.
@@ -1674,13 +1665,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(),
@@ -1743,7 +1735,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,
@@ -1765,14 +1756,12 @@ 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,
             unused_macros: FxHashSet(),
             current_type_ascription: Vec::new(),
             injected_crate: None,
-            ignore_extern_prelude_feature: false,
         }
     }
 
@@ -1975,14 +1964,9 @@ fn resolve_ident_in_lexical_scope(&mut self,
         if !module.no_implicit_prelude {
             // `record_used` means that we don't try to load crates during speculative resolution
             if record_used && ns == TypeNS && self.extern_prelude.contains(&ident.name) {
-                if !self.session.features_untracked().extern_prelude &&
-                   !self.ignore_extern_prelude_feature {
-                    feature_err(&self.session.parse_sess, "extern_prelude",
-                                ident.span, GateIssue::Language,
-                                "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);
@@ -2010,13 +1994,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()) {
@@ -3303,9 +3280,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  {
@@ -3584,7 +3564,6 @@ fn resolve_path_with_parent_scope(
                     }
                     if name == keywords::Extern.name() ||
                        name == keywords::CrateRoot.name() &&
-                       self.session.features_untracked().extern_absolute_paths &&
                        self.session.rust_2018() {
                         module = Some(ModuleOrUniformRoot::UniformRoot(name));
                         continue;
@@ -3723,12 +3702,6 @@ fn lint_if_path_starts_with_module(
             return
         }
 
-        // In the 2015 edition there's no use in emitting lints unless the
-        // crate's already enabled the feature that we're going to suggest
-        if !self.session.features_untracked().crate_in_paths {
-            return
-        }
-
         let (diag_id, diag_span) = match crate_lint {
             CrateLint::No => return,
             CrateLint::SimplePath(id) => (id, path_span),
@@ -4425,17 +4398,26 @@ fn lookup_import_candidates<FilterFn>(&mut self,
             )
         );
 
-        if self.session.features_untracked().extern_prelude {
+        if self.session.rust_2018() {
             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 => {}
+                }
             }
         }
 
@@ -4597,7 +4579,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 {
@@ -4821,7 +4802,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 d955a21ef233256c71cb4f1ae26f2a740c71e654..35d96b9302b43229575ebec76abb445b2c64e48c 100644 (file)
 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,14 +109,6 @@ 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,
-}
-
 // 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.
@@ -341,21 +332,30 @@ 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;
@@ -682,14 +682,6 @@ enum WhereToResolve<'a> {
                 }
                 WhereToResolve::ExternPrelude => {
                     if use_prelude && self.extern_prelude.contains(&ident.name) {
-                        if !self.session.features_untracked().extern_prelude &&
-                           !self.ignore_extern_prelude_feature {
-                            feature_err(&self.session.parse_sess, "extern_prelude",
-                                        ident.span, GateIssue::Language,
-                                        "access to extern crates through prelude is experimental")
-                                        .emit();
-                        }
-
                         let crate_id =
                             self.crate_loader.process_path_extern(ident.name, ident.span);
                         let crate_root =
@@ -980,7 +972,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);
                     }
                 }
             };
@@ -1132,69 +1123,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 == CrateNum::BuiltinMacros { 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 e7d3a8ef661673f4d98afddd55d8ea9930e4cbcd..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 })
@@ -738,7 +746,7 @@ struct UniformPathsCanaryResults<'a> {
             // 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() {
-                return;
+                continue;
             }
 
             {
@@ -753,7 +761,7 @@ struct UniformPathsCanaryResults<'a> {
                 let possible_resultions =
                     1 + all_results.filter(|&def| def != first).count();
                 if possible_resultions <= 1 {
-                    return;
+                    continue;
                 }
             }
 
index 8747f239d3418885b9bbc3f1b1a2e1f0212a9d53..c71ad5ff21da03a885500ff0897cb48f4c8955d7 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use spec::{LinkerFlavor, Target, TargetResult, PanicStrategy, LldFlavor};
+use spec::{LinkerFlavor, Target, TargetResult, PanicStrategy};
 
 pub fn target() -> TargetResult {
     let mut base = super::windows_msvc_base::opts();
@@ -17,7 +17,6 @@ pub fn target() -> TargetResult {
 
     // FIXME: this shouldn't be panic=abort, it should be panic=unwind
     base.panic_strategy = PanicStrategy::Abort;
-    base.linker = Some("rust-lld".to_owned());
 
     Ok(Target {
         llvm_target: "aarch64-pc-windows-msvc".to_string(),
@@ -29,7 +28,7 @@ pub fn target() -> TargetResult {
         target_os: "windows".to_string(),
         target_env: "msvc".to_string(),
         target_vendor: "pc".to_string(),
-        linker_flavor: LinkerFlavor::Lld(LldFlavor::Link),
+        linker_flavor: LinkerFlavor::Msvc,
         options: base,
     })
 }
index 7fe1af819512951ec02cd061c4e54585d66b2338..a6618efebb31017bf933de30bace186678c546e4 100644 (file)
@@ -11,9 +11,9 @@
 //! New recursive solver modeled on Chalk's recursive solver. Most of
 //! the guts are broken up into modules; see the comments in those modules.
 
-#![feature(crate_in_paths)]
+#![cfg_attr(stage0, feature(crate_in_paths))]
 #![feature(crate_visibility_modifier)]
-#![feature(extern_prelude)]
+#![cfg_attr(stage0, feature(extern_prelude))]
 #![feature(in_band_lifetimes)]
 #![cfg_attr(not(stage0), feature(nll))]
 
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 a283e032e0e023a11654a66d81575c0300a236bf..f2c20238734e63b2f54ff89be711a240e8679c06 100644 (file)
@@ -504,7 +504,7 @@ fn sig_of_closure_with_mismatched_number_of_arguments(
             .sig
             .inputs()
             .iter()
-            .map(|ty| ArgKind::from_expected_ty(ty))
+            .map(|ty| ArgKind::from_expected_ty(ty, None))
             .collect();
         let (closure_span, found_args) = self.get_fn_like_arguments(expr_map_node);
         let expected_span = expected_sig.cause_span.unwrap_or(closure_span);
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 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 aa27fe528e1fd19d01542efd73fa8cab098817b2..0dc7bc75c3d40673be192692c7fac144c19dfe6e 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 {
@@ -3344,11 +3347,34 @@ fn check_field(&self,
                                 }
                             };
                     }
+                    ty::Array(_, len) => {
+                        if let (Some(len), Ok(user_index)) = (
+                            len.assert_usize(self.tcx),
+                            field.as_str().parse::<u64>()
+                        ) {
+                            let base = self.tcx.hir.node_to_pretty_string(base.id);
+                            let help = "instead of using tuple indexing, use array indexing";
+                            let suggestion = format!("{}[{}]", base, field);
+                            let applicability = if len < user_index {
+                                Applicability::MachineApplicable
+                            } else {
+                                Applicability::MaybeIncorrect
+                            };
+                            err.span_suggestion_with_applicability(
+                                expr.span, help, suggestion, applicability
+                            );
+                        }
+                    }
                     ty::RawPtr(..) => {
                         let base = self.tcx.hir.node_to_pretty_string(base.id);
                         let msg = format!("`{}` is a native pointer; try dereferencing it", base);
                         let suggestion = format!("(*{}).{}", base, field);
-                        err.span_suggestion(field.span, &msg, suggestion);
+                        err.span_suggestion_with_applicability(
+                            field.span,
+                            &msg,
+                            suggestion,
+                            Applicability::MaybeIncorrect,
+                        );
                     }
                     _ => {}
                 }
@@ -4716,7 +4742,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) {
@@ -4746,7 +4777,12 @@ pub fn suggest_ref_or_into(
                         }
                     }) .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,
+                    );
                 }
             }
         }
index 5004880ce47b8bb1967176633a8600a43c4e9e9b..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;
@@ -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 e163fc68cbda73b4d20917f0fb9086be1eb4554d..845bfad7807d32734be3695cd9af68e3221b66d6 100644 (file)
@@ -11,3 +11,4 @@ path = "lib.rs"
 pulldown-cmark = { version = "0.1.2", default-features = false }
 minifier = "0.0.19"
 tempfile = "3"
+parking_lot = "0.6.4"
index e7e371cd5678569fafbbc64bf074eaf495daf8df..34c4c70159f3abf36611b782a622c81104317a02 100644 (file)
@@ -69,7 +69,7 @@ pub fn get_blanket_impls<F>(
         let real_name = name.clone().map(|name| Ident::from_str(&name));
         let param_env = self.cx.tcx.param_env(def_id);
         for &trait_def_id in self.cx.all_traits.iter() {
-            if !self.cx.access_levels.borrow().is_doc_reachable(trait_def_id) ||
+            if !self.cx.renderinfo.borrow().access_levels.is_doc_reachable(trait_def_id) ||
                self.cx.generated_synthetics
                       .borrow_mut()
                       .get(&(def_id, trait_def_id))
index 507461f2ea175f9a24e1bd4d4537411e524a310d..1ea130cf16ae2f4e8e4cc29679883da520c85e99 100644 (file)
@@ -29,8 +29,6 @@
     self,
     GetDefId,
     ToSource,
-    get_auto_traits_with_def_id,
-    get_blanket_impls_with_def_id,
 };
 
 use super::Clean;
@@ -56,7 +54,7 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa
     let inner = match def {
         Def::Trait(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Trait);
-            ret.extend(build_impls(cx, did, false));
+            ret.extend(build_impls(cx, did));
             clean::TraitItem(build_external_trait(cx, did))
         }
         Def::Fn(did) => {
@@ -65,27 +63,27 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa
         }
         Def::Struct(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Struct);
-            ret.extend(build_impls(cx, did, true));
+            ret.extend(build_impls(cx, did));
             clean::StructItem(build_struct(cx, did))
         }
         Def::Union(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Union);
-            ret.extend(build_impls(cx, did, true));
+            ret.extend(build_impls(cx, did));
             clean::UnionItem(build_union(cx, did))
         }
         Def::TyAlias(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Typedef);
-            ret.extend(build_impls(cx, did, false));
+            ret.extend(build_impls(cx, did));
             clean::TypedefItem(build_type_alias(cx, did), false)
         }
         Def::Enum(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Enum);
-            ret.extend(build_impls(cx, did, true));
+            ret.extend(build_impls(cx, did));
             clean::EnumItem(build_enum(cx, did))
         }
         Def::ForeignTy(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Foreign);
-            ret.extend(build_impls(cx, did, false));
+            ret.extend(build_impls(cx, did));
             clean::ForeignTypeItem
         }
         // Never inline enum variants but leave them shown as re-exports.
@@ -159,12 +157,11 @@ pub fn load_attrs(cx: &DocContext, did: DefId) -> clean::Attributes {
 /// These names are used later on by HTML rendering to generate things like
 /// source links back to the original item.
 pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
+    let mut crate_name = cx.tcx.crate_name(did.krate).to_string();
     if did.is_local() {
-        debug!("record_extern_fqn(did={:?}, kind+{:?}): def_id is local, aborting", did, kind);
-        return;
+        crate_name = cx.crate_name.clone().unwrap_or(crate_name);
     }
 
-    let crate_name = cx.tcx.crate_name(did.krate).to_string();
     let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| {
         // extern blocks have an empty name
         let s = elem.data.to_string();
@@ -179,7 +176,12 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
     } else {
         once(crate_name).chain(relative).collect()
     };
-    cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind));
+
+    if did.is_local() {
+        cx.renderinfo.borrow_mut().exact_paths.insert(did, fqn);
+    } else {
+        cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind));
+    }
 }
 
 pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait {
@@ -271,7 +273,7 @@ fn build_type_alias(cx: &DocContext, did: DefId) -> clean::Typedef {
     }
 }
 
-pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec<clean::Item> {
+pub fn build_impls(cx: &DocContext, did: DefId) -> Vec<clean::Item> {
     let tcx = cx.tcx;
     let mut impls = Vec::new();
 
@@ -279,85 +281,6 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec<clean:
         build_impl(cx, did, &mut impls);
     }
 
-    if auto_traits {
-        let auto_impls = get_auto_traits_with_def_id(cx, did);
-        {
-            let mut renderinfo = cx.renderinfo.borrow_mut();
-            let new_impls: Vec<clean::Item> = auto_impls.into_iter()
-                .filter(|i| renderinfo.inlined.insert(i.def_id)).collect();
-
-            impls.extend(new_impls);
-        }
-        impls.extend(get_blanket_impls_with_def_id(cx, did));
-    }
-
-    // If this is the first time we've inlined something from another crate, then
-    // we inline *all* impls from all the crates into this crate. Note that there's
-    // currently no way for us to filter this based on type, and we likely need
-    // many impls for a variety of reasons.
-    //
-    // Primarily, the impls will be used to populate the documentation for this
-    // type being inlined, but impls can also be used when generating
-    // documentation for primitives (no way to find those specifically).
-    if cx.populated_all_crate_impls.get() {
-        return impls;
-    }
-
-    cx.populated_all_crate_impls.set(true);
-
-    for &cnum in tcx.crates().iter() {
-        for did in tcx.all_trait_implementations(cnum).iter() {
-            build_impl(cx, *did, &mut impls);
-        }
-    }
-
-    // Also try to inline primitive impls from other crates.
-    let lang_items = tcx.lang_items();
-    let primitive_impls = [
-        lang_items.isize_impl(),
-        lang_items.i8_impl(),
-        lang_items.i16_impl(),
-        lang_items.i32_impl(),
-        lang_items.i64_impl(),
-        lang_items.i128_impl(),
-        lang_items.usize_impl(),
-        lang_items.u8_impl(),
-        lang_items.u16_impl(),
-        lang_items.u32_impl(),
-        lang_items.u64_impl(),
-        lang_items.u128_impl(),
-        lang_items.f32_impl(),
-        lang_items.f64_impl(),
-        lang_items.f32_runtime_impl(),
-        lang_items.f64_runtime_impl(),
-        lang_items.char_impl(),
-        lang_items.str_impl(),
-        lang_items.slice_impl(),
-        lang_items.slice_u8_impl(),
-        lang_items.str_alloc_impl(),
-        lang_items.slice_alloc_impl(),
-        lang_items.slice_u8_alloc_impl(),
-        lang_items.const_ptr_impl(),
-        lang_items.mut_ptr_impl(),
-    ];
-
-    for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {
-        if !def_id.is_local() {
-            build_impl(cx, def_id, &mut impls);
-
-            let auto_impls = get_auto_traits_with_def_id(cx, def_id);
-            let blanket_impls = get_blanket_impls_with_def_id(cx, def_id);
-            let mut renderinfo = cx.renderinfo.borrow_mut();
-
-            let new_impls: Vec<clean::Item> = auto_impls.into_iter()
-                .chain(blanket_impls.into_iter())
-                .filter(|i| renderinfo.inlined.insert(i.def_id))
-                .collect();
-
-            impls.extend(new_impls);
-        }
-    }
-
     impls
 }
 
@@ -372,30 +295,60 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
 
     // Only inline impl if the implemented trait is
     // reachable in rustdoc generated documentation
-    if let Some(traitref) = associated_trait {
-        if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) {
-            return
+    if !did.is_local() {
+        if let Some(traitref) = associated_trait {
+            if !cx.renderinfo.borrow().access_levels.is_doc_reachable(traitref.def_id) {
+                return
+            }
         }
     }
 
-    let for_ = tcx.type_of(did).clean(cx);
+    let for_ = if let Some(nodeid) = tcx.hir.as_local_node_id(did) {
+        match tcx.hir.expect_item(nodeid).node {
+            hir::ItemKind::Impl(.., ref t, _) => {
+                t.clean(cx)
+            }
+            _ => panic!("did given to build_impl was not an impl"),
+        }
+    } else {
+        tcx.type_of(did).clean(cx)
+    };
 
     // Only inline impl if the implementing type is
     // reachable in rustdoc generated documentation
-    if let Some(did) = for_.def_id() {
-        if !cx.access_levels.borrow().is_doc_reachable(did) {
-            return
+    if !did.is_local() {
+        if let Some(did) = for_.def_id() {
+            if !cx.renderinfo.borrow().access_levels.is_doc_reachable(did) {
+                return
+            }
         }
     }
 
     let predicates = tcx.predicates_of(did);
-    let trait_items = tcx.associated_items(did).filter_map(|item| {
-        if associated_trait.is_some() || item.vis == ty::Visibility::Public {
-            Some(item.clean(cx))
-        } else {
-            None
+    let (trait_items, generics) = if let Some(nodeid) = tcx.hir.as_local_node_id(did) {
+        match tcx.hir.expect_item(nodeid).node {
+            hir::ItemKind::Impl(.., ref gen, _, _, ref item_ids) => {
+                (
+                    item_ids.iter()
+                            .map(|ii| tcx.hir.impl_item(ii.id).clean(cx))
+                            .collect::<Vec<_>>(),
+                    gen.clean(cx),
+                )
+            }
+            _ => panic!("did given to build_impl was not an impl"),
         }
-    }).collect::<Vec<_>>();
+    } else {
+        (
+            tcx.associated_items(did).filter_map(|item| {
+                if associated_trait.is_some() || item.vis == ty::Visibility::Public {
+                    Some(item.clean(cx))
+                } else {
+                    None
+                }
+            }).collect::<Vec<_>>(),
+            (tcx.generics_of(did), &predicates).clean(cx),
+        )
+    };
     let polarity = tcx.impl_polarity(did);
     let trait_ = associated_trait.clean(cx).map(|bound| {
         match bound {
@@ -417,10 +370,12 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
            .collect()
     }).unwrap_or(FxHashSet());
 
+    debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id());
+
     ret.push(clean::Item {
         inner: clean::ImplItem(clean::Impl {
             unsafety: hir::Unsafety::Normal,
-            generics: (tcx.generics_of(did), &predicates).clean(cx),
+            generics,
             provided_trait_methods: provided,
             trait_,
             for_,
@@ -465,7 +420,11 @@ fn fill_in(cx: &DocContext, did: DefId, items: &mut Vec<clean::Item>,
 }
 
 pub fn print_inlined_const(cx: &DocContext, did: DefId) -> String {
-    cx.tcx.rendered_const(did)
+    if let Some(node_id) = cx.tcx.hir.as_local_node_id(did) {
+        cx.tcx.hir.node_to_pretty_string(node_id)
+    } else {
+        cx.tcx.rendered_const(did)
+    }
 }
 
 fn build_const(cx: &DocContext, did: DefId) -> clean::Constant {
@@ -576,16 +535,27 @@ fn separate_supertrait_bounds(mut g: clean::Generics)
 }
 
 pub fn record_extern_trait(cx: &DocContext, did: DefId) {
-    if cx.external_traits.borrow().contains_key(&did) ||
-        cx.active_extern_traits.borrow().contains(&did)
-    {
+    if did.is_local() {
         return;
     }
 
+    {
+        let external_traits = cx.external_traits.lock();
+        if external_traits.borrow().contains_key(&did) ||
+            cx.active_extern_traits.borrow().contains(&did)
+        {
+            return;
+        }
+    }
+
     cx.active_extern_traits.borrow_mut().push(did);
 
+    debug!("record_extern_trait: {:?}", did);
     let trait_ = build_external_trait(cx, did);
 
-    cx.external_traits.borrow_mut().insert(did, trait_);
+    {
+        let external_traits = cx.external_traits.lock();
+        external_traits.borrow_mut().insert(did, trait_);
+    }
     cx.active_extern_traits.borrow_mut().remove_item(&did);
 }
index 20b17afeab2f63f9c98096a1d166e457c3b8cfe0..a982933f6c1a26a594bb4fd80846462671d36d03 100644 (file)
@@ -28,7 +28,6 @@
 use syntax_pos::{self, DUMMY_SP, Pos, FileName};
 
 use rustc::mir::interpret::ConstValue;
-use rustc::middle::privacy::AccessLevels;
 use rustc::middle::resolve_lifetime as rl;
 use rustc::ty::fold::TypeFolder;
 use rustc::middle::lang_items;
@@ -56,6 +55,8 @@
 use std::sync::Arc;
 use std::u32;
 
+use parking_lot::ReentrantMutex;
+
 use core::{self, DocContext};
 use doctree;
 use visit_ast;
@@ -135,10 +136,9 @@ pub struct Crate {
     pub module: Option<Item>,
     pub externs: Vec<(CrateNum, ExternalCrate)>,
     pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
-    pub access_levels: Arc<AccessLevels<DefId>>,
     // These are later on moved into `CACHEKEY`, leaving the map empty.
     // Only here so that they can be filtered through the rustdoc passes.
-    pub external_traits: FxHashMap<DefId, Trait>,
+    pub external_traits: Arc<ReentrantMutex<RefCell<FxHashMap<DefId, Trait>>>>,
     pub masked_crates: FxHashSet<CrateNum>,
 }
 
@@ -209,9 +209,6 @@ fn clean(&self, cx: &DocContext) -> Crate {
             }));
         }
 
-        let mut access_levels = cx.access_levels.borrow_mut();
-        let mut external_traits = cx.external_traits.borrow_mut();
-
         Crate {
             name,
             version: None,
@@ -219,8 +216,7 @@ fn clean(&self, cx: &DocContext) -> Crate {
             module: Some(module),
             externs,
             primitives,
-            access_levels: Arc::new(mem::replace(&mut access_levels, Default::default())),
-            external_traits: mem::replace(&mut external_traits, Default::default()),
+            external_traits: cx.external_traits.clone(),
             masked_crates,
         }
     }
@@ -579,9 +575,9 @@ fn clean(&self, cx: &DocContext) -> Item {
         let mut items: Vec<Item> = vec![];
         items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
         items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
-        items.extend(self.structs.iter().flat_map(|x| x.clean(cx)));
-        items.extend(self.unions.iter().flat_map(|x| x.clean(cx)));
-        items.extend(self.enums.iter().flat_map(|x| x.clean(cx)));
+        items.extend(self.structs.iter().map(|x| x.clean(cx)));
+        items.extend(self.unions.iter().map(|x| x.clean(cx)));
+        items.extend(self.enums.iter().map(|x| x.clean(cx)));
         items.extend(self.fns.iter().map(|x| x.clean(cx)));
         items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx)));
         items.extend(self.mods.iter().map(|x| x.clean(cx)));
@@ -2436,7 +2432,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                 if let Def::TyAlias(def_id) = path.def {
                     // Substitute private type aliases
                     if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) {
-                        if !cx.access_levels.borrow().is_exported(def_id) {
+                        if !cx.renderinfo.borrow().access_levels.is_exported(def_id) {
                             alias = Some(&cx.tcx.hir.expect_item(node_id).node);
                         }
                     }
@@ -2816,14 +2812,10 @@ pub struct Union {
     pub fields_stripped: bool,
 }
 
-impl Clean<Vec<Item>> for doctree::Struct {
-    fn clean(&self, cx: &DocContext) -> Vec<Item> {
-        let name = self.name.clean(cx);
-        let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
-        ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone()));
-
-        ret.push(Item {
-            name: Some(name),
+impl Clean<Item> for doctree::Struct {
+    fn clean(&self, cx: &DocContext) -> Item {
+        Item {
+            name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
             def_id: cx.tcx.hir.local_def_id(self.id),
@@ -2836,20 +2828,14 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
                 fields: self.fields.clean(cx),
                 fields_stripped: false,
             }),
-        });
-
-        ret
+        }
     }
 }
 
-impl Clean<Vec<Item>> for doctree::Union {
-    fn clean(&self, cx: &DocContext) -> Vec<Item> {
-        let name = self.name.clean(cx);
-        let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
-        ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone()));
-
-        ret.push(Item {
-            name: Some(name),
+impl Clean<Item> for doctree::Union {
+    fn clean(&self, cx: &DocContext) -> Item {
+        Item {
+            name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
             def_id: cx.tcx.hir.local_def_id(self.id),
@@ -2862,9 +2848,7 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
                 fields: self.fields.clean(cx),
                 fields_stripped: false,
             }),
-        });
-
-        ret
+        }
     }
 }
 
@@ -2895,14 +2879,10 @@ pub struct Enum {
     pub variants_stripped: bool,
 }
 
-impl Clean<Vec<Item>> for doctree::Enum {
-    fn clean(&self, cx: &DocContext) -> Vec<Item> {
-        let name = self.name.clean(cx);
-        let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
-        ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone()));
-
-        ret.push(Item {
-            name: Some(name),
+impl Clean<Item> for doctree::Enum {
+    fn clean(&self, cx: &DocContext) -> Item {
+        Item {
+            name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
             def_id: cx.tcx.hir.local_def_id(self.id),
@@ -2914,9 +2894,7 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
                 generics: self.generics.clean(cx),
                 variants_stripped: false,
             }),
-        });
-
-        ret
+        }
     }
 }
 
@@ -3445,11 +3423,7 @@ fn build_deref_target_impls(cx: &DocContext,
         let primitive = match *target {
             ResolvedPath { did, .. } if did.is_local() => continue,
             ResolvedPath { did, .. } => {
-                // We set the last parameter to false to avoid looking for auto-impls for traits
-                // and therefore avoid an ICE.
-                // The reason behind this is that auto-traits don't propagate through Deref so
-                // we're not supposed to synthesise impls for them.
-                ret.extend(inline::build_impls(cx, did, false));
+                ret.extend(inline::build_impls(cx, did));
                 continue
             }
             _ => match target.primitive_type() {
index a312913a69c17bf2ffd23e18acd40a608d6cdee3..093788d209569d0b5c0393b596e8b6f768783fb4 100644 (file)
@@ -26,7 +26,7 @@
 use rustc_metadata::cstore::CStore;
 use rustc_target::spec::TargetTriple;
 
-use syntax::ast::{self, Ident};
+use syntax::ast::{self, Ident, NodeId};
 use syntax::source_map;
 use syntax::edition::Edition;
 use syntax::feature_gate::UnstableFeatures;
 use syntax_pos::DUMMY_SP;
 use errors;
 use errors::emitter::{Emitter, EmitterWriter};
+use parking_lot::ReentrantMutex;
 
-use std::cell::{RefCell, Cell};
+use std::cell::RefCell;
 use std::mem;
 use rustc_data_structures::sync::{self, Lrc};
 use std::rc::Rc;
+use std::sync::Arc;
 use std::path::PathBuf;
 
 use visit_ast::RustdocVisitor;
@@ -60,16 +62,13 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
     /// The stack of module NodeIds up till this point
     pub crate_name: Option<String>,
     pub cstore: Rc<CStore>,
-    pub populated_all_crate_impls: Cell<bool>,
     // Note that external items for which `doc(hidden)` applies to are shown as
     // non-reachable while local items aren't. This is because we're reusing
     // the access levels from crateanalysis.
-    /// Later on moved into `clean::Crate`
-    pub access_levels: RefCell<AccessLevels<DefId>>,
     /// Later on moved into `html::render::CACHE_KEY`
     pub renderinfo: RefCell<RenderInfo>,
     /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
-    pub external_traits: RefCell<FxHashMap<DefId, clean::Trait>>,
+    pub external_traits: Arc<ReentrantMutex<RefCell<FxHashMap<DefId, clean::Trait>>>>,
     /// Used while populating `external_traits` to ensure we don't process the same trait twice at
     /// the same time.
     pub active_extern_traits: RefCell<Vec<DefId>>,
@@ -164,6 +163,16 @@ pub fn next_def_id(&self, crate_num: CrateNum) -> DefId {
         def_id.clone()
     }
 
+    /// Like the function of the same name on the HIR map, but skips calling it on fake DefIds.
+    /// (This avoids a slice-index-out-of-bounds panic.)
+    pub fn as_local_node_id(&self, def_id: DefId) -> Option<NodeId> {
+        if self.all_fake_def_ids.borrow().contains(&def_id) {
+            None
+        } else {
+            self.tcx.hir.as_local_node_id(def_id)
+        }
+    }
+
     pub fn get_real_ty<F>(&self,
                           def_id: DefId,
                           def_ctor: &F,
@@ -260,9 +269,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 +309,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 +333,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 +398,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,
@@ -443,12 +455,10 @@ pub fn run_core(search_paths: SearchPaths,
                                                         |_| Ok(()));
         let driver::InnerExpansionResult {
             mut hir_forest,
-            mut resolver,
+            resolver,
             ..
         } = abort_on_err(result, &sess);
 
-        resolver.ignore_extern_prelude_feature = true;
-
         // We need to hold on to the complete resolver, so we clone everything
         // for the analysis passes to use. Suboptimal, but necessary in the
         // current architecture.
@@ -506,16 +516,17 @@ pub fn run_core(search_paths: SearchPaths,
                 clean::path_to_def(&tcx, &["core", "marker", "Send"])
             };
 
+            let mut renderinfo = RenderInfo::default();
+            renderinfo.access_levels = access_levels;
+
             let ctxt = DocContext {
                 tcx,
                 resolver: &resolver,
                 crate_name,
                 cstore: cstore.clone(),
-                populated_all_crate_impls: Cell::new(false),
-                access_levels: RefCell::new(access_levels),
                 external_traits: Default::default(),
                 active_extern_traits: Default::default(),
-                renderinfo: Default::default(),
+                renderinfo: RefCell::new(renderinfo),
                 ty_substs: Default::default(),
                 lt_substs: Default::default(),
                 impl_trait_bounds: Default::default(),
index 6d96bc8e3603886bf558aca97f3114d3c496e0e5..b8e27c531708379d2851156e2616f51e31afb8f7 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::mem;
-
 use clean::*;
 
 pub struct StripItem(pub Item);
@@ -116,11 +114,14 @@ fn fold_mod(&mut self, m: Module) -> Module {
     fn fold_crate(&mut self, mut c: Crate) -> Crate {
         c.module = c.module.take().and_then(|module| self.fold_item(module));
 
-        let traits = mem::replace(&mut c.external_traits, Default::default());
-        c.external_traits.extend(traits.into_iter().map(|(k, mut v)| {
-            v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
-            (k, v)
-        }));
+        {
+            let guard = c.external_traits.lock();
+            let traits = guard.replace(Default::default());
+            guard.borrow_mut().extend(traits.into_iter().map(|(k, mut v)| {
+                v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
+                (k, v)
+            }));
+        }
         c
     }
 }
index d4e22dd91d7d5d23fb8d9d7871a8e4b0d8e3a9c8..3e1720f8b8ab2a639c74fbaf5ee4ed07ed689664 100644 (file)
@@ -313,7 +313,7 @@ pub struct Cache {
     // Note that external items for which `doc(hidden)` applies to are shown as
     // non-reachable while local items aren't. This is because we're reusing
     // the access levels from crateanalysis.
-    pub access_levels: Arc<AccessLevels<DefId>>,
+    pub access_levels: AccessLevels<DefId>,
 
     /// The version of the crate being documented, if given from the `--crate-version` flag.
     pub crate_version: Option<String>,
@@ -337,6 +337,15 @@ pub struct Cache {
     // and their parent id here and indexes them at the end of crate parsing.
     orphan_impl_items: Vec<(DefId, clean::Item)>,
 
+    // Similarly to `orphan_impl_items`, sometimes trait impls are picked up
+    // even though the trait itself is not exported. This can happen if a trait
+    // was defined in function/expression scope, since the impl will be picked
+    // up by `collect-trait-impls` but the trait won't be scraped out in the HIR
+    // crawl. In order to prevent crashes when looking for spotlight traits or
+    // when gathering trait documentation on a type, hold impls here while
+    // folding and add them to the cache later on if we find the trait.
+    orphan_trait_impls: Vec<(DefId, FxHashSet<DefId>, Impl)>,
+
     /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
     /// we need the alias element to have an array of items.
     aliases: FxHashMap<String, Vec<IndexItem>>,
@@ -350,6 +359,7 @@ pub struct RenderInfo {
     pub external_paths: ::core::ExternalPaths,
     pub external_typarams: FxHashMap<DefId, String>,
     pub exact_paths: FxHashMap<DefId, Vec<String>>,
+    pub access_levels: AccessLevels<DefId>,
     pub deref_trait_did: Option<DefId>,
     pub deref_mut_trait_did: Option<DefId>,
     pub owned_box_did: Option<DefId>,
@@ -569,6 +579,7 @@ pub fn run(mut krate: clean::Crate,
         external_paths,
         external_typarams,
         exact_paths,
+        access_levels,
         deref_trait_did,
         deref_mut_trait_did,
         owned_box_did,
@@ -591,10 +602,11 @@ pub fn run(mut krate: clean::Crate,
         extern_locations: FxHashMap(),
         primitive_locations: FxHashMap(),
         stripped_mod: false,
-        access_levels: krate.access_levels.clone(),
+        access_levels,
         crate_version: krate.version.take(),
         orphan_impl_items: Vec::new(),
-        traits: mem::replace(&mut krate.external_traits, FxHashMap()),
+        orphan_trait_impls: Vec::new(),
+        traits: krate.external_traits.lock().replace(FxHashMap()),
         deref_trait_did,
         deref_mut_trait_did,
         owned_box_did,
@@ -636,6 +648,14 @@ pub fn run(mut krate: clean::Crate,
     cache.stack.push(krate.name.clone());
     krate = cache.fold_crate(krate);
 
+    for (trait_did, dids, impl_) in cache.orphan_trait_impls.drain(..) {
+        if cache.traits.contains_key(&trait_did) {
+            for did in dids {
+                cache.impls.entry(did).or_insert(vec![]).push(impl_.clone());
+            }
+        }
+    }
+
     // Build our search index
     let index = build_index(&krate, &mut cache);
 
@@ -1223,6 +1243,10 @@ fn emit_source(&mut self, filename: &FileName) -> io::Result<()> {
 
 impl DocFolder for Cache {
     fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
+        if item.def_id.is_local() {
+            debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id);
+        }
+
         // If this is a stripped module,
         // we don't want it or its children in the search index.
         let orig_stripped_mod = match item.inner {
@@ -1453,10 +1477,16 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                 } else {
                     unreachable!()
                 };
-                for did in dids {
-                    self.impls.entry(did).or_default().push(Impl {
-                        impl_item: item.clone(),
-                    });
+                let impl_item = Impl {
+                    impl_item: item,
+                };
+                if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) {
+                    for did in dids {
+                        self.impls.entry(did).or_insert(vec![]).push(impl_item.clone());
+                    }
+                } else {
+                    let trait_did = impl_item.trait_did().unwrap();
+                    self.orphan_trait_impls.push((trait_did, dids, impl_item));
                 }
                 None
             } else {
@@ -1830,8 +1860,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("::")
@@ -2301,17 +2331,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),
     }
@@ -2702,6 +2736,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,
@@ -2905,9 +2947,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'>
@@ -4716,6 +4761,7 @@ fn test_name_sorting() {
                  "Fruit1", "Fruit01",
                  "Fruit2", "Fruit02",
                  "Fruit20",
+                 "Fruit30x",
                  "Fruit100",
                  "Pear"];
     let mut sorted = names.to_owned();
index bc471d427048b5651f4d612724bc4fa658824948..5607c97a49689d578f275b08302853e40be58a88 100644 (file)
@@ -24,6 +24,7 @@
 #![feature(ptr_offset_from)]
 #![feature(crate_visibility_modifier)]
 #![feature(const_fn)]
+#![feature(drain_filter)]
 
 #![recursion_limit="256"]
 
@@ -48,6 +49,7 @@
 extern crate pulldown_cmark;
 extern crate tempfile;
 extern crate minifier;
+extern crate parking_lot;
 
 extern crate serialize as rustc_serialize; // used by deriving
 
@@ -404,8 +406,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 +565,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 +614,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 +699,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 +714,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 2d5512c538f55c005081878aea5c6cc01b82e735..7b2eb2259d6791bac9976858dd2b34d86f1c38ff 100644 (file)
@@ -69,16 +69,21 @@ fn new(cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self {
     /// Resolve a given string as a path, along with whether or not it is
     /// in the value namespace. Also returns an optional URL fragment in the case
     /// of variants and methods
-    fn resolve(&self, path_str: &str, is_val: bool, current_item: &Option<String>)
+    fn resolve(&self,
+               path_str: &str,
+               is_val: bool,
+               current_item: &Option<String>,
+               parent_id: Option<NodeId>)
         -> Result<(Def, Option<String>), ()>
     {
         let cx = self.cx;
 
         // In case we're in a module, try to resolve the relative
         // path
-        if let Some(id) = self.mod_ids.last() {
+        if let Some(id) = parent_id.or(self.mod_ids.last().cloned()) {
+            // FIXME: `with_scope` requires the NodeId of a module
             let result = cx.resolver.borrow_mut()
-                                    .with_scope(*id,
+                                    .with_scope(id,
                 |resolver| {
                     resolver.resolve_str_path_error(DUMMY_SP,
                                                     &path_str, is_val)
@@ -129,8 +134,9 @@ fn resolve(&self, path_str: &str, is_val: bool, current_item: &Option<String>)
                 }
             }
 
+            // FIXME: `with_scope` requires the NodeId of a module
             let ty = cx.resolver.borrow_mut()
-                                .with_scope(*id,
+                                .with_scope(id,
                 |resolver| {
                     resolver.resolve_str_path_error(DUMMY_SP, &path, false)
             })?;
@@ -218,6 +224,20 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
             None
         };
 
+        // FIXME: get the resolver to work with non-local resolve scopes
+        let parent_node = self.cx.as_local_node_id(item.def_id).and_then(|node_id| {
+            // FIXME: this fails hard for impls in non-module scope, but is necessary for the
+            // current resolve() implementation
+            match self.cx.tcx.hir.get_module_parent_node(node_id) {
+                id if id != node_id => Some(id),
+                _ => None,
+            }
+        });
+
+        if parent_node.is_some() {
+            debug!("got parent node for {} {:?}, id {:?}", item.type_(), item.name, item.def_id);
+        }
+
         let current_item = match item.inner {
             ModuleItem(..) => {
                 if item.attrs.inner_docs {
@@ -227,10 +247,10 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         None
                     }
                 } else {
-                    match self.mod_ids.last() {
-                        Some(parent) if *parent != NodeId::new(0) => {
+                    match parent_node.or(self.mod_ids.last().cloned()) {
+                        Some(parent) if parent != NodeId::new(0) => {
                             //FIXME: can we pull the parent module's name from elsewhere?
-                            Some(self.cx.tcx.hir.name(*parent).to_string())
+                            Some(self.cx.tcx.hir.name(parent).to_string())
                         }
                         _ => None,
                     }
@@ -294,7 +314,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
 
                 match kind {
                     PathKind::Value => {
-                        if let Ok(def) = self.resolve(path_str, true, &current_item) {
+                        if let Ok(def) = self.resolve(path_str, true, &current_item, parent_node) {
                             def
                         } else {
                             resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
@@ -305,7 +325,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         }
                     }
                     PathKind::Type => {
-                        if let Ok(def) = self.resolve(path_str, false, &current_item) {
+                        if let Ok(def) = self.resolve(path_str, false, &current_item, parent_node) {
                             def
                         } else {
                             resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
@@ -316,16 +336,18 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                     PathKind::Unknown => {
                         // try everything!
                         if let Some(macro_def) = macro_resolve(cx, path_str) {
-                            if let Ok(type_def) = self.resolve(path_str, false, &current_item) {
+                            if let Ok(type_def) =
+                                self.resolve(path_str, false, &current_item, parent_node)
+                            {
                                 let (type_kind, article, type_disambig)
                                     = type_ns_kind(type_def.0, path_str);
                                 ambiguity_error(cx, &item.attrs, path_str,
                                                 article, type_kind, &type_disambig,
                                                 "a", "macro", &format!("macro@{}", path_str));
                                 continue;
-                            } else if let Ok(value_def) = self.resolve(path_str,
-                                                                       true,
-                                                                       &current_item) {
+                            } else if let Ok(value_def) =
+                                self.resolve(path_str, true, &current_item, parent_node)
+                            {
                                 let (value_kind, value_disambig)
                                     = value_ns_kind(value_def.0, path_str)
                                         .expect("struct and mod cases should have been \
@@ -335,12 +357,16 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                                                 "a", "macro", &format!("macro@{}", path_str));
                             }
                             (macro_def, None)
-                        } else if let Ok(type_def) = self.resolve(path_str, false, &current_item) {
+                        } else if let Ok(type_def) =
+                            self.resolve(path_str, false, &current_item, parent_node)
+                        {
                             // It is imperative we search for not-a-value first
                             // Otherwise we will find struct ctors for when we are looking
                             // for structs, and the link won't work.
                             // if there is something in both namespaces
-                            if let Ok(value_def) = self.resolve(path_str, true, &current_item) {
+                            if let Ok(value_def) =
+                                self.resolve(path_str, true, &current_item, parent_node)
+                            {
                                 let kind = value_ns_kind(value_def.0, path_str);
                                 if let Some((value_kind, value_disambig)) = kind {
                                     let (type_kind, article, type_disambig)
@@ -352,7 +378,9 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                                 }
                             }
                             type_def
-                        } else if let Ok(value_def) = self.resolve(path_str, true, &current_item) {
+                        } else if let Ok(value_def) =
+                            self.resolve(path_str, true, &current_item, parent_node)
+                        {
                             value_def
                         } else {
                             resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
new file mode 100644 (file)
index 0000000..70e1a9b
--- /dev/null
@@ -0,0 +1,219 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use clean::*;
+
+use rustc::util::nodemap::FxHashSet;
+use rustc::hir::def_id::DefId;
+
+use super::Pass;
+use core::DocContext;
+use fold::DocFolder;
+
+pub const COLLECT_TRAIT_IMPLS: Pass =
+    Pass::early("collect-trait-impls", collect_trait_impls,
+                "retrieves trait impls for items in the crate");
+
+pub fn collect_trait_impls(krate: Crate, cx: &DocContext) -> Crate {
+    let mut synth = SyntheticImplCollector::new(cx);
+    let mut krate = synth.fold_crate(krate);
+
+    let prims: FxHashSet<PrimitiveType> =
+        krate.primitives.iter().map(|p| p.1).collect();
+
+    let crate_items = {
+        let mut coll = ItemCollector::new();
+        krate = coll.fold_crate(krate);
+        coll.items
+    };
+
+    let mut new_items = Vec::new();
+
+    for &cnum in cx.tcx.crates().iter() {
+        for &did in cx.tcx.all_trait_implementations(cnum).iter() {
+            inline::build_impl(cx, did, &mut new_items);
+        }
+    }
+
+    // Also try to inline primitive impls from other crates.
+    let lang_items = cx.tcx.lang_items();
+    let primitive_impls = [
+        lang_items.isize_impl(),
+        lang_items.i8_impl(),
+        lang_items.i16_impl(),
+        lang_items.i32_impl(),
+        lang_items.i64_impl(),
+        lang_items.i128_impl(),
+        lang_items.usize_impl(),
+        lang_items.u8_impl(),
+        lang_items.u16_impl(),
+        lang_items.u32_impl(),
+        lang_items.u64_impl(),
+        lang_items.u128_impl(),
+        lang_items.f32_impl(),
+        lang_items.f64_impl(),
+        lang_items.f32_runtime_impl(),
+        lang_items.f64_runtime_impl(),
+        lang_items.char_impl(),
+        lang_items.str_impl(),
+        lang_items.slice_impl(),
+        lang_items.slice_u8_impl(),
+        lang_items.str_alloc_impl(),
+        lang_items.slice_alloc_impl(),
+        lang_items.slice_u8_alloc_impl(),
+        lang_items.const_ptr_impl(),
+        lang_items.mut_ptr_impl(),
+    ];
+
+    for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {
+        if !def_id.is_local() {
+            inline::build_impl(cx, def_id, &mut new_items);
+
+            let auto_impls = get_auto_traits_with_def_id(cx, def_id);
+            let blanket_impls = get_blanket_impls_with_def_id(cx, def_id);
+            let mut renderinfo = cx.renderinfo.borrow_mut();
+
+            let new_impls: Vec<Item> = auto_impls.into_iter()
+                .chain(blanket_impls.into_iter())
+                .filter(|i| renderinfo.inlined.insert(i.def_id))
+                .collect();
+
+            new_items.extend(new_impls);
+        }
+    }
+
+    let mut cleaner = BadImplStripper {
+        prims,
+        items: crate_items,
+    };
+
+    // scan through included items ahead of time to splice in Deref targets to the "valid" sets
+    for it in &new_items {
+        if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = it.inner {
+            if cleaner.keep_item(for_) && trait_.def_id() == cx.tcx.lang_items().deref_trait() {
+                let target = items.iter().filter_map(|item| {
+                    match item.inner {
+                        TypedefItem(ref t, true) => Some(&t.type_),
+                        _ => None,
+                    }
+                }).next().expect("Deref impl without Target type");
+
+                if let Some(prim) = target.primitive_type() {
+                    cleaner.prims.insert(prim);
+                } else if let Some(did) = target.def_id() {
+                    cleaner.items.insert(did);
+                }
+            }
+        }
+    }
+
+    new_items.retain(|it| {
+        if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = it.inner {
+            cleaner.keep_item(for_) ||
+                trait_.as_ref().map_or(false, |t| cleaner.keep_item(t)) ||
+                blanket_impl.is_some()
+        } else {
+            true
+        }
+    });
+
+    // `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations`
+    // doesn't work with it anyway, so pull them from the HIR map instead
+    for &trait_did in cx.all_traits.iter() {
+        for &impl_node in cx.tcx.hir.trait_impls(trait_did) {
+            let impl_did = cx.tcx.hir.local_def_id(impl_node);
+            inline::build_impl(cx, impl_did, &mut new_items);
+        }
+    }
+
+    if let Some(ref mut it) = krate.module {
+        if let ModuleItem(Module { ref mut items, .. }) = it.inner {
+            items.extend(synth.impls);
+            items.extend(new_items);
+        } else {
+            panic!("collect-trait-impls can't run");
+        }
+    } else {
+        panic!("collect-trait-impls can't run");
+    }
+
+    krate
+}
+
+struct SyntheticImplCollector<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
+    cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>,
+    impls: Vec<Item>,
+}
+
+impl<'a, 'tcx, 'rcx, 'cstore> SyntheticImplCollector<'a, 'tcx, 'rcx, 'cstore> {
+    fn new(cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self {
+        SyntheticImplCollector {
+            cx,
+            impls: Vec::new(),
+        }
+    }
+}
+
+impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for SyntheticImplCollector<'a, 'tcx, 'rcx, 'cstore> {
+    fn fold_item(&mut self, i: Item) -> Option<Item> {
+        if i.is_struct() || i.is_enum() || i.is_union() {
+            if let (Some(node_id), Some(name)) =
+                (self.cx.tcx.hir.as_local_node_id(i.def_id), i.name.clone())
+            {
+                self.impls.extend(get_auto_traits_with_node_id(self.cx, node_id, name.clone()));
+                self.impls.extend(get_blanket_impls_with_node_id(self.cx, node_id, name));
+            } else {
+                self.impls.extend(get_auto_traits_with_def_id(self.cx, i.def_id));
+                self.impls.extend(get_blanket_impls_with_def_id(self.cx, i.def_id));
+            }
+        }
+
+        self.fold_item_recur(i)
+    }
+}
+
+#[derive(Default)]
+struct ItemCollector {
+    items: FxHashSet<DefId>,
+}
+
+impl ItemCollector {
+    fn new() -> Self {
+        Self::default()
+    }
+}
+
+impl DocFolder for ItemCollector {
+    fn fold_item(&mut self, i: Item) -> Option<Item> {
+        self.items.insert(i.def_id);
+
+        self.fold_item_recur(i)
+    }
+}
+
+struct BadImplStripper {
+    prims: FxHashSet<PrimitiveType>,
+    items: FxHashSet<DefId>,
+}
+
+impl BadImplStripper {
+    fn keep_item(&self, ty: &Type) -> bool {
+        if let Generic(_) = ty {
+            // keep impls made on generics
+            true
+        } else if let Some(prim) = ty.primitive_type() {
+            self.prims.contains(&prim)
+        } else if let Some(did) = ty.def_id() {
+            self.items.contains(&did)
+        } else {
+            false
+        }
+    }
+}
index 16251877bb10637faa7a993d5a012ea8f4e08ca4..24fec62dd573a3876b8e5d153e6dc32128a6cb14 100644 (file)
@@ -43,6 +43,9 @@
 mod collect_intra_doc_links;
 pub use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS;
 
+mod collect_trait_impls;
+pub use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;
+
 /// Represents a single pass.
 #[derive(Copy, Clone)]
 pub enum Pass {
@@ -132,10 +135,12 @@ pub fn late_fn(self) -> Option<fn(clean::Crate) -> clean::Crate> {
     STRIP_PRIV_IMPORTS,
     PROPAGATE_DOC_CFG,
     COLLECT_INTRA_DOC_LINKS,
+    COLLECT_TRAIT_IMPLS,
 ];
 
 /// The list of passes run by default.
 pub const DEFAULT_PASSES: &'static [&'static str] = &[
+    "collect-trait-impls",
     "strip-hidden",
     "strip-private",
     "collect-intra-doc-links",
@@ -146,6 +151,7 @@ pub fn late_fn(self) -> Option<fn(clean::Crate) -> clean::Crate> {
 
 /// The list of default passes run with `--document-private-items` is passed to rustdoc.
 pub const DEFAULT_PRIVATE_PASSES: &'static [&'static str] = &[
+    "collect-trait-impls",
     "strip-priv-imports",
     "collect-intra-doc-links",
     "collapse-docs",
@@ -189,6 +195,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
                 // We need to recurse into stripped modules to strip things
                 // like impl methods but when doing so we must not add any
                 // items to the `retained` set.
+                debug!("Stripper: recursing into stripped {} {:?}", i.type_(), i.name);
                 let old = mem::replace(&mut self.update_retained, false);
                 let ret = self.fold_item_recur(i);
                 self.update_retained = old;
@@ -212,6 +219,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             | clean::ForeignTypeItem => {
                 if i.def_id.is_local() {
                     if !self.access_levels.is_exported(i.def_id) {
+                        debug!("Stripper: stripping {} {:?}", i.type_(), i.name);
                         return None;
                     }
                 }
@@ -225,6 +233,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
 
             clean::ModuleItem(..) => {
                 if i.def_id.is_local() && i.visibility != Some(clean::Public) {
+                    debug!("Stripper: stripping module {:?}", i.name);
                     let old = mem::replace(&mut self.update_retained, false);
                     let ret = StripItem(self.fold_item_recur(i).unwrap()).strip();
                     self.update_retained = old;
@@ -296,11 +305,13 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             }
             if let Some(did) = imp.for_.def_id() {
                 if did.is_local() && !imp.for_.is_generic() && !self.retained.contains(&did) {
+                    debug!("ImplStripper: impl item for stripped type; removing");
                     return None;
                 }
             }
             if let Some(did) = imp.trait_.def_id() {
                 if did.is_local() && !self.retained.contains(&did) {
+                    debug!("ImplStripper: impl item for stripped trait; removing");
                     return None;
                 }
             }
@@ -308,6 +319,8 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
                 for typaram in generics {
                     if let Some(did) = typaram.def_id() {
                         if did.is_local() && !self.retained.contains(&did) {
+                            debug!("ImplStripper: stripped item in trait's generics; \
+                                    removing impl");
                             return None;
                         }
                     }
index cc0b6fb6d67053b16219e896f9209920177e395b..24dd4cc13bfe88b782e3232c61bb03eda691a5a9 100644 (file)
@@ -35,7 +35,9 @@ pub fn strip_hidden(krate: clean::Crate, _: &DocContext) -> clean::Crate {
 
     // strip all impls referencing stripped items
     let mut stripper = ImplStripper { retained: &retained };
-    stripper.fold_crate(krate)
+    let krate = stripper.fold_crate(krate);
+
+    krate
 }
 
 struct Stripper<'a> {
@@ -46,7 +48,7 @@ struct Stripper<'a> {
 impl<'a> fold::DocFolder for Stripper<'a> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         if i.attrs.lists("doc").has_word("hidden") {
-            debug!("found one in strip_hidden; removing");
+            debug!("strip_hidden: stripping {} {:?}", i.type_(), i.name);
             // use a dedicated hidden item for given item type if any
             match i.inner {
                 clean::StructFieldItem(..) | clean::ModuleItem(..) => {
index 3b17a768ffdee6fd6ca8d5bb0a0d91a9dfa86c9c..46d0034497e28b39f811ee394158b42477ebaae0 100644 (file)
 
 /// Strip private items from the point of view of a crate or externally from a
 /// crate, specified by the `xcrate` flag.
-pub fn strip_private(mut krate: clean::Crate, _: &DocContext) -> clean::Crate {
+pub fn strip_private(mut krate: clean::Crate, cx: &DocContext) -> clean::Crate {
     // This stripper collects all *retained* nodes.
     let mut retained = DefIdSet();
-    let access_levels = krate.access_levels.clone();
+    let access_levels = cx.renderinfo.borrow().access_levels.clone();
 
     // strip all private items
     {
index 3b07a2ccdde09379e8e10fd706d8db6b733f80ca..8a9ca924ee1ab997e06c3f74c55890c3a7553ec5 100644 (file)
@@ -775,7 +775,7 @@ fn main() {
 assert_eq!(2+2, 4);
 }".to_string();
         let output = make_test(input, None, false, &opts);
-        assert_eq!(output, (expected.clone(), 2));
+        assert_eq!(output, (expected, 2));
     }
 
     #[test]
@@ -973,7 +973,7 @@ fn main() {
 assert_eq!(2+2, 4);
 }".to_string();
         let output = make_test(input, None, false, &opts);
-        assert_eq!(output, (expected.clone(), 2));
+        assert_eq!(output, (expected, 2));
     }
 
     #[test]
@@ -988,7 +988,7 @@ fn make_test_dont_insert_main() {
 //Ceci n'est pas une `fn main`
 assert_eq!(2+2, 4);".to_string();
         let output = make_test(input, None, true, &opts);
-        assert_eq!(output, (expected.clone(), 1));
+        assert_eq!(output, (expected, 1));
     }
 
     #[test]
@@ -1003,6 +1003,6 @@ fn make_test_display_warnings() {
 assert_eq!(2+2, 4);
 }".to_string();
         let output = make_test(input, None, false, &opts);
-        assert_eq!(output, (expected.clone(), 1));
+        assert_eq!(output, (expected, 1));
     }
 }
index 0aaf2d526f934a1fcc186a29267fdad3443b526a..0e12fd34eb7d84b99bc36723133f8a46b4684fc4 100644 (file)
@@ -269,7 +269,10 @@ fn inherits_doc_hidden(cx: &core::DocContext, mut node: ast::NodeId) -> bool {
                 Def::Enum(did) |
                 Def::ForeignTy(did) |
                 Def::TyAlias(did) if !self_is_hidden => {
-                    self.cx.access_levels.borrow_mut().map.insert(did, AccessLevel::Public);
+                    self.cx.renderinfo
+                        .borrow_mut()
+                        .access_levels.map
+                        .insert(did, AccessLevel::Public);
                 },
                 Def::Mod(did) => if !self_is_hidden {
                     ::visit_lib::LibEmbargoVisitor::new(self.cx).visit_mod(did);
@@ -284,7 +287,7 @@ fn inherits_doc_hidden(cx: &core::DocContext, mut node: ast::NodeId) -> bool {
             Some(n) => n, None => return false
         };
 
-        let is_private = !self.cx.access_levels.borrow().is_public(def_did);
+        let is_private = !self.cx.renderinfo.borrow().access_levels.is_public(def_did);
         let is_hidden = inherits_doc_hidden(self.cx, def_node_id);
 
         // Only inline if requested or if the item would otherwise be stripped
@@ -510,9 +513,9 @@ pub fn visit_item(&mut self, item: &hir::Item,
                           ref tr,
                           ref ty,
                           ref item_ids) => {
-                // Don't duplicate impls when inlining, we'll pick them up
-                // regardless of where they're located.
-                if !self.inlining {
+                // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
+                // them up regardless of where they're located.
+                if !self.inlining && tr.is_none() {
                     let items = item_ids.iter()
                                         .map(|ii| self.cx.tcx.hir.impl_item(ii.id).clone())
                                         .collect();
index 10a4e69dcc6cd901fb540ce5663ea4aa547eb284..fd81f937f30c70e27bda1290311f3a2dc2bf372f 100644 (file)
@@ -38,7 +38,7 @@ pub fn new(
     ) -> LibEmbargoVisitor<'a, 'tcx, 'rcx, 'cstore> {
         LibEmbargoVisitor {
             cx,
-            access_levels: cx.access_levels.borrow_mut(),
+            access_levels: RefMut::map(cx.renderinfo.borrow_mut(), |ri| &mut ri.access_levels),
             prev_level: Some(AccessLevel::Public),
             visited_mods: FxHashSet()
         }
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 237af2f04e59d5fe9ad183e005a1adad09a2d42d..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
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 87ac2091cad41f44a5523370273b24fce39b7029..64fc14d42d9b77f0884c5a4749bb336ca0c237e1 100644 (file)
@@ -74,46 +74,19 @@ pub unsafe fn tanhf(n: f32) -> f32 {
     f64::tanh(n as f64) as f32
 }
 
-// Right now all these functions, the f64 version of the functions above, all
-// shell out to random names. These names aren't actually defined anywhere, per
-// se, but we need this to compile somehow.
-//
-// The idea with this is that when you're using wasm then, for now, we have no
-// way of providing an implementation of these which delegates to a "correct"
-// implementation. For example most wasm applications probably just want to
-// delegate to the javascript `Math` object and its related functions, but wasm
-// doesn't currently have the ability to seamlessly do that (when you
-// instantiate a module you have to set that up).
-//
-// As a result these are just defined here with "hopefully helpful" names. The
-// symbols won't ever be needed or show up unless these functions are called,
-// and hopefully when they're called the errors are self-explanatory enough to
-// figure out what's going on.
-
+// These symbols are all defined in `compiler-builtins`
 extern {
-    #[link_name = "Math_acos"]
     pub fn acos(n: f64) -> f64;
-    #[link_name = "Math_asin"]
     pub fn asin(n: f64) -> f64;
-    #[link_name = "Math_atan"]
     pub fn atan(n: f64) -> f64;
-    #[link_name = "Math_atan2"]
     pub fn atan2(a: f64, b: f64) -> f64;
-    #[link_name = "Math_cbrt"]
     pub fn cbrt(n: f64) -> f64;
-    #[link_name = "Math_cosh"]
     pub fn cosh(n: f64) -> f64;
-    #[link_name = "Math_expm1"]
     pub fn expm1(n: f64) -> f64;
     pub fn fdim(a: f64, b: f64) -> f64;
-    #[link_name = "Math_log1p"]
     pub fn log1p(n: f64) -> f64;
-    #[link_name = "Math_sinh"]
     pub fn sinh(n: f64) -> f64;
-    #[link_name = "Math_tan"]
     pub fn tan(n: f64) -> f64;
-    #[link_name = "Math_tanh"]
     pub fn tanh(n: f64) -> f64;
-    #[link_name = "Math_hypot"]
     pub fn hypot(x: f64, y: f64) -> f64;
 }
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 7266d807d3ba8644fa60ea4b4c5810f417b4f92d..d44d2146d82c9c495f26be2c449d0c8bcf9d35be 100644 (file)
@@ -394,18 +394,12 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // Allows trait methods with arbitrary self types
     (active, arbitrary_self_types, "1.23.0", Some(44874), None),
 
-    // `crate` in paths
-    (active, crate_in_paths, "1.23.0", Some(45477), Some(Edition::Edition2018)),
-
     // In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`)
     (active, in_band_lifetimes, "1.23.0", Some(44524), None),
 
     // Generic associated types (RFC 1598)
     (active, generic_associated_types, "1.23.0", Some(44265), None),
 
-    // Resolve absolute paths as paths from other crates
-    (active, extern_absolute_paths, "1.24.0", Some(44660), Some(Edition::Edition2018)),
-
     // `extern` in paths
     (active, extern_in_paths, "1.23.0", Some(44660), None),
 
@@ -455,9 +449,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // #[doc(alias = "...")]
     (active, doc_alias, "1.27.0", Some(50146), None),
 
-    // Access to crate names passed via `--extern` through prelude
-    (active, extern_prelude, "1.27.0", Some(44660), Some(Edition::Edition2018)),
-
     // Scoped lints
     (active, tool_lints, "1.28.0", Some(44690), None),
 
@@ -515,6 +506,12 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
 
     // 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! (
@@ -677,7 +674,12 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     (accepted, panic_handler, "1.30.0", Some(44489), None),
     // Used to preserve symbols (see llvm.used)
     (accepted, used, "1.30.0", Some(40289), None),
-
+    // `crate` in paths
+    (accepted, crate_in_paths, "1.30.0", Some(45477), None),
+    // Resolve absolute paths as paths from other crates
+    (accepted, extern_absolute_paths, "1.30.0", Some(44660), None),
+    // Access to crate names passed via `--extern` through prelude
+    (accepted, extern_prelude, "1.30.0", Some(44660), None),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must
@@ -711,7 +713,7 @@ pub enum AttributeGate {
 impl AttributeGate {
     fn is_deprecated(&self) -> bool {
         match *self {
-            Gated(Stability::Deprecated(_), ..) => true,
+            Gated(Stability::Deprecated(_, _), ..) => true,
             _ => false,
         }
     }
@@ -720,8 +722,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
@@ -970,6 +973,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",
@@ -1044,7 +1051,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",
@@ -1057,7 +1064,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",
@@ -1136,9 +1144,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
@@ -1879,10 +1888,7 @@ fn visit_path(&mut self, path: &'a ast::Path, _id: NodeId) {
             // cannot be kept in identifiers, so it's kept in paths instead and we take it from
             // there while keeping location info from the ident span.
             let span = segment.ident.span.with_ctxt(path.span.ctxt());
-            if segment.ident.name == keywords::Crate.name() {
-                gate_feature_post!(&self, crate_in_paths, span,
-                                   "`crate` in paths is experimental");
-            } else if segment.ident.name == keywords::Extern.name() {
+            if segment.ident.name == keywords::Extern.name() {
                 gate_feature_post!(&self, extern_in_paths, span,
                                    "`extern` in paths is experimental");
             }
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),
index 5a081f0363340dd895d0958955d0c84661f60f05..caddcd9b9dc9479a20908d93c3e47c49b021379e 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit 5a081f0363340dd895d0958955d0c84661f60f05
+Subproject commit caddcd9b9dc9479a20908d93c3e47c49b021379e
index 29b7d508f1c1e5aa0f3bf53f02a7cc4ec1f6fc72..f8ff3d37fd23e6b657a9920f23f786bdb241ff73 100644 (file)
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2018-09-11
+2018-09-16
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 aa8158c6eb381a8aa855e8cbf0b8a80edc1fe99d..69af01ccf0369210e4dceb47ff105693c53bb134 100644 (file)
@@ -7,6 +7,5 @@ all:
        $(RUSTC) basic.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib
        $(RUSTC) shadow-mod.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib
        $(RUSTC) shadow-prelude.rs --extern Vec=$(TMPDIR)/libep_vec.rlib
-       $(RUSTC) feature-gate.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "access to extern crates through prelude is experimental"
        $(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "unresolved import"
        $(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "failed to resolve"
diff --git a/src/test/run-make-fulldeps/extern-prelude/feature-gate.rs b/src/test/run-make-fulldeps/extern-prelude/feature-gate.rs
deleted file mode 100644 (file)
index 49763f3..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
-    let s = ep_lib::S; // Feature error
-}
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
index 6a706bdb9b2b6af133d24c63b3da2eaa57afe8f4..6ae06f2d56190879351966c43a44bf1822225864 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_imports)]
 // ignore-cross-compile
 
 #![feature(rustc_private)]
diff --git a/src/test/run-pass-fulldeps/custom-derive-partial-eq.stderr b/src/test/run-pass-fulldeps/custom-derive-partial-eq.stderr
new file mode 100644 (file)
index 0000000..ba956e4
--- /dev/null
@@ -0,0 +1,6 @@
+warning: `#[derive]` for custom traits is deprecated and will be removed in the future. Prefer using procedural macro custom derive.
+  --> $DIR/custom-derive-partial-eq.rs:17:10
+   |
+LL | #[derive(CustomPartialEq)] // Check that this is not a stability error.
+   |          ^^^^^^^^^^^^^^^
+
index a0747e0fbf59f9d94081d7173fdcf2ef212899fb..1e42355f83421ad926c8a761c9062f4c940721e4 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 #![feature(rustc_private)]
 #![no_std]
 
index 4c5b3259902eb39a7479bbd09baeeae8d9393ed3..8b56ade21f955f84bc19d5cd4934f01fa151aeba 100644 (file)
@@ -8,16 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_imports)]
 
 #![feature(box_syntax)]
 #![feature(rustc_private)]
 
 extern crate serialize;
+use serialize as rustc_serialize;
 
 use serialize::{Encodable, Decodable};
 use serialize::json;
 
-#[derive(Encodable, Decodable)]
+#[derive(RustcEncodable, RustcDecodable)]
 struct A {
     foo: Box<[bool]>,
 }
index 6e5eb86c584116ab287768b69d112726ebc516a7..15edd4d49508e1806bd4d570ca0cc3edcc6a6a52 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_imports)]
 // This briefly tests the capability of `Cell` and `RefCell` to implement the
 // `Encodable` and `Decodable` traits via `#[derive(Encodable, Decodable)]`
 
 #![feature(rustc_private)]
 
 extern crate serialize;
+use serialize as rustc_serialize;
 
 use std::cell::{Cell, RefCell};
 use serialize::{Encodable, Decodable};
 use serialize::json;
 
-#[derive(Encodable, Decodable)]
+#[derive(RustcEncodable, RustcDecodable)]
 struct A {
     baz: isize
 }
 
-#[derive(Encodable, Decodable)]
+#[derive(RustcEncodable, RustcDecodable)]
 struct B {
     foo: Cell<bool>,
     bar: RefCell<A>,
index e967873280470431417e1246ee6bec5f8b8d777a..b95c947d21587881c55cb1f349496539057c3213 100644 (file)
@@ -11,6 +11,7 @@
 #![feature(rustc_private)]
 
 extern crate serialize;
+use serialize as rustc_serialize;
 
 mod submod {
     // if any of these are implemented without global calls for any
@@ -20,21 +21,21 @@ mod submod {
                Hash,
                Clone,
                Debug,
-               Encodable, Decodable)]
+               RustcEncodable, RustcDecodable)]
     enum A { A1(usize), A2(isize) }
 
     #[derive(PartialEq, PartialOrd, Eq, Ord,
                Hash,
                Clone,
                Debug,
-               Encodable, Decodable)]
+               RustcEncodable, RustcDecodable)]
     struct B { x: usize, y: isize }
 
     #[derive(PartialEq, PartialOrd, Eq, Ord,
                Hash,
                Clone,
                Debug,
-               Encodable, Decodable)]
+               RustcEncodable, RustcDecodable)]
     struct C(usize, isize);
 
 }
index 532f2456599763b4fd897f2ee7b746af108ab02b..1deeb24243714d4c688413605ea3dcadcad026d5 100644 (file)
@@ -8,8 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_upper_case_globals)]
 #![feature(rustc_private)]
 extern crate serialize;
+use serialize as rustc_serialize;
 
 pub const other: u8 = 1;
 pub const f: u8 = 1;
@@ -18,7 +20,7 @@
 pub const state: u8 = 1;
 pub const cmp: u8 = 1;
 
-#[derive(Ord,Eq,PartialOrd,PartialEq,Debug,Decodable,Encodable,Hash)]
+#[derive(Ord,Eq,PartialOrd,PartialEq,Debug,RustcDecodable,RustcEncodable,Hash)]
 struct Foo {}
 
 fn main() {
index db30bfbf747901499fea6b30f1c9260a5f184dfc..48f54188796798c696677466b251f61520ba2141 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unknown_lints)]
 // Check that an arena (TypedArena) can carry elements whose drop
 // methods might access borrowed data, as long as the borrowed data
 // has lifetime that strictly outlives the arena itself.
index 4f419e70074fc673a329cecb20e89b9f859b2612..5121ecd6cf31161b69e71dd1796e00e46e8fb715 100644 (file)
@@ -8,10 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
+#![allow(dead_code)]
+#![allow(unused_imports)]
 
 #![feature(rustc_private)]
 
 extern crate serialize;
+use serialize as rustc_serialize;
 
 use std::io::Cursor;
 use std::io::prelude::*;
 use serialize::json;
 use serialize::opaque;
 
-#[derive(Encodable)]
+#[derive(RustcEncodable)]
 struct Foo {
     baz: bool,
 }
 
-#[derive(Encodable)]
+#[derive(RustcEncodable)]
 struct Bar {
     froboz: usize,
 }
index 907967d115d583ec7ecc67ce5e7e6ddc6fede761..5426dd94637a6ecbce2a07c532ee7397a71d0f07 100644 (file)
@@ -8,14 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_mut)]
+#![allow(unused_imports)]
 #![feature(rustc_private)]
 
 extern crate serialize;
+extern crate serialize as rustc_serialize;
 
 use serialize::{Encodable, Decodable};
 use serialize::json;
 
-#[derive(Encodable, Decodable, PartialEq, Debug)]
+#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
 struct UnitLikeStruct;
 
 pub fn main() {
index 15ac1d55cc8c41a2164112f0f917eac8dff55bda..362aeabd60ee69cfa9fc067e57136fd9f48b327a 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_variables)]
 // no-prefer-dynamic
 // ignore-cross-compile
 
index 0c208773884d4841d57237eadd2c9bc01a1c79a5..717a35707b415bab9b23b252de9d84f4798c8045 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_imports)]
+#![allow(unused_must_use)]
 // pretty-expanded FIXME #23616
 
 #![feature(rustc_private)]
index 03311d76e46d43619f6c3a1731bcbbf68eb1e68c..016f61395295d39ea84c8c5769db4771dde739c5 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
+#![allow(unused_imports)]
 // ignore-cross-compile
 #![feature(quote, rustc_private)]
 
index ae7eb84d3e8eca8524feafae48d2b9ed2c102efc..6abdf98bb384479e2743d8a8f475dcda919e13da 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 #![feature(rustc_private)]
 
 extern crate serialize;
index f999d2d0ed99c8899a3cbe00ba8db91a05bb766d..2e1104afae0318f2018d543cfb1e0df77f79da26 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
 #![feature(rustc_private)]
 
 extern crate serialize;
index bc3fa162e02bda34d8e145d4819a49b5b28c839b..2d72b42a5bd7b333bb402d411b51ab19a44b7723 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 
 #![feature(rustc_private)]
 
index 8cb9dc4a1b6ec5ca2aab7dc2c9cb1c1a781874c4..8633e906082c6cce8f3a36dd4b6e5f9954f8a393 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // aux-build:custom_derive_plugin.rs
 // ignore-stage1
 
index 86d7cd54d973949b9f466e213ac09caca29c90f4..5d00b5944346ea4b0d20ec0a68f624e8325e19cf 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(plugin_as_library)]
+#![allow(unused_imports)]
 // aux-build:macro_crate_test.rs
 // ignore-stage1
 
index 9245e85edd6ddf085351f180bea6765a2c0f4063..6e8314b968092864445a0107839430bba8e78f4a 100644 (file)
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(plugin_as_library)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_imports)]
 // aux-build:macro_crate_test.rs
 // ignore-stage1
 
index 06f78b10e5e93071231b19f591f75f08a3bdd9dc..c3e7787cf7f30e216e95a26084452f9dc200848b 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(plugin_as_library)]
+#![allow(dead_code)]
 // aux-build:macro_crate_test.rs
 // ignore-stage1
 
index 3eb7e8cc9a46dfbb2ff6d4dc6ea38dfc91158ca4..4c36f097ec1149f810d6f3387647035f28668591 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_parens)]
 // aux-build:cond_plugin.rs
 // ignore-stage1
 
index dfe97eb587cfb9f1cb6c60406419b880014cd51d..9d2120e6764f74ac9653232f5d5f549b87e48059 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_variables)]
+#![allow(unused_imports)]
 // aux-build:call-site.rs
 // ignore-stage1
 
index 93023f8f8edfc25e2a982babb5e48a9f86e00091..e7e8b3d665ea1731fa7c5b5cbca64481b75cc3ce 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // aux-build:derive-attr-cfg.rs
 // ignore-stage1
 
index ba5a639a759cb826f156524c92730897f7420119..64ad57107c7b26029d09d88172eff1769bb541c9 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(path_statements)]
+#![allow(dead_code)]
 // aux-build:derive-same-struct.rs
 // ignore-stage1
 
diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.stdout b/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.stdout
new file mode 100644 (file)
index 0000000..77605de
--- /dev/null
@@ -0,0 +1 @@
+input1: "struct A;"
index 0df0288216eff20bca370b29164fbfd24c59248e..9c2ba481f5e97e2c76119b483a970962c6cb4cd4 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // aux-build:derive-two-attrs.rs
 
 extern crate derive_two_attrs as foo;
index 71807e21d962e4dbe9bac59f09d8559115703940..298a652aacceb113c7036cf7b325a94999e7e385 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_variables)]
 // aux-build:derive-union.rs
 // ignore-stage1
 
index 38a2716aee77beaa56fc164d36e91d26ee8645b0..2b0a57dafefc96fc4caaf9c217ae8f7a999181dc 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_imports)]
 // aux-build:empty-crate.rs
 // ignore-stage1
 
index 579e8c337733af325147ecb3fbb7ff98e17de121..2d15b4e60b4261e0820b99f1b01c109ef5232e51 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_macros)]
 // aux-build:hygiene_example_codegen.rs
 // aux-build:hygiene_example.rs
 // ignore-stage1
index 3fc7446815eb4cf9dacf5f5dc3a07c66519ee50b..f722109260103550092d0fbd53c8999fef6c85d8 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // aux-build:issue-39889.rs
 // ignore-stage1
 
index 410faaeb3eeaccf7d646abcdcfa3797ee346d0a5..046591665750cbf296458f2c62ef7f87b8536d73 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(path_statements)]
 // aux-build:issue-50061.rs
 // ignore-stage1
 
index c73441e30e6d57b7933f57be500715eb3ed9fd6d..79d6d27dc598daa91f732091ca9326de744c62db 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_variables)]
 // aux-build:lifetimes.rs
 // ignore-stage1
 
index 67c12377814704d84d2abcc32464ab60d8e2996a..cf1e076f270b603701c564343502b0f2addb8d4c 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(path_statements)]
+#![allow(dead_code)]
 // aux-build:derive-atob.rs
 // aux-build:derive-ctod.rs
 // ignore-stage1
index 54d651df1f9afacc68e87a89dea3b2cb3af1fe7e..49011e19a513d724e689b315c4956fcc0c808067 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
+#![allow(path_statements)]
 // aux-build:derive-a.rs
 // ignore-stage1
 
index c9056e08d4426faba5d9c2fffdcced41ebe4ed6e..db52aa5d3a62ac667fba09c9d338f70813882bf5 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // aux-build:derive-nothing.rs
 // ignore-stage1
 
index 55fed8693a06517eb4b0d2562d82e9987636071b..ec12ad17e8f88ee431a88fc07e31ce4474dd45d7 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_imports)]
 // ignore-cross-compile
 
 #![feature(quote, rustc_private)]
index 8e6a69cb58479e1af384cb19729e1554ca4d12dc..7f46e0928a2fb680ed033cf18d509e4768d7cc31 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_imports)]
 // ignore-cross-compile
 #![feature(quote, rustc_private)]
 
index d3be1ddcb8c32f274983f7b1649e0b8a83ba0853..7e85becfc3c69ceb5e40bb0df47afe32632ba69a 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // ignore-cross-compile
 #![feature(quote, rustc_private)]
 #![deny(unused_variables)]
index 670f5380d81fa4666ef45ff4f6c626f8f25af368..013c331d0fd321ef783e7f37a1a318dd5f14dc83 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
+#![allow(unused_imports)]
 
 // Test a sample usage pattern for regions. Makes use of the
 // following features:
index 417707e89322c27611f685ec7a724d73c87a7a3c..099f3e58c6c9cf728ae73b6ddeb42a1fc590b812 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
+#![allow(unused_imports)]
 // This test can't be a unit test in std,
 // because it needs TempDir, which is in extra
 
index ef368ed604bea810890c7df702b1336b9c4e7214..17b2ee39c884b727326d2f392cb952aaeea740b1 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
 // Since we mark some ABIs as "nounwind" to LLVM, we must make sure that
 // we never unwind through them.
 
index 77b9efb0012f067e199362325da3575ceeeefbaf..5c87840fe1ee6342fe8f5a2daf55722473f8c7c6 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
+
 
 
 // Regression test for issue #374
index 6f89c5d377f54511501a1d12fce65cbee058094e..92ae68fb6a35e6c0ce713bb6e2d1c3071091c405 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(stable_features)]
+#![allow(unused_variables)]
+
 // #45662
 
 #![feature(repr_align)]
index c1f75d5ee74ea828e208e081d6432dace8bfab6b..7188496dab9ccb8367299533755ef3572d440cb9 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
+
 #![feature(box_syntax)]
 
 struct pair<A,B> {
index 23a1e7998012c9394892667edffb5e6b9c4a38d6..7895e89d58687aa0a8be4b203ba0952017a01fff 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
+
 
 // pretty-expanded FIXME #23616
 
index f15b013c07ba497a02278a7fa3c1d55788841732..a62bd67a5ace27a562ca7e8339f8788b2ea030bb 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(stable_features)]
+
 #![feature(allocator_api, nonnull)]
 
 use std::alloc::{Alloc, Global, Layout, handle_alloc_error};
index 246dd83fbef298f26a68c7e0daa7a042c7106204..debfcc5c552c43189b3beecd5a3b6b65eb4a7ff2 100644 (file)
@@ -12,6 +12,7 @@
 //[mir]compile-flags: -Z borrowck=mir
 
 #![feature(asm)]
+#![allow(dead_code)]
 
 use std::cell::Cell;
 
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 286c92ce50ee30a58b0e86b694f83a1f05eb7776..1d8923af479a155937eedb0f9991e7c18f484aa6 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(stable_features)]
 #![feature(atomic_access)]
 use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT};
 use std::sync::atomic::Ordering::*;
index 2f33eb9ca40932fb32c244c18fa95dbf0903fd1c..5829f764eba7705dfdcc011dfd2769c22cf84e9a 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(stable_features)]
+
 #![feature(extended_compare_and_swap)]
 use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT};
 use std::sync::atomic::Ordering::*;
index 2d478e954e7cb7cb493e98b9da4e2ad124f80b33..25f4c6fd10bd0151dfcdb8019cc409529f5a64de 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
+#![allow(deprecated)]
 // ignore-cloudabi no process support
 // ignore-emscripten no threads support
 
index 2a86489c69aa58018244b699f00304e6314cf10d..4ea78d352e33a2c983b36d73fff6a4b1db344deb 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_attributes)]
+
 // pretty-expanded FIXME #23616
 
 #![feature(custom_attribute, test)]
index c8683f2d1475139b2bb7ea99600f0d7757b2a5d2..34a8b62f9fccb8ac924b3eed12ae6b173de96d6b 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_attributes)]
+
 // pretty-expanded FIXME #23616
 
 #![feature(custom_attribute, test)]
index bcfb4b330f5eda6ff3e46578601fb2eb40f47a2e..5b89cec70c0a86c515ae74d66bb08b0f75cb7b13 100644 (file)
@@ -7,6 +7,10 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
+
+#![allow(unused_attributes)]
+#![allow(unknown_lints)]
+
 // pretty-expanded FIXME #23616
 
 #![allow(unused_attribute)]
index e87b9e3d82a24ae3fba6d98647dbf8b93d4d6ba6..827da72bc44ab674de823a3d8c489f77b8d773e6 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_attributes)]
+
 // This test ensures we can attach attributes to the formals in all
 // places where generic parameter lists occur, assuming appropriate
 // feature gates are enabled.
index 3ed9e8548dcbc05d693d888f49e4d651998c3963..b8bfad8cfcbd9ea93b8856ed73f0c1fd28e4c6c0 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_imports)]
 #![deny(unused_assignments)]
 
 use std::mem;
index 4a1bfa3eb42668e5f2f30a33ab632d16cd5047c5..0fe347fc43c086b995d676834ca0b6320f73d7db 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 #[derive(Debug)]
 struct Pair<T, U> { a: T, b: U }
 struct Triple { x: isize, y: isize, z: isize }
index ad433cc26a790bdf3984052049e8d82bcfdf8fd2..efddcaa14d3f307f5f40429325aeb8f91e6a29ee 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(path_statements)]
+#![allow(dead_code)]
 macro_rules! auto {
     () => (struct S;)
 }
index 2b8fcd303b66ed7dbf843d0ef370f7dcd9a3e43f..0b2098b0f055b82bcde07a1bb8ee5f8e12944be3 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 // Binop corner cases
 
 fn test_nil() {
index bb654b1a20b9102ac1c1f658db6582e51756d198..6066bc32b26b3b01a3d4a948b10920ccb8b64867 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
+#![allow(unused_imports)]
 mod bar {
     pub fn foo() -> bool { true }
 }
index 73cba2e4e0a7ca73bb1eae25d7e16fab0a73ab10..342f67ae44f982ed4bdb36e3a4efc9e40f4f12f5 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_snake_case)]
 
 fn asBlock<F>(f: F) -> usize where F: FnOnce() -> usize {
    return f();
index ac8f5012573616c56fabc935be30af47814a968a..acb0f2dd298d414ea6c40aefbe58ce81afc59544 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
+#![allow(unused_parens)]
 // This test has some extra semis in it that the pretty-printer won't
 // reproduce so we don't want to automatically reformat it
 
index 7e7c5ee4125565111043bca8f7b6fa5cb0ce86db..6f8cdd1b4fcc56aededf1ae7afe1699c09729187 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_variables)]
+#![allow(unused_imports)]
 // ignore-wasm32-bare compiled with panic=abort by default
 
 // Test that builtin implementations of `Clone` cleanup everything
index 3259b1cc0679e516954471b7091ccb3aa209d956..287e68294878beaf3cc8002a9f453ec478c9df17 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_imports)]
 
 // aux-build:trait_superkinds_in_metadata.rs
 
index 6bc81f4a36bcddf56a22302b88ff80c91e11a2e4..84601f68d163fefcb8e700bca32c0ad7a9f19ab9 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // Tests that even when a type parameter doesn't implement a required
 // super-builtin-kind of a trait, if the type parameter is never used,
 // the type can implement the trait anyway.
index 80fa5362a8be940c134ea9a112487991f03e805c..b88854cd7fa6a1bdfce5350513f102e5f9859c40 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
 
 pub fn main() {
     let i: isize = 'Q' as isize;
index c1fcf49654626735f0449d8d5542d92e7e93607e..9f26ee818e6a9483ab6f49999c887cff47dc1bc9 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 
 use std::cell::Cell;
 
index 9c87f2ca68203c9bf60ffdd996def1579d1344de..a95870c2b27feb4b944ede022a3cee49513db0e5 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // Static recursion check shouldn't fail when given a foreign item (#18279)
 
 // aux-build:check_static_recursion_foreign_helper.rs
index dd900c56b40b1109c006934a7b9637bc32c67734..6ff3aff45cba1bcea8667953146271b2f373084f 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(stable_features)]
+#![allow(unused_imports)]
 // Test that cleanup scope for temporaries created in a match
 // arm is confined to the match arm itself.
 
index f69a0332cc4f42e49d5a6fa5e1f05130dc759345..4f8ded9012f8f42f696b9c8addcda51ea641b46f 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_snake_case)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
 // Test that the lifetime of rvalues in for loops is extended
 // to the for loop itself.
 
index b5bf35a7006a33a95682a2ed112fcdb119b00797..8cf014a4d2a2d8cbcffaae8948a6650f20cba7a7 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_snake_case)]
+#![allow(unused_variables)]
 // Test that destructors for rvalue temporaries run either at end of
 // statement or end of block, as appropriate given the temporary
 // lifetime rules.
index ae455d916b6f9fe984cee5af9e64ac1e6c1a4cfc..90b2031afd486be55eca9bde36c8ffcde8c2f27c 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
 // Test cleanup of rvalue temporary that occurs while `box` construction
 // is in progress. This scenario revealed a rather terrible bug.  The
 // ingredients are:
index 6ac7acd2a6b6821951b901f5bcf718f9fdec8816..0358eec0d7645032e2182804d41b4a7cd9eb8b17 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
 // ignore-emscripten no threads support
 
 #![feature(box_syntax)]
index ba700e4e326515c55afc4f7afb5bc20f4ffa7998..44778517c44438c978f92ae3208d901fbcb036cd 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // If we use GEPi rather than GEP_tup_like when
 // storing closure data (as we used to do), the u64 would
 // overwrite the u16.
index 4003c2ec4f7e4aa6a1f209a394148894778952c7..462dc42dbc2b2b483bfc4e6b7dd1afa6b463c55e 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // Test several functions can be used for constants
 // 1. Vec::new()
 // 2. String::new()
index c4fc9ee53fd7fbde976b50d682d728cc48dbd5a5..5d8bc31c2a3375be93898b38453a5a1fa918acd7 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(stable_features)]
 // ignore-windows - this is a unix-specific test
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
index d6d0c2b36f647c888e5b16b3d40d8c4066fa0a4d..46b409fb13a84bc94763e528af8a0bc5dc43e6cb 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(stable_features)]
 // ignore-windows - this is a unix-specific test
 // ignore-pretty issue #37199
 // ignore-cloudabi no processes
index 6bb9503c2b0e4c0600dc9858e61e7dc14796739b..b31f4d39f82f793f5a42b8063fe61361ddd1c61e 100644 (file)
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unconditional_recursion)]
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
+#![allow(unused_mut)]
 
 
 
index eaec9b1926a20dc51211c17ff44969b11f0fb3b9..aaf017c0ad37438b6c290cf1628dd14e4f893554 100644 (file)
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
+#![allow(stable_features)]
+#![allow(deprecated)]
+#![allow(unused_imports)]
 // compile-flags:--test
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
index c94c877c12c6d320875795d4d731206bdcab4602..14f5913e3776b17c6982472e1fe6e907174805f9 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(stable_features)]
 // compile-flags:-C target-feature=-crt-static -Z unstable-options
 // ignore-musl - requires changing the linker which is hard
 
index ae8e5f629704893e380bb51d4aa956b83854b198..dbc483241ab2c547df9e6f33349ff051f754c16a 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(stable_features)]
 // compile-flags:-C target-feature=+crt-static -Z unstable-options
 
 #![feature(cfg_target_feature)]
index 61de804a80a81100dc4e6c368cdb2a8690a7cfe6..d4e25bb5c3c6edb22da7623a3f3fab230d5642c2 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 
 trait Foo {
     fn f(&self) {
index 9b06bf837ae0ccf266e24f63ce341dfb7cf1afc1..fce5e911c57aa3a6bea8ecd6b12ce37665c3db22 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 trait Trait<T> {}
 struct Foo<U, V=i32>(U, V) where U: Trait<V>;
 
index 13257529ed9f860eaaae4d975ef1b7f552f492f2..06d4f16826fbf18f769d4abe23a97ada72fc3d16 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(stable_features)]
 #![feature(core, core_intrinsics)]
 
 extern crate core;
index 723a98bcdfa0d85a894e7aea8d20739afdc0aff0..9f54f50e54000ae47888043da333bf5a40e6f19c 100644 (file)
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
+#![allow(unreachable_code)]
 // Test various cases where we permit an unconstrained variable
 // to fallback based on control-flow.
 //
index 664a329c228ae4a3ca52050ee6a2b1812ff38788..195c55d374b822739c8b51e1a602a06946c57ba9 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_imports)]
 // Test a regression found when building compiler. The `produce()`
 // error type `T` winds up getting unified with result of `x.parse()`;
 // the type of the closure given to `unwrap_or_else` needs to be
index 13ce6a07e3641ad0be295e31e5077a7925c34104..9fa3fbca071b264f0e0f187181eb82ec63e4303c 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
 fn check_expr() {
index 0a490466ef73b3f109b38b62e50ed2e7c9402fdc..c4401781f5940052990f67b3617daedec85469a0 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
+#![allow(unreachable_code)]
 // pretty-expanded FIXME #23616
 
 use std::ops::Add;
index 2d2cf6fbf0a7fc60a7672eec85899ae7f1333f9e..985ed08d34ddf90d89fdaa34778cbef13d7f9bba 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
 trait thing<A> {
index 1751eacc6b7ce42bb90b831fd87870d6aff0d40a..b805b01ae39bdb9ea2f837ff0e732d30be15afed 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_mut)]
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
 // edition:2015
 // aux-build:edition-kw-macro-2015.rs
 
index f2794a4b8d81ab403c2a5007e7e8ac71425e48c4..1e3d0c5f7778d9f4f354db81c19260f2240ad288 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_mut)]
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
 // edition:2015
 // aux-build:edition-kw-macro-2018.rs
 
index 7d5de00cdb8c2b3702555d5bc10d03dbdf691899..9b2e49c5111e1af0779b796091314270f8553cdd 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_assignments)]
 // edition:2018
 // aux-build:edition-kw-macro-2015.rs
 
index 6462fc4da60a02125c45235ecf7577ec1508ffc8..be632b113741c5ba743d82ecc427a65bc0a3ca83 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_assignments)]
 // edition:2018
 // aux-build:edition-kw-macro-2018.rs
 
index f52a21a997d78a00dfff2a46f1592bf4e80b7d10..28bfb368b6e6b537bd8bfd422552924c925acd12 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_variables)]
 // pretty-expanded FIXME #23616
 
 pub fn main() {
index e92f24a27519e8d6bfcb3c4dc5bdd148953c5fd3..6bb2fe4b34df1ad46a8cb6c109bdd3f5b81e5b79 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_variables)]
+#![allow(deprecated)]
 // ignore-cloudabi no environment variables present
 // ignore-emscripten env vars don't work?
 
index 296764269dec058da0f1d614bf3bb3c263f0df1b..9a461991c1e62d3f60a2e647819f517dd7e035c0 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_imports)]
+
 // ignore-windows
 // ignore-wasm32-bare no libc to test ffi with
 
index e3cd1edd20987786dfa1cf891d42203885d77387..754e30f3adfd915599a34322e78c293dea00376f 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
+#![allow(unused_variables)]
 // Checks if the correct registers are being used to pass arguments
 // when the sysv64 ABI is specified.
 
index 4dfb15418405dd8ecdf5405479fb6112adf26ecd..e8047b3cb7f8c782f0c080c343baa8e26e0d6227 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_assignments)]
+#![allow(unknown_lints)]
 
 #![allow(dead_assignment)]
 
index e63d5c2293a810be4dd8ddd48dd01f3bec39819b..0193fe4b83328dc97335d54c153bd2f0098329fa 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
 #![feature(existential_type)]
 
 fn main() {
index fa3970b62805b808dd533260d80ddb5cd702fc0e..b86af5d2fabd8d5e85da5d0d1ffcf69c3d3a9e75 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
 // pretty-expanded FIXME #23616
 
 pub fn main() {
index 4f821ebcc185a67493d49c341d156724c16b9dce..36724f0b64808ce27df9e1c7862e3d202e22b483 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_upper_case_globals)]
+#![allow(dead_code)]
 // Test that a glob-export functions as an import
 // when referenced within its own local scope.
 
index 664555caf26bb944163e88cd2e9e7bc5f9ad7468..3459b3c84c573381c7b54e0925ca437b1ab4a769 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 
 
 
index 02ac2a0b67b14f1107a5790157bd7a86bbe24f3c..9fb0f07b6a03eea0d54fd3e406e4e23b88372fa3 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // Issue #521
 
 // pretty-expanded FIXME #23616
index 5ab6c7774d55cf3a83c3012fe4ef9a8db6f9393f..938c556038ff9bd13e6fc98fe13597746e9fe065 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 
 
 use std::cell::Cell;
index 900da3c2d6ab29830790a3ac7975d2d13be14242..903e97b315869776f0880503beb881f06df7d7f6 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
 use std::ops::{Deref, DerefMut};
index 6971f775231d5f7179bff9ea971a10e59fe748ee..892fae417ad6d8a84e3b3108ba1428f0931c3120 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_upper_case_globals)]
 pub const arg0: u8 = 1;
 
 pub fn main() {
index efd7f66e93b837d92e73ccc3aaca2c7542ebf625..3be15552dc1c6efd9c1fe7887f232ab1422b427e 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(stable_features)]
 // Issue 4691: Ensure that functional-struct-updates operates
 // correctly and moves rather than copy when appropriate.
 
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));
 }
index 53c3eff5b81ee11dc22d2c35f300571f394da821..32f262c5a404cf3e5cbb6ac373d438a946749c3a 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_snake_case)]
 
 #[derive(Copy, Clone)]
 enum Q { R(Option<usize>) }
index d79dbabac2d42e4ca82e48aed87e7b61f94e26fb..af4e2efb2ba37788224aa1c814cd8c9b4cc6b74f 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_shorthand_field_patterns)]
 
 #[derive(Copy, Clone)]
 struct Pair { x: isize, y: isize }
index 2e98e0fe5ca3d24a3b5547ad89bff219576b5427..2b30b5ca9fcc6591a71b33749f7ddf03563ef841 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
+#![allow(unused_mut)]
 // ignore-emscripten No support for threads
 
 /**
index 1e1fde4d1e2be75c8db4970620d7a76c6d36979b..1aed2844c965aeaf2ed73086258bfd3ea6d18c68 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 // A test of the macro system. Can we do HTML literals?
 
 /*
index 8d475a99b818833ac41830362b72b7ac02c4ed74..5c5c4c80ab18f009ac5bb6a0a43f747ac789dee9 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_parens)]
 // pretty-expanded FIXME #23616
 
 fn foo() { if (return) { } }
index c14f3dc72916d6e26b0e03510691cf05b55cefae..90d858c28585be7dd405f0e63ce5714e6249d597 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_shorthand_field_patterns)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
 // pretty-expanded FIXME #23616
 
 #![feature(slice_patterns)]
index f00005fc7d0b58c8fadf64c80937111339a82d47..a3e0f9dc0393514e2be72827ebbf717d030a2d6e 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // issue #680
 
 
index c8f9a0e4cab6d9b7e07c593c163fea185c892ab8..0ad0ecf8ce92c6fb4477a4d6cf19582a1807f8c3 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
 // Makes sure that zero-initializing large types is reasonably fast,
 // Doing it incorrectly causes massive slowdown in LLVM during
 // optimisation.
index a270b003981669377b9a28a38d31a48f6f4d0964..dd838ef98db9ca3dda97933b4babac9a6b5beacb 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
 #![feature(box_syntax)]
 
 use std::cell::Cell;
index 28fba70eb24d96c5daccc484c2d902b0278ab4d2..7d708b475fca5436c053ac3812f58e01aa293122 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
 use std::ptr;
index a18d82fb7a4e7e22c334fe85204ff5b500795ae7..e861f21762991be81296ef697b6a18b3299c5c77 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_mut)]
 // ignore-wasm32
 // ignore-emscripten
 
index f9cb5da29a7d0eaa8883d242cd7c5f09f09ea7ff..2eaa73ed6f751e535b7842695dddfec8e6f17109 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 #[repr(u16)]
 enum DeviceKind {
     Nil = 0,
index 0fc13319b8734a8337bcea6d6f0100e97906f6d5..97fa8d36d137c92fc6f6e09723b6a729d16a839d 100644 (file)
@@ -8,6 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(non_upper_case_globals)]
+#![allow(unused_attributes)]
+#![allow(dead_code)]
+#![allow(unknown_lints)]
 // These are attributes of the implicit crate. Really this just needs to parse
 // for completeness since .rs files linked from .rc files support this
 // notation to specify their module's attributes
index 2827a6df3373767f09fcf59581cf17a614301930..b07b0359a2d72c3328db70ac0e6b4a6927e1efde 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 
 
 
index 9838fe62394ce17b1696bdebac12201634c6a6d5..6dbfacf047425027b8ad21313756e44c94cea755 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // return -> return
 // mod -> module
 // match -> match
index 1c5d8a69bf3406a9a7eb7d9f9ddea8376f6fba87..9788b1e06036f5cd21bf8f0dadce8a4c61ad87dc 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
+#![allow(dead_code)]
 use std::thread;
 
 fn user(_i: isize) {}
index 5109c6fc77726d31ee0d620dfacaced9a300d7fd..ec12f257f6108da9213f68267421862fd64a604c 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_mut)]
 // This should typecheck even though the type of e is not fully
 // resolved when we finish typechecking the ||.
 
index e9c66093fb0cfe98f649f1b4ebf77c234fe57e4e..bd685dd4244955dcf8044e2cd2c0c1f7a391de50 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 
 
 
index a2b01f29ae127f457695fc0c7e7a37b6816e85aa..bed94de7b952830f872c55f2f88283862e533e92 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
+#![allow(unused_parens)]
 // Issue #1818
 
 
index 5fbcfadf870e1682be4f2c44a96ed55bbfce3028..d63a712c1aaf8efe8138d20dde3c34b979166a6f 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // Make sure #1399 stays fixed
 
 struct A { a: Box<isize> }
index cb2a2061406a243d9928d439c9fccb92d1ec6a98..747c7d2eae4002e2b9a025f2649f5177a3f9118f 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // Make sure #1399 stays fixed
 
 #![feature(box_syntax)]
index d71d7e751a045c2f24c2fcbcc5941e850a4f1119..a4a3edf71c0c4c532cc8b1fc249204e18cf0218c 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_mut)]
 
 
 fn foo(x: isize) { println!("{}", x); }
index fcaeda9a5495bfeb929cb5143543fbb3ba62ff78..19340ed0e97b8196978ec2f37fa3fd8fd8fc7dbd 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// dont-check-compiler-stderr (rust-lang/rust#54222)
+
 // ignore-wasm32-bare no libc to test ffi with
 
 // compile-flags: -lrust_test_helpers
index 3336ce7e723de6e79050b89f347985f91b2c2045..e2369e85d56dd8ae014849440a58507866fb1e9f 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_upper_case_globals)]
 #[cfg(not(target_os = "macos"))]
 #[link_section=".moretext"]
 fn i_live_in_more_text() -> &'static str {
index 6e65cb2afd4ff38c59063c1235c9276a4589690e..14ef8c1f51f7d6a32426053d83ba63c9930ae452 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 //
+#![allow(dead_code)]
 
 
 #![forbid(non_camel_case_types)]
index 3b4bd001e8dc051abba93eecb027eb383160c5e5..8115a2c50e3d675a4cf57df226cceb8da366211b 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // This is ok because we often use the trailing underscore to mean 'prime'
 
 // pretty-expanded FIXME #23616
index 37612415555099880cca736a9bdb71aa99168693..bab777d09730d2188b958133a4bb655e24676e09 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 // pretty-expanded FIXME #23616
 
 #![feature(box_syntax)]
index 76b44832a8a1651f1c1d06360a8495e1cfbb8466..bccc939e85ed50117e408ddaf0a37797855b9c2f 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unreachable_code)]
 // pretty-expanded FIXME #23616
 
 #![allow(dead_code)]
index 1991e2b178d51c4ddb76f25d19e5e5d6960884b3..4c501a78b576c87abbc0f91e90e887004a9b44b5 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
 #[derive(Clone, Debug)]
 enum foo {
   a(usize),
index e8852377957f88ed3a406dff051bd8f6d1e99de8..19a7c7105c93ca9a63867223de26546178b8d6e0 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
 #[derive(Debug)]
 enum foo {
   a(usize),
index f0844b8e1eb1770d24a5058aa71dfdaaa8798274..f34d5cbd9e314d27937e04f7dc21f3b7bae03a23 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_snake_case)]
 trait Product {
     fn product(&self) -> isize;
 }
index 3055f90ee259772e4472d49c75e278533d734d1d..7e06530b38c8f5fdc3427b380a7b23b9389b1c2e 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
 struct S<T> {
index 211827f92222ca0ca02f501a9cc28908e3d3b942..6c7c39e5aa5278c39f0ab8dd45b7d369230bde94 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 
 
 
index 00e97ebc24e7ba5f5f1fa4b6a616a2cec0d6bc55..899f3f4ba30286845e8ca44bddfa27adb01d1c60 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_upper_case_globals)]
 /*!
  * On x86_64-linux-gnu and possibly other platforms, structs get 8-byte "preferred" alignment,
  * but their "ABI" alignment (i.e., what actually matters for data layout) is the largest alignment
index d8eafb806f74765432735847d64814f03c4e89b0..c00fb68f9f7ff68c757284e30c7bf7a67645db03 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 
 use std::mem::{size_of, align_of};
 use std::os::raw::c_int;
index 72a8847094b2c08630fc7412b940a19a81eecb23..87879e0841410115ab758492b01e67d7688511ca 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
 
 // pretty-expanded FIXME #23616
 
index 1ad68cb9de0522a8d4df3ff7beb2c15c77414b6e..ca8693868565d6f47abc340206e8059280b0ce58 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 
 pub fn main() {
     struct b {
index 5c0af392f44df27c659d6cebedccf666c1c4dee7..a1b9eda8b897509b0fcd3bb6f5f01ed41fc0de66 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_variables)]
+#![allow(unreachable_code)]
 // Test that we can extract a ! through pattern matching then use it as several different types.
 
 #![feature(never_type)]
index 428eed0787a833db32a0959fed1a74f89a35c61a..c2871469de16832073f0c2ff888153e23f1df3f6 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // Test that the lambda kind is inferred correctly as a return
 // expression
 
index 439ea3f2b579c0919e998c7042156e51c2e9ea7d..4d545c7a969db701b87b5eca482d551cf00d3774 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // Test that the lambda kind is inferred correctly as a return
 // expression
 
index e7da8d7bf93c7b1705f52c286e163b27793a3132..20817cddd05c2a3da880cefc20b170557bbdcdd4 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 
 
 #[derive(Clone)]
index 818ea4c9f23262429aec69bc932fbad5d7cbce87..3dbad08f1d87ef80a5fdf805f45d4be810ee1fb4 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 #[derive(Copy, Clone)]
 struct mytype(Mytype);
 
index 97ee237771f3fae9bd6e8e307f8c1d44714c63f4..96bc80c21259174fe3dc5cc5d36d5e58101e2d83 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(improper_ctypes)]
+#![allow(dead_code)]
 // Issue #901
 // pretty-expanded FIXME #23616
 
index 7868077fbf244cac6a4861196ec770bd4f177fa1..f5f089691182b310ac6d573e7a579cb5d1df2deb 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(stable_features)]
 #![feature(no_core, core)]
 #![no_core]
 
index b097d350c8d5e299aefe18eb468ae79f286db6f2..bdeae618c8b914af24c24ef583369ffa3111880f 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 
 use std::mem;
 
index c3a1164ba9c6af2e1c229e7e2311fefe822bb09e..1d66388275e9b83e0ba5b01883205c1b60d044ee 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_variables)]
 use std::cmp;
 use std::ops;
 
diff --git a/src/test/run-pass/optimization-fuel-0.stdout b/src/test/run-pass/optimization-fuel-0.stdout
new file mode 100644 (file)
index 0000000..3ad405b
--- /dev/null
@@ -0,0 +1 @@
+optimization-fuel-exhausted: Reorder fields of "S1"
diff --git a/src/test/run-pass/optimization-fuel-1.stdout b/src/test/run-pass/optimization-fuel-1.stdout
new file mode 100644 (file)
index 0000000..197e452
--- /dev/null
@@ -0,0 +1 @@
+optimization-fuel-exhausted: Reorder fields of "S2"
index e22edb3caede49ea89f1d9ec8c80679bdff05177..32faab4c12c5f79307f7ea667225cac40743a26a 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 use std::cell::Cell;
 
 struct dtor<'a> {
index 6ed07fb2f7d25a884e2d67e88e07d00db09527e8..cd0f7cdbf6dab9f5941fba268271d9c2c8f9799b 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
+#![allow(unconditional_recursion)]
 // ignore-android: FIXME (#20004)
 // ignore-musl
 // ignore-cloudabi no processes
index 2171b8c481d1fd7c24b7f4f882437ba67534bf1f..e4013854e7895a3e9e3deb1f54c79d4856248ed6 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
+#![allow(unused_assignments)]
+#![allow(unknown_lints)]
 // pretty-expanded FIXME #23616
 
 #![allow(dead_assignment)]
index e4e07941470a815655bf5fdb73c603a4e7b2c066..edbb311fcda8380e9f1cc978505db156dce0cc8d 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
 // Regression test for issue #152.
 pub fn main() {
     let mut b: usize = 1_usize;
index 22b24ebb3b589b5fcdbe7beca6a4714156e9dcbb..5c904295bb47545038f99f9298486a881de1aee4 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 #![allow(unreachable_code)]
 
 fn dont_call_me() { panic!(); println!("{}", 1); }
index e0fe1ea72df16486312de38ba7c6f57dae96687b..3359f1064c9c6b029ce09fbd7f3d0897167dcbb4 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(deprecated)]
 // ignore-cloudabi no files or I/O
 // ignore-wasm32-bare no files or I/O
 
index 29dc6984e234a48459e3634103074a469484ec94..24fb400150aa851712ddb171ebee0e4f906bb1f8 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // Regression test for #37154: the problem here was that the cache
 // results in a false error because it was caching skolemized results
 // even after those skolemized regions had been popped.
index 9a6ea2272fea7c5ca453595a1c0f3343eed99212..c4a3856bcbc2e0718faaee36005f9430b8c83e9a 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unreachable_code)]
 // A regression test extracted from image-0.3.11. The point of
 // failure was in `index_colors` below.
 
@@ -92,6 +95,10 @@ pub fn index_colors<Pix>(image: &ImageBuffer<Pix, Vec<u8>>)
                          -> ImageBuffer<Luma<u8>, Vec<u8>>
 where Pix: Pixel<Subpixel=u8> + 'static,
 {
+    // When NLL-enabled, `let mut` below is deemed unnecessary (due to
+    // the remaining code being unreachable); so ignore that lint.
+    #![allow(unused_mut)]
+
     let mut indices: ImageBuffer<_,Vec<_>> = loop { };
     for (pixel, idx) in image.pixels().zip(indices.pixels_mut()) {
         // failured occurred here ^^ because we were requiring that we
index ac1b6aebec5b1cd1785a5389115a5a8ac6d11ba8..3a4d2b3e60208ab877a7e21fdb4ba43bf504bde8 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_variables)]
 // Test coercions between pointers which don't do anything fancy like unsizing.
 
 // pretty-expanded FIXME #23616
index 3313196a5eced2a8bb17bcf124adc5b11be4a2b4..5f6b9b17e3607fa841328ff99d9889a4509c4a5f 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // Check that functions can modify local state.
 
 // pretty-expanded FIXME #23616
index b6d4d09d69727239a4e4cd4235a5a5797d7e0995..809c1ba702bfb9b2730b8deb5586a1ef8e10d247 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
 // Make sure the type inference for the new range expression work as
 // good as the old one. Check out issue #21672, #21595 and #21649 for
 // more details.
index 4c249bbe1f73e338b90d88a775e7b9227f205a3d..2fae4d3cf269329e8932594b6562a833e726c3a3 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_comparisons)]
+#![allow(dead_code)]
+#![allow(unused_mut)]
 // Test range syntax.
 
 
index 6c2731fa5a9bb85fc5bca85b7358cea2cacc5ce4..09132efe18cfb1d22888b4cafa8e9779bf9f14b2 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_comparisons)]
 // Test that you only need the syntax gate if you don't mention the structs.
 // (Obsoleted since both features are stabilized)
 
index bc869113fe90000e5be3114e827c9693ad823c74..02392be7e4f2d490b980068792359801d1015cb3 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 #![feature(box_syntax)]
 
 trait get {
index 56b15c243618f4d5b621659698d17efd33b60a67..d7ddd9505d78c7ad91bad4db7c8f6428461694a5 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 
 
 
index 6159b24165e44db866e84c78cbc9fc49212b9071..0ad97e78d1afab0608b76259a66c89a51541abae 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(non_upper_case_globals)]
 
 const foo: isize = 4 >> 1;
 enum bs { thing = foo }
index 4d0c2900a0fad5ab14390f02caf7f2abc7fcdb42..ccc3396e50c0236ec2e23b93cc7794781af1b9c3 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 use std::cell::Cell;
 
 #[derive(Debug)]
index c92a9ca8480ca7c5fc979d813997196f5e2a4044..d3ba221b34a064713e86a4ebf3ba32b5dfca817d 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 use std::cell::Cell;
 
 struct shrinky_pointer<'a> {
index 032a4b662cb1a3dbb4c640ae0060067a8e0cd03b..72ee3dbfe2da2ef7f425ccc1143fb9a334fa27bf 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
 
 
 // pretty-expanded FIXME #23616
index 629387d4cb11d554840a56c89b2f3f96ec2046f2..8c3e4b391e995b73fec99613c241735685cc8bd3 100644 (file)
@@ -8,6 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// This test is just checking that we won't ICE if logging is turned
+// on; don't bother trying to compare that (copious) output. (Note
+// also that this test potentially silly, since we do not build+test
+// debug versions of rustc as part of our continuous integration
+// process...)
+//
+// dont-check-compiler-stdout
+// dont-check-compiler-stderr
+
 // rustc-env:RUST_LOG=debug
 
 fn main() {}
index 307ead4b74f741cf6fd9188ec4d04765c610c345..a85fe6733dd80e068fa107f286d39c59e6eb91cc 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_imports)]
 // ignore-cloudabi can't run commands
 // ignore-emscripten can't run commands
 
index 0fc5fe498a62d6012d580df01e90d6e0def615f8..c9ab466e445598222dd6739e058626d526d14b3a 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
 
 pub fn main() {
     // Test that lambdas behave as unary expressions with block-like expressions
index b764fc6f1ec967143c1f00731debf9ba96ef8e73..b2028927da46eb4f9b96f30e356012844ac5bfb8 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
 fn foo(c: Vec<isize> ) {
     let a: isize = 5;
     let mut b: Vec<isize> = Vec::new();
index d2a32da4feaa29ffcc286a93ae96ff2118b026c6..b54ba3d2ce749e8f37eafa7c65c5d87cdad2f5b6 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_imports)]
 mod foo {
     pub fn f() {}
 
index f5e2239538f65ada5d7a55c08c976b04a3412b87..c964bcb94ef83aea40da5d4bd5b235892768458e 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
 // Be sure that when a SIGPIPE would have been received that the entire process
 // doesn't die in a ball of fire, but rather it's gracefully handled.
 
index 04c1af4326bbd2a067d8dcf2213f9587d7f2fd35..6feb2da5fac52f4b8a0b6e42977996653ff013a0 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_mut)]
 
 
 pub fn main() { let mut n; n = 1; println!("{}", n); }
index cd8273c6bc2b8fdcaef69e7cb72ded2c991a88c1..2d8ac6d99f7cfab5b46b820cbad53e0ecfe0eda3 100644 (file)
@@ -10,6 +10,7 @@
 
 #![feature(global_asm)]
 #![feature(naked_functions)]
+#![allow(dead_code)]
 
 #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
 global_asm!(r#"
index 13d55e0172e71f41f80c2ee28d46106927af0711..0da63f93cc6b31013eb4ece7b11c68fa2774aed2 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 enum clam<T> { a(T, isize), b, }
 
 fn uhoh<T>(v: Vec<clam<T>> ) {
index 76c06d560d754417f786c7f4a09d8634acaee546..03425e0472520c6d4b28d2a3b0ae111328b5d665 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // Possibly-dynamic size of typaram should be cleared at pointer boundary.
 
 // pretty-expanded FIXME #23616
index d3a6b104dba55f441f526482f63c69d680258c55..5624910cee9ee0a1959eb0bb994357557e585df2 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // Possibly-dynamic size of typaram should be cleared at pointer boundary.
 
 
index 90ea7537c6e607aea721549fca788db37ea8c6d7..49fb417675518e4a2fe5235cc2c7973b1796fe9a 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
 #![feature(non_ascii_idents)]
index b1d7e5435c4cb9b33d905aa3b78cb234a6c7a38b..041286fe656a0d10a3154f5e34628cc530c284da 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(stable_features)]
 // min-llvm-version 6.0
 // ^ needs MCSubtargetInfo::checkFeatures()
 // ignore-cloudabi no std::env
index 7974366c395fc922f0c4b2e728322a2e576f7d8d..22d1eeb0e0afc37532437e73ab1077c80c009756 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 
 
 #[derive(Copy, Clone, Debug)]
index a1bbd190211272170958c3b7a4a4a401edf85529..5e120bd80ee23ab087018d5feb4f9f385f6fac40 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_upper_case_globals)]
+#![allow(dead_code)]
 // exec-env:RUST_MIN_STACK=16000000
 // rustc-env:RUST_MIN_STACK=16000000
 //
index 51520c77751b0678b56bfa09b47f212b86a9722a..5958565823f346b7cda97fe437024583d6c4d5cf 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
 pub mod a {
index 2e5386d6866edefa56136210f1648fd0651dce22..8fcbfce0f7a625ca5fb1ddbddd6bdc5d4cf51e82 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // Issue #5041 - avoid overlapping memcpy when src and dest of a swap are the same
 
 // pretty-expanded FIXME #23616
index fd60c61463818ec78e4938b9cab157d3587a3a72..c6445190c0a4929e9edcd081c2a128c707823f5f 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
 /*
   This is about the simplest program that can successfully send a
   message.
index a7e7cc2062095de7669aaee90c8e5c9060e66844..f618d16c598a59b5c6a60549b4a46c9decba2a4e 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
 // compile-flags: --edition 2018
 
 #![feature(try_blocks)]
index aafb52e4c491fd73683435eaed533f62e71c03ff..94e2d57999313a21a31f3b4ea44cf7808de4c945 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 // compile-flags: --edition 2015
 
 fn main() {
index 53d6185020a0235ffb5f16b691780e4d66548f20..045a8a503203253b153703256a7be8c6441858c1 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_upper_case_globals)]
+#![allow(dead_code)]
 // `expr?` expands to:
 //
 // match expr {
index d615c5f1034dc8c27a21007a589d602e0858924a..f212e560bf28018759340b98aa5d04ea89ed4d8f 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // ignore-cloudabi no std::fs
 
 use std::fs::File;
index b8c0d80c5a67cb627a562572c9807733fd8300c0..7c2333ffdaacf6da33b03b243beb191c5a23f55d 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(stable_features)]
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
 
index 86ca37deb02d1aeb6e68f5c6fd5a67187112d744..b6fb2119308db0101fa2235e2eb68f302cbf2825 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 
 type point = (isize, isize);
 
index 4a169c0a384aa2bcf8bebe4f476447ef956544c4..a66830e23df1a454c070e7f9dd8a0ceac2d37b12 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 
 #![feature(core_intrinsics)]
 
index 18fb8e2e408f196f5d599b2954a170a251dbd1d9..b5eb2fe170510d05434f5505e756c23f7a6ea22e 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
+#![allow(unused_variables)]
 // Type ascription doesn't lead to unsoundness
 
 #![feature(type_ascription)]
index 7e2360caa93ff3d8c925a08aefda2bd764946d87..8fef294c0cf17cfede8c92ea1607806568d3c162 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
 
 
 // pretty-expanded FIXME #23616
index d7fb85ca4842e6824736ab98df5857b885c259c8..b918c3fc396df0b98ef35b612b4a6b36a0eefe37 100644 (file)
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_upper_case_globals)]
+#![allow(dead_code)]
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
 // Test a scenario where we generate a constraint like `?1 <: &?2`.
 // In such a case, it is important that we instantiate `?1` with `&?3`
 // where `?3 <: ?2`, and not with `&?2`. This is a regression test for
index 1a3bdcca7a1e522878fe1ff9811d1195225fae4e..e05f6f153a43e94ab22b09f182b0fcd9afbfaae4 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
 #![feature(box_syntax)]
index c59e40934fb4b2762ce69a1f734fa0ab1cfaff07..246cf209efb212bcf164cfefaa8579c7e9932d05 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
 
 
 // pretty-expanded FIXME #23616
index fea2bd978eb9692975f3dff98d7f1b7a4c44b3e0..76ac2d14b93a4f50cc055ab61a12ccf4c41a4bd6 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 
 // pretty-expanded FIXME #23616
 
index 67ead80c89b2562394b5a6ac53dfae2025bbda52..94d46b1a96eb96efc32e03549e0851ac50b68dd3 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
 fn f(a: *const isize) -> *const isize { return a; }
index 5eb079988f5be7e1b3d9937290ec2f90e8ca80b9..26cadf16e29dd7177eb0a67a48b3667e00463f60 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
 #![feature(never_type)]
 
 use std::mem::size_of;
index 113d52ffb35b9c0f6513670a66330d97dcef4b2f..ee482ea3c52f91f0e6c567479285f1398e176193 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // This test checks that the `_` type placeholder works
 // correctly for enabling type inference.
 
index d386f27d8c23b3a16b9f0a49c69ebea11d56f4c7..fecc6d705095c0d781b2784a0a14c98569026751 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(dead_code)]
 #![feature(box_syntax)]
 
 // Example from lkuper's intern talk, August 2012 -- now with static
index 8e8fd9bf648431c31b2a69894efb6ba32ad1285a..f2b6e9cd2551ef7330d5a76a1c6df69005967470 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(dead_code)]
 #![feature(box_syntax)]
 
 // Example from lkuper's intern talk, August 2012.
index 54d5415a5539b6e952803c7c597434da22e3c054..2dbe2c0a402854fd9126224525fcf409ae1674c2 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(deprecated)]
 // aux-build:typeid-intrinsic-aux1.rs
 // aux-build:typeid-intrinsic-aux2.rs
 
index 2acaff262690bb1771a3086114a39aa54944b640..a1047d47b4be9085be30759261698ded04257365 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
+#![allow(unused_assignments)]
+#![allow(unknown_lints)]
 // pretty-expanded FIXME #23616
 
 #![allow(dead_assignment)]
index 4dd1a565c9f14b330439bafdd68cfb1e843cdb34..0f601021f6aa348c2b42a50536a950d7a8a9bea7 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 struct Foo<'a>(&'a u8);
 
 fn foo(x: &u8) -> Foo<'_> {
index 67eceba020c803a03a98bf297e04c3e3fff3c78a..17ed465f99531ff270d015bbc37d6f5640340ca1 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_assignments)]
+#![allow(unknown_lints)]
 // pretty-expanded FIXME #23616
 
 #![allow(unused_variables)]
index 6448056fb11f4db1448b7ce57008c48c09890b9d..4e2570695069753599cb67e0b66d0b68990ed17c 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
+#![allow(unreachable_code)]
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
index 5cb5e8c4f99cd9271053911f1750dec46f28e016..4fffe98e4b2472f4c0076898c15f61d5de07b661 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
+#![allow(dead_code)]
 
 #![allow(path_statements)]
 #![allow(unreachable_code)]
index f3a2ad749a16824c1f0cff7c0c4f20d4f110f8b9..ac5a0db1cd2b993a32029317aae889dce1c08a79 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 //
 // See also: compile-fail/unsafe-fn-called-from-safe.rs
 
index 37c72ba8ab06565bb5cc9173a6fd823c0905a992..a40a764bfc228be42f87d8d21d01c138571038ee 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 //
 // See also: compile-fail/unsafe-fn-called-from-safe.rs
 
index 26f7b767988d240581d7bcb39cf838c352b06de7..6a58c9aa90b70c8786ea040debfbd37e1b5c5bea 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(type_alias_bounds)]
+#![allow(dead_code)]
 // Test syntax checks for `?Sized` syntax.
 
 use std::marker::PhantomData;
index 90b99f98533dee439dc64c93d06f8f7af5d80a35..e4480d7e97a4b147c8f23d0f18e32e8a8aa16014 100644 (file)
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unconditional_recursion)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_imports)]
 #![feature(box_syntax)]
 
 // Test sized-ness checking in substitution.
index 85ee21e09025592244d37820aa4b0968e054132b..e0ddc854fa0825c46ee7a57c0ffa9a342f898c78 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 // ignore-emscripten no threads support
 
 use std::sync::mpsc::{channel, Sender};
index 60016f59594696aefa4b5b6abcf2cf0d2224c84f..c669b522ab2be16b1c4a03fb00f3233bcf1669b3 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_variables)]
 pub struct A;
 
 mod test {
index 49ad171eaa2b6ff699cbebb22f91ff5441ff53a0..3115a359ff1452afdcf67dd9d82290b9f3cbb086 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_imports)]
 // pretty-expanded FIXME #23616
 
 pub use foo::bar::{self, First};
index 09a3849b9153bec7cdb201b3387105c86b8a4cfa..d6899e79152b8c27616b499e3e4c070a35a8f22d 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(stable_features)]
 // pretty-expanded FIXME #23616
 
 #![allow(unused_imports)]
index 579070a295adf90a0f4c40b668701eef3ff6147d..4614e47609a6612b22280c9771d47592730a4dfe 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 //
+#![allow(non_snake_case)]
 
 #![feature(non_ascii_idents)]
 
index 18987d1e016b1fa6a1a7f9d9212d34bf952447a6..0c92778cec474db01b6f54ed0aa2c565e378eb2a 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_attributes)]
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
 // pp-exact - Make sure we actually print the attributes
 // pretty-expanded FIXME #23616
 
index 03ba5587fcec86867c60de18c4c0ecd76fbeee7e..799917c4b0538f595d2d6b0ffd54302a2cdce9e5 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(stable_features)]
 #![feature(volatile)]
 use std::ptr::{read_volatile, write_volatile};
 
index 81a3c94eec3137fd612863539d7f595f6268cf45..0c059cb607e77b635432c15321288123201de55a 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 // compile-flags:-D improper-ctypes
 
 // pretty-expanded FIXME #23616
index 35120e428a7bd3d508103707da582cebd2ee66a8..c688ec540da81e3152d79a414c4f18c3081d47b1 100644 (file)
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
+#![allow(unreachable_code)]
+#![allow(unused_parens)]
 // compile-flags: -Z borrowck=compare
 
 #![recursion_limit = "128"]
index cdb5e3fe1d4ae59e4d23d427eb31252985281b71..b71f633bef45c79da6d35d6c67de51447a1c489f 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
+#![allow(unused_variables)]
 // Test that the `wf` checker properly handles bound regions in object
 // types. Compiling this code used to trigger an ICE.
 
index 7339fe47dc297125301d51e1453a5f6225e5e46b..d190e91575eccf5e434b3df4eeb8897069dc83b9 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)]
 
 use std::sync::Mutex;
 
index 5a23adeceb5c01e4258cf9e7ac3c95a033f5b83d..0fcd3efd9cec53938c4e58383d05ad0b04dfd071 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 //
+#![allow(dead_code)]
 // compile-flags: -O
 
 use std::collections::HashSet;
index bbdd65f7e5b2de33c645c62728b23b59c4d70904..8ea7ec67f1b316cc3c165e3a1b374a4c0cb66742 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_camel_case_types)]
 pub type HANDLE = usize;
 pub type DWORD = u32;
 pub type SIZE_T = u32;
index db884638622d190ba23d5e81f70148c1449fa623..9910c53492686abbb5d22f1cc5dfc081449012f1 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
+#![allow(unused_mut)]
 // ignore-emscripten no threads support
 
 use std::thread;
index cab68794e1cc4d6a9ef04b731f8435532250ec2b..0b60345233947e18ee253b3ecaf43c2a238922e5 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unused_must_use)]
+#![allow(unused_mut)]
 // ignore-emscripten no threads support
 
 use std::thread;
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' },
     ],
 };
index b3b403a7b86aa921de44438b216ed1e7dcc8aef8..01a4a410b03fb81fa7a86d9b3a55bfb904d26276 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-stage1
+
 // Issue #52129: ICE when trying to document the `quote` proc-macro from proc_macro
 
 // As of this writing, we don't currently attempt to document proc-macros. However, we shouldn't
diff --git a/src/test/rustdoc/inline_cross/auxiliary/trait-vis.rs b/src/test/rustdoc/inline_cross/auxiliary/trait-vis.rs
new file mode 100644 (file)
index 0000000..7457a5d
--- /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.
+
+#![crate_name = "inner"]
+
+pub struct SomeStruct;
+
+fn asdf() {
+    const _FOO: () = {
+        impl Clone for SomeStruct {
+            fn clone(&self) -> Self {
+                SomeStruct
+            }
+        }
+    };
+}
diff --git a/src/test/rustdoc/inline_cross/trait-vis.rs b/src/test/rustdoc/inline_cross/trait-vis.rs
new file mode 100644 (file)
index 0000000..5b5410b
--- /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.
+
+// aux-build:trait-vis.rs
+
+extern crate inner;
+
+// @has trait_vis/struct.SomeStruct.html
+// @has - '//code' 'impl Clone for SomeStruct'
+pub use inner::SomeStruct;
diff --git a/src/test/rustdoc/inline_local/trait-vis.rs b/src/test/rustdoc/inline_local/trait-vis.rs
new file mode 100644 (file)
index 0000000..73b1cc2
--- /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.
+
+pub trait ThisTrait {}
+
+mod asdf {
+    use ThisTrait;
+
+    pub struct SomeStruct;
+
+    impl ThisTrait for SomeStruct {}
+
+    trait PrivateTrait {}
+
+    impl PrivateTrait for SomeStruct {}
+}
+
+// @has trait_vis/struct.SomeStruct.html
+// @has - '//code' 'impl ThisTrait for SomeStruct'
+// !@has - '//code' 'impl PrivateTrait for SomeStruct'
+pub use asdf::SomeStruct;
diff --git a/src/test/rustdoc/intra-link-in-bodies.rs b/src/test/rustdoc/intra-link-in-bodies.rs
new file mode 100644 (file)
index 0000000..8c01941
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// we need to make sure that intra-doc links on trait impls get resolved in the right scope
+
+#![deny(intra_doc_link_resolution_failure)]
+
+pub mod inner {
+    pub struct SomethingOutOfScope;
+}
+
+pub mod other {
+    use inner::SomethingOutOfScope;
+    use SomeTrait;
+
+    pub struct OtherStruct;
+
+    /// Let's link to [SomethingOutOfScope] while we're at it.
+    impl SomeTrait for OtherStruct {}
+}
+
+pub trait SomeTrait {}
+
+pub struct SomeStruct;
+
+fn __implementation_details() {
+    use inner::SomethingOutOfScope;
+
+    // FIXME: intra-links resolve in their nearest module scope, not their actual scope in cases
+    // like this
+    // Let's link to [SomethingOutOfScope] while we're at it.
+    impl SomeTrait for SomeStruct {}
+}
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
index b4351b8268c8b8afcef503df0df672ad81e3d9c8..a771b1b15ce4d66543d91a2296147c1cd62f318e 100644 (file)
@@ -10,9 +10,6 @@
 
 #![crate_name = "foo"]
 
-// we need to reexport something from libstd so that `all_trait_implementations` is called.
-pub use std::string::String;
-
 include!("primitive/primitive-generic-impl.rs");
 
 // @has foo/primitive.i32.html '//h3[@id="impl-ToString"]//code' 'impl<T> ToString for T'
diff --git a/src/test/rustdoc/traits-in-bodies-private.rs b/src/test/rustdoc/traits-in-bodies-private.rs
new file mode 100644 (file)
index 0000000..ac3be7e
--- /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.
+
+// when implementing the fix for traits-in-bodies, there was an ICE when documenting private items
+// and a trait was defined in non-module scope
+
+// compile-flags:--document-private-items
+
+// @has traits_in_bodies_private/struct.SomeStruct.html
+// @!has - '//code' 'impl HiddenTrait for SomeStruct'
+pub struct SomeStruct;
+
+fn __implementation_details() {
+    trait HiddenTrait {}
+    impl HiddenTrait for SomeStruct {}
+}
index 3acf4af5fd247fd7495338f5f809faba2da4aaa3..a1d4019bba2bfe7e0dcc9fa7f63870f3ca5e4615 100644 (file)
 //prior to fixing `everybody_loops` to preserve items, rustdoc would crash on this file, as it
 //didn't see that `SomeStruct` implemented `Clone`
 
-//FIXME(misdreavus): whenever rustdoc shows traits impl'd inside bodies, make sure this test
-//reflects that
-
 pub struct Bounded<T: Clone>(T);
 
+// @has traits_in_bodies/struct.SomeStruct.html
+// @has - '//code' 'impl Clone for SomeStruct'
 pub struct SomeStruct;
 
 fn asdf() -> Bounded<SomeStruct> {
@@ -27,3 +26,37 @@ fn clone(&self) -> SomeStruct {
 
     Bounded(SomeStruct)
 }
+
+// @has traits_in_bodies/struct.Point.html
+// @has - '//code' 'impl Copy for Point'
+#[derive(Clone)]
+pub struct Point {
+    x: i32,
+    y: i32,
+}
+
+const _FOO: () = {
+    impl Copy for Point {}
+    ()
+};
+
+// @has traits_in_bodies/struct.Inception.html
+// @has - '//code' 'impl Clone for Inception'
+pub struct Inception;
+
+static _BAR: usize = {
+    trait HiddenTrait {
+        fn hidden_fn(&self) {
+            for _ in 0..5 {
+                impl Clone for Inception {
+                    fn clone(&self) -> Self {
+                        // we need to go deeper
+                        Inception
+                    }
+                }
+            }
+        }
+    }
+
+    5
+};
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
+}
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!"));
+}
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 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
 
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`.
diff --git a/src/test/ui/feature-gates/feature-gate-crate_in_paths.rs b/src/test/ui/feature-gates/feature-gate-crate_in_paths.rs
deleted file mode 100644 (file)
index e667dab..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct S;
-
-fn main() {
-    let _ = crate::S; //~ ERROR `crate` in paths is experimental
-}
diff --git a/src/test/ui/feature-gates/feature-gate-crate_in_paths.stderr b/src/test/ui/feature-gates/feature-gate-crate_in_paths.stderr
deleted file mode 100644 (file)
index 32115ba..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: `crate` in paths is experimental (see issue #45477)
-  --> $DIR/feature-gate-crate_in_paths.rs:14:13
-   |
-LL |     let _ = crate::S; //~ ERROR `crate` in paths is experimental
-   |             ^^^^^
-   |
-   = help: add #![feature(crate_in_paths)] to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
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/hygiene/dollar-crate-modern.stderr b/src/test/ui/hygiene/dollar-crate-modern.stderr
new file mode 100644 (file)
index 0000000..5fa7d8e
--- /dev/null
@@ -0,0 +1,8 @@
+warning: the feature `crate_in_paths` has been stable since 1.30.0 and no longer requires an attribute to enable
+  --> $DIR/dollar-crate-modern.rs:16:24
+   |
+LL | #![feature(decl_macro, crate_in_paths)]
+   |                        ^^^^^^^^^^^^^^
+   |
+   = note: #[warn(stable_features)] on by default
+
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 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 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");
+    }
+}
diff --git a/src/test/ui/issues/issue-53712.rs b/src/test/ui/issues/issue-53712.rs
new file mode 100644 (file)
index 0000000..2353904
--- /dev/null
@@ -0,0 +1,9 @@
+// issue #53712: make the error generated by using tuple indexing on an array more specific
+
+fn main() {
+    let arr = [10, 20, 30, 40, 50];
+    arr.0;
+    //~^ ERROR no field `0` on type `[{integer}; 5]` [E0609]
+    //~| HELP instead of using tuple indexing, use array indexing
+    //~| SUGGESTION arr[0]
+}
diff --git a/src/test/ui/issues/issue-53712.stderr b/src/test/ui/issues/issue-53712.stderr
new file mode 100644 (file)
index 0000000..db85919
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0609]: no field `0` on type `[{integer}; 5]`
+  --> $DIR/issue-53712.rs:5:9
+   |
+LL |     arr.0;
+   |     ----^
+   |     |
+   |     help: instead of using tuple indexing, use array indexing: `arr[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
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 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`.
diff --git a/src/test/ui/macros/macro-path-prelude-pass.stderr b/src/test/ui/macros/macro-path-prelude-pass.stderr
new file mode 100644 (file)
index 0000000..edae6a3
--- /dev/null
@@ -0,0 +1,8 @@
+warning: the feature `extern_prelude` has been stable since 1.30.0 and no longer requires an attribute to enable
+  --> $DIR/macro-path-prelude-pass.rs:13:12
+   |
+LL | #![feature(extern_prelude)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: #[warn(stable_features)] on by default
+
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
 
diff --git a/src/test/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs b/src/test/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs
new file mode 100644 (file)
index 0000000..e35c809
--- /dev/null
@@ -0,0 +1,35 @@
+// 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.
+//
+// run-pass
+//
+// FIXME(#54366) - We probably shouldn't allow #[thread_local] static mut to get a 'static lifetime.
+
+#![feature(nll)]
+#![feature(thread_local)]
+
+#[thread_local]
+static mut X1: u64 = 0;
+
+struct S1 {
+    a: &'static mut u64,
+}
+
+impl S1 {
+    fn new(_x: u64) -> S1 {
+        S1 {
+            a: unsafe { &mut X1 },
+        }
+    }
+}
+
+fn main() {
+    S1::new(0).a;
+}
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
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
diff --git a/src/test/ui/run-pass/extern/extern-prelude-core.stderr b/src/test/ui/run-pass/extern/extern-prelude-core.stderr
new file mode 100644 (file)
index 0000000..f769953
--- /dev/null
@@ -0,0 +1,8 @@
+warning: the feature `extern_prelude` has been stable since 1.30.0 and no longer requires an attribute to enable
+  --> $DIR/extern-prelude-core.rs:12:12
+   |
+LL | #![feature(extern_prelude, lang_items, start, alloc)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: #[warn(stable_features)] on by default
+
diff --git a/src/test/ui/run-pass/extern/extern-prelude-std.stderr b/src/test/ui/run-pass/extern/extern-prelude-std.stderr
new file mode 100644 (file)
index 0000000..8c059b4
--- /dev/null
@@ -0,0 +1,8 @@
+warning: the feature `extern_prelude` has been stable since 1.30.0 and no longer requires an attribute to enable
+  --> $DIR/extern-prelude-std.rs:12:12
+   |
+LL | #![feature(extern_prelude)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: #[warn(stable_features)] on by default
+
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",);
     }
 }
diff --git a/src/test/ui/run-pass/rfcs/rfc-2126-crate-paths/crate-path-absolute.stderr b/src/test/ui/run-pass/rfcs/rfc-2126-crate-paths/crate-path-absolute.stderr
new file mode 100644 (file)
index 0000000..f95237f
--- /dev/null
@@ -0,0 +1,8 @@
+warning: the feature `crate_in_paths` has been stable since 1.30.0 and no longer requires an attribute to enable
+  --> $DIR/crate-path-absolute.rs:12:12
+   |
+LL | #![feature(crate_in_paths)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: #[warn(stable_features)] on by default
+
diff --git a/src/test/ui/run-pass/rfcs/rfc-2126-crate-paths/crate-path-visibility-ambiguity.stderr b/src/test/ui/run-pass/rfcs/rfc-2126-crate-paths/crate-path-visibility-ambiguity.stderr
new file mode 100644 (file)
index 0000000..91f918d
--- /dev/null
@@ -0,0 +1,8 @@
+warning: the feature `crate_in_paths` has been stable since 1.30.0 and no longer requires an attribute to enable
+  --> $DIR/crate-path-visibility-ambiguity.rs:12:12
+   |
+LL | #![feature(crate_in_paths)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: #[warn(stable_features)] on by default
+
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();
+    }
+}
index fbdac98d2582e9f3e87860e0c59617356c95ea49..7d997fe493a7bc01b53ccf4c4f2d48e0d6e9a974 100644 (file)
@@ -37,7 +37,7 @@ fn main() {
     {
         // 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 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 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 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 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 a5d82949485802abb45f888d5b8b7f23927f031d..de314a8b2d45bce4958fc23939c5e4286e31621c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a5d82949485802abb45f888d5b8b7f23927f031d
+Subproject commit de314a8b2d45bce4958fc23939c5e4286e31621c
index daa922393c7417dcee930a880c80668cda3e308a..125907ad08853b92d35e86aecebcf0f784f348d5 160000 (submodule)
@@ -1 +1 @@
-Subproject commit daa922393c7417dcee930a880c80668cda3e308a
+Subproject commit 125907ad08853b92d35e86aecebcf0f784f348d5
index 6679ec79c1dd6d13804a6ef810871998ea8b47df..a4d839275c3ebc4bb5f8da11c6b21ce41dd2461a 100644 (file)
@@ -21,6 +21,7 @@ pub enum Mode {
     CompileFail,
     ParseFail,
     RunFail,
+    /// This now behaves like a `ui` test that has an implict `// run-pass`.
     RunPass,
     RunPassValgrind,
     Pretty,
index db856a1dcf94fe4fc2defe721673bd1c76c5fd2e..8829d8808366b87f027b2c6df347e800966773f0 100644 (file)
@@ -199,6 +199,10 @@ pub struct TestProps {
     pub force_host: bool,
     // Check stdout for error-pattern output as well as stderr
     pub check_stdout: bool,
+    // For UI tests, allows compiler to generate arbitrary output to stdout
+    pub dont_check_compiler_stdout: bool,
+    // For UI tests, allows compiler to generate arbitrary output to stderr
+    pub dont_check_compiler_stderr: bool,
     // Don't force a --crate-type=dylib flag on the command line
     pub no_prefer_dynamic: bool,
     // Run --pretty expanded when running pretty printing tests
@@ -249,6 +253,8 @@ pub fn new() -> Self {
             build_aux_docs: false,
             force_host: false,
             check_stdout: false,
+            dont_check_compiler_stdout: false,
+            dont_check_compiler_stderr: false,
             no_prefer_dynamic: false,
             pretty_expanded: false,
             pretty_mode: "normal".to_string(),
@@ -327,6 +333,14 @@ fn load_from(&mut self, testfile: &Path, cfg: Option<&str>, config: &Config) {
                 self.check_stdout = config.parse_check_stdout(ln);
             }
 
+            if !self.dont_check_compiler_stdout {
+                self.dont_check_compiler_stdout = config.parse_dont_check_compiler_stdout(ln);
+            }
+
+            if !self.dont_check_compiler_stderr {
+                self.dont_check_compiler_stderr = config.parse_dont_check_compiler_stderr(ln);
+            }
+
             if !self.no_prefer_dynamic {
                 self.no_prefer_dynamic = config.parse_no_prefer_dynamic(ln);
             }
@@ -510,6 +524,14 @@ fn parse_check_stdout(&self, line: &str) -> bool {
         self.parse_name_directive(line, "check-stdout")
     }
 
+    fn parse_dont_check_compiler_stdout(&self, line: &str) -> bool {
+        self.parse_name_directive(line, "dont-check-compiler-stdout")
+    }
+
+    fn parse_dont_check_compiler_stderr(&self, line: &str) -> bool {
+        self.parse_name_directive(line, "dont-check-compiler-stderr")
+    }
+
     fn parse_no_prefer_dynamic(&self, line: &str) -> bool {
         self.parse_name_directive(line, "no-prefer-dynamic")
     }
index 2d49c83edb917db3d67d26069fc8fb95c5ee09e5..401dec7b184b1b9d5a5a95dc8668d960bc355717 100644 (file)
@@ -247,7 +247,6 @@ fn run_revision(&self) {
         match self.config.mode {
             CompileFail | ParseFail => self.run_cfail_test(),
             RunFail => self.run_rfail_test(),
-            RunPass => self.run_rpass_test(),
             RunPassValgrind => self.run_valgrind_test(),
             Pretty => self.run_pretty_test(),
             DebugInfoGdb => self.run_debuginfo_gdb_test(),
@@ -257,13 +256,43 @@ fn run_revision(&self) {
             CodegenUnits => self.run_codegen_units_test(),
             Incremental => self.run_incremental_test(),
             RunMake => self.run_rmake_test(),
-            Ui => self.run_ui_test(),
+            RunPass | Ui => self.run_ui_test(),
             MirOpt => self.run_mir_opt_test(),
         }
     }
 
+    fn should_run_successfully(&self) -> bool {
+        let run_pass = match self.config.mode {
+            RunPass => true,
+            Ui => self.props.run_pass,
+            _ => unimplemented!(),
+        };
+        return run_pass && !self.props.skip_codegen;
+    }
+
+    fn should_compile_successfully(&self) -> bool {
+        match self.config.mode {
+            ParseFail | CompileFail => self.props.compile_pass,
+            RunPass => true,
+            Ui => self.props.compile_pass,
+            Incremental => {
+                let revision = self.revision
+                    .expect("incremental tests require a list of revisions");
+                if revision.starts_with("rpass") || revision.starts_with("rfail") {
+                    true
+                } else if revision.starts_with("cfail") {
+                    // FIXME: would be nice if incremental revs could start with "cpass"
+                    self.props.compile_pass
+                } else {
+                    panic!("revision name must begin with rpass, rfail, or cfail");
+                }
+            }
+            mode => panic!("unimplemented for mode {:?}", mode),
+        }
+    }
+
     fn check_if_test_should_compile(&self, proc_res: &ProcRes) {
-        if self.props.compile_pass {
+        if self.should_compile_successfully() {
             if !proc_res.status.success() {
                 self.fatal_proc_rec("test compilation failed although it shouldn't!", proc_res);
             }
@@ -1677,7 +1706,7 @@ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> C
                     rustc.arg("-Zui-testing");
                 }
             }
-            Ui => {
+            RunPass | Ui => {
                 if !self
                     .props
                     .compile_flags
@@ -1706,7 +1735,7 @@ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> C
 
                 rustc.arg(dir_opt);
             }
-            RunPass | RunFail | RunPassValgrind | Pretty | DebugInfoGdb | DebugInfoLldb
+            RunFail | RunPassValgrind | Pretty | DebugInfoGdb | DebugInfoLldb
             | Codegen | Rustdoc | RunMake | CodegenUnits => {
                 // do not use JSON output
             }
@@ -2638,8 +2667,12 @@ fn run_ui_test(&self) {
         let normalized_stderr = self.normalize_output(&stderr, &self.props.normalize_stderr);
 
         let mut errors = 0;
-        errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout);
-        errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr);
+        if !self.props.dont_check_compiler_stdout {
+            errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout);
+        }
+        if !self.props.dont_check_compiler_stderr {
+            errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr);
+        }
 
         let modes_to_prune = vec![CompareMode::Nll];
         self.prune_duplicate_outputs(&modes_to_prune);
@@ -2691,7 +2724,7 @@ fn run_ui_test(&self) {
 
         let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
 
-        if self.props.run_pass {
+        if self.should_run_successfully() {
             let proc_res = self.exec_compiled_test();
 
             if !proc_res.status.success() {
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
index f76c2d4e8cc542e061bc63020c33c248cb14f658..72c47273e63b5fdb7c9d7d9c4bba5d3d0bb92dae 100644 (file)
@@ -51,6 +51,7 @@
     "ordslice",           // Apache-2.0, rls
     "cloudabi",           // BSD-2-Clause, (rls -> crossbeam-channel 0.2 -> rand 0.5)
     "ryu",                // Apache-2.0, rls/cargo/... (b/c of serde)
+    "bytesize",           // Apache-2.0, cargo
 ];
 
 /// Which crates to check against the whitelist?