]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #54280 - japaric:no-cas-for-thumbv6, r=alexcrichton
authorPietro Albini <pietro@pietroalbini.org>
Sat, 22 Sep 2018 07:56:28 +0000 (09:56 +0200)
committerGitHub <noreply@github.com>
Sat, 22 Sep 2018 07:56:28 +0000 (09:56 +0200)
remove (more) CAS API from Atomic* types where not natively supported

closes #54276

In PR #51953 I made the Atomic* types available on targets like thumbv6m and
msp430 with the intention of *only* exposing the load and store API on those
types -- the rest of the API doesn't work on those targets because the are no
native instructions to implement CAS loops.

Unfortunately, it seems I didn't properly cfg away all the CAS API on those
targets, as evidenced in #54276. This PR amends the issue by removing the rest
of the CAS API.

This is technically a breaking change because *libraries* that were using this
API and were being compiled for e.g. thumbv6m-none-eabi will stop compiling.
However, using those libraries (before this change) in programs (binaries) would
lead to linking errors when compiled for e.g. thumbv6m so this change
effectively shifts a linker error in binaries to a compiler error in libraries.

On a side note: extending the Atomic API is a bit error prone because of these
non-cas targets. Unless the author of the change is aware of these targets and
properly uses `#[cfg(atomic = "cas")]` they could end up exposing new CAS API on
these targets. I can't think of a test to check that an API is not present on
some target, but we could extend the `tidy` tool to check that *all* newly added
atomic API has the `#[cfg(atomic = "cas")]` attribute unless it's whitelisted in
`tidy` then the author of the change would have to verify if the API can be used
on non-cas targets.

In any case, I'd like to plug this hole ASAP. We can revisit testing in a
follow-up issue / PR.

r? @alexcrichton
cc @mvirkkunen

504 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/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/tests/slice.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/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/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/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_target/spec/aarch64_pc_windows_msvc.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/parse/token.rs
src/libsyntax/ptr.rs
src/libsyntax_ext/format.rs
src/libsyntax_ext/test.rs
src/libsyntax_pos/symbol.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-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/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/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-mutate-in-guard.nll.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-41962.rs
src/test/ui/borrowck/issue-41962.stderr
src/test/ui/error-codes/E0008.nll.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0301.nll.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-dropck-ugeh-2.stderr
src/test/ui/feature-gates/feature-gate-panic-implementation.rs
src/test/ui/feature-gates/feature-gate-panic-implementation.stderr
src/test/ui/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-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/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-move-in-while.nll.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/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/rust-2018/dyn-keyword.fixed [new file with mode: 0644]
src/test/ui/rust-2018/dyn-keyword.rs [new file with mode: 0644]
src/test/ui/rust-2018/dyn-keyword.stderr [new file with mode: 0644]
src/test/ui/rust-2018/dyn-trait-compatibility.rs [new file with mode: 0644]
src/test/ui/rust-2018/dyn-trait-compatibility.stderr [new file with mode: 0644]
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/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 9f9c58ef900eedd23975793f53809908effbbc3e..c2c3f37db3726e1c750fc15729e192c75accd1ee 100644 (file)
@@ -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",
 ]
 
@@ -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)",
@@ -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)",
@@ -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",
 ]
@@ -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)",
@@ -2085,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)",
@@ -2174,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",
@@ -2218,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]]
@@ -2434,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)",
 ]
@@ -2621,7 +2646,7 @@ 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",
@@ -3015,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"
@@ -3123,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"
@@ -3147,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"
@@ -3177,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"
@@ -3202,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"
@@ -3349,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 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 da4a56cfecd6e5323c8cfc92a16f4213bc71cfe3..e4ac79a26d860957b48c83aac379bfc0dbbd6723 100644 (file)
@@ -1618,6 +1618,63 @@ pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
         }
     }
 
+    /// Copies elements from one part of the slice to another part of itself,
+    /// using a memmove.
+    ///
+    /// `src` is the range within `self` to copy from. `dest` is the starting
+    /// index of the range within `self` to copy to, which will have the same
+    /// length as `src`. The two ranges may overlap. The ends of the two ranges
+    /// must be less than or equal to `self.len()`.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if either range exceeds the end of the slice,
+    /// or if the end of `src` is before the start.
+    ///
+    /// # Examples
+    ///
+    /// Copying four bytes within a slice:
+    ///
+    /// ```
+    /// # #![feature(copy_within)]
+    /// let mut bytes = *b"Hello, World!";
+    ///
+    /// bytes.copy_within(1..5, 8);
+    ///
+    /// assert_eq!(&bytes, b"Hello, Wello!");
+    /// ```
+    #[unstable(feature = "copy_within", issue = "54236")]
+    pub fn copy_within<R: ops::RangeBounds<usize>>(&mut self, src: R, dest: usize)
+    where
+        T: Copy,
+    {
+        let src_start = match src.start_bound() {
+            ops::Bound::Included(&n) => n,
+            ops::Bound::Excluded(&n) => n
+                .checked_add(1)
+                .unwrap_or_else(|| slice_index_overflow_fail()),
+            ops::Bound::Unbounded => 0,
+        };
+        let src_end = match src.end_bound() {
+            ops::Bound::Included(&n) => n
+                .checked_add(1)
+                .unwrap_or_else(|| slice_index_overflow_fail()),
+            ops::Bound::Excluded(&n) => n,
+            ops::Bound::Unbounded => self.len(),
+        };
+        assert!(src_start <= src_end, "src end is before src start");
+        assert!(src_end <= self.len(), "src is out of bounds");
+        let count = src_end - src_start;
+        assert!(dest <= self.len() - count, "dest is out of bounds");
+        unsafe {
+            ptr::copy(
+                self.get_unchecked(src_start),
+                self.get_unchecked_mut(dest),
+                count,
+            );
+        }
+    }
+
     /// Swaps all elements in `self` with those in `other`.
     ///
     /// The length of `other` must be the same as `self`.
index 4f3086575c0cf2f0e89d494b125c81e1734874a4..8fc32f40b9920275a3f364edd5b0e44d556fe257 100644 (file)
@@ -39,6 +39,7 @@
 #![feature(inner_deref)]
 #![feature(slice_internals)]
 #![feature(option_replace)]
+#![feature(copy_within)]
 
 extern crate core;
 extern crate test;
index 012dc9bf5e0b93751c40ea628adf19adcce71459..d46a35ab82cfcae93dbaed7f6f3ceba5853adba7 100644 (file)
@@ -1000,3 +1000,49 @@ fn test_align_to_empty_mid() {
         assert_eq!(mid.as_ptr() as usize % mem::align_of::<Chunk>(), 0);
     }
 }
+
+#[test]
+fn test_copy_within() {
+    // Start to end, with a RangeTo.
+    let mut bytes = *b"Hello, World!";
+    bytes.copy_within(..3, 10);
+    assert_eq!(&bytes, b"Hello, WorHel");
+
+    // End to start, with a RangeFrom.
+    let mut bytes = *b"Hello, World!";
+    bytes.copy_within(10.., 0);
+    assert_eq!(&bytes, b"ld!lo, World!");
+
+    // Overlapping, with a RangeInclusive.
+    let mut bytes = *b"Hello, World!";
+    bytes.copy_within(0..=11, 1);
+    assert_eq!(&bytes, b"HHello, World");
+
+    // Whole slice, with a RangeFull.
+    let mut bytes = *b"Hello, World!";
+    bytes.copy_within(.., 0);
+    assert_eq!(&bytes, b"Hello, World!");
+}
+
+#[test]
+#[should_panic(expected = "src is out of bounds")]
+fn test_copy_within_panics_src_too_long() {
+    let mut bytes = *b"Hello, World!";
+    // The length is only 13, so 14 is out of bounds.
+    bytes.copy_within(10..14, 0);
+}
+
+#[test]
+#[should_panic(expected = "dest is out of bounds")]
+fn test_copy_within_panics_dest_too_long() {
+    let mut bytes = *b"Hello, World!";
+    // The length is only 13, so a slice of length 4 starting at index 10 is out of bounds.
+    bytes.copy_within(0..4, 10);
+}
+#[test]
+#[should_panic(expected = "src end is before src start")]
+fn test_copy_within_panics_src_inverted() {
+    let mut bytes = *b"Hello, World!";
+    // 2 is greater than 1, so this range is invalid.
+    bytes.copy_within(2..1, 0);
+}
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 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 4c0eeba74415076b3616e2edab6df8a32da371b7..e4d633c3f2cf27ccb1e1bb4a2025f699f0145016 100644 (file)
@@ -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],
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 6738267b5b8c809ef5f987b39d88c0ddce10bc6f..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
@@ -1436,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
@@ -1571,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 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 828364734f4a901b2c5de604da3c17fe58c71615..fb8744e4d96d6ecb1d2685c3ed8ec9dcaad8bf03 100644 (file)
@@ -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,11 +1308,12 @@ 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_suggestion_with_applicability(
@@ -1326,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..74e7c6c21edd9c6acd002b03b7275436b3ccb63e 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
                     );
@@ -1937,8 +1937,7 @@ fn check_ident(&mut self, cx: &EarlyContext, ident: ast::Ident) {
         let next_edition = match cx.sess.edition() {
             Edition::Edition2015 => {
                 match &ident.as_str()[..] {
-                    "async" |
-                    "try" => Edition::Edition2018,
+                    "async" | "try" | "dyn" => Edition::Edition2018,
                     _ => return,
                 }
             }
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 87a32b5a53e7a0d4365b4c1407dd0817c42d6b03..d2285e8cbf1bea5ac1884b1bffdf2453c5023751 100644 (file)
@@ -42,7 +42,7 @@
 use syntax::parse::source_file_to_stream;
 use syntax::symbol::Symbol;
 use syntax_pos::{Span, NO_EXPANSION, FileName};
-use rustc_data_structures::indexed_set::IdxSet;
+use rustc_data_structures::bit_set::BitSet;
 use rustc::hir;
 
 macro_rules! provide {
@@ -141,7 +141,7 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
         mir
     }
     mir_const_qualif => {
-        (cdata.mir_const_qualif(def_id.index), Lrc::new(IdxSet::new_empty(0)))
+        (cdata.mir_const_qualif(def_id.index), Lrc::new(BitSet::new_empty(0)))
     }
     fn_sig => { cdata.fn_sig(def_id.index, tcx) }
     inherent_impls => { Lrc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
index 02207c63b34642ae7522391ffdda27ce2039db9b..adff34af61ed8e9bd98a0566409d185849f55408 100644 (file)
@@ -622,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 4671332f2824c57e113fa00ea4c33cdf6b9b8f96..9187cb97e69e52f387e37605ae3df7a00b780aa1 100644 (file)
@@ -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);
 
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 3c694fe7b4e58d18ebe6e8c0b0762b5f475df9e0..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,
@@ -255,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(),
@@ -333,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());
 
@@ -408,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.
@@ -801,7 +824,7 @@ enum LocalMutationIsAllowed {
     No,
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 enum InitializationRequiringAction {
     Update,
     Borrow,
@@ -1595,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];
@@ -1653,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,
@@ -1969,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 10dddfed6a577da4273dc4dada5b69b3cf070985..343ef067a6ce86aac59e251bb1e3dd7d58dd8ec8 100644 (file)
@@ -1429,8 +1429,6 @@ pub struct Resolver<'a, 'b: 'a> {
     ambiguity_errors: Vec<AmbiguityError<'a>>,
     /// `use` injections are delayed for better placement and deduplication
     use_injections: Vec<UseError<'a>>,
-    /// `use` injections for proc macros wrongly imported with #[macro_use]
-    proc_mac_errors: Vec<macros::ProcMacError>,
     /// crate-local macro expanded `macro_export` referred to by a module-relative path
     macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>,
 
@@ -1458,9 +1456,6 @@ pub struct Resolver<'a, 'b: 'a> {
     /// Avoid duplicated errors for "name already defined".
     name_already_seen: FxHashMap<Name, Span>,
 
-    /// A set of procedural macros imported by `#[macro_use]` that have already been warned about
-    warned_proc_macros: FxHashSet<Name>,
-
     potentially_unused_imports: Vec<&'a ImportDirective<'a>>,
 
     /// This table maps struct IDs into struct constructor IDs,
@@ -1744,7 +1739,6 @@ pub fn new(session: &'a Session,
             privacy_errors: Vec::new(),
             ambiguity_errors: Vec::new(),
             use_injections: Vec::new(),
-            proc_mac_errors: Vec::new(),
             macro_expanded_macro_export_errors: BTreeSet::new(),
 
             arenas,
@@ -1766,7 +1760,6 @@ pub fn new(session: &'a Session,
             local_macro_def_scopes: FxHashMap(),
             name_already_seen: FxHashMap(),
             whitelisted_legacy_custom_derives: Vec::new(),
-            warned_proc_macros: FxHashSet(),
             potentially_unused_imports: Vec::new(),
             struct_constructors: DefIdMap(),
             found_unresolved_macro: false,
@@ -3299,9 +3292,12 @@ fn type_ascription_suggestion(&self,
                         err.span_label(base_span,
                                        "expecting a type here because of type ascription");
                         if line_sp != line_base_sp {
-                            err.span_suggestion_short(sp,
-                                                      "did you mean to use `;` here instead?",
-                                                      ";".to_string());
+                            err.span_suggestion_short_with_applicability(
+                                sp,
+                                "did you mean to use `;` here instead?",
+                                ";".to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
                         }
                         break;
                     } else if snippet.trim().len() != 0  {
@@ -4602,7 +4598,6 @@ fn report_ambiguity_error(&self, ident: Ident, b1: &NameBinding, b2: &NameBindin
 
     fn report_errors(&mut self, krate: &Crate) {
         self.report_with_use_injections(krate);
-        self.report_proc_macro_import(krate);
         let mut reported_spans = FxHashSet();
 
         for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
@@ -4826,7 +4821,12 @@ fn show_candidates(err: &mut DiagnosticBuilder,
             *candidate = format!("use {};\n{}", candidate, additional_newline);
         }
 
-        err.span_suggestions(span, &msg, path_strings);
+        err.span_suggestions_with_applicability(
+            span,
+            &msg,
+            path_strings,
+            Applicability::Unspecified,
+        );
     } else {
         let mut msg = msg;
         msg.push(':');
index d955a21ef233256c71cb4f1ae26f2a740c71e654..cb561b2597b397920e0ac9464bf584e382e04ad5 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;
@@ -980,7 +980,6 @@ pub fn finalize_current_module_macro_resolutions(&mut self) {
                     check_consistency(self, binding.def_ignoring_ambiguity());
                     if from_prelude {
                         self.record_use(ident, MacroNS, binding);
-                        self.err_if_macro_use_proc_macro(ident.name, span, binding);
                     }
                 }
             };
@@ -1132,69 +1131,6 @@ pub fn define_macro(&mut self,
         }
     }
 
-    /// Error if `ext` is a Macros 1.1 procedural macro being imported by `#[macro_use]`
-    fn err_if_macro_use_proc_macro(&mut self, name: Name, use_span: Span,
-                                   binding: &NameBinding<'a>) {
-        let krate = match binding.def() {
-            Def::NonMacroAttr(..) | Def::Err => return,
-            Def::Macro(def_id, _) => def_id.krate,
-            _ => unreachable!(),
-        };
-
-        // Plugin-based syntax extensions are exempt from this check
-        if krate == 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 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 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..e8f1733e532de7125db292e8c224e571d8960812 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,
@@ -506,16 +518,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 75311d938516f2b9da63c9480bbb1283932a53f8..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("::")
index 73057b19016c6a6081095cec2216e44bb1e44879..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 => {
@@ -694,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);
 
@@ -706,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..8ddb7473162b0db32780d199bb3812cfe36f64c2 100644 (file)
@@ -515,6 +515,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! (
@@ -711,7 +717,7 @@ pub enum AttributeGate {
 impl AttributeGate {
     fn is_deprecated(&self) -> bool {
         match *self {
-            Gated(Stability::Deprecated(_), ..) => true,
+            Gated(Stability::Deprecated(_, _), ..) => true,
             _ => false,
         }
     }
@@ -720,8 +726,9 @@ fn is_deprecated(&self) -> bool {
 #[derive(Copy, Clone, Debug)]
 pub enum Stability {
     Unstable,
-    // Argument is tracking issue link.
-    Deprecated(&'static str),
+    // First argument is tracking issue link; second argument is an optional
+    // help message, which defaults to "remove this attribute"
+    Deprecated(&'static str, Option<&'static str>),
 }
 
 // fn() is not Debug
@@ -970,6 +977,10 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                      "the `#[rustc_test_marker]` attribute \
                                       is used internally to track tests",
                                      cfg_fn!(rustc_attrs))),
+    ("rustc_test_marker2", Normal, Gated(Stability::Unstable,
+                                         "rustc_attrs",
+                                         "temporarily used by rustc to report some errors",
+                                         cfg_fn!(rustc_attrs))),
     ("rustc_transparent_macro", Whitelisted, Gated(Stability::Unstable,
                                                    "rustc_attrs",
                                                    "used internally for testing macro hygiene",
@@ -1044,7 +1055,7 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
     ("no_builtins", Whitelisted, Ungated),
     ("no_mangle", Whitelisted, Ungated),
     ("no_debug", Whitelisted, Gated(
-        Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
+        Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721", None),
         "no_debug",
         "the `#[no_debug]` attribute was an experimental feature that has been \
          deprecated due to lack of demand",
@@ -1057,7 +1068,8 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                                        cfg_fn!(omit_gdb_pretty_printer_section))),
     ("unsafe_destructor_blind_to_params",
      Normal,
-     Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
+     Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761",
+                                 Some("replace this attribute with `#[may_dangle]`")),
            "dropck_parametricity",
            "unsafe_destructor_blind_to_params has been replaced by \
             may_dangle and will be removed in the future",
@@ -1136,9 +1148,10 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
     ("panic_implementation",
      Normal,
      Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/44489\
-                                  #issuecomment-415140224"),
+                                  #issuecomment-415140224",
+                                 Some("replace this attribute with `#[panic_handler]`")),
            "panic_implementation",
-           "This attribute was renamed to `panic_handler`",
+           "this attribute was renamed to `panic_handler`",
            cfg_fn!(panic_implementation))),
 
     // RFC 2070
index 2aaab6aaa16d931942844d5f06e73ff3bb076b3d..68b468417182a0bef98e6e699e195b2215f3d10f 100644 (file)
@@ -46,7 +46,7 @@
 extern crate serialize as rustc_serialize; // used by deriving
 
 use rustc_data_structures::sync::Lock;
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bit_set::GrowableBitSet;
 pub use rustc_data_structures::small_vec::OneVector;
 pub use rustc_data_structures::thin_vec::ThinVec;
 use ast::AttrId;
@@ -82,8 +82,8 @@ macro_rules! unwrap_or {
 }
 
 pub struct Globals {
-    used_attrs: Lock<BitVector<AttrId>>,
-    known_attrs: Lock<BitVector<AttrId>>,
+    used_attrs: Lock<GrowableBitSet<AttrId>>,
+    known_attrs: Lock<GrowableBitSet<AttrId>>,
     syntax_pos_globals: syntax_pos::Globals,
 }
 
@@ -92,8 +92,8 @@ fn new() -> Globals {
         Globals {
             // We have no idea how many attributes their will be, so just
             // initiate the vectors with 0 bits. We'll grow them as necessary.
-            used_attrs: Lock::new(BitVector::new()),
-            known_attrs: Lock::new(BitVector::new()),
+            used_attrs: Lock::new(GrowableBitSet::new_empty()),
+            known_attrs: Lock::new(GrowableBitSet::new_empty()),
             syntax_pos_globals: syntax_pos::Globals::new(),
         }
     }
index 48e034b117f187857dc3334c4b8cbece92b75aaf..f7af8a3c34cf3b0cd402d027b51b9338cf4b12fa 100644 (file)
@@ -1578,8 +1578,9 @@ fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool)
             impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
             TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
         } else if self.check_keyword(keywords::Dyn) &&
-                  self.look_ahead(1, |t| t.can_begin_bound() &&
-                                         !can_continue_type_after_non_fn_ident(t)) {
+                  (self.span.edition() == Edition::Edition2018 ||
+                   self.look_ahead(1, |t| t.can_begin_bound() &&
+                                         !can_continue_type_after_non_fn_ident(t))) {
             self.bump(); // `dyn`
             // Always parse bounds greedily for better error recovery.
             let bounds = self.parse_generic_bounds()?;
@@ -3882,7 +3883,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;
index 6e8014284ec401c2d2ec93a9650a8cae331cd6aa..01bc7f6ad302be195c1ef2369a219f3573fab4ea 100644 (file)
@@ -136,6 +136,7 @@ fn ident_can_begin_type(ident: ast::Ident, is_raw: bool) -> bool {
         keywords::Unsafe.name(),
         keywords::Extern.name(),
         keywords::Typeof.name(),
+        keywords::Dyn.name(),
     ].contains(&ident.name)
 }
 
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 defdca9abd15ae89ab057f20b2cb057ec759ecd3..d412412fc655e8782e8bae6943e3bbe7bb8f3ba7 100644 (file)
@@ -414,26 +414,25 @@ pub fn fresh() -> Self {
     (50, Yield,              "yield")
 
     // Edition-specific keywords reserved for future use.
-    (51, Async,              "async") // >= 2018 Edition Only
-    (52, Try,                "try") // >= 2018 Edition Only
+    (51, Async,              "async") // >= 2018 Edition only
+    (52, Dyn,                "dyn") // >= 2018 Edition only
+    (53, Try,                "try") // >= 2018 Edition only
 
     // Special lifetime names
-    (53, UnderscoreLifetime, "'_")
-    (54, StaticLifetime,     "'static")
+    (54, UnderscoreLifetime, "'_")
+    (55, StaticLifetime,     "'static")
 
     // Weak keywords, have special meaning only in specific contexts.
-    (55, Auto,               "auto")
-    (56, Catch,              "catch")
-    (57, Default,            "default")
-    (58, Dyn,                "dyn")
+    (56, Auto,               "auto")
+    (57, Catch,              "catch")
+    (58, Default,            "default")
     (59, Union,              "union")
     (60, Existential,        "existential")
 }
 
 impl Symbol {
     fn is_unused_keyword_2018(self) -> bool {
-        self >= keywords::Async.name() &&
-        self <= keywords::Try.name()
+        self >= keywords::Async.name() && self <= keywords::Try.name()
     }
 }
 
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 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 {}
+}
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!"));
+}
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
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 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`.
diff --git a/src/test/ui/error-codes/E0008.nll.stderr b/src/test/ui/error-codes/E0008.nll.stderr
new file mode 100644 (file)
index 0000000..ce627cb
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0008]: cannot bind by-move into a pattern guard
+  --> $DIR/E0008.rs:13:14
+   |
+LL |         Some(s) if s.len() == 0 => {},
+   |              ^ moves value into pattern guard
+   |
+   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0008`.
diff --git a/src/test/ui/error-codes/E0301.nll.stderr b/src/test/ui/error-codes/E0301.nll.stderr
new file mode 100644 (file)
index 0000000..f060eb9
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0301]: cannot mutably borrow in a pattern guard
+  --> $DIR/E0301.rs:14:19
+   |
+LL |         option if option.take().is_none() => {}, //~ ERROR E0301
+   |                   ^^^^^^ borrowed mutably in pattern guard
+   |
+   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0301`.
index 80d81ea03cb6df4ffdc9bb28dcbe382da4ea3f78..d3d5bd498cfe8084777a7eb9de586d47b503872b 100644 (file)
@@ -2,7 +2,7 @@ error: use of deprecated attribute `dropck_parametricity`: unsafe_destructor_bli
   --> $DIR/feature-gate-dropck-ugeh-2.rs:17:5
    |
 LL |     #[unsafe_destructor_blind_to_params]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this attribute with `#[may_dangle]`
    |
 note: lint level defined here
   --> $DIR/feature-gate-dropck-ugeh-2.rs:11:9
index 84e5f302c1676e027c04c17a6e9862642daa8d76..ca51154884f1227fb047c5df0bc3940fbcb87993 100644 (file)
@@ -15,7 +15,7 @@
 
 use core::panic::PanicInfo;
 
-#[panic_implementation] //~ ERROR This attribute was renamed to `panic_handler` (see issue #44489)
+#[panic_implementation] //~ ERROR this attribute was renamed to `panic_handler` (see issue #44489)
 fn panic(info: &PanicInfo) -> ! {
     loop {}
 }
index 926a49ae83199b4c6e07c386d6f5a3719ecfb685..a54780468c42de97a4c48303f78e7fe4d8435237 100644 (file)
@@ -1,7 +1,7 @@
-error[E0658]: This attribute was renamed to `panic_handler` (see issue #44489)
+error[E0658]: this attribute was renamed to `panic_handler` (see issue #44489)
   --> $DIR/feature-gate-panic-implementation.rs:18:1
    |
-LL | #[panic_implementation] //~ ERROR This attribute was renamed to `panic_handler` (see issue #44489)
+LL | #[panic_implementation] //~ ERROR this attribute was renamed to `panic_handler` (see issue #44489)
    | ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(panic_implementation)] to the crate attributes to enable
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`.
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`.
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 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/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`.
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/rust-2018/dyn-keyword.fixed b/src/test/ui/rust-2018/dyn-keyword.fixed
new file mode 100644 (file)
index 0000000..e9cda1a
--- /dev/null
@@ -0,0 +1,10 @@
+// edition:2015
+// run-rustfix
+
+#![allow(unused_variables)]
+#![deny(keyword_idents)]
+
+fn main() {
+    let r#dyn = (); //~ ERROR dyn
+    //~^ WARN hard error in the 2018 edition
+}
diff --git a/src/test/ui/rust-2018/dyn-keyword.rs b/src/test/ui/rust-2018/dyn-keyword.rs
new file mode 100644 (file)
index 0000000..bdd3a90
--- /dev/null
@@ -0,0 +1,10 @@
+// edition:2015
+// run-rustfix
+
+#![allow(unused_variables)]
+#![deny(keyword_idents)]
+
+fn main() {
+    let dyn = (); //~ ERROR dyn
+    //~^ WARN hard error in the 2018 edition
+}
diff --git a/src/test/ui/rust-2018/dyn-keyword.stderr b/src/test/ui/rust-2018/dyn-keyword.stderr
new file mode 100644 (file)
index 0000000..5a3e00a
--- /dev/null
@@ -0,0 +1,16 @@
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-keyword.rs:8:9
+   |
+LL |     let dyn = (); //~ ERROR dyn
+   |         ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+note: lint level defined here
+  --> $DIR/dyn-keyword.rs:5:9
+   |
+LL | #![deny(keyword_idents)]
+   |         ^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rust-2018/dyn-trait-compatibility.rs b/src/test/ui/rust-2018/dyn-trait-compatibility.rs
new file mode 100644 (file)
index 0000000..9548df5
--- /dev/null
@@ -0,0 +1,8 @@
+// edition:2018
+
+type A0 = dyn;
+type A1 = dyn::dyn; //~ERROR expected identifier, found reserved keyword
+type A2 = dyn<dyn, dyn>; //~ERROR expected identifier, found `<`
+type A3 = dyn<<dyn as dyn>::dyn>;
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/dyn-trait-compatibility.stderr b/src/test/ui/rust-2018/dyn-trait-compatibility.stderr
new file mode 100644 (file)
index 0000000..ea04833
--- /dev/null
@@ -0,0 +1,14 @@
+error: expected identifier, found reserved keyword `dyn`
+  --> $DIR/dyn-trait-compatibility.rs:4:16
+   |
+LL | type A1 = dyn::dyn; //~ERROR expected identifier, found reserved keyword
+   |                ^^^ expected identifier, found reserved keyword
+
+error: expected identifier, found `<`
+  --> $DIR/dyn-trait-compatibility.rs:5:14
+   |
+LL | type A2 = dyn<dyn, dyn>; //~ERROR expected identifier, found `<`
+   |              ^ expected identifier
+
+error: aborting due to 2 previous errors
+
index a5d82949485802abb45f888d5b8b7f23927f031d..b1e1d388ea09ecc27515345b180dd02263b087df 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a5d82949485802abb45f888d5b8b7f23927f031d
+Subproject commit b1e1d388ea09ecc27515345b180dd02263b087df
index 183639b70bacf457920694d78a19cefe3565e1c0..125907ad08853b92d35e86aecebcf0f784f348d5 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 183639b70bacf457920694d78a19cefe3565e1c0
+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 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?